Skip to main content

Writing compliant API samples

This page is the operational companion to the SDK sample coverage policy, which states what a compliant <RequestExample> and <ResponseExample> must contain. Here: how to actually write that block today — which language form to pick per SDK status, how to sample long pages, and how to check your work with the generator before it reaches review. If a page you touch fails the audit, fix it against this page, not by pattern-matching what shipped last.

1. What the audit checks — the per-operation floor

The content scanner and the paired source-pin tests (scripts/docs-request-examples-coverage.test.mjs, scripts/docs-sdk-samples.test.mjs) fail a page when any of these is true: The policy page is the authority; the test names are listed here so you can run the exact check the scanner runs before you push.

2. Language idiom per SDK status

Write each sample against the SDK status reported on the SDK index — that page and each language page below are the source of truth for what is published today versus what you must vendor from source:
  • Node.js — published; use the typed client.
  • Python — published (core-scope); the typed client exists, but generated samples deliberately use plain requests so the snippet works for a reader who has not installed the SDK.
  • Go — unpublished; vendor from source (client.Request escape hatch) or write a plain net/http client.
  • Ruby — unpublished; vendor from source (client.request escape hatch) or write plain Net::HTTP.
  • PHP — unpublished; vendor from source (OrbitClient::request escape hatch) or write the curl extension.
  • Java — unpublished; vendor from source.
  • C# — unpublished; vendor from source.
For Go, Ruby, and PHP today, the correct sample uses either the vendored SDK’s untyped escape hatch (the same client.Request / client.request / $client->request form the generated tabs use) or a plain standard-library HTTP client — not an import that assumes a registry (go get github.com/devotel/orbit-go does not resolve today, which is why the generated Go tab imports the module only because the docs toolchain vendors it). If you hand-write a Go/Ruby/PHP sample in an overlay, include the bare HTTP form — an SDK import alone fails the audit’s “SDK-import without bare HTTP” check. Typed helper methods legitimately exist only for the published SDKs — Node (orbit.messages.send(...)) and Python (client.messages.send_sms(...)) — and even Python’s generated tab uses plain requests by design. For Go, Ruby, and PHP, the typed wrappers exist in vendored source, but the universal form that works for every route is the escape hatch above; use it unless the page is explicitly teaching the vendored workspace.

3. Sampling long pages — the two most-used forms

The first-15/two-form split is a fixed constant (FULL_SLICES_MAX = 15 in both generate-endpoint-docs.ts and render-code-tabs.ts), not a per-page choice. When a page exceeds 15 operations the two most-used forms are always cURL and Node.js (TypeScript) — measured by usage, not by an editor’s pick. Never choose a different pair and never shift an operation’s order just to move it in or out of the full slice: reordering the catalogue shifts the cut for the whole page. If an operation beyond the fifteenth needs the full six languages, promote it in the page’s _overlay file instead (worked example per the policy’s fix-forward checklist).

4. Run the generator and check the banner count

After editing samples in an overlay or a hand-authored page under api-reference/, run the whole docs regeneration chain from the repo root:
docs:regen runs sync-openapi, generate-endpoint-docs, generate-error-codes-docs, generate-webhook-events-docs, and render-code-tabs in one pass — the same five step the predev/prebuild chain runs. Then re-open the page and check the banner + endpoint count: for a page over the threshold, the generated footer count must still match the number of operations that trimmed to the two-form slice; for a page at or under 15 operations, no banner should appear at all and every block must carry the full six. A mismatch means the catalogue regenerated with an unexpected entry — re-check your _overlay placement rather than editing the generated file.

5. Common mistakes — the recurring audit findings

These ship repeatedly on new pages (billing, agents, and others today):
  1. Python-only (or any language alone) — a page that opens with python and nothing else fails the floor even if the Python block is correct. Bash and TypeScript are the floor; everything else is additive.
  2. SDK import without the bare HTTP form — writing import orbit_sdk or require 'orbit_sdk' against an unpublished or optional dependency. Show the bare HTTP form (cURL, or the plain stdlib client) beside any SDK import, and for Go/Ruby/PHP prefer the escape hatch or plain client as Section 2 describes.
  3. Placeholder request bodies — a fenced block whose body is ```{} or { "..." }. The audit reads a placeholder body as missing. Copy the operation’s real body exactly as the generated catalogue entry carries it, with real field names and example values.
  4. Editing generated files by hand — anything under api-reference/endpoints/* that carries the generator header is overwritten on regen. Put the worked sample in the page’s _overlay file; generations preserve the overlay and drop hand edits to the generated body.
Work through the floor table in Section 1 against your diff before review; the fixes above are the recurring shapes, not a taxonomy to memorize.