Errors and Rate Limits

What each status code means, why a 403 is usually the domain check, and how fast you may call.

Status codes

StatusMeaningWhat to do
200Accepted. For /v1/domains/{domain_id}/calls this means the origination was accepted, not that the call connected.
400The request was malformed, or a field failed validation.Fix the request. Retrying unchanged will not help.
403Not permitted — see below.Re-authenticate once; if it persists, check the domain.
429You exceeded the rate limit.Back off and retry.
502The telephony platform refused the origination.Safe to retry after a short delay.
500Something failed on our side.Retry with backoff. Report it if it persists.

Validation errors name the offending field:

{
  "errors": [
    { "from_extension": ["Parameter must be a numeric extension."] }
  ]
}

Other errors carry a message:

{ "message": "Forbidden" }

Why a request is refused

Two independent checks run on every request, and a failure of either is a 403:

1. Permission — what your service user may do. Your credentials are granted a fixed set of permissions. Today the partner surface is user:read (list a domain's users) and call:originate (place a call).

2. Active integration — which domains you may touch. Separately, and on every request, we check that you hold an enabled integration on the domain your path names. Holding call:originate does not let you place a call on an arbitrary domain; it lets you place calls on domains you integrate with.

That second check is where most unexpected 403s come from. It also means access can change without anything changing on your side: a customer disabling your integration revokes your access to their domain immediately, with no change to your credentials and no notice through this API. If a domain that worked yesterday returns 403 today and a fresh token does not fix it, that is the first thing to check.

The response will not tell you which check failed

Every one of these returns the same 403 with the same body:

  • an expired or revoked token
  • a valid token whose service user lacks the permission
  • a valid, permitted token whose path names a domain you do not integrate with
  • a domain_id that does not exist at all
  • a malformed path, where the domain_id segment is missing entirely

This is intentional. Distinguishing them would let an unauthenticated caller enumerate which domains exist and which integrations are live. Diagnose in this order:

  1. Re-authenticate. If a brand-new token succeeds, the old one had simply expired.
  2. Check the domain_id in your path — is it the customer's domain (yourcustomer.kricktalk), not the domain from the token response, which is your own? That mix-up is the single most common cause. Confirm the segment is populated at all: a URL that collapses to /v1/domains//calls matches no route and returns the gateway's own 403.
  3. Confirm with the customer that your integration on that domain is still enabled.
  4. If all three hold, contact KrickTalk.

Rate limits

Each endpoint is limited to 5 requests per second, with a short burst allowance of 10.

Exceeding it returns 429. Retry with exponential backoff and jitter; do not retry in a tight loop.

These limits are per endpoint and generous for interactive use — a person clicking a call button comes nowhere near them. If you are approaching the limit you are probably polling or backfilling, which this API is not designed for. Talk to us about your use case rather than engineering around the limit.

Retrying safely

  • 400 — never retry unchanged.
  • 403 — retry once after re-authenticating; then stop and diagnose. Retrying a permissions
    failure in a loop will not fix it.
  • 429, 500, 502 — retry with exponential backoff.
❗️

Retrying a call can ring a phone twice

Placing a call is not idempotent, and there is no request-deduplication key. If POST /v1/domains/{domain_id}/calls times out you cannot know whether the origination was accepted, and retrying may ring the user a second time.

For a user-initiated action, prefer surfacing the failure and letting them click again over retrying automatically. If you must retry, wait several seconds — a call_id in a 502 body confirms we reached the platform and it declined, which is the one case that is safe to retry promptly.

Getting help

Include the call_id (for call failures), the domain_id, and the approximate timestamp of the request. Those three let us find the request in our logs. Never send credentials or access tokens.


Did this page help you?