Errors and safe retries

Use HTTP status, stable code, request ID, and your original idempotency evidence together. Public errors intentionally avoid revealing internal tenant or provider detail.

Error envelope

{
  "code": "invalid_request",
  "message": "The request could not be completed.",
  "requestId": "req_...",
  "retryable": false,
  "fieldErrors": []
}

Retain the response X-Request-Id and JSON requestId. Do not expose authorization headers or message bodies in application logs.

Status and action

StatusTypical codeCaller action
400invalid_requestCorrect method, path, query, identifier, channel, recipient, template, variables, or key format. Do not retry unchanged.
401unauthorizedVerify the credential is present, active, unexpired, correctly stored, and in the right environment.
403forbiddenCheck actions, channels, Server App status, tenant hierarchy state, and exact Project/App match.
404not_foundCheck the caller-scoped identifier or currency. Cross-tenant records are not enumerable.
409idempotency_conflictStop. The key was used with different material; reconcile caller state before choosing a new operation.
402insufficient_fundsResolve account funding or billing readiness; do not loop retries.
403budget_blocked or entitlement_blockedReview the authoritative account policy and do not bypass it by changing identifiers.
503provider_unavailableNo message is accepted when a required price or route is unavailable. Retry later with bounded backoff and the same operation key.
500internal_errorTreat the result as ambiguous, retry the exact request with the same idempotency key, and escalate with the request ID if persistent.

Retry policy

  • Retry only transient network failures, selected 5xx responses, or documented availability responses.
  • Use exponential backoff with jitter and a maximum attempt or time budget.
  • Reuse the same message body and idempotency key after an ambiguous POST.
  • Do not retry authentication, authorization, validation, policy, funding, or conflict failures unchanged.
  • Use circuit breaking when persistent failures could amplify load.

Support evidence

Provide the safe MessageHop request ID, message ID, project ID, app ID, approximate UTC time, endpoint, HTTP status, stable error code, and whether the operation was retried. Never provide the raw credential, OTP, recipient list, or full message body.