Skip to main content

Integration

Add SDK examples

Drop `x-codeSamples` into your OpenAPI operations and NookDocs merges them into the endpoint's Try-It code card — auto-generated curl + real SDK snippets side by side in one tab strip.

Auto-generated curl / JS / Python examples are the bare minimum. Your users probably have an SDK. The x-codeSamples OpenAPI extension (a ReDoc convention, widely adopted) lets you attach hand-written or Speakeasy/Stainless-generated SDK examples directly to each operation, and NookDocs merges them into the endpoint code card automatically.

Why this matters

The Try-It code card on every endpoint page ships three auto-generated tabs by default: cURL, JavaScript (fetch), Python (requests). These are fine for exploration but not what your users actually paste into their codebase — they paste SDK calls. x-codeSamples gives you that extra tab strip with zero UI configuration on our side. Drop the extension into your spec, redeploy, done.

The extension

paths:
  /payments:
    post:
      operationId: createPayment
      summary: Create a payment
      x-codeSamples:
        - lang: TypeScript
          label: "@acme/sdk"
          source: |
            import Acme from "@acme/sdk";
            const acme = new Acme({ apiKey: process.env.ACME_KEY });
            const payment = await acme.payments.create({
              amount: 1000,
              currency: "usd",
              source: "tok_visa",
            });
        - lang: Python
          label: "acme-python"
          source: |
            from acme import Acme
            acme = Acme(api_key="sk_...")
            payment = acme.payments.create(
                amount=1000,
                currency="usd",
                source="tok_visa",
            )
        - lang: Go
          label: "acme-go"
          source: |
            acme := acme.New("sk_...")
            payment, err := acme.Payments.Create(&acme.PaymentCreateParams{
                Amount: acme.Int64(1000),
                Currency: acme.String("usd"),
                Source: acme.String("tok_visa"),
            })

Each entry becomes a tab in the endpoint's code card. Tab labels come from label (fallback: lang). The tab content is the source string verbatim, syntax-highlighted via Prism based on lang.

Field reference

x-codeSamples[].langstringpathrequired

Language slug. Controls syntax highlighting. Common values: typescript, javascript, python, ruby, go, rust, java, php, csharp, swift, kotlin, bash, curl. Free-form — unknown slugs render as plain text without highlighting.

x-codeSamples[].labelstringpath

Human-readable tab label. Falls back to lang when omitted. Use this to differentiate multiple entries of the same language (e.g. "SDK" vs "REST (fetch)" for two TypeScript samples).

x-codeSamples[].sourcestringpathrequired

The code snippet. Multiline strings via YAML | block scalar are the cleanest — indentation is preserved exactly. Keep it under ~50 lines per tab so readers can scan without scrolling the whole page.

How NookDocs merges these

The endpoint code card renders tabs in this order:

  1. Auto-generated — cURL + JS fetch + Python requests, synthesised from the spec.

  2. x-codeSamples — appended after, in the order declared in the spec.

If x-codeSamples contains a language that conflicts with an auto-generated tab (e.g. you provided your own curl), your version wins — the auto-gen is dropped. This gives you full control when you need it.

Reader clicks a tab → the Try-It playground uses the currently visible tab's language as the base for its "Run request" call where applicable (for cURL, fetch, requests — SDK snippets are display-only).

Generator tools

You don't have to hand-write these. Commercial and open-source tools generate x-codeSamples entries from your OpenAPI spec automatically:

Speakeasy

Commercial. Generates idiomatic SDKs for 7+ languages and emits matching x-codeSamples entries back into the spec. Keeps SDK calls and docs in sync as your spec evolves.

Stainless

Commercial. Similar positioning — SDK gen + docs examples. Used by OpenAI, Anthropic, Cloudflare.

openapi-generator

Open source. Generates client code but doesn't auto-emit x-codeSamples. You'd post-process the output.

Hand-written

Totally fine for small specs. Pay attention to authentication setup — readers will copy-paste, so make the snippets runnable after one env-var swap.

Authoring guidance

Keep them paste-runnable

The fastest path from "read the docs" to "first 200 response" is a snippet the reader can paste, swap the API key, and run. Include the import line. Include the env-var lookup. Omit everything else — no explanatory comments, no try/catch unless the point is the try/catch.

// Good — copy, paste, swap key, run
import Acme from "@acme/sdk";
const acme = new Acme({ apiKey: process.env.ACME_KEY });
const payment = await acme.payments.create({ amount: 1000, currency: "usd" });
// Bad — too much scaffolding, reader stops reading halfway through
async function createPaymentExample() {
  try {
    // First, initialize the SDK with your API key from env
    const acme = new Acme({
      apiKey: process.env.ACME_KEY ?? "fallback-value",
    });
    // Now call the payments.create method...
    const payment = await acme.payments.create({
      amount: 1000, // in cents
      currency: "usd",
      /* more options here */
    });
    console.log("Created payment", payment.id);
  } catch (err) {
    console.error("Payment failed:", err);
  }
}

One variant per use case

Don't ship 6 TypeScript samples for the same endpoint. Pick one canonical example per SDK, per operation. Use the label field to differentiate if you truly need two (e.g. "SDK (async)" vs "SDK (sync)").

Keep labels short

Tab strips break layout when labels are long. Target ≤12 chars. "@acme/sdk" beats "Acme TypeScript SDK (npm package)".

Order by user preference

Tabs render in declared order. Put your users' most likely language first — for B2B SaaS that's usually TypeScript or Python. Not cURL — cURL is already auto-generated.

Inspect the merged output

Every endpoint page serves the agent-filtered MDX at /<endpoint-path>.md. The x-codeSamples entries appear there too so LLMs helping users generate integration code can see what canonical SDK usage looks like:

curl -sL https://docs.acme.com/api-reference/payments/create-payment.md

The Copy-for-LLMs button in the endpoint page header emits the same view.

Limitations

  • No inline execution. Unlike cURL / fetch / requests tabs, SDK snippets are display-only. The Try-It playground doesn't execute arbitrary SDK calls.

  • No syntax validation. We render whatever source string you provide. Broken snippets ship as broken snippets.

  • No Speakeasy/Stainless-specific field names. Both tools emit standard x-codeSamples. If your generator uses a proprietary extension (e.g. x-speakeasy-code-samples or similar), rename to x-codeSamples or configure the generator to output the standard form.

Related

Was this page helpful?

Last updated August 7, 2026