Skip to main content

API recipes: operations endpoints

Four operational surfaces endpoint-guides cover conceptually but only sample once. Each recipe below is a runnable loop — read, write, decide — over the exact endpoints the linked page documents. Base URL is https://api.orbit.devotel.io/api/v1 throughout; authenticate with X-API-Key and a test key (dv_test_sk_…) for the sandbox.

1. Verify approvals: run the second-officer round trip

The four-eyes gate on Verify approvals has a full queue lifecycle — policy, queue, decision — and a client needs all three calls to drive it. Read the current policy to predict whether your next change will queue (any authenticated member can read it):
cURL
Turn the gate on (owner/admin only — the requester’s own key is usually not this):
cURL
From the next request onward, an OTP template edit or an over-threshold resend burst returns gated: true and queues instead of applying. Read the queue the approver’s key sees:
cURL
Decide one item — approve, or reject with a reason the requester reads back. The approver must differ from the requester: a self-approve fails 409 FOUR_EYES_VIOLATION before anything moves.
cURL
cURL — reject instead
An approved item executes in its own plane — a template body applies to its verification profile; a resend burst re-enters the normal dispatch path. Expected results are 200 with data.settings on reads, 200 with the decided item on approve/reject, and 403 on any of the three writes from a non-owner/admin key. Every decision lands in the audit log as verify.approval.approved / verify.approval.rejected. Canonical pages: Verify approvals: set up the second-officer gate, OTP approvals reference.

2. Fallback chains: preview the resolved cascade, then let smart-send arm it

A per-message cascade_policy resolves an ordered fallback set without sending when you run it through POST /messages/route-preview. Preview before you arm — the Fallback chains guide’s step 7 names both preview endpoints; this is the API loop it refers to. Preview the router’s primary plus the cascade — same body shape as smart-send, read-only:
cURL
The reply carries the recommendation block the smart route preview guide documents, plus a resolved cascade block when cascade_policy was in the request: the fallback channel list, the ordering (static / adaptive / off), and a cost estimate. A 200 with data.cascade.ordering: "off" means the policy suppressed the arm — the send below would ride the primary channel with no fallback stamped. Arm it with the real send — the same cascade_policy on POST /messages/smart-send stamps the resolved chain onto the message’s metadata as fallback_channels, so a terminal DLR on the primary escalates to the next entry:
cURL
202 Accepted returns the persisted send with data.channel naming the router’s primary pick and the fallback set stamped on its metadata. voice and fax are filtered out of cascade_policy.fallback_channels — the per-message cascade is messaging-only; OTP step-up chains that admit voice belong on a Verify profile, per the chain-type table in Fallback chains. Canonical pages: Smart-send fallback chains, Smart route preview.

3. Message history: run the q= search DSL over the API

The search message history guide documents the fielded DSL; the API loop adds the list endpoint, URL-encoding rules, and cursor pagination. Encode the expression — spaces to %20, : to %3A, > to %3E — and it rides GET /messages alongside the pagination params:
cURL
Page the matches with the same cursor contract as any list — meta.pagination.cursor while has_more is true:
cURL
A malformed expression returns 422 INVALID_QUERY naming the rejected field, operator, or clause (INVALID_QUERY_FIELD on an unknown field, INVALID_QUERY_SYNTAX on an unterminated quote) — fix the named clause; never retry the same string. Each matching row carries both the provider-side identifier (external_id) and the canonical Orbit id (id, msg_…), so a look-up can deep-link into the message detail page. Canonical pages: Search message history, Pagination.

4. SMPP: set the no-delivery receipt window on a termination rule

The SMPP receipt timeout window guide sets receipt_timeout_seconds on a termination rule’s deliver hop (10–120 s, platform default 30). This loop hashes the exact API body the guided contract ships and where it goes. Write the rule — absorb submit_sm traffic onto WhatsApp with a 45-second UNDELIV window:
cURL
201 Created returns the rule. Out-of-range or non-integer windows (25.5, 0, 121) answer 422 at rule-write time, and a rule in shadow mode evaluates without moving traffic until you flip it to enforce. The deadline only arms for submissions whose registered_delivery requested a receipt: a bind that never requests receipts gets none from the timeout either. Canonical pages: SMPP receipt timeout window, Send-side DLR model.

See also