Skip to content
TriedDocs
Overview

Authentication

Secret API keys, scopes, IP allowlists, per-key rate limits and browser public keys.

Every request to the Tried API carries a key in the Authorization header. Secret API keys are for your servers. Public keys are for browsers that start web calls and chats from your own site.

Secret API keys#

Send the key as a bearer token:

curl https://api.tried.com.au/v2/list-agents \
  -H "Authorization: Bearer key_3f9a0c1d2b4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f506"
  • A key is key_ followed by 48 hex characters.
  • Tried looks keys up by a SHA-256 hash, keeps an encrypted copy (used to sign webhooks), and shows a masked form (the first 8 and last 4 characters) as masked_key. The full key is returned once, in the response to Create API key. Store it then.
  • A key belongs to one workspace. Every request made with it reads and writes that workspace only. IDs from another workspace return 404.
  • A key acts with the admin role, so it can call every route its scopes allow.
  • Each request updates the key's last_used_timestamp, so you can see when an old key is safe to delete during rotation.

Create, edit and delete keys in the dashboard under Settings, API Keys, or with the API keys endpoints. Keys can be managed by workspace admins and developers.

The webhook key#

One key per workspace can be flagged is_webhook_key. Its secret signs the webhooks Tried sends you (the x-tried-signature header, also sent as x-retell-signature). Setting the flag on one key clears it on the others. See Webhooks for how to verify a signature.

Check a key#

Get API key info returns the details of the key that made the request. Use it in a health check to confirm a deployed key is valid.

Scopes#

A key with no scopes has full access. A key with scopes can only call routes that map to one of them. The admin scope grants every route.

Scope Routes it covers
kb Any path containing knowledge-base
numbers Paths containing phone-number, sip-trunk, branded-caller, verified-number, concurrency-settings or phone-number-bindings
calls Create, register, get, list, stop and delete calls, get-call-recording, /v2/calls/... live routes, batch calls, SMS, chats, contacts, backfill-call-analysis and kb-retrievals
analytics Paths starting with /analytics, /qa, /alerts, /alert-events, /get-concurrency and /dashboards
agents Paths containing agent, retell-llm, conversation-flow, voice, test-case, batch-test, test-run, copilot, share-links or workflows
admin Everything else (workspace, members, API keys, billing, exports, assets, integrations, webhook deliveries)

The rules are checked top to bottom and the first match wins. For example, /delete-phone-number/{phone_number} needs numbers, and /list-chat-agents needs calls because it matches chat before agent. Each endpoint page names the scope it needs in its Errors table.

A request outside the key's scopes returns:

{ "status": 403, "message": "This API key lacks the \"numbers\" scope" }

Set scopes with the scopes field on Create API key or Update API key. Allowed values: agents, calls, numbers, kb, analytics, admin.

IP allowlist#

allowed_ips restricts a key to a list of up to 50 IP addresses (IPv4 or IPv6, exact match, no CIDR ranges). An empty list allows any address. A request from any other address returns:

{ "status": 403, "message": "This API key is not allowed from 203.0.113.7" }

The check runs before the per-key rate limit and scopes.

Per-key rate limit#

rate_limit_per_minute (1 to 100000) overrides the default of 600 requests per minute for one key. Set it to null to go back to the default. See Rate limits.

Public keys#

Public keys let a browser start a web call or a chat without exposing a secret key. A public key is public_key_ followed by 32 hex characters, and you send it the same way:

const res = await fetch("https://api.tried.com.au/v3/create-web-call", {
  method: "POST",
  headers: {
    Authorization: "Bearer public_key_9b1c2d3e4f5061728394a5b6c7d8e9f0",
    "Content-Type": "application/json",
    "x-recaptcha-token": token,
  },
  body: JSON.stringify({}),
});

A public key is limited in these ways:

  • Routes. Only POST /v3/create-web-call, POST /create-chat, POST /create-chat-completion and POST /end-chat/{chat_id}. Any other route returns 403 with A public key can only start web calls and chats.
  • Origin. The request's Origin header must match one of the key's allowed_domains. *.example.com matches example.com and its subdomains. An entry with a port matches that host and port only. A missing or unlisted Origin is treated as an invalid key and returns 401.
  • Agent. Web calls always use the key's voice agent. Passing a different agent_id returns 403. Chats use the key's chat agent, or a weighted pick across its chat agents for A/B splits.
  • Chat ownership. create-chat-completion and end-chat only work on chats started with the same key.
  • reCAPTCHA v3. When the key has reCAPTCHA on, send the token in the x-recaptcha-token header or a recaptcha_token body field. A score below the key's threshold returns 403. Needs keys Real scoring needs RECAPTCHA_SECRET. Without it the check runs in mock mode.
  • Countries. Requests from a country on the key's blocked list return 403. The country comes from the cf-ipcountry, x-vercel-ip-country or x-country-code header set by your CDN or load balancer.
  • Rates. 30 requests per minute per IP address per key by default, plus the key's own rate_limit_per_minute when set. Both return 429.

Manage public keys with the public key endpoints or in the dashboard. Requests made with a public key get metadata.public_key_id and metadata.origin added to the call or chat.

Dashboard sessions#

The dashboard calls the same routes with a signed tried_session cookie that lasts 30 days. Sessions carry the user's role (admin, developer or member). The member role is read-only on write routes. Sessions are for the dashboard only. Use an API key from your servers.

Internal routes#

Routes under /internal/ are called by Tried's own agent workers with an x-tried-internal header. They are not part of the customer API, are served on the private network only, and reject API keys. Do not call them.

Errors#

Status Message Cause
401 Missing or invalid API key / session No Authorization header, an unknown or deleted key, or a public key from a disallowed Origin.
403 This API key is not allowed from <ip> The key's IP allowlist.
403 This API key lacks the "<scope>" scope The key's scopes.
403 Requires role: admin (or admin or developer) A dashboard session without the needed role.
429 Rate limit exceeded for this API key: ... See Rate limits.

Retell compatibility#

Retell uses the same Authorization: Bearer <key> header, so the Retell SDKs authenticate against Tried once you change the base URL. See Using the Retell SDKs.