Developer & Integration
This appendix is for engineers integrating with or operating Orbit. Each feature is marked ✅ Available, 🟡 Partial, or 🔜 Not yet wired so you can build against what's real today.
Some surfaces below ship a working data model and management API but aren't fully wired end-to-end yet (e.g. the campaign dialer, programmatic API-key auth). They're flagged so you don't build against a stub.
1. Authentication — ✅ Available
- Model: stateless JWT (HS256), sent as
Authorization: Bearer <jwt>. - Tenant resolution: the FQDN subdomain identifies the tenant
(
acme-orbit.comstice.com→ tenantacme); login isPOST /auth/login. - Passwords: hashed with bcrypt. Token lifetime is short-lived (the login
service defaults to ~8 hours);
/auth/refreshre-issues,/auth/logoutis a client-side no-op (stateless). - Internal SSO:
/auth/exchangetrades a valid token for a fresh session (admin ↔ agent) — used by the Agent SDK; not an external IdP. - Token storage (web UI): browser
localStorage(admin_auth_token, and a separate agent token). No cookies. - MFA / SSO (SAML/OAuth/OIDC): 🔜 not present today.
All protected endpoints (/api/...) require a Bearer JWT and run on
tenant-scoped connections (row-level security + per-router ownership checks).
2. API keys — 🟡 Partial (issue & manage; programmatic auth not yet wired)
You can mint and revoke scoped API keys from Settings → API Keys (or REST):
| Aspect | Detail |
|---|---|
| Format | sk_… (32 random bytes, base64url). Shown once at creation. |
| Storage | Only the SHA-256 hash + a 10-char display prefix are kept. |
| Scopes | Free-form list (e.g. calls, recordings, users, queues). |
| Expiry | Optional expires_at. |
| Gating | Requires the api-access license + api_keys.create / api_keys.delete permission. |
| REST | GET / POST / DELETE /api/api-keys. |
Keys are issuable and validatable in the data layer, but no public endpoint
authenticates with an API key yet — every real API today is JWT-Bearer (§1).
Treat API keys as forward-looking until an x-api-key auth path is confirmed for
your deployment.
3. Programmable call handling — ✅ Available
An Application can handle a call three ways: if call_flow_sid is set, the
visual flow engine runs; otherwise the Application is driven
by a webhook / WebSocket handler (call_hook_url) or a static verb list
(app_json). (Confirm the exact precedence for your build if you mix them.)
Webhook model (jambonz-style):
- Request: method =
call_hook_method(defaultPOST), JSON body:{ "callId", "traceId", "accountSid", "applicationSid","from", "to", "direction", "callStatus": "ringing" } - Headers:
Content-Type: application/json,User-Agent: SaaS-SBC/1.0, optional Basic auth. (HMACX-Signaturebody-signing is supported in the client but there's no UI to store a webhook secret yet, so it's dormant today.) - Response: HTTP 2xx with a JSON array of verbs to execute. HTTP path
retries with backoff (10s timeout); a
ws(s)://URL upgrades to a bidirectional WebSocket (subprotocolaudio.drachtio.org) that auto-reconnects. - Status callbacks:
call_status_hook_urlreceives POSTed call-status updates.
This is fully implemented — point an Application at your service to drive calls programmatically.