Skip to main content
This guide shows you how to explore on-chain prediction markets utilizing the DFlow Prediction Market Metadata API, and accessing their token addresses for trading.
This quickstart demonstrates how to use the Prediction Market Metadata API to build discovery UIs. For trading tokens, see the Trade Tokens guide.

Overview

The DFlow Prediction Market Metadata API includes multiple ways to discover prediction market outcome tokens:
  1. Fetch all events
  2. Fetch events by market status
  3. Get events by relevant categories and tags
1

Fetch Events with Nested Markets

Use the /api/v1/events endpoint with withNestedMarkets=true to retrieve events along with their associated markets. Each market contains token addresses in the accounts field that you can use for trading.
/// Base URL for the DFlow Prediction Market Metadata API
const METADATA_API_BASE_URL = "https://prediction-markets-api.dflow.net";

/// Fetch events with nested markets included
const response = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/events?withNestedMarkets=true&limit=200`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

if (!response.ok) {
  throw new Error("Failed to fetch events");
}

const data = await response.json();
const events = data.events;

/// Log details of each event and nested markets
events.forEach((event: any) => {
  console.log("Event:", {
    ticker: event.ticker,
    title: event.title,
    subtitle: event.subtitle,
    seriesTicker: event.seriesTicker,
  });

  if (event.markets && event.markets.length > 0) {
    event.markets.forEach((market: any) => {
      const accounts = market.accounts;
      const accountValues = Object.values(accounts);

      console.log("  Market:", {
        ticker: market.ticker,
        title: market.title,
        status: market.status,
        accounts: accountValues.map((account: any) => ({
          yesMint: account.yesMint,
          noMint: account.noMint,
        })),
      });
    });
  }
});
2

Fetch Events by Market Status

Use the status filter on /api/v1/events endpoint to retrieve and markets that are actively available for trading or markets that are coming soon.
/// Base URL for the DFlow Prediction Market Metadata API
const METADATA_API_BASE_URL = "https://prediction-markets-api.dflow.net";

/// Fetch events with nested markets included
const response = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/events?withNestedMarkets=true&status=active&limit=200`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

if (!response.ok) {
  throw new Error("Failed to fetch events");
}

const data = await response.json();
const events = data.events;

/// Log details of each event and nested markets
events.forEach((event: any) => {
  console.log("Event:", {
    ticker: event.ticker,
    title: event.title,
    subtitle: event.subtitle,
    seriesTicker: event.seriesTicker,
  });

  if (event.markets && event.markets.length > 0) {
    event.markets.forEach((market: any) => {
      const accounts = market.accounts;
      const accountValues = Object.values(accounts);

      console.log("  Market:", {
        ticker: market.ticker,
        title: market.title,
        status: market.status,
        accounts: accountValues.map((account: any) => ({
          yesMint: account.yesMint,
          noMint: account.noMint,
        })),
      });
    });
  }
});
/// Base URL for the DFlow Prediction Market Metadata API
const METADATA_API_BASE_URL = "https://prediction-markets-api.dflow.net";

/// Fetch events with nested markets included
const response = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/events?withNestedMarkets=true&status=initialized&limit=200`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

if (!response.ok) {
  throw new Error("Failed to fetch events");
}

const data = await response.json();
const events = data.events;

/// Log details of each event and nested markets
events.forEach((event: any) => {
  console.log("Event:", {
    ticker: event.ticker,
    title: event.title,
    subtitle: event.subtitle,
    seriesTicker: event.seriesTicker,
  });

  if (event.markets && event.markets.length > 0) {
    event.markets.forEach((market: any) => {
      const accounts = market.accounts;
      const accountValues = Object.values(accounts);

      console.log("  Market:", {
        ticker: market.ticker,
        title: market.title,
        status: market.status,
        accounts: accountValues.map((account: any) => ({
          yesMint: account.yesMint,
          noMint: account.noMint,
        })),
      });
    });
  }
});
3

Get Events by Categories and Tags

Use categories tags to filter series and find relevant events and markets. This approach involves: (1) retrieving available tags organized by category, (2) filtering series by tags or categories, and (3) fetching events filtered by series tickers (comma-separated) to discover markets.
/// Base URL for the DFlow Prediction Market Metadata API
const METADATA_API_BASE_URL = "https://prediction-markets-api.dflow.net";

/// Fetch tags organized by categories
const response = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/tags_by_categories`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

if (!response.ok) {
  throw new Error("Failed to fetch tags by categories");
}

const data = await response.json();
const tagsByCategories = data.tagsByCategories;

/// Display available categories and their tags
Object.entries(tagsByCategories).forEach(([category, tags]: [string, any]) => {
  console.log(`  Tags for ${category}: ${tags.join(", ")}`);
});
/// Select a category or tags from the tags_by_categories response
const selectedCategory = "Sports";
const selectedTag = "Football";

/// Option 1: Filter series by category
const responseByCategory = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/series?category=${selectedCategory}`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

const dataByCategory = await responseByCategory.json();

/// Log series with ticker and title
console.log(
  `Found ${dataByCategory.series.length} series with "${selectedCategory}"`
);
dataByCategory.series.forEach((s: any) => {
  console.log(`  ${s.ticker}: ${s.title}`);
});

/// Extract series tickers for filtering events
const categorizedSeriesTickers = dataByCategory.series.map((s) => s.ticker);

/// Option 2: Filter series by tag
const responseByTag = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/series?tags=${selectedTag}`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

if (!responseByTag.ok) {
  throw new Error("Failed to fetch series");
}

const dataByTag = await responseByTag.json();

/// Log series with ticker and title
console.log(`Found ${dataByTag.series.length} series with "${selectedTag}"`);
dataByTag.series.forEach((s: any) => {
  console.log(`  ${s.ticker}: ${s.title}`);
});

/// Extract series tickers for filtering events
const taggedSeriesTickers = dataByTag.series.map((s) => s.ticker);

/// Option 3: Filter by both category and tags (comma-separated)
const selectedTags = "Football,Soccer";
const responseWithBoth = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/series?category=${selectedCategory}&tags=${selectedTags}`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

const dataWithBoth = await responseWithBoth.json();
const filteredSeries = dataWithBoth.series;

/// Log series with ticker and title
console.log(
  `Found ${filteredSeries.length} series with category "${selectedCategory}" and tags "${selectedTags}"`
);
filteredSeries.forEach((s: any) => {
  console.log(`  ${s.ticker}: ${s.title}`);
});

/// Extract series tickers for filtering events
const seriesTickers = filteredSeries.map((s) => s.ticker);
/// Option 1: Filter by a single series ticker
const selectedSeriesTicker = seriesTickers[0]; // Example: "KXNFLGAME"

/// Fetch events filtered by a single series ticker with nested markets
const response = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/events?seriesTickers=${selectedSeriesTicker}&withNestedMarkets=true&limit=100`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

/// Option 2: Filter by multiple series tickers (comma-separated)
const multipleSeriesTickers = seriesTickers.slice(0, 3).join(","); // Example: "KXNFLGAME,KXNBAGAME,KXNHLGAME"

/// Fetch events filtered by multiple series tickers with nested markets
const responseMultiple = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/events?seriesTickers=${multipleSeriesTickers}&withNestedMarkets=true&limit=100`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

if (!response.ok) {
  throw new Error("Failed to fetch events by series");
}

const data = await response.json();
const filteredEvents = data.events;

/// Use responseMultiple for multiple series tickers
/// const dataMultiple = await responseMultiple.json();
/// const filteredEvents = dataMultiple.events;

/// Log details of each event and markets
filteredEvents.forEach((event) => {
  console.log("Event:", {
    ticker: event.ticker,
    title: event.title,
    subtitle: event.subtitle,
    seriesTicker: event.seriesTicker,
  });

  if (event.markets && event.markets.length > 0) {
    event.markets.forEach((market) => {
      const accounts = market.accounts;
      const accountValues = Object.values(accounts);

      console.log("  Market:", {
        ticker: market.ticker,
        title: market.title,
        status: market.status,
        accounts: accountValues.map((account) => ({
          yesMint: account.yesMint,
          noMint: account.noMint,
        })),
      });
    });
  }
});

API Response Structure

Events Response

The events endpoint returns:
  • Event Information: Ticker, title, subtitle, series ticker
  • Nested Markets (when withNestedMarkets=true): Array of markets with:
    • Market ticker, title, status
    • Accounts: Object containing yesMint and noMint token addresses
    • Volume, open interest, timing information

Tags by Categories Response

Returns a mapping of categories to arrays of tags:
{
  "tagsByCategories": {
    "Sports": ["Football", "Soccer", "Basketball", "Hockey", "Baseball", "NFL"],
    "Crypto": ["Pre-Market", "SOL", "BTC", "ETH", "SHIBA", "Dogecoin"]
  }
}

Series Response

Returns series templates with:
  • Ticker: Used to filter events
  • Title: Human-readable series name
  • Category: Series category
  • Tags: Array of associated tags
  • Frequency: How often events in this series occur

Next Steps