Skip to main content
When a money movement or verification fails, the resource carries two fields that explain why:
  • failure_reason — a stable, machine-readable code. Branch on this.
  • failure_reason_message — human-readable copy describing the failure. Show this to a user, but do not hardcode or match on it: the wording is English today and may be reworded or localized later.
Both fields appear in REST responses and in the matching webhook event payloads, so you get the same reason whether you poll or receive a push.
Branch on failure_reason, not on failure_reason_message — the code is stable, the message is not. This mirrors how you branch on a top-level error code rather than its message. See Errors.

When the fields are present

failure_reason and failure_reason_message are null (or absent) unless the resource actually failed. They are populated on:
  • Failed money movements — an onramp, offramp, conversion, or transfer that ends in a failed state.
  • Failed verifications — the kyc.rejected webhook event and the verification endpoints.
Some codes are intentionally generic. We expose what is safe and actionable; we do not reveal internal or provider mechanics. Any internal state we do not surface specifically collapses to a generic code — failed for money movements, verification_failed for verifications.

Money movement codes

These apply to a failed onramp, offramp, conversion, or transfer. temporarily_unavailable is the retryable one — retry the request with backoff. failed is deliberately generic: a provider decline, invalid upstream input, a released hold, and anything otherwise unrecognised all collapse to it. funding_failed is reported on an offramp whose funding transfer could not be completed. The offramp fails immediately rather than sitting in processing until its quote expires, and no funds moved — create a new quote and retry.

Verification (KYC) codes

These apply to the kyc.rejected webhook event and the verification endpoints. The first eight are actionable — the applicant can usually fix the problem and resubmit. verification_failed is deliberately generic: any rejection we should not detail collapses to it, and we never reveal the underlying detection.