This page maps every common failure to its cause and recovery steps. Find your symptom below; every error response includes a request_id — quote it when you contact support. For the full error envelope and code list, see Errors.

Quick lookup

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:
  1. Check the key prefix against the base URL you are calling. This mismatch causes the large majority of 401s.
  2. Confirm the header is exactly Authorization: Bearer sk_test_... — no quotes, no missing Bearer.
  3. Check the dashboard under Settings → API Keys that the key still exists and was not rotated or revoked.
  4. If it was rotated, update your secrets manager and redeploy. See Authentication & Security.
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:
  1. Read the agent (GET /agents/{id}) and compare available_credit to the order amount. Also check whether today’s spend has hit daily_limit.
  2. Check the operator’s vault balance in the Wallet Usage dashboard — borrowing capacity equals vault collateral.
  3. Unwind outstanding credit (repay), deposit more collateral via vault.deposit, or raise the agent’s credit_limit / daily_limit with agents.update if collateral allows. See Vault Funding.
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:
  1. The merchant adds the agent via merchants.allowlist.add (or the dashboard).
  2. Allowlist changes are on-chain — allow roughly one block (~2s on Base) before retrying. A retry immediately after the add can still 403.
  3. Verify with merchants.allowlist.list, then resubmit the payment.
If the code is AGENT_REVOKED instead, the agent was revoked by its operator and cannot be re-enabled — create a new agent.
Cause: You exceeded per-key or per-agent rate limits. The response carries 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:
Retries are safe because every POST carries an Idempotency-Key. If you hit limits under normal load, request a per-agent limit increase via support.
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:
  1. Check the agent’s status and screening detail in the dashboard.
  2. 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.
  3. 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.
In sandbox, AML_DECLINED is only triggered deliberately via the designated test wallets — see Testing.
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:
  1. Recreate the order with orders.create (same parameters are fine) and submit the payment against the new order_id.
  2. If this recurs, move order creation closer to payment time — create the order when the agent decides to pay, not when it starts browsing.
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:
  1. Check the Observatory for current settlement latency and any active incident.
  2. Check the platform status endpoint (GET /status) for degraded components.
  3. Do not resubmit — the payment is queued and settles automatically on recovery; idempotency prevents double-settlement anyway.
  4. If a payment is pending beyond a few minutes with no incident posted, contact support with the payment_id and, if present, the settlement_tx hash. SLA terms are in SLA.
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:
  1. Confirm the endpoint returns 2xx quickly (under a few seconds). Acknowledge first, process asynchronously.
  2. Check your signature verification: it must use the raw request body (not re-serialized JSON) with the Sohopay-Signature and Sohopay-Timestamp headers. See Webhooks.
  3. Fire a test delivery and watch your logs:
  4. Still nothing? Point the webhook at webhook.site temporarily — if deliveries appear there, the problem is on your endpoint, not SohoPay’s sender.
  5. Remember deliveries can arrive out of order and more than once — dedupe by event_id.
Log the request_id from every error response and the settlement_tx from every settled payment. Support can trace any issue from either in minutes.

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.