> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing compliant API samples

> How to author a sample block that passes the coverage audit: the per-operation language floor, the idiom for Go, Ruby, and PHP before their SDKs publish, the two-language trim on long pages, and how to verify with the generator.

# Writing compliant API samples

This page is the operational companion to the
[SDK sample coverage policy](/api-reference/sdk-language-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:

| Check               | Fails when                                                                                                                                                                                     |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Language floor      | A `<RequestExample>` block lacks **bash (cURL)** or **TypeScript (Node.js)** — a Python-only, curl-only, or SDK-only block fails outright.                                                     |
| Full-slice coverage | An operation inside the page's first-15 slice is missing any of the six languages (cURL, Node.js, Python, Go, Ruby, PHP — in that order).                                                      |
| Response envelope   | A `<ResponseExample>` omits the complete envelope — `data` plus `meta.request_id` and `meta.timestamp` — or an error envelope without a labelled status fence (for example, `json 422 Error`). |
| Overlay samples     | A hand-written overlay "Worked sequences" block ships something other than cURL-only, cURL + TypeScript, or the full six.                                                                      |

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](/sdks/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](/sdks/node) — published; use the typed client.
* [Python](/sdks/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](/sdks/go) — unpublished; vendor from source (`client.Request`
  escape hatch) or write a plain `net/http` client.
* [Ruby](/sdks/ruby) — unpublished; vendor from source (`client.request`
  escape hatch) or write plain `Net::HTTP`.
* [PHP](/sdks/php) — unpublished; vendor from source
  (`OrbitClient::request` escape hatch) or write the `curl` extension.
* [Java](/sdks/java) — unpublished; vendor from source.
* [C#](/sdks/csharp) — 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:

```bash theme={null}
pnpm --filter @devotel/docs run docs:regen
```

`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.
