Authentication: API keys, JWT, and OAuth flows
How to authenticate with Call2Me — Bearer API keys for server-to-server, JWT for dashboard sessions, and rotation patterns that don't break production.
Updated May 6, 2026
Call2Me supports two authentication mechanisms — pick the right one for the client.
API keys (server-to-server)
For backends, scripts, agent platforms (Composio, Pipedream, Zapier), and any integration that lives outside the browser, use an API key.
curl -H "Authorization: Bearer sk_call2me_live_..." \
https://api.call2me.app/v1/agents
API keys are minted at
dash.call2me.app/api-keys and
are workspace-scoped — a key issued from workspace acme can never act on
workspace widgets-inc.
Scopes
A key is either full access (default) or read-only:
curl -X POST https://api.call2me.app/v1/api-keys \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "analytics", "read_only": true}'
- Read-only —
GET/HEAD/OPTIONSonly; every write returns403. Safe for analytics dashboards and reporting jobs. - Full access — create, update and delete everything the account can.
There are no separate write/admin tiers. An earlier version of this page
described three; only the single read_only flag exists (corrected
6 October 2026).
Rotation
Keys are long-lived but rotatable. Recommended pattern:
- Mint the new key, give it a name like
prod-2026-q2. - Deploy it to your infrastructure.
- Confirm the new key is in use (calls and requests succeed) — once you see traffic, you know deployment took.
- Revoke the old key.
The platform never auto-expires keys. Active keys stay active until you revoke them.
JWT (dashboard sessions)
When users log in to the dashboard, the platform issues a short-lived JWT plus a refresh token. The dashboard handles this transparently — you only encounter JWTs if you're embedding Call2Me's dashboard or building a white-label SDK.
The flow:
POST /v1/auth/login
{ "email": "...", "password": "..." }
→ { "access_token": "eyJ...", "refresh_token": "...", "expires_in": 3600 }
When the access token expires, exchange the refresh token:
POST /v1/auth/refresh
{ "refresh_token": "..." }
You almost never need this for normal API integration — pick API keys unless you're explicitly building a multi-user web client.
What happens when auth fails
| Status | Cause | Fix |
|---|---|---|
401 Unauthorized | Missing or invalid Bearer header | Check the Authorization header is set |
401 token_expired | JWT past its exp | Use the refresh token to mint a new one |
403 Forbidden | Key doesn't have the required scope | Mint a key with the right scope |
429 Too Many Requests | Rate limit hit | Back off; see Errors & rate limits |
What's next
- API Reference — every endpoint, request/response shape
- Webhooks — receive events when calls happen
- Errors & rate limits — what to retry, what to surface
Frequently asked
Q.What's the difference between an API key and a JWT?
API keys are long-lived secrets you mint in the dashboard, used for server-to-server calls. JWTs are short-lived tokens issued during a dashboard login and rotated automatically — you don't usually handle them directly.
Q.Where do I create an API key?
dash.call2me.app/api-keys. Each key is workspace-scoped, rotatable, and revocable. Names help you tell them apart in audit logs.
Q.Can I scope an API key to read-only?
Yes. Create the key with read_only: true and it can only make GET/HEAD/OPTIONS requests; any write returns 403. There is no finer-grained scope: a key is either read-only or full access.
Q.How do I rotate a key without downtime?
Issue the new key first, deploy it everywhere it's needed, verify traffic is flowing with the new key, then revoke the old one. The platform never invalidates a key until you explicitly revoke it.