# Test mode: build without real money

> Build and test every payment flow without real money: test mode, ak_test_ API keys, sandbox test cards, test webhooks, sample data and event simulators.

Source: https://anytime-capital.com/docs/test-mode · Markdown: https://anytime-capital.com/docs/test-mode.md · All docs: https://anytime-capital.com/docs/llms-full.txt

Test mode is a full copy of your business where no real money moves. Payment links, invoices, quotes, checkout, subscriptions, refunds, the API and webhooks all work, on test data that is kept apart from your live data. You can use it before your business is verified, so you can build your integration while verification runs.

## Switch test mode on

1. In the dashboard, turn on **Test mode** in the header. Anyone on your team can: the test business has the same people with the same roles.
2. An amber bar reading **Test mode — no real money moves** shows on every page while it is on, and on your test checkout, invoice and billing pages.
3. Everything you create is test data: it never appears in live mode, and live data never appears in test mode.
4. Turn the switch off (or choose **Switch to live** in the bar) to go back to your live data.

> **Live only:** Banking, crypto, payouts to your bank, verification, your team, referrals, custom checkout domains, accounting sync, stablecoin checkout and 1099-K requests work with real money or real accounts, so they stay in live mode. Your business name, logo and contact details come from live mode each time you switch.

## Test cards

Pay your test checkout with these cards. Use any future expiry date and any three-digit security code. A real card is never charged in test mode.

| Card number | What happens | Webhook event |
| --- | --- | --- |
| `4242 4242 4242 4242` | The payment succeeds. | `payment.succeeded` |
| `4000 0000 0000 0002` | The card is declined; the payment is recorded as failed. | `payment.failed` |

The sandbox has no test card yet for these: Insufficient funds and other specific decline reasons; 3-D Secure authentication; Disputes. Test how your integration handles them with the [event simulator](https://anytime-capital.com/docs/test-mode.md#test-your-integration).

## Test API keys

With test mode on, **Settings → Developers** makes test keys, which start with `ak_test_`. A test key reaches your test data only; a live key (`ak_live_`) never reaches it. Everything else is the same: the base URL, restricted permissions, idempotency, rate limits, the [MCP server](https://anytime-capital.com/docs/build-with-ai.md) and the [Node SDK](https://anytime-capital.com/docs/quickstart.md#node-sdk). Every object says which mode it is in with `livemode` — `false` in test mode.

```bash
export ANYTIME_API_KEY="ak_test_…"

curl "https://anytime-capital.com/api/v1/payments?limit=1" \
  -H "Authorization: Bearer $ANYTIME_API_KEY"
```

**Every object carries livemode**

```json
{
  "object": "payment",
  "livemode": false,
  "id": "pay_7Hq2LmX9cR4tVb",
  "status": "paid",
  "amountCents": 12500,
  "amountRefundedCents": 0,
  "netCents": 12088,
  "currency": "usd",
  "description": "Consulting — October",
  "source": {
    "type": "payment_link",
    "id": "pl_4kTz8QwN2xYb6RcD1mPa"
  },
  "paymentLinkId": "pl_4kTz8QwN2xYb6RcD1mPa",
  "customer": {
    "name": "Jordan Lee",
    "email": "jordan@example.com",
    "country": "US"
  },
  "card": {
    "brand": "visa",
    "last4": "4242"
  },
  "paymentMethod": {
    "type": "card",
    "label": "Visa •••• 4242"
  },
  "clientReference": "order_1042",
  "metadata": {
    "campaign": "fall-launch"
  },
  "amountDetails": {
    "subtotalCents": 12500,
    "discountCents": 0,
    "shippingCents": 0,
    "taxCents": 0,
    "customerFeeCents": 0
  },
  "dispute": null,
  "failureMessage": null,
  "createdAt": "2026-10-14T16:02:11.000Z",
  "paidAt": "2026-10-14T16:02:15.000Z"
}
```

## Test webhooks

Webhook endpoints added in test mode receive test events only, and live endpoints never receive them. Each event says `livemode: false`, on the event and on the object it carries, and is signed with the endpoint's own secret exactly like a live one — so the same handler works for both. See [Webhooks](https://anytime-capital.com/docs/webhooks.md).

**A test event**

```json
{
  "id": "evt_3f9a1c2b7d4e6f8a0b1c2d3e4f5a6b7c",
  "type": "payment.succeeded",
  "created": "2026-10-14T16:02:16.000Z",
  "livemode": false,
  "data": {
    "object": "payment",
    "livemode": false,
    "id": "pay_7Hq2LmX9cR4tVb",
    "status": "paid",
    "amountCents": 12500,
    "amountRefundedCents": 0,
    "netCents": 12088,
    "currency": "usd",
    "description": "Consulting — October",
    "source": {
      "type": "payment_link",
      "id": "pl_4kTz8QwN2xYb6RcD1mPa"
    },
    "paymentLinkId": "pl_4kTz8QwN2xYb6RcD1mPa",
    "customer": {
      "name": "Jordan Lee",
      "email": "jordan@example.com",
      "country": "US"
    },
    "card": {
      "brand": "visa",
      "last4": "4242"
    },
    "paymentMethod": {
      "type": "card",
      "label": "Visa •••• 4242"
    },
    "clientReference": "order_1042",
    "metadata": {
      "campaign": "fall-launch"
    },
    "amountDetails": {
      "subtotalCents": 12500,
      "discountCents": 0,
      "shippingCents": 0,
      "taxCents": 0,
      "customerFeeCents": 0
    },
    "dispute": null,
    "failureMessage": null,
    "createdAt": "2026-10-14T16:02:11.000Z",
    "paidAt": "2026-10-14T16:02:15.000Z"
  }
}
```

## Test your integration

Some events take days to happen for real: a dispute, a renewal, an invoice paid by bank transfer. The event simulator sends one to your test endpoints now, built from your own test data with the same shape, signature and delivery as the real event. It changes nothing else and moves no money. Use **Send test event** in the test mode bar, or the API with a test key (a live key gets `403 TEST_MODE_ONLY`).

`POST /test-helpers/events` with `type` and, optionally, `objectId` (a `pay_…`, `re_…`, `inv_…` or `sub_…`; left out, your newest test object that fits). It needs the `webhook_endpoints` write permission and answers `409 NOTHING_TO_SEND` when you have no test object of that kind yet: make a test payment, or load sample data. The full reference is [Test helpers API](https://anytime-capital.com/docs/test-helpers.md).

**Request**

```bash
curl -X POST https://anytime-capital.com/api/v1/test-helpers/events \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: test-event-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"payment.succeeded"}'
```

**Response (201)**

```json
{
  "object": "test_event",
  "id": "evt_9b2c4d6e8f0a1b3c5d7e9f1a2b4c6d8e",
  "type": "payment.succeeded",
  "livemode": false,
  "objectId": "pay_7Hq2LmX9cR4tVb",
  "deliveries": 1,
  "sample": false
}
```

| Event | What `data` carries |
| --- | --- |
| `payment.succeeded` | Your newest paid test payment (or `objectId`, a `pay_…`). |
| `payment.failed` | Your newest failed test payment. |
| `refund.created` | Your newest test refund (or a `re_…`). |
| `dispute.opened` | Your newest paid test payment, shown disputed (`status: "disputed"`), as the real event carries it. |
| `invoice.paid` | Your newest test invoice (or an `inv_…`), shown paid in full. |
| `subscription.updated` | Your newest test subscription (or a `sub_…`). |

### Payment succeeded (payment.succeeded)

Your newest paid test payment (or `objectId`, a `pay_…`).

**curl**

```bash
curl -X POST https://anytime-capital.com/api/v1/test-helpers/events \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: test-payment-succeeded-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"payment.succeeded"}'
```

**Node SDK**

```typescript
const event = await client.testHelpers.events.create({ type: "payment.succeeded" });
console.log(event.id, event.deliveries); // evt_…, endpoints it was queued for
```

### Payment failed (payment.failed)

Your newest failed test payment.

**curl**

```bash
curl -X POST https://anytime-capital.com/api/v1/test-helpers/events \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: test-payment-failed-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"payment.failed"}'
```

**Node SDK**

```typescript
const event = await client.testHelpers.events.create({ type: "payment.failed" });
console.log(event.id, event.deliveries); // evt_…, endpoints it was queued for
```

### Refund created (refund.created)

Your newest test refund (or a `re_…`).

**curl**

```bash
curl -X POST https://anytime-capital.com/api/v1/test-helpers/events \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: test-refund-created-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"refund.created"}'
```

**Node SDK**

```typescript
const event = await client.testHelpers.events.create({ type: "refund.created" });
console.log(event.id, event.deliveries); // evt_…, endpoints it was queued for
```

### Dispute opened (dispute.opened)

Your newest paid test payment, shown disputed (`status: "disputed"`), as the real event carries it.

**curl**

```bash
curl -X POST https://anytime-capital.com/api/v1/test-helpers/events \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: test-dispute-opened-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"dispute.opened"}'
```

**Node SDK**

```typescript
const event = await client.testHelpers.events.create({ type: "dispute.opened" });
console.log(event.id, event.deliveries); // evt_…, endpoints it was queued for
```

### Invoice paid (invoice.paid)

Your newest test invoice (or an `inv_…`), shown paid in full.

**curl**

```bash
curl -X POST https://anytime-capital.com/api/v1/test-helpers/events \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: test-invoice-paid-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"invoice.paid"}'
```

**Node SDK**

```typescript
const event = await client.testHelpers.events.create({ type: "invoice.paid" });
console.log(event.id, event.deliveries); // evt_…, endpoints it was queued for
```

### Subscription updated (subscription.updated)

Your newest test subscription (or a `sub_…`).

**curl**

```bash
curl -X POST https://anytime-capital.com/api/v1/test-helpers/events \
  -H "Authorization: Bearer $ANYTIME_API_KEY" \
  -H "Idempotency-Key: test-subscription-updated-1" \
  -H "Content-Type: application/json" \
  -d '{"type":"subscription.updated"}'
```

**Node SDK**

```typescript
const event = await client.testHelpers.events.create({ type: "subscription.updated" });
console.log(event.id, event.deliveries); // evt_…, endpoints it was queued for
```

## Sample data

Owners and admins can choose **Load sample data** in the test mode bar to fill test mode with three customers, three products, two payment links, an open invoice, a monthly plan with a subscriber, and payments that succeeded, failed and were refunded. Loading it again adds nothing. The links, the invoice and the plan are real test objects you can pay with a test card; the sample payments and the subscriber are records to explore (their ids start `pay_sample` and `mem_sample`), so refunding or cancelling one isn't possible.

## Reset test data

**Reset test data** in the test mode bar (owners and admins) deletes every test payment, link, invoice, quote, customer, product, subscription and the rest of your test data. Test API keys, test webhook endpoints, your team and settings stay. Your live data is never touched.

## What is different in test mode

- No real money moves, and nothing is paid out.
- Emails never reach customers: receipts, invoices and reminders go to the business's owners and admins (and whoever acted) instead, marked [TEST], saying who they would have gone to.
- Scheduled work runs in live mode only: automatic invoice reminders, trial and card-expiry reminders, scheduled plan changes, usage billing at period end and automatic decisions on held payments. Test your handling of those with the event simulator.
- Test payments never show in Anytime Capital's own reports, and don't count toward pricing offers or referrals.

## Shopify, WooCommerce and Zapier

- **Shopify**: with your store's payment provider in test mode, Shopify's test orders are paid on your Anytime Capital test mode with a test card. See [Shopify](https://anytime-capital.com/docs/shopify.md).
- **WooCommerce**: turn on **Test mode** in the plugin settings and paste a test key (`ak_test_…`) and a test webhook endpoint's secret. See [WooCommerce](https://anytime-capital.com/docs/woocommerce.md#test-mode).
- **Zapier**: connect with a test key to build and try your Zaps on test data, then reconnect with a live key. See [Zapier](https://anytime-capital.com/docs/zapier.md).

## Going live

1. Finish verification in **Settings → Verification** (live mode).
2. Create a live key and live webhook endpoints in **Settings → Developers** with test mode off.
3. Swap the key and webhook secret in your server's environment. Nothing else in your code changes.
4. Check `livemode` in your webhook handler if you send test and live events to the same server.

---

Anytime Capital is a fintech company, not a bank. Payment processing, banking and payout services are provided by Anytime Capital's licensed partners. Rates shown are for US card payments; international cards, currency conversion and disputes may carry additional fees shown in your dashboard before you accept a payment.
