Test mode only. With a test key (ak_test_…), send your test webhook endpoints one event of a type you choose, built from your own test data with the same shape, signature and delivery as the real event, and livemode: false. Nothing else changes and no money moves. A live key gets 403 TEST_MODE_ONLY and nothing is read. Types: payment.succeeded, payment.failed, refund.created, dispute.opened, invoice.paid, subscription.updated. See Test mode for an example of each. AI assistants can send one too, with the MCP server's send_test_event tool and the same test key.
| Topic | Detail |
|---|---|
| Endpoints | `POST /api/v1/test-helpers/events` |
| Key permissions | webhook_endpoints:write |
| Samples | curl; Node.js 18+ with the built-in fetch (in an ES module); the Node SDK (preview: not on npm yet); Python with requests. |
| Every request can also answer | 401 UNAUTHORIZED, 401 API_KEY_EXPIRED, 403 NOT_ENROLLED, 403 PERMISSION_DENIED, 403 IP_NOT_ALLOWED, 429 RATE_LIMITED, 500 INTERNAL_ERROR. See Error codes. |
The test event object
What the simulator sent: the event's id (the same evt_… your endpoints receive), its type, the test object it is about and how many of your endpoints it was queued for.
{
"object": "test_event",
"id": "evt_9b2c4d6e8f0a1b3c5d7e9f1a2b4c6d8e",
"type": "payment.succeeded",
"livemode": false,
"objectId": "pay_7Hq2LmX9cR4tVb",
"deliveries": 1,
"sample": false
}| Field | Type | Description |
|---|---|---|
object | string | The type of object. Always test_event. |
id | string | The event's id, evt_…, as your endpoints receive it. |
type | string | The event sent. One of payment.succeeded, payment.failed, refund.created, dispute.opened, invoice.paid, subscription.updated. |
livemode | boolean | Always false: test events never carry live data. Always false. |
objectId | string | The test object the event carries as data. |
deliveries | integer | Deliveries queued: one per enabled endpoint that takes this event (0 when none does). |
sample | boolean | True when the object is from Load sample data (ids pay_sample…). |
Endpoints
Send a test webhook event
/api/v1/test-helpers/eventswebhook_endpoints:writeSupports Idempotency-Key.Test mode only: needs an ak_test_ key (a live key gets 403 TEST_MODE_ONLY). Sends your test webhook endpoints one event — payment.succeeded, payment.failed, refund.created, dispute.opened, invoice.paid or subscription.updated — marked livemode: false, built from one of your test objects (objectId, or the newest that fits) exactly as the real event carries it. Nothing else changes and no money moves. 409 NOTHING_TO_SEND when you have no test object of that kind yet. With an ak_test_ key only. Leave out objectId to use your newest test object that fits.
Headers
Idempotency-Keystring- Recommended. A unique key such as a UUID: a retry with the same key within 24 hours gets the first response back instead of acting twice. See Idempotency.
Body
typestringrequired- The event to send. One of
payment.succeeded,payment.failed,refund.created,dispute.opened,invoice.paid,subscription.updated. objectIdstring- The test object it is about (
pay_…,re_…,inv_…,sub_…); left out, the newest that fits. Up to 64 characters.
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",
"objectId": "pay_7Hq2LmX9cR4tVb"
}'const res = await fetch("https://anytime-capital.com/api/v1/test-helpers/events", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "test-payment-succeeded-1",
},
body: JSON.stringify({ type: "payment.succeeded", objectId: "pay_7Hq2LmX9cR4tVb" }),
});
const testEvent = await res.json();
if (!res.ok) throw new Error(`${testEvent.error.code}: ${testEvent.error.message}`);import os
import requests
res = requests.post(
"https://anytime-capital.com/api/v1/test-helpers/events",
headers={
"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}",
"Idempotency-Key": "test-payment-succeeded-1",
},
json={"type": "payment.succeeded", "objectId": "pay_7Hq2LmX9cR4tVb"},
timeout=30,
)
testEvent = res.json()
if not res.ok:
raise RuntimeError(f"{testEvent['error']['code']}: {testEvent['error']['message']}"){
"object": "test_event",
"id": "evt_9b2c4d6e8f0a1b3c5d7e9f1a2b4c6d8e",
"type": "payment.succeeded",
"livemode": false,
"objectId": "pay_7Hq2LmX9cR4tVb",
"deliveries": 1,
"sample": false
}Errors
- 400
INVALID_JSON - The body isn't valid JSON, or couldn't be read. An empty body reads as
{}. SendContent-Type: application/jsonand a JSON object. - 400
INVALID_INPUT - A field, filter,
limitorcursoris missing or invalid. The message starts with the field's name, as inamountCents: …, or readsInvalid cursor.Fix the named field. Don't retry the same request unchanged. - 400
INVALID_IDEMPOTENCY_KEY - The
Idempotency-Keyheader is empty, longer than 255 characters, or has characters other than printable ASCII. Use a UUID. See Idempotency. - 403
TEST_MODE_ONLY - A test helper was called with a live key. Test helpers never touch live data. Use a test key (
ak_test_…): turn on Test mode in the dashboard and create one in Settings → Developers. - 404
NOT_FOUND - No such object on your business (an id from another business reads the same), or no such endpoint under
/api/v1, which still answers in JSON. Check the id and the path. Ids are case-sensitive. - 409
NOTHING_TO_SEND - You have no test object of the kind this event is about yet (no paid test payment for
payment.succeeded, no test invoice forinvoice.paid…). Make one in test mode first (pay a test link with a test card), or choose Load sample data in the test mode bar. - 422
IDEMPOTENCY_KEY_REUSED - The
Idempotency-Keywas used in the last 24 hours with a different body or endpoint. Use a new key for a new request; reuse a key only to retry the same request. - 503
NOT_CONFIGURED - The part of Anytime Capital Payments this needs isn't available right now. Retry later, with the same
Idempotency-Keyon a write.