Errors

Errors

Every non-2xx response uses the same envelope. Branch on error.code — it is stable. The message is for humans and may change.

Error envelope
HTTP/1.1 403 Forbidden

{
  "error": {
    "code": "consent_required",
    "message": "The user has not opted in to messages from this app.",
    "type": "permission_error",
    "requestId": "req_...",
    "docUrl": "https://www.quic.chat/developers/errors#consent_required"
  }
}

Quote requestId when you contact support; it is also in the QuiC-Request-Id header and in your console's request log.

Types#

invalid_request_error
Fix the request (400, 413, 415, 422).
authentication_error
Check the API key (401).
permission_error
Allowed by nobody right now: consent, access level, scope or app status (403).
not_found_error
404.
conflict_error
The resource is in the wrong state (409).
idempotency_error
Idempotency-Key problems.
rate_limit_error
Slow down (429).
api_error
Our fault (5xx). Safe to retry.

Codes#

Error codes
codeHTTPMeaning
invalid_request400The request failed validation. error.details lists the fields.
invalid_json400The body is not valid JSON.
idempotency_key_required400POST /messages needs an Idempotency-Key header.
invalid_api_key401Missing, unknown, revoked or expired API key.
insufficient_scope403The key lacks the scope this endpoint needs.
app_suspended403The app is suspended or rejected and cannot use the API.
key_environment_mismatch403A live key was used before the app was approved. Use a sandbox key.
recipient_not_tester403Sandbox: the user is not an accepted tester of this app.
recipient_outside_org403Internal live: the user is not in your organization.
recipient_org_blocks_businesses403The user's organization does not allow outside businesses.
recipient_unavailable403The user's account is not active.
email_addressing_not_allowed403Addressing by email needs an internal live app and a live key.
not_found404The resource does not exist for this app.
recipient_not_found404No such appUserId (or email) for this app.
route_not_found404No such endpoint. Check the method and path.
media_not_uploaded409Upload the bytes to the upload URL before sending.
idempotency_in_progress409A request with this Idempotency-Key is still running. Retry shortly.
subscription_limit_reached409An app can have at most 5 webhook endpoints.
subscription_not_verified409Verify the webhook endpoint before sending test events.
delivery_in_progress409Only delivered or failed deliveries can be replayed.
payload_expired409The delivery payload passed its 7-day retention and cannot be replayed.
payload_too_large413The request body is too large.
media_too_large413The file is larger than its type allows.
unsupported_media_type415MIME type not allowed, or the body is not application/json.
idempotency_key_reused422The Idempotency-Key was used with a different body.
media_invalid422The uploaded file doesn't match what was declared.
verify_token_mismatch422The verify token doesn't match the endpoint's.
webhook_url_https_required422Webhook URLs must use https.
webhook_url_port_not_allowed422Webhook URLs must use port 443.
webhook_url_blocked_address422The URL resolves to a private or reserved address.
webhook_url_blocked_host422The host is internal or not a fully-qualified domain name.
webhook_url_dns_failed422The webhook host could not be resolved.
webhook_url_invalid_url422Not a valid absolute URL (no credentials or fragments).
rate_limited429Too many requests. Wait Retry-After seconds.
daily_quota_exceeded429The app's daily message quota is used up (resets 00:00 UTC).
business_initiated_cap429More than 3 business-initiated messages to this user in 24 hours.
media_rate_limited429Too many media uploads this hour.
internal_error500Something went wrong on our side. Retry with the same Idempotency-Key.