How to read a worked sample
Every endpoint guide in these docs ships a worked sample — a request you can copy verbatim, and the exact response envelope the platform returns. This index shows you how to turn a sample into a running call, and where the rest of the worked examples live.Reading an endpoint’s sample
A worked sample is a complete request: method, path, headers, and body. Nothing in it is a placeholder except your API key — so translating the curl block to your language is mechanical.- Copy the request as written. Base URL is always
https://api.orbit.devotel.io/api/v1; substitute a Test key (dv_test_sk_…) forX-API-Keyand the sample runs against the sandbox. - Translate it per language. The headers and JSON body carry over unchanged — only the HTTP client differs.
cURL
fetch
orbit.messages.send({ channel: "sms", to, body }) — and returns the same data the raw response carries. Pick whichever you read faster; the envelope below is identical either way.
Typed SDK tab, or raw fetch — one canonical pattern
Every endpoint page renders the same slice of languages: cURL, Node.js (TypeScript), and for the most-used operations Python, Go, Ruby, and PHP. Which client each tab shows is one decision, made once — here is the whole rule.Why the non-published-language tabs use raw HTTP
The SDK coverage matrix tells you which SDKs are on a registry today. Only Node and Web (npm) and Python (PyPI) install from a package manager — Go, Ruby, PHP, Java, and .NET live in workspace source, unpublished. A tab for a language whose SDK has no published package renders the raw HTTP call (plainfetch, requests, net/http, curl_exec) against the documented path, so the sample compiles and runs the day you paste it. This is deliberate, not a gap: an import that 404s on a registry is a worse sample than no import at all.
When the Node tab switches to the typed SDK
The Node SDK is feature-complete and published, so the Node tab has a real choice. Use Typed SDK whenever a typed method for the route exists — which today means one of the six core resources:orbit.messages, orbit.contacts, orbit.campaigns, orbit.verify, orbit.voice, and orbit.webhooks (check the coverage matrix before writing). Fall back to raw fetch() only for a route no typed method covers — and when you do, keep the escape-hatch shape (import { Orbit } + constructor, then the raw call) so a reader can move the call inside a typed client later without restructuring auth.
Migrating a sample from fetch to the typed SDK
The swap is verbatim — same body, same envelope; only the transport changes. Messaging send, before:fetch (before)
Idempotency-Key on every non-GET:
Node SDK (after)
{ data, meta } envelope comes back — see the four envelope shapes for what you branch on either way.
The snippet template contributors follow
New samples and doc overlays copy this shape exactly — the readers’ tabs stay uniform:Snippet template — escape-hatch signature
X-API-Key, and never an SDK import on a block that only uses fetch. The SDK index is the source of truth for “is the language published and does the route have a typed method” — if the matrix says no, the tab says raw fetch.
The four envelope shapes
Every response the platform returns is one of four shapes. Recognize the shape at a glance and you know how to read the body:- Success envelope —
{ data, meta }, HTTP 2xx. The resource (or a resource id) sits underdata;metacarries the request correlation id: - Success with pagination — the same
{ data, meta }, withmeta.paginationtelling you how to fetch the next page: - 207 Multi-Status batch envelope — bulk endpoints answer
207on partial success and give you one row per recipient; branch onstatusper row, never blanket-retry the batch:Canonical sample: Bulk sends (207 and all) and the Verify API. - Error envelope —
{ error, meta }on any non-2xx status. Branch on the stableerror.code, never on the human-readableerror.message:Canonical sample: API error handling by example.
Branching on a 207 in code
Bulk sends —POST /messages/batch, POST /verify/bulk — answer with one result row per recipient. Treat the HTTP status as a summary and handle each row by its own status:
Idempotency on the batch call. POST endpoints that create resources accept an
Idempotency-Key header; the SDK mints one per call, raw fetch must set it explicitly. A retry with the same key returns the original envelope — no duplicate sends, no second charge. The full contract lives in Idempotency and safe retries.Node
Python
Where the worked examples live
Samples are spread across the docs deliberately — each sits next to the endpoint it exercises. This page is the index:- REST API recipes — sixteen task-by-task worked samples (messaging, voice, campaigns, CDP, webhook round trips), each pairing curl with Node or Python.
- API recipes: operations endpoints — the operational surfaces as six runnable loops: the Verify second-officer approvals round trip, a cascade policy previewed through route-preview before smart-send arms it, the message-history
q=search DSL over the API, the SMPP no-delivery receipt window on a termination rule, the brand-identity trust posture read, and a risk-score pre-send gate. - API recipes: contact lifecycle — opt-outs bulk export/re-opt-in round trip, AI segment autopilot through a materialized lookalike audience, per-contact frequency-cap rules behind the send decision, and a day of usage for metering guardrails.
- Error handling by example — three worked failures with the fix in code.
- Endpoint worked samples — each endpoint family page carries a curated sample block (messaging, campaigns, voice, and the rest).
- Starter examples and the Quickstart — five runnable repos and the end-to-end first call, when a single request/response isn’t enough.
Pagination in one paragraph
List endpoints paginate one of two ways, and the response tells you which: most endpoints are cursor-based — readmeta.pagination.cursor when has_more is true and pass it back as ?cursor=…; a smaller set of dashboard-oriented families is offset-based — the page metadata (items, total, limit, offset) lives inside the data envelope instead. The shape of the response you’re holding identifies the style.
The cursor loop in code
Node
Python