https://api-sandbox.sohopay.xyz/v1, keys sk_test_...) skips KYB and comes pre-funded with test vault collateral, so nothing here costs real USDC.
End-to-end sandbox test
1
Create a test agent
Provision an agent with a small credit line (see Agent Setup for field semantics):Confirm the
201 response includes a wallet_address and status: "active", and that an agent.created webhook arrives.2
Allowlist the agent
The merchant must allowlist the agent before the Policy Service will co-sign for it. In sandbox, do this from the Dashboard under Merchant → Allowlist, or via the allowlist API. Skipping this step is the most common cause of
403 AGENT_NOT_ALLOWLISTED in first integrations — which makes it a good negative test: try step 4 once before allowlisting and confirm you get the 403.3
Create an order
order_id and expires_at — you have 10 minutes.4
Pay the order
Submit the payment with Expect a
"sandbox_auto" so SohoPay signs on the agent’s behalf:202, then poll GET /payments/{payment_id} until status is settled (usually under 2 seconds).5
Verify on Sepolia Basescan
Take the
settlement_tx hash from the settled payment and open it at sepolia.basescan.org. You should see the USDC TransferWithAuthorization to the order’s settlement_address. This is the ground truth — if it’s on Basescan, the merchant was paid.Also confirm the payment appears in the Live Feed dashboard.
6
Verify the webhooks arrived
Your endpoint should have received
payment.created followed by payment.settled, each with a valid HMAC-SHA256 signature in the Sohopay-Signature header. Verify the signature and the Sohopay-Timestamp, and confirm your handler deduplicates by event_id — replay the same event twice and check it’s processed once. Signature verification code is in Webhooks.Simulating error cases
The sandbox provides magic amounts as test helpers: creating an order with one of these amounts makes the subsequent payment fail deterministically with the corresponding error, so you can exercise every recovery path from Error Handling without engineering real failure conditions.Magic amounts only behave this way in the sandbox. On mainnet they are ordinary amounts, so keep them out of any code path that could reach production.
ORDER_EXPIRED the honest way: create an order, wait 10 minutes, submit the payment, and confirm your code creates a fresh order rather than retrying.
Ready for production?
Work through this checklist before switching tosk_live_ keys and https://api.sohopay.xyz/v1:
- Webhook verification implemented — HMAC-SHA256 signature and timestamp checked, events deduplicated by
event_id, retries tolerated. - Idempotency keys on all POSTs — derived from stable identifiers, not random per attempt.
- Retry with backoff and jitter —
Retry-Afterhonored,AML_DECLINEDnever retried, circuit breaker for sustained 500s. - Monitoring in place — alerts on payment failure rate,
withdrawablevault balance, and unexpectedagent.key_rotatedevents;request_idandsettlement_txlogged everywhere. - KYB approved — mainnet requires KYB; allow 1–3 business days.
- Mainnet key stored in a secrets manager —
sk_live_never in code, config files, or CI logs; separate from sandbox credentials.
All boxes checked? You’re ready to take the same flow to mainnet on Base.
Next steps
Error Handling
The recovery playbooks behind each simulated failure.
Webhooks
Signature verification and event handling in depth.
KYB
Start merchant verification while you finish testing.

