Before you touch mainnet, prove the whole flow in the sandbox — happy path and failure paths. This page walks an end-to-end test on Base Sepolia, shows how to trigger specific errors on demand, and ends with the production-readiness checklist. The sandbox (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

Note the order_id and expires_at — you have 10 minutes.
4

Pay the order

Submit the payment with "sandbox_auto" so SohoPay signs on the agent’s behalf:
Expect a 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.
Also test 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 to sk_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 jitterRetry-After honored, AML_DECLINED never retried, circuit breaker for sustained 500s.
  • Monitoring in place — alerts on payment failure rate, withdrawable vault balance, and unexpected agent.key_rotated events; request_id and settlement_tx logged everywhere.
  • KYB approved — mainnet requires KYB; allow 1–3 business days.
  • Mainnet key stored in a secrets managersk_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.