request_id — quote it when you contact support. For the full error envelope and code list, see Errors.
Quick lookup
401 INVALID_API_KEY — authentication failures
401 INVALID_API_KEY — authentication failures
Cause: The key is wrong, revoked, or — most commonly — a key from one environment sent to the other’s base URL. Sandbox keys (
sk_test_) only work against https://api-sandbox.sohopay.xyz/v1; mainnet keys (sk_live_) only against https://api.sohopay.xyz/v1.Recovery:- Check the key prefix against the base URL you are calling. This mismatch causes the large majority of 401s.
- Confirm the header is exactly
Authorization: Bearer sk_test_...— no quotes, no missingBearer. - Check the dashboard under Settings → API Keys that the key still exists and was not rotated or revoked.
- If it was rotated, update your secrets manager and redeploy. See Authentication & Security.
402 INSUFFICIENT_CREDIT — credit and vault issues
402 INSUFFICIENT_CREDIT — credit and vault issues
Cause: The payment amount exceeds the agent’s
available_credit. Credit is backed by vault collateral, and is consumed by outstanding (not-yet-repaid) spend and capped by the agent’s daily_limit.Recovery:- Read the agent (
GET /agents/{id}) and compareavailable_creditto the order amount. Also check whether today’s spend has hitdaily_limit. - Check the operator’s vault balance in the Wallet Usage dashboard — borrowing capacity equals vault collateral.
- Unwind outstanding credit (repay), deposit more collateral via
vault.deposit, or raise the agent’scredit_limit/daily_limitwithagents.updateif collateral allows. See Vault Funding.
403 AGENT_NOT_ALLOWLISTED — allowlist issues
403 AGENT_NOT_ALLOWLISTED — allowlist issues
Cause: The merchant enforces an on-chain allowlist and this agent’s wallet is not on it. The Policy Service fails closed, so the payment is refused before signing.Recovery:
- The merchant adds the agent via
merchants.allowlist.add(or the dashboard). - Allowlist changes are on-chain — allow roughly one block (~2s on Base) before retrying. A retry immediately after the add can still 403.
- Verify with
merchants.allowlist.list, then resubmit the payment.
AGENT_REVOKED instead, the agent was revoked by its operator and cannot be re-enabled — create a new agent.429 RATE_LIMITED — rate limiting
429 RATE_LIMITED — rate limiting
Cause: You exceeded per-key or per-agent rate limits. The response carries Retries are safe because every POST carries an
Retry-After (seconds) plus X-RateLimit-Limit and X-RateLimit-Remaining.Recovery: Honor Retry-After, then back off exponentially. The official SDKs do this automatically; if you call the API directly:Idempotency-Key. If you hit limits under normal load, request a per-agent limit increase via support.402 AML_DECLINED — AML declines
402 AML_DECLINED — AML declines
Cause: Didit wallet screening flagged the agent or counterparty wallet. The Policy Service fails closed, so no settlement occurs. You also receive an
agent.aml_declined webhook.Recovery:- Check the agent’s status and screening detail in the dashboard.
- If you believe it is a false positive, appeal via support with the
agent_id,request_id, and any documentation of the wallet’s provenance. Appeals resolve in 24–48 hours. - If the decline stands, create a new agent with a clean wallet — SohoPay provisions the wallet inside MPC, so a fresh agent gets a fresh address. See AML Screening.
AML_DECLINED is only triggered deliberately via the designated test wallets — see Testing.400 ORDER_EXPIRED — expired orders
400 ORDER_EXPIRED — expired orders
Cause: Orders live 10 minutes. A payment submitted after the TTL is rejected — the EIP-712 authorization it would sign is time-bound, so expired orders can never be revived.Recovery:
- Recreate the order with
orders.create(same parameters are fine) and submit the payment against the neworder_id. - If this recurs, move order creation closer to payment time — create the order when the agent decides to pay, not when it starts browsing.
Settlement delayed — payment stuck in pending
Settlement delayed — payment stuck in pending
Cause: Normal finality on Base is ~1 second; sandbox usually settles under 2 seconds. Longer delays mean Base network congestion or a Policy Service disruption — SohoPay is fail-closed, so a Policy Service outage pauses settlements rather than skipping checks.Recovery:
- Check the Observatory for current settlement latency and any active incident.
- Check the platform status endpoint (
GET /status) for degraded components. - Do not resubmit — the payment is queued and settles automatically on recovery; idempotency prevents double-settlement anyway.
- If a payment is pending beyond a few minutes with no incident posted, contact support with the
payment_idand, if present, thesettlement_txhash. SLA terms are in SLA.
Webhook not received — events never arrive
Webhook not received — events never arrive
Cause: Your endpoint is unreachable, too slow, returning non-2xx, or rejecting deliveries during signature verification. SohoPay counts anything other than a fast 2xx as a failure and retries at 5s, 30s, 2m, 10m, 1h, then hourly up to 24h.Recovery:
- Confirm the endpoint returns 2xx quickly (under a few seconds). Acknowledge first, process asynchronously.
- Check your signature verification: it must use the raw request body (not re-serialized JSON) with the
Sohopay-SignatureandSohopay-Timestampheaders. See Webhooks. - Fire a test delivery and watch your logs:
- Still nothing? Point the webhook at webhook.site temporarily — if deliveries appear there, the problem is on your endpoint, not SohoPay’s sender.
- Remember deliveries can arrive out of order and more than once — dedupe by
event_id.
Next steps
Error Reference
Every error code, envelope shape, and HTTP status.
Error Handling Guide
Retry, backoff, and recovery patterns in depth.
Best Practices
Prevent these issues before they happen.

