Skip to main content

Worked organization samples

The endpoint list below documents each operation’s parameters; this overlay walks the org profile the way a dashboard shell or account-integration actually uses it: read the org → branch on plan and wallet balance → update name and settings → handle the auth failures. Every request uses your API key (X-API-Key) against https://api.orbit.devotel.io. The base plan field, budget, and settings keys you see here are the public contract — examples below tab cURL and Node.js (TypeScript). Every response follows the same envelope — data plus a meta block carrying request_id and timestamp. Quote meta.request_id when you report a failure; support can trace the request end-to-end from it.

1. Read the org profile

GET /api/v1/organization returns the authenticated organization’s record: name, slug, plan, wallet balance, team-member and per-second rate limits, logo, branding, general settings, and whether it is a subaccount. This is the call the dashboard shell makes on every page load, so it is also the right “ping” for a server-side client — a 200 here confirms the key is valid, scoped to a live org, and outside its rate limit.
200
Field notes a reader will hit on first integration:
  • balance is the wallet balance in USD cents — 250000 is $2,500.00. It is null on the brief degraded shell (see below), so branch on that before rendering a dollar figure.
  • billing_currency is resolved from settings.wallet_currency and falls back to USD; format every cost figure with it so displayed amounts match the currency billing charges against.
  • monthlyBudgetCents is the org’s monthly budget ceiling — the denominator spend-percent billing alerts divide by. null means no budget is set and spend-percent alerts never fire.
  • isSubaccount is derived server-side from the org’s parent link. A true value gates reseller-only affordances — a subaccount cannot create nested subaccounts.
  • A transient database blip returns a degraded shell — same 200, id + plan + tenantId filled from the auth context, the remaining DB-sourced fields null. Handle the nulls rather than erroring; the next poll self-corrects.

2. Branch on plan and balance

A typical shell reads the org once, then decides what to render: a low-balance banner, a plan-gated feature, a budget progress bar. Both edge cases matter — the balance can be null (degraded shell) and the budget can be null (never configured).
Node.js
Wallet semantics per endpoint family (what fires a running balance down, what tops it up) live in the billing reference; this page documents the org record itself.

3. Update name and general settings

PUT /api/v1/organization updates the org’s name, general settings, and monthly budget. It shares its handler with PUT /api/v1/settings/general, so the same write-boundary guards apply (unsubscribe-redirect URL checks, escalation-recipient allowlist, IP-allowlist lockout protection) and the settings cache invalidates immediately. Requires the owner or admin role — a member or developer key gets 403 (see Errors). The settings bag is free-form JSONB; a few keys are load-bearing and are listed below. Regional display prefs (timezone, locale, dateFormat) can be sent either as top-level fields or inside settings — the controller folds top-level values into the bag before writing, and lifts them back to the top level on read.
200
Semantics to code against:
  • monthly_budget_cents — integer budget ceiling in cents; 0 is rejected (a zero divisor would make every spend-percent alert fire). Send null to clear the budget; omit the field to leave it unchanged.
  • name — 1–200 characters; the rename echoes to the org record provider-side, so the dashboard header updates without a separate call.
  • settings.dnc_sync_enabled — must be a literal boolean. A string "true" or numeric 1 is rejected at validation — and even if it slipped through, the DNC pre-flight endpoint gates on the literal boolean and would keep returning 403.
  • Idempotency-Key — pass a stable client-generated value to dedupe retries on transient timeouts; the same key replays the original response for 24 h on 2xx. 409 means the same key is still in flight.
Sandbox. The update is a control-plane write — it changes only your org’s own record, triggers no provider delivery, and deducts no credits, so it is safe to exercise from any environment. The X-Test-Mode header matters for session-authenticated calls (browser clients): set X-Test-Mode: true to route the call through the test-mode pipeline and see meta.test_mode: true on the response. For server-to-server keys it is ignored — use a dv_test_sk_* test-prefixed key, which unconditionally enables sandbox behaviour, instead of toggling the header on a dv_live_sk_* key. The read and the update both honour the header for session clients, so a full read→write round trip in test mode touches no live state.

4. Errors

Errors follow the { error, meta } envelope. The two failures every integration must handle: 401 — the API key is invalid or has been revoked. This fires for a malformed key, a key that was rotated or deleted under Developer → API keys, and a key whose owning org was removed. Do not retry a 401 — rotate from a known-good credential before re-sending anything.
401
403 — role too low for the write. PUT /api/v1/organization requires the owner or admin role. A member or developer-role key (and a session for a user without the role) cannot update the org — reads still work with any role:
403
A validation failure (a 0 budget, a non-boolean dnc_sync_enabled, an unsafe unsubscribe or sandbox webhook URL) returns 422 VALIDATION_ERROR with a details object pointing at the rejected field, the same shape the rest of this page’s writes follow.