Exchange your API key for a 15-minute voice token pinned to one line. Call this from your server whenever the SDK's tokenProvider asks, and return the body to the browser as-is.
The request carries your workspace API key, so it must never be made from a browser or a mobile app. Put an authenticated route in front of it on your own backend — the snippets in the rail are complete examples — and have that route decide which lineId the signed-in user may call from.
Headers
Authorization: Bearer YOUR_API_KEY and Content-Type: application/json. The same key you use against api.tryprojectblue.com.
Request body
lineIdstringRequired
The line to call from, exactly as returned by GET https://api.tryprojectblue.com/get-lines with the same API key. Calls are placed from that line's number and count toward its dialer plan. Shared and trial lines are refused.
Response
tokenstringRequired
Opaque, short-lived voice token scoped to one line. Hand the whole response body to the SDK's tokenProvider; never store the token or build on its contents.
expiresAtstring (ISO 8601)Required
When the token stops working. Always 15 minutes from mint.
ttlSecondsnumberRequired
Token lifetime in seconds. Currently 900.
lineIdstringRequired
The line this token is pinned to, echoed back.
inboundEnabledbooleanRequired
Whether this token can also receive calls. True only when the line has an inbound number and someone in your workspace is in its ring set. Can differ from one mint to the next.
maxCallsPerTokennumberRequired
Outbound calls one token may place before it must be refreshed. Currently 10. The SDK refreshes ahead of this limit, so you never hit it in normal use.
allowanceobject | nullRequired
Today's minute allowance for the workspace and for this line. Null only when the plan could not be read at mint time; the token is still valid.
state"ok" | "soft" | "hard"Required
ok: within plan. soft: near the included minutes — warn your users. hard is never returned on a 200; a hard stop is a 402 dialer_cap_reached refusal instead.
usednumberRequired
Whole minutes used today across the workspace.
includednumberRequired
Minutes included in today's plan across the workspace.
capnumber | nullRequired
Workspace ceiling in minutes for today. Null when the account has no cap.
pctnumberRequired
used ÷ included, as a whole percent.
periodEndstring (ISO 8601)Required
When today's allowance resets — midnight UTC. A capped line resumes calling at this time.
lineobject | nullRequired
This line's own standing against its daily cap.
usednumberRequired
Minutes this line has used today.
capnumber | nullRequired
This line's daily cap in minutes, or null for none.
cappedbooleanRequired
True when this line has hit its cap. The next mint for it returns 402 even if the workspace still has minutes.
Forward it unchanged
Return the upstream status, body, and Retry-After header to the browser exactly as received. The SDK reads expiresAt, maxCallsPerToken, inboundEnabled, and allowance to schedule its own refreshes and to raise typed errors. If you reshape the body, refresh timing and error handling degrade to defaults.
Guard the .json() call. A proxy in front of the app can return a non-JSON 502 or 503, and an unhandled throw in your route becomes a generic 500 in the browser instead of a retryable token_unavailable.
Refusals
Every non-2xx body is { error, code }, plus extra fields on the cap and rate-limit cases. Unlike the messaging API, code is always present here, and the SDK maps it to a DialerError code for you.
Status
code
SDK code
Meaning
401
invalid_api_key
token_unavailable
Missing, revoked, or wrong API key.
400
invalid_line_id
line_unavailable
lineId missing or not a value from /get-lines. Refused before the rate-limit slot is spent.
404
line_not_found
line_unavailable
Not one of this workspace's lines. Returned for other workspaces' lines too — existence is never confirmed.
403
line_inbound_only
line_unavailable
The line receives calls but cannot place them.
403
line_not_eligible
line_unavailable
Shared and trial lines are not an SDK surface.
403
dialer_subscription_required
subscription_required
No Dialer add-on on the workspace.
402
account_paywalled
account_paywalled
The account is past due.
402
dialer_cap_reached
cap_reached
The workspace or this line has used today's minutes. Body carries used, included, cap, periodEnd.
404
dialer_not_provisioned
not_provisioned
Business registration (Phone Compliance) not yet approved, so calling is not provisioned.
403
api_key_unsupported
token_unavailable
A legacy key that cannot mint. Create a new key in Settings → API Keys.
429
rate_limited
rate_limited
Too many mints for this key. Body carries retryAfterSeconds; a Retry-After header is set.
500
dialer_misconfigured
token_unavailable
Calling is not fully configured for this account. Contact support.
503
dialer_unavailable
token_unavailable
Token service temporarily unavailable. Retry with backoff.
The mint has its own rate limit
This endpoint allows 30 mints per minute per API key, separate from the 60 requests per minute on the messaging API. A well-behaved SDK session mints once at start, then roughly once every 14 minutes and once per 10 calls, so the limit only matters if your server mints on every page load. Malformed requests are refused before they consume a slot.