Skip to main content
Everything on this page runs in test mode: one base URL (https://api.agentcard.sh), with test vs live decided by the credential you authenticate with, never by the host. Test-mode activity is simulated end to end — simulated money, instant identity outcomes, fake merchants — but it flows through the same settlement core, produces the same API shapes, and fires the same webhooks (with livemode: false) that live traffic does. If your integration handles everything this page can throw at it, it is ready for production traffic.
The dashboard drives all of this without code: Cards → Issue a test card walks the transaction lifecycle, Users simulates identity outcomes, and Earnings (test view) shows revenue accruing on simulated volume. This page is the API equivalent.

Test cards

Issue cards in test mode exactly as in live — POST /api/v1/cards — after the instant sandbox identity and payment-method steps from the quickstart. Test cards carry fake 4242… numbers, hold simulated balances, and follow the live one-time-use contract: the first approved authorization consumes the card.

Attaching a card (BYOC)

The attach flow verifies a real consumer card through Basis Theory and the card network, so in test mode it reads Basis Theory’s BIN enrichment for whatever PAN you enter — the card must classify as eligible: a US-issued consumer Visa, or a consumer Mastercard from any country. Use Basis Theory’s US consumer Visa test card:
The ubiquitous 4242 4242 4242 4242 does not attach — Basis Theory enriches it as a commercial, non-US (Bermuda) card, so it’s correctly rejected (the program is consumer-only, and Visa must be US-issued). In sandbox, the ineligible verdict points you at the card above.
To exercise the ineligible branches (which fall back to the issued-card path — the agent routes to create_card): 4000 0566 5566 5556 (business → commercial_card) and 4900 0000 0000 0011 (unknown funding → funding_unknown). Full list: Basis Theory test cards.

Simulate transactions

Test merchants never charge a test card on their own — these helpers are the merchant. Each one drives the same settlement pipeline a real network event does, so the Payment rows, card state changes, and transaction.* webhooks are byte-for-byte what live produces.

The one-shot charge

POST /api/v1/cards/{id}/test_charge authorizes and settles in one call — the happy path:
Fires transaction.authorized then transaction.cleared, and closes the one-time-use card.

The full lifecycle, step by step

Real transactions are not one-shot: they hold as PENDING, settle later (sometimes for less), get reversed, decline, and refund. Each state has its own helper so you can test the handling code paths individually. Authorize — a PENDING hold, the state your webhook consumer must treat as not-yet-final:
Returns the payment id used by the steps below; fires transaction.authorized. An approved authorization consumes a one-time-use card (declines never do). Decline — the branch most integrations forget to build:
Fires transaction.declined with your decline_reason. An authorization for more than the card’s balance auto-declines with insufficient_funds, the way live does — no need to force it. Capture — settle a PENDING authorization, fully or partially:
Fires transaction.cleared at the captured amount. Omit amountCents for a full capture; a partial capture settles for less than the hold, exactly like a merchant finalizing a smaller total. Reverse — void a PENDING authorization instead of settling it:
Fires transaction.voided. (A one-time-use card consumed by the authorization stays closed — live reversals do not resurrect cards either.) Refund — a merchant refund of a settled transaction:
Mirrors the live rail exactly: the refund is not a mutation of the original — it arrives as a separate transaction.cleared with a negative amount_cents (correlate by merchant). Partial refunds are allowed up to the settled amount; the original payment stays SETTLED.
Every helper responds with the events it fired, and each delivery is inspectable in the dashboard under Settings → Webhooks → your endpoint → Deliveries — payload, response code, and retries included.

Simulate identity outcomes

Test-mode verifications never complete on their own (there is no reviewer behind them). Force a verdict with POST /api/v2/kyc/simulateapproved, rejected, or requires_input — and the status plus the identity.verification.updated webhook land exactly like a real review. The full walkthrough, including the test-mode page end users see, is in Identity verification → Testing.

Watch revenue accrue

Test-mode settled volume accrues the same earnings signal live volume does. The dashboard’s Earnings page (test view) has a one-click simulated transaction that shows your interchange share appearing in real time — the same math applied to your live volume.

Webhooks in test mode

Endpoints belong to one mode: an endpoint registered in the test view receives only livemode: false events. Register one endpoint per mode to run both, and use the dashboard’s send test event button to prove your handler before any traffic. Everything else — signatures, retries, the event catalog — is identical to live; see Webhooks.

Going live

Nothing on this page exists in live mode: the helpers return 403 sandbox_only on live credentials, and live verdicts come from real merchants and the identity provider. When the flows above all behave, follow Getting to production.