API Authentication & API Keys¶
How to authenticate against the AstraPBX API (https://devpbx.astradial.com/api/v1). There are three credential types for normal org access plus a separate admin path. Picking the wrong one is the most common source of Invalid credentials / Authentication failed errors — this page maps each to its exact use.
TL;DR — for an integration/partner, use an ak_ API key
Create an ak_… API key in the dashboard (API & Webhooks → API Keys → + Create API Key) and send it as X-API-Key: ak_…. It doesn't expire, has granular permissions, and needs no login step. Don't use the JWT /auth/login flow for ak_ keys — they are a different system.
The three credential types¶
| Method | Credential | Sent as | Expires? | Best for |
|---|---|---|---|---|
1. API key (ak_) | ak_… key (from UI) | X-API-Key: ak_… | No (until revoked) | Integrations, CRM, partners (recommended) |
2. Org key (org_) | org_… key | X-API-Key: org_… | No | Org-level programmatic access |
| 3. JWT (Bearer) | org_… key + api_secret → token | Authorization: Bearer <jwt> | Yes — 24h | Short-lived org-scoped sessions |
All three resolve to the same org scope. The middleware (authenticateOrg) checks them in order: X-API-Key starting ak_ → org API key; else X-API-Key → org key; else Authorization: Bearer → JWT.
Method 1 — ak_ API key (recommended)¶
A per-org key with granular permissions, created and managed in the dashboard.
Create it (UI): dashboard → API & Webhooks → API Keys → + Create API Key → name it, pick permissions, Create Key.
- You get
api_key(ak_…) andapi_secret(as_…) shown once — save them. (See the note on the secret below.) - Permissions are granular:
calls.read/write/click_to_call/originate_ai/recording/live/transfer/hangup/holdandcrm.read/write/delete/assign/customize. - Manage/revoke from the same page. Revoked keys stop working immediately.
Use it:
curl https://devpbx.astradial.com/api/v1/calls/count \
-H "X-API-Key: ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# -> 200 {"total":23,"active":0,...}
No login, no JWT. The key alone authenticates and the call is scoped to that key's permissions.
The as_ secret is not checked
The API only validates the ak_ key — the as_ secret is stored (hashed) but not currently verified on requests. So the ak_ key alone is the full credential: if it leaks, revoke it immediately and issue a new one. Never paste a live key into chat, tickets, or screenshots.
Method 2 — Org key (org_) directly¶
Every org has a master org_… key. It can be sent directly as X-API-Key (no JWT step) for full org access:
curl https://devpbx.astradial.com/api/v1/calls/count \
-H "X-API-Key: org_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
This is full-org scope (no granular permissions), so prefer a scoped ak_ key for integrations. The org must be active — an inactive/suspended org returns 401 "Invalid authentication or organization not active".
Method 3 — JWT Bearer token¶
For short-lived org-scoped tokens, exchange the org_ key + plaintext api_secret for a JWT:
curl -X POST https://devpbx.astradial.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"api_key":"org_xxxx","api_secret":"<org api secret>"}'
# -> { "token": "eyJhbGci..." }
Then:
- The token expires after 24 hours — re-call
/auth/loginto refresh. Reusing an old token returns401 "Authentication failed". - The
api_secrethere is the org secret (returned once when the org was created viaPOST /api/v1/organizations; unrecoverable afterward, no rotate endpoint). It is not anak_/as_key.
Admin authentication (platform management)¶
Endpoints under /api/v1/admin/* (create/suspend orgs, etc.) require admin auth, not org auth:
POST /api/v1/admin/authwith the server's admin username/password → admin JWT (24h), used only for/admin/*.- Server-to-server callers may use the
X-Internal-Keyheader (INTERNAL_API_KEY). With it,POST /api/v1/auth/admin-token({org_id}) orPOST /api/v1/admin/impersonate/:orgIdmints an org token without that org's secret.
Don't use admin tokens for regular API operations.
Common errors → cause¶
| Response | Cause | Fix |
|---|---|---|
400 "API key and secret are required" | Called /auth/login without both fields | Send api_key + api_secret |
401 "Invalid credentials" (on /auth/login) | Put an ak_ key into /auth/login — wrong system, or wrong org secret | Use the ak_ key via X-API-Key instead; or use the correct org_ key + org api_secret |
401 "Authentication failed" | Expired or malformed JWT | Re-login for a fresh token (JWTs last 24h) |
401 "Invalid authentication or organization not active" | Unknown key, or the org is not active | Use a valid key for an active org |
401 "Authentication required" | No X-API-Key and no Authorization header | Add one of them |
403 (permission) | ak_ key lacks the required permission | Re-issue the key with the needed calls.*/crm.* permission |
Recommended flow for a new integration¶
- In the org's dashboard, create an
ak_API key with only the permissions the integration needs. - Store the
ak_key in the integration's secret store. - Call endpoints with
X-API-Key: ak_…— no login, no token refresh. - Rotate by creating a new key and revoking the old one (keys don't expire on their own).
- Reserve the
org_+JWT flow for cases that specifically need a short-lived bearer token; reserve/admin/*for org provisioning only.
Related¶
- API Reference
- Live Swagger:
https://devpbx.astradial.com/api-docs