API recipes: contact lifecycle
The contact-lifecycle cookbook. The canonical pages — Opt-outs API, Segments API, Frequency Caps API, Analytics API — document each endpoint; these recipes chain them into runnable loops: read, write, decide. All four loops stay on tenant-owned controls — opt-outs, segments, and caps are your rules, set and enforced by your key. Base URL ishttps://api.orbit.devotel.io/api/v1 throughout; authenticate with X-API-Key and a test key (dv_test_sk_…) for the sandbox.
1. Opt-outs: bulk suppress → export → re-opt-in one channel
A suppression file arrives from support and you need the round trip: opt the contacts out in one batch, export the suppression list as compliance evidence, then restore the one contact who re-consents by phone or email.contact identifies the address-book row by phone (E.164) or email — pick the id off GET /contacts first if your file lists raw addresses.
Bulk opt-out — up to 500 rows per call, per-row outcomes isolated:
cURL
succeeded / skipped / failed count independently, so one unknown phone number never rolls the rest back:
207
ok: false, status: "failed", and an actionable error string — clean the named rows and resend only them; skipped rows (already opted out) never double-stamp the consent trail.
Export the suppression list — compliance evidence, up to 10 000 contacts:
cURL
200
channel to export every opt-out across channels. Past 10 000, page GET /contacts/optouts on its cursor instead — same rows, no cap.
Re-opt-in the one contact who re-consents — delete the channel’s opt-out:
cURL
200 returns the updated contact row. The contact is eligible again on that channel subject to consent records — the delete clears the suppression, and any affirmative-consent requirement (a WhatsApp 24-hour window, RCS marketing consent) still has to be satisfied by your own capture. The round trip closes: every enlisted row, plus one restored.
Labelled error envelope — a channel outside the canonical nine (case-insensitive, whitespace-trimmed) fails the whole request before any row is processed:
422
200 with already_opted_out: true, not an error.
Canonical page: Opt-outs API. Envelope reference: API error handling by example.
2. Segments: autopilot → evaluate → materialize-lookalike → members
The AI-assisted audience loop: describe the audience, persist the suggestion as a real segment, force a re-evaluation when data moves, then grow it — preview a lookalike expansion and materialize it as a static segment you can page members out of. Autopilot from a description — suggest rules + live preview in one round-trip, nothing persisted:cURL
200
POST /contacts/segments (the main cookbook’s task 15); membership materializes on create.
Labelled error envelope — the model emits a rule the segmentation engine cannot validate, and the error names the field:
422
503 means no AI provider is configured on the deployment — fall back to the manual builder.
Evaluate on demand — after data (not rules) changed, rebuild membership now instead of waiting for the periodic refresh:
cURL
200 returns the evaluation result — the matched count, duration, and the membership diff — in the standard envelope.
Materialize a lookalike audience — promote a preview into a new static segment (no rules, auto_refresh off — the k-NN snapshot is a point-in-time cohort the refresh scheduler never wipes):
cURL
201 returns materialized: true plus the new segment — its id is a first-class segment you activate like any other. A preview with no candidates returns 200 with materialized: false and a reason, persisting nothing.
Read members — page the materialized snapshot with the same cursor contract as any list:
cURL
meta.pagination.cursor while has_more is true. The members list reads the last-materialized snapshot — call evaluate (above) first if you need the very latest audience.
Canonical pages: Segments API (AI surfaces), Contacts API (saved-segment CRUD + membership).
3. Frequency caps: read the rules behind a send decision
Caps are the tenant’s rolling-window limits on how often one contact can be messaged. Two reads serve the “what applies to this contact?” question: the per-contact rules read, then the live per-recipient usage you branch a send decision on. Rule writes ridePATCH /frequency-caps/:id; reads ride GET /contacts/:id/frequency-caps (rules) and GET /contacts/:id/cap-status (live usage) — the decision loop below uses the rule IDs from the first read to target back-off per category.
Read the rules that apply to the contact — flat plus grouped by channel, globals separated:
cURL
200
cURL
max_count / current_count / sends_remaining and (once slots are exhausted) the next_slot_at ISO timestamp, plus the channel’s consent state — one read answers both “how many left” and “may we send at all”.
Update a rule — widen the marketing SMS cap; rule writes are owner/admin/developer with frequency-caps:write:
cURL
Node.js — branch your composer on the snapshot
429
4. Usage: fetch a day of metering for guardrails
The metering guardrail read: the home-overview usage chart’s same daily timeline, pulled for a one-day window so your own guardrails (budget dashboards, spend alerts, anomaly heuristics) sit on the numbers the platform charts. Read-only; an explicitstart_date / end_date pair takes precedence over the days trailing window.
cURL
200
totals into a budget check before you queue a batch, or row-by-row into a daily anomaly heuristic. For spend-shaped guardrails instead of volume, the billing surface’s spend series and burn rate (the main cookbook’s task 22) price the same window.
Labelled error envelope — an explicit pair with a missing end:
400
start_date (or end_date) is a 400 — the pair refines together, and the details issues list names the fix instead of silently falling back to the trailing days window.
Canonical page: Analytics API → per-day usage timeline. Finer-grained metering (rate a batch, credit notes): Usage metering.
See also
- REST API recipes — the main task-by-task cookbook these four loops extend
- API recipes: operations endpoints — the operational surfaces (approvals, cascade preview, search DSL, SMPP window, brand trust, risk gate)
- Using worked samples — translate any curl block here into your HTTP client
- API error handling by example — retriable-vs-terminal for every failure shape above