Authentication
DIDHub APIs use two authentication mechanisms depending on how you're calling.
| Mechanism | Use it for | Where it goes |
|---|---|---|
| API key (Bearer token) | Server-to-server calls (your backend → DIDHub API) | Authorization: Bearer $KEY header |
| OAuth 2.0 | Per-user calls (your app acting on behalf of a DIDHub user) | Standard OAuth Authorization Code flow against auth.contaqt.com |
API keys
Dashboard → Settings → API & Webhooks → API keys → Create key.
Each key has:
- Scopes — restrict what the key can do (
numbers:read,numbers:write,trunks:*, etc.) - Environment — production vs sandbox
- Rotation date — DIDHub will email a reminder 14 days before key expiry
Treat API keys as secrets:
WARNING
- ✅ Store in a secrets manager (1Password, Vault, AWS Secrets Manager)
- ✅ Rotate every 90 days
- ❌ Never commit to git
- ❌ Never paste into a public chat
- ❌ Never put in a URL query string (they end up in logs)
OAuth 2.0
If you're building a multi-tenant app where end users authenticate with their own DIDHub account, use OAuth.
DIDHub's OAuth is issued by https://auth.contaqt.com (the shared identity provider for sip.io, pbx.im, and didhub.io). Standard Authorization Code with PKCE flow:
text
GET https://auth.contaqt.com/oauth2/authorize
?client_id=YOUR_CLIENT_ID
&response_type=code
&redirect_uri=https://your-app.com/auth/callback
&scope=numbers:read+numbers:write
&state=RANDOM
&code_challenge=CHALLENGE
&code_challenge_method=S256Full details in the OAuth integration guide (coming soon).
Errors
A missing or invalid token returns 401 Unauthorized:
json
{
"error": "unauthorized",
"message": "Missing or invalid API key",
"request_id": "req_a4f9c2b1"
}A valid token without the required scope returns 403 Forbidden:
json
{
"error": "forbidden",
"message": "API key lacks scope: numbers:write",
"request_id": "req_a4f9c2b1"
}See Errors & rate limits for the full taxonomy.