Skip to main content
During development, you can use the developer endpoints without an API key. For production use, you’ll need an API key to avoid rate limits.
Use the Metadata API to discover markets and map outcome token mints for trading.

Get Events with Nested Markets

You get events (real-world questions) and include their nested markets so you can read outcome mints from the accounts field. If you need the data model, review Event fields.
const METADATA_API_BASE_URL = "https://dev-prediction-markets-api.dflow.net";

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 get events");
}

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

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 accountValues = Object.values(market.accounts);

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

Filter Events by Market Status

Filter events to focus on markets that match a given status (for example, active vs. initialized). If you need the full status flow, see Prediction Market Lifecycle.
const METADATA_API_BASE_URL = "https://dev-prediction-markets-api.dflow.net";

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 get events");
}

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

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

      console.log("Market:", {
        ticker: market.ticker,
        title: market.title,
        status: market.status,
        accounts: accountValues.map((account: any) => ({
          yesMint: account.yesMint,
          noMint: account.noMint,
        })),
      });
    });
  }
});
const METADATA_API_BASE_URL = "https://dev-prediction-markets-api.dflow.net";

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 get events");
}

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

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

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

Filter Events by Categories and Tags

Use tags to find relevant series (event templates) and then get events for those series. This keeps discovery focused without hardcoding tickers.
const METADATA_API_BASE_URL = "https://dev-prediction-markets-api.dflow.net";

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 get tags by categories");
}

const data = (await response.json()) as { tagsByCategories: Record<string, any[]> };
const tagsByCategories = data.tagsByCategories;

Object.entries(tagsByCategories).forEach(
    ([category, tags]: [string, any]) => {
        const tagList = Array.isArray(tags) ? tags.join(", ") : String(tags ?? "");
        console.log(`Tags for ${category}: ${tagList}`);
    }
);
const METADATA_API_BASE_URL = "https://dev-prediction-markets-api.dflow.net";

const selectedCategory = "Sports";
const selectedTag = "Football";

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();
const categorizedSeriesTickers = dataByCategory.series.map((s: any) => s.ticker);

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 get series");
}

const dataByTag = await responseByTag.json();
const taggedSeriesTickers = dataByTag.series.map((s: any) => s.ticker);

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;
const seriesTickers = filteredSeries.map((s: any) => s.ticker);
const METADATA_API_BASE_URL = "https://dev-prediction-markets-api.dflow.net";

const selectedSeriesTicker = seriesTickers[0];

const response = await fetch(
  `${METADATA_API_BASE_URL}/api/v1/events?seriesTickers=${selectedSeriesTicker}&withNestedMarkets=true&limit=100`,
  {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  }
);

const multipleSeriesTickers = seriesTickers.slice(0, 3).join(",");
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 get events by series");
}

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

filteredEvents.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 accountValues = Object.values(market.accounts);

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

Review API Responses

Use event and series responses to extract outcome mints and filter markets. If you only need outcome mints, you can skip to the accounts map in each market object.

Events Response

You receive event metadata and nested markets (when withNestedMarkets=true), including yesMint and noMint in market accounts.

Tags by Categories Response

You receive a map of categories to tag arrays, which you use to filter series.

Series Response

You receive series metadata, including ticker, title, category, tags, and frequency.

API Routes

Cookbook Repository

This recipe, along with many more, is available in the DFlow Cookbook Repo. You can clone it and start coding immediately.