Tutorials

Build a Typed Discord API Client from Its OpenAPI Spec

Discord publishes an official OpenAPI spec at discord/discord-api-spec — but the repo's own README calls it a "public preview" and warns it's "subject to breaking changes without advance notice" and "should not be used within production environments." Unlike GitHub, Stripe, OpenAI, or Twilio, Discord itself doesn't publish an official REST client SDK at all — libraries like discord.js and discord.py are community-maintained, not first-party. That makes generating a client from this spec more useful than usual, with one important caveat: treat it as a preview, not a stable dependency.

Where the spec lives

Fact Value
Repo discord/discord-api-spec
File specs/openapi.json (stable subset) or specs/openapi_preview.json (unstable/experimental)
Spec version OpenAPI 3.1.0, API version 10
Size ~1.2 MB (openapi.json)
License MIT
Status Official, auto-generated, explicitly labeled preview quality per README

Only the HTTP API is covered — Discord's Gateway (WebSocket) events aren't part of this spec, so a generated client covers REST endpoints only, not real-time bot events.

How to fetch it

curl -sL -o discord-openapi.json \
  https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json

Use openapi.json for the stable, public API surface. openapi_preview.json adds unstable/experimental endpoints the README explicitly says not to rely on in production.

The honest complication: it's labeled preview, and it says so directly

This is different from a size or schema-shape complication — it's a stability statement from Discord itself. The repo README says, verbatim: "The public preview of the OpenAPI spec is subject to breaking changes without advance notice, and should not be used within production environments." It also documents specific known gaps:

  • Many operations and fields have no descriptions.
  • Operations aren't tagged, which weakens generated docs navigation.
  • Flag fields (bitfields) don't detail individual flag meanings.
  • Optional query parameters are typed as nullable even where that doesn't map to real semantics.

There's also a genuine schema quirk worth knowing before you generate: Discord uses both anyOf and oneOf to mean the same thing (exactly one type from the list, never a combination), and disambiguates with a custom x-discord-union: oneOf extension. A generator that doesn't understand that extension will still produce usable code — the actual JSON Schema semantics are followed correctly — but won't take advantage of Discord's clarification that these are always exclusive choices, not composable fields.

Generate a TypeScript client locally

npx @openapitools/openapi-generator-cli generate \
  -i discord-openapi.json \
  -g typescript-fetch \
  -o ./generated/discord-client

Given the OpenAPI 3.1 base and the preview-quality gaps in descriptions and tags, expect to hand-annotate or post-process the generated output more than you would for a more mature spec — method names will be correct (Discord sets operationId on most endpoints), but generated doc comments will be sparse.

The hosted path

Sourced reads the Discord spec directly and produces hosted docs, a TypeScript SDK preview, a Python SDK preview, and an llms.txt file in one pass — useful specifically because Discord doesn't otherwise offer official hosted docs or an official SDK to compare against. Point Sourced at your repo or paste the raw openapi.json URL. Previews are free and unlimited, with up to two hosted noindex docs sites and one hosted MCP server, no credit card required — a fast way to see what a typed Discord REST client and browsable docs look like before deciding whether the preview-quality spec is solid enough for your use case.

When this actually makes sense

  • Filling a real gap. Discord has no official SDK — community libraries like discord.js (JS) and discord.py (Python) are widely used and well-maintained, but they're not first-party, and they're built around the Gateway/bot pattern more than the plain REST API. A generated client from the official spec is a legitimate option for pure REST use (managing applications, webhooks, or slash commands from a backend) where you don't want a full bot framework.
  • Learning 3.1 union-heavy codegen on a smaller, more approachable spec (1.2 MB) than Stripe or OpenAI's.
  • Agent tooling. An MCP server generated from the Discord spec gives an agent typed tool calls against Discord's REST API for automation use cases.
  • Internal wrappers around specific Discord REST operations (e.g., posting to a webhook, managing application commands) where a full bot library is unnecessary weight.

If you're building an actual Discord bot with Gateway events, slash commands, and interaction handling, use discord.js, discord.py, or another established community library for your language — they handle the Gateway connection, sharding, and interaction lifecycle that this REST-only OpenAPI spec doesn't cover at all.

FAQ

Does Discord have an official OpenAPI spec?

Yes, at discord/discord-api-spec, maintained by Discord and auto-generated from their internal API definitions. It explicitly covers only the HTTP API, version 10, not the Gateway (WebSocket) API.

Is the Discord OpenAPI spec safe to use in production?

Discord's own README says no: "should not be used within production environments" and "subject to breaking changes without advance notice." Treat generated output as something to validate against the live API regularly, not a stable dependency to pin and forget.

Does Discord publish an official SDK?

No. Unlike GitHub, Stripe, OpenAI, and Twilio, Discord does not publish a first-party REST or bot client library. discord.js, discord.py, and similar libraries are community-maintained, which is part of why generating a client from the official spec is more useful here than for vendors with a strong official SDK.

What's the difference between openapi.json and openapi_preview.json?

openapi.json covers the stable, public API. openapi_preview.json adds unstable and experimental endpoints that Discord explicitly says should not be considered stable. Start with openapi.json unless you specifically need an experimental feature.

Why does the spec use both anyOf and oneOf for the same kind of union?

Discord's README explains they use oneOf where technically possible and fall back to anyOf (for example, when all fields in the union are optional, which breaks strict oneOf validation), marking both with a custom x-discord-union: oneOf extension to clarify that only one type applies at a time.

Should I use a generated client for a Discord bot?

Not for a Gateway-based bot — this spec only covers the REST API, not the WebSocket Gateway events, slash command interaction handling, or sharding that a bot needs. Use discord.js, discord.py, or a similar library for bot development; reserve a generated client for pure REST automation, internal tooling, or agent use cases.