One shape
Every error is JSON with two keys: error, a stable code to branch on, and message, a sentence for people. A few errors add a key, such as retry_after_seconds on 429 rate_limited. Branch on error, never on message: messages can change.
Same Idempotency-Key, different body
The response · 409
HTTP 409
Cache-Control: no-store
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was used with a different request body"
}
What the status tells you
| HTTP | Meaning | Retry? |
|---|---|---|
400 | The request is malformed: a missing or invalid field, header or JSON body. The message names the field. | No. Fix the request. |
401 | No credentials, or they are not valid here (for example a sandbox key on the live API). | No. |
403 | The credentials are valid but this action is not allowed, for example while a merchant account is not active. | No. |
404 | The object does not exist, or it is not yours. The two are not told apart. | No. |
409 | The request conflicts with the object's current state, or reuses an idempotency key with a different body. | Not as is. |
422 | Well formed, but a rule refuses it: a refund larger than what remains, a payout with nothing to pay, a payout hold. | Only after the condition changes. |
429 | Too many requests, or too many failed sign-ins. | Yes, after Retry-After seconds. |
500 | Our fault. | Yes, with the same idempotency key. |
502 | The bank did not confirm the request. | Yes, with the same idempotency key: it never moves money twice. |
503 | A service this call needs is not configured on this deployment. | Later. |
Every code
176 codes, generated by scanning every Worker's source for the codes it answers with, under the lowest HTTP status each one uses.
HTTP 400 · 20 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
account_not_found | 400 | onboard | That account isn’t in the bank connection. Choose it again. |
account_type | 400 | onboard | Choose a checking or savings account. |
below_floor | 400 | onboard, partners | The proposed … … below SMP’s floor of …. |
business_first | 400 | onboard | Add your business’s legal name before connecting its bank account. |
consent_needed | 400, 409 | onboard | Agree to the face match, or decline it, first. |
customer_data_refused | 400 | gateway | Only email and name are accepted for each customer; refused: …. Never upload customer or account IDs, bank details or tokens from another provider. |
ignored | 400 | onboard | Not an Identity Verification webhook |
invalid_json | 400 | onboard, partners, admin | Request body must be a JSON object |
invalid_link | 400 | onboard | That link isn’t valid. |
no_hit | 400 | admin | That screening is …: there is nothing to decide. |
no_proposal | 400 | admin | There is no partner proposal to accept. |
not_a_merchant_fee | 400 | onboard | … is charged to partners, not merchants |
not_available | 400 | partners, portal | The test bank exists only in the sandbox |
photos_missing | 400 | onboard | Add … first. |
plaid_error | 400, 502 | onboard, partners, portal | Plaid said: … |
reason_required | 400 | admin | This price is below the floor (…) in its …: write why. |
screening_has_no_hit | 400 | onboard | Screening … is … |
validation_error | 400 | gateway, connect, onboard, partners, portal, admin | allowed_origin must be the https origin of your checkout page, e.g. https://shop.example.com |
weak_password | 400 | admin | message set at runtime |
wrong_code | 400 | onboard, admin | That code isn’t right. Check the email and try again. |
HTTP 401 · 8 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
challenge_expired | 401 | partners, portal | That sign-in expired. Enter your email and password again. |
invalid_code | 401, 403 | partners, portal | That code is not right |
invalid_credentials | 401 | partners, portal | Email or password is incorrect |
invalid_signature | 401 | partners | The webhook signature or timestamp did not verify |
signed_out | 401 | admin | Sign in to the CRM. |
unauthorized | 401 | gateway, connect, onboard, partners, portal | Admin token required |
unverified_webhook | 401 | onboard | This webhook’s signature could not be verified. |
wrong_credentials | 401 | admin | That email and password don’t match a CRM login. |
HTTP 403 · 14 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
account_closed | 403 | portal | This account is closed. Its records stay here to read; nothing can be changed. |
account_suspended | 403 | portal | This merchant account is suspended. Contact work@socialmatters.pro. |
agent_inactive | 403 | partners | This agent is not active |
consent_is_personal | 403 | onboard | Only … can agree to or decline …’s face match. Email … their own link, or add their ID photos here and a person at SMP reviews them without a face match. |
csrf | 403 | admin | This page is out of date. Reload it and try again. |
forbidden | 403 | gateway, connect, onboard, partners, portal | This page is not allowed to use this checkout session |
invalid_password | 403 | partners, portal | Password is incorrect |
login_disabled | 403 | partners | This login is disabled |
migration_excluded | 403 | gateway | This account's customers can't be migrated. |
not_allowed | 403 | admin | This login can’t use the CRM. |
owner_session | 403 | onboard | This link is for adding your own ID only. |
partner_inactive | 403 | partners | This partner account is not active |
partner_pending | 403 | partners | message set at runtime |
selfie_is_personal | 403 | onboard | A selfie is taken by the person themself, after they agree to the face match. Email … their own link. |
HTTP 404 · 6 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
invite_not_found | 404 | partners | This invite is invalid or has expired |
no_integration | 404, 409 | onboard, admin | Name your website or app on the first page first. |
not_enabled | 404 | portal | … is not enabled for this account |
not_found | 404 | gateway, connect, onboard, partners, portal, admin | Checkout session not found |
screening_not_found | 404 | onboard | No screening … for this merchant |
unknown_fee_code | 404 | onboard | No fee schedule entry for … |
HTTP 409 · gateway · 21 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
authorization_text_changed | 409 | gateway, partners, portal | The words changed. Read the new ones and sign again. |
bank_not_linked | 409 | gateway | Link a bank account first |
conflict | 409 | gateway, portal | Another change landed at the same instant; send it again |
hold_exists | 409 | gateway, partners | A manual reserve hold is already on |
idempotency_conflict | 409 | gateway | This Idempotency-Key was used with a different request body |
invalid_state | 409, 422 | gateway, connect, onboard, partners, admin | Bank account is …; link it again |
last_merchant_key | 409 | gateway | This is the last working merchant key; create or rotate in a replacement first |
merchant_not_provisioned | 409 | gateway | The merchant has no bank sub-account yet |
no_release_delay | 409 | gateway | This merchant has no release delay to clear |
one_site_per_account | 409 | gateway | An account is for one website or one app. A second one is a new application, and applying is free. |
payment_not_pending | 409 | gateway | The payment is … |
payout_rejected | 409 | gateway | The bank rejected the payout: … |
pricing_not_configured | 409, 503 | gateway, onboard, partners, admin | No active price for …; the payment was not taken |
quote_changed | 409 | gateway, portal | The payable balance (… cents) or its fee changed since it was shown; confirm the new figures |
refund_rejected | 409 | gateway | The bank rejected the refund: … |
reserve_not_available | 409 | gateway | The bank has no reserve account set up yet |
review_decided | 409 | gateway | This review was already … |
session_busy | 409 | gateway | This payment is already being processed. Wait a moment. |
site_change_needs_review | 409 | gateway | Your website or app is the one we reviewed. Ask us to change it and we review the new one. |
too_late_to_void | 409 | gateway | The bank has settled this debit; refund it once it settles |
too_many_keys | 409 | gateway | A merchant holds at most … working keys; revoke one first |
HTTP 409 · connect · 1 code
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
plaid_not_configured | 409, 503 | connect, onboard, partners, portal | Plaid credentials are not configured on this deployment |
HTTP 409 · onboard · 25 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
agreements_changed | 409 | onboard | The documents changed since you opened them. Read them again, then sign. |
agreements_not_final | 409 | onboard | message set at runtime |
already_recorded | 409 | onboard | … is already recorded |
already_signed | 409 | onboard | This signature was already stored. Reload the page. |
already_submitted | 409 | onboard | Your integration is in review. |
applicant_locked | 409 | onboard | You already answered the face match as …, so “This is me” can’t move to someone else. |
application_exists | 409 | onboard | This merchant already has an application in progress. |
bank_first | 409 | onboard | Connect your payout bank account first: the Fee Debit Authorization names it. |
category_not_bank_approved | 409 | onboard | High-risk pricing needs a category a bank approved in writing |
certification_incomplete | 409 | onboard, admin | … certification case… still to pass: …. |
consent_locked | 409 | onboard | The ID check has already run, so the face match answer can’t be changed here. Email work@socialmatters.pro. |
consent_text_changed | 409 | onboard | The notice changed while you were reading it. Read it again and agree. |
duplicate_review_open | 409 | onboard, admin | This application matches an existing merchant; approve it with duplicate_acknowledged: true if it is a separate business |
integration_in_review | 409 | onboard | Your website or app is in review: ask us to change it. |
no_referral_link | 409 | onboard, admin | Your referral link isn’t active, so this merchant can’t be attributed to you. Ask SMP. |
no_sandbox | 409 | onboard | Your sandbox account isn’t ready yet: open the first page again to get it. |
no_webhook | 409 | onboard | Subscribe a webhook endpoint first: the check sends it one event with a wrong signature. |
not_editable | 409 | onboard | message set at runtime |
not_sandbox | 409 | onboard | Sandbox accounts are made in the sandbox. |
sanctions_lists_unavailable | 409 | onboard | Sanctions lists are not loaded; screening could not run |
sanctions_review_open | 409 | onboard | Sanctions hits need a disposition first |
sanctions_true_match | 409 | onboard | A sanctions match was confirmed |
screening_already_decided | 409 | onboard | A disposition already exists for that screening |
tick_not_recorded | 409 | onboard | We haven’t recorded your tick on the … box. Untick it, tick it again, then submit. |
version_exists | 409 | onboard, admin | … already has a version effective … |
HTTP 409 · partners · 8 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
agent_exists | 409 | partners | This partner already has an agent with that email |
already_ending | 409 | partners | This partnership already ends on … |
already_suspended | 409 | partners | This agent is already suspended |
application_fee_unpaid | 409 | partners | This application is reviewed once its application fee is paid |
email_in_use | 409 | partners | An application or login already uses this email |
intent_used | 409 | partners, portal | That bank connection is already confirmed |
not_pending | 409 | partners | Only a pending application can be decided |
partnership_ending | 409 | partners | This partnership has an end date: no new agents or referral links |
HTTP 409 · portal · 2 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
already_active | 409 | portal | This teammate already set a password |
not_enrolled | 409 | portal | Two-step sign-in is not set up |
HTTP 409 · admin · 12 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
already_decided | 409 | admin | That screening already has a decision. |
already_open | 409 | admin | This merchant’s sub-balance is already open. |
decision_in_progress | 409 | admin | Someone else is deciding this application. Reload. |
invalid_transition | 409 | admin | A … merchant can’t be set …. |
no_bank | 409 | admin | There is no payout account to review. |
no_check | 409 | admin | …’s ID hasn’t been checked yet. |
no_enrollment | 409 | admin | Start the setup again. |
no_sub_account | 409 | admin | Open the merchant’s sub-balance at the bank first. |
not_live | 409 | admin | Only an approved integration can be switched off. |
not_submitted | 409 | admin | Only a submitted integration can be approved (this one is …). |
not_switched_off | 409 | admin | Only a switched-off integration can be switched back on. |
reconciliation_hold | 409 | admin | A reconciliation hold lifts when the ledger and the bank agree again. |
HTTP 410 · 5 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
code_expired | 410 | onboard | That code has expired. Ask for a new one. |
intent_expired | 410 | partners, portal | That bank connection expired. Start again. |
link_expired | 410 | onboard, partners, portal | This link has expired. Start again with your email. |
link_used | 410 | onboard | This link was already used. Sign in with your email to continue. |
setup_expired | 410 | admin | This setup link has expired. Ask for a new one from the sign-in page. |
HTTP 413 · 1 code
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
too_large | 413 | onboard | Files can be up to 10 MB. Take the photo again or save the PDF smaller. |
HTTP 415 · 2 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
photo_required | 415 | onboard | Use a photo (JPEG, PNG, WebP or HEIC) taken of the ID itself, not a scan or a PDF. |
unsupported_file | 415 | onboard | Upload a PDF or a photo (JPEG, PNG, WebP or HEIC). |
HTTP 422 · 20 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
agent_deactivated | 422 | partners | A deactivated agent has no cut |
authorization_mismatch | 422 | gateway | The payment details changed. Review them again before you pay; nothing was charged. |
authorization_not_in_force | 422 | gateway | No standing authorization is in force for this account and amount |
authorization_required | 422 | gateway | … schedules need authorization_text_sha256: fetch the words with POST /v1/debit-schedules/authorization-text, show them to the payer before they agree, and send the SHA-256 of exactly what was shown. |
early_payouts_off | 422 | gateway | Pay me now (early payouts) is off for this account; only Social Matter Payments turns it on |
ends_on_in_past | 422 | partners | An end date cannot be before today (UTC) |
incomplete | 422 | onboard | message set at runtime |
landing_url_not_yours | 422 | gateway | landing_url must be on your own site (…) |
no_ach_numbers | 422 | connect | The bank didn't give an account and routing number for this account, so it can't be debited. Choose a checking or savings account, or pay with routing and account number. |
no_payout_account | 422 | gateway, portal | The merchant has no payout bank account on file |
not_on_hold_schedule | 422 | gateway | Payout requests are for merchants on the Hold schedule |
nothing_to_pay | 422 | gateway | Payable balance is … cents |
over_limit | 422 | gateway | Each debit would be over this account's per-payment limit of $… |
payday_aware_off | 422 | gateway | Payday-aware debits are off for this account: turn them on (PUT /v1/account/payday-aware-debits) or send payday_window_days 0 |
payment_not_confirmed | 422 | partners | The provider's record does not confirm this payment: … |
payout_below_fee | 422 | gateway | The early payout fee (… cents) is not less than the payable balance (… cents) |
payout_held | 422 | gateway | Payouts are on hold (…): … |
refund_exceeds_payment | 422 | gateway | The refund is more than what remains refundable on this payment |
signature | 422 | onboard | message set at runtime |
unsupported_account | 422 | partners, portal | message set at runtime |
HTTP 423 · 1 code
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
locked | 423, 429 | partners, portal, admin | Too many failed attempts; try again later |
HTTP 429 · 5 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
rate_limited | 429 | gateway | Rate limit exceeded. Maximum … requests per minute. |
too_many_attempts | 429 | onboard | Too many tries. Ask for a new code. |
too_many_events | 429 | onboard | Too many ticks have been recorded for this application. Reload the page and sign. |
too_many_invites | 429 | portal | This account has sent … team invitations in the last 24 hours, the most it can. Try again after … UTC. |
too_soon | 429 | onboard | We just sent a code. Wait 30 seconds before asking for another. |
HTTP 500 · 2 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
code_generation_failed | 500 | partners | Could not generate a unique referral code |
internal_error | 500 | gateway, connect, onboard, partners, portal, admin | An internal error occurred |
HTTP 502 · 5 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
bank_link_failed | 502 | gateway | We couldn't confirm that bank account, and nothing was charged. Try again. |
bank_link_unavailable | 502 | gateway | Your bank's sign-in couldn't start. Try again. |
bank_unavailable | 502 | gateway | The bank did not confirm the debit. Retry with the same Idempotency-Key. |
micro_deposits_failed | 502 | connect | The bank did not accept the micro-deposits: … |
unavailable | 502, 503 | portal | Webhook delivery is not configured here |
HTTP 503 · 11 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
admin_unavailable | 503 | partners | ADMIN_API_TOKEN is not configured |
application_fee_unavailable | 503 | partners | Partner applications are closed until the application fee checkout is configured |
engine_pending | 503 | admin | Bounce Protection isn’t in the engine yet (…). Nothing was changed. |
not_configured | 503 | gateway, onboard | Bank linking is not available here |
not_connected | 503 | partners, admin | Merchant submissions are not connected (ONBOARD service binding). |
plaid_unreachable | 503 | onboard | We couldn’t reach Plaid. Try again, or upload a voided check, a bank letter or a bank document. |
provider_unavailable | 503 | partners | … could not be read; retry |
referral_redirect_unconfigured | 503 | partners | MERCHANT_APPLY_URL is not set |
sandbox_unavailable | 503 | onboard | Sandbox accounts are not connected yet. Your application is saved; try again shortly. |
vault_unavailable | 503 | partners, portal | Vault public key is not configured |
webhook_not_configured | 503 | partners | Whop is not configured on this deployment |
Status set at runtime · 7 codes
| Code | HTTP | Returned by | Example message |
|---|---|---|---|
ach_company_config_invalid | — | gateway | message set at runtime |
bad_response | — | gateway | message set at runtime |
funding_refused | — | gateway | The bank refused the transfer: … |
onboard_unavailable | — | partners | The application service did not answer. |
payments_paused | — | gateway | New payments are paused: … returns in the last … days. They resume on their own |
relink_required | — | gateway | message set at runtime |
reserve_released | — | gateway | This reserve was already released by … on … |
