Skip to content

Authentication

DIDHub APIs use two authentication mechanisms depending on how you're calling.

MechanismUse it forWhere it goes
API key (Bearer token)Server-to-server calls (your backend → DIDHub API)Authorization: Bearer $KEY header
OAuth 2.0Per-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=S256

Full 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.

Built with VitePress · API reference powered by Scalar · didhub.io