DocsDeveloper HubAPI Keys & Authentication
Generate secret workspace API keys and authenticate programmatic requests

API keys and authentication

Use a server-side API key to access the public API reference. Dashboard routes use a separate login token.

Base URL

The production Voice AI API base URL is:

Plain text
https://api.tunk.ai/agent/v1

Append the endpoint path once: /agents becomes https://api.tunk.ai/agent/v1/agents. For local development, use your backend port, for example http://localhost:3001/v1.

Speech-to-Text uses the separate base URL https://api.tunk.ai/v1. The /agent/v1 prefix applies to all Voice AI endpoints, including webhooks, agents, calls, batches, phone numbers, knowledge base and usage.

Create a key

Open Developer Hub → API Keys, generate a key, and store it in your server's environment. Select the workspace whose resources you want to access and copy its workspace UUID.

Required headers

HeaderWhen to include itValue
X-Api-KeyEvery public API requestYour API key
X-Workspace-IdWorkspace-scoped requestsThe workspace UUID; include it in all examples
Idempotency-KeyEvery public API POSTA unique value for each logical operation
Content-TypeJSON request bodiesapplication/json

Keys bound to a workspace can supply that scope automatically. A conflicting workspace header is rejected. For keys without a workspace binding, provide X-Workspace-Id.

The backend also accepts tunk-api-key, x-tunk-api-key, or raw Authorization: tunk-.... Authorization: Bearer <API_KEY> is not accepted by this public API. Use X-Api-Key to avoid confusion with dashboard JWT authentication.

Verify access

Shell
export TUNK_BASE_URL='https://api.tunk.ai/agent/v1'
export TUNK_API_KEY='<your-api-key>'
export TUNK_WORKSPACE_ID='<workspace-uuid>'

curl --fail-with-body "$TUNK_BASE_URL/agents?page=1&limit=20" \
  -H "X-Api-Key: $TUNK_API_KEY" \
  -H "X-Workspace-Id: $TUNK_WORKSPACE_ID"

Idempotency

Send a fresh Idempotency-Key for each new POST, including webhook creation, test delivery and secret rotation. Reuse that value when retrying the same request. A fresh test event needs a fresh key.

Completed responses with status below 500 are cached for 24 hours by API key, request path, and idempotency key. Reuse the same body when retrying; the middleware does not compare bodies. This is response replay, not a guarantee of exactly-once execution: simultaneous requests or Redis failures can still repeat work. Do not send concurrent duplicate mutations.

Troubleshooting

ResponseCheck
401Missing, invalid or inactive API key; a Bearer API key was used
403Workspace access or a workspace-bound key/header mismatch
411Missing workspace scope
400 with IDEMPOTENCY_KEY_REQUIREDMissing Idempotency-Key on a public POST
400 with VALIDATION_ERRORRequest fields do not match the reference
429Rate limits; slow down and retry with backoff

Keep keys private

Store keys in a secret manager or ignored .env file. Never include real keys in browser code, public examples, screenshots, or committed Postman collections. Revoke compromised keys in the API Keys manager.

Continue with the API quickstart or webhook guide.

Need help? Reach out on our support portal.