REST API
For developers not using Node.js. Call the API directly with any HTTP client.
Base URL
https://checkout.vonpay.com
Authentication
All merchant-facing endpoints require a Bearer token:
Authorization: Bearer vp_sk_live_xxx
Endpoints
Create Session
curl -X POST https://checkout.vonpay.com/v1/sessions \
-H "Authorization: Bearer vp_sk_live_xxx" \
-H "Content-Type: application/json" \
-H "Von-Pay-Version: 2026-04-14" \
-H "Idempotency-Key: unique_key_123" \
-d '{
"amount": 1499,
"currency": "USD",
"country": "US",
"successUrl": "https://mystore.com/confirm",
"lineItems": [{"name": "Widget", "quantity": 1, "unitAmount": 1499}]
}'
Response (201):
{
"id": "vp_cs_live_k7x9m2n4p3",
"checkoutUrl": "https://checkout.vonpay.com/checkout?session=vp_cs_live_k7x9m2n4p3",
"expiresAt": "2026-03-31T15:30:00.000Z"
}
Get Session Status
curl https://checkout.vonpay.com/v1/sessions/vp_cs_live_k7x9m2n4p3 \
-H "Authorization: Bearer vp_sk_live_xxx" \
-H "Von-Pay-Version: 2026-04-14"
Health Check
curl https://checkout.vonpay.com/api/health
No authentication required.
The full server-side resource set —
POST /v1/payment_intents(+/capture,/void),POST /v1/refunds,POST /v1/tokens, andGET /v1/capabilities— is documented per-resource in API Reference, Payment Intents, Refunds, Tokens, and Capabilities, and in full in the OpenAPI spec. They're all plain HTTP with the same Bearer-token auth shown above.
Webhook Subscriptions
Programmatically manage your webhook endpoints. Secret key only (vp_sk_*) — publishable keys receive 403. Reads are limited to 100/min per key; writes (create / update / delete / rotate / test) to 30/min per key.
| Method | Path | Description |
|---|---|---|
GET | /v1/webhook_subscriptions | List subscriptions (cursor pagination) |
POST | /v1/webhook_subscriptions | Create a subscription |
GET | /v1/webhook_subscriptions/{id} | Retrieve a subscription |
PATCH | /v1/webhook_subscriptions/{id} | Update a subscription |
DELETE | /v1/webhook_subscriptions/{id} | Delete a subscription |
POST | /v1/webhook_subscriptions/{id}/rotate_signing_secret | Rotate the signing secret |
POST | /v1/webhook_subscriptions/{id}/send_test_event | Send a signed test event |
GET | /v1/webhook_events/{id} | Retrieve a delivered event record |
This management API is camelCase end to end (enabledEvents, signingSecret, lastDeliveryAt); the delivered event payload is snake_case (see below). Cross-merchant or cross-mode access returns an opaque 404 (never 403).
Create a subscription
curl -X POST https://checkout.vonpay.com/v1/webhook_subscriptions \
-H "Authorization: Bearer vp_sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://mystore.com/webhooks/vonpay",
"enabledEvents": ["charge.succeeded", "charge.refunded"],
"description": "Order fulfillment"
}'
Response (201) — includes the signing secret, returned only once:
{
"id": "b6f2c1a0-3e4d-4c8b-9a1f-2d5e7c9b0a13",
"object": "webhook_subscription",
"url": "https://mystore.com/webhooks/vonpay",
"enabledEvents": ["charge.succeeded", "charge.refunded"],
"status": "active",
"description": "Order fulfillment",
"signingSecret": "whsec_3f9a2b...",
"apiVersion": "2026-04-14",
"lastDeliveryAt": null,
"lastSuccessAt": null,
"lastErrorAt": null,
"createdAt": "2026-06-18T12:00:00.000Z"
}
signingSecret (the whsec_… value) is returned only on create and on rotate_signing_secret — never on reads. Store it immediately; if you lose it, rotate to get a new one. You need it to verify the x-vonpay-signature header on every delivery.
Selectable events
The event types you can pass in enabledEvents:
| Event | Fires when |
|---|---|
charge.succeeded | A charge is captured |
charge.failed | A charge attempt fails |
charge.refunded | A charge is refunded (full or partial) |
payment_intent.succeeded | A payment intent reaches succeeded |
payment_intent.failed | A payment intent fails |
payment_intent.cancelled | A payment intent is voided / cancelled |
Other catalog event types (session.*, dispute.*) are modeled in the SDK's WebhookEvent type so your handler can switch on type forward-compatibly. Always handle an unrecognized type gracefully.
Update, rotate, delete
# Pause without deleting (stops deliveries; keeps the config + secret)
curl -X PATCH https://checkout.vonpay.com/v1/webhook_subscriptions/b6f2c1a0-3e4d-4c8b-9a1f-2d5e7c9b0a13 \
-H "Authorization: Bearer vp_sk_live_xxx" -H "Content-Type: application/json" \
-d '{"status": "paused"}'
# Rotate the signing secret (returns a new whsec_ once)
curl -X POST https://checkout.vonpay.com/v1/webhook_subscriptions/b6f2c1a0-3e4d-4c8b-9a1f-2d5e7c9b0a13/rotate_signing_secret \
-H "Authorization: Bearer vp_sk_live_xxx"
# Delete
curl -X DELETE https://checkout.vonpay.com/v1/webhook_subscriptions/b6f2c1a0-3e4d-4c8b-9a1f-2d5e7c9b0a13 \
-H "Authorization: Bearer vp_sk_live_xxx"
PATCH accepts any of url, enabledEvents, description, and status:
status | Behavior |
|---|---|
active | Receives deliveries normally. |
paused | Stops deliveries; config + signing secret retained. Resume by patching back to active. |
disabled | System-suspended (e.g. after sustained failures / auto-pause). Resume by patching to active once your endpoint is healthy. |
Send a test event
curl -X POST https://checkout.vonpay.com/v1/webhook_subscriptions/b6f2c1a0-3e4d-4c8b-9a1f-2d5e7c9b0a13/send_test_event \
-H "Authorization: Bearer vp_sk_live_xxx" -H "Content-Type: application/json" \
-d '{"eventType": "charge.succeeded"}'
The response is synchronous — it reports exactly what your endpoint returned to the signed test delivery:
{
"delivered": true,
"response_status": 200,
"delivery_attempt_id": "vp_wda_test_...",
"signature_preview": "t=1749000000",
"error": null
}
delivered: false with a non-null response_status means your endpoint was reached and returned a non-2xx — useful for confirming your error handling, not a failure of the test itself.
Refund event payload
charge.refunded delivers the following under data (snake_case):
| Field | Type | Notes |
|---|---|---|
transaction_id | string | Settlement-ledger id of the original charge (vp_tx_*) |
refund_id | string | null | Identifies which refund in a multi-partial sequence (vpr_*) |
amount | number | Refund amount in minor units — not the original charge total |
currency | string | ISO-4217, uppercase |
reason | string | null | One of customer_request, duplicate, fraudulent, other |
is_partial | boolean | null | True when amount < original_charge_amount |
original_charge_amount | number | null | Full charge total before refund — compute remaining refundable balance from this |
session_id, payment_intent_id | string | null | Source ids; null on flows where they don't apply |
The subscription's apiVersion (pinned at create time) governs the delivered payload shape; the event envelope itself carries no per-event version field. See Webhook events for every event's payload and Signature verification for the x-vonpay-signature contract.
Rate Limits
| Endpoint | Limit |
|---|---|
POST /v1/sessions | 10/min per IP, 30/min per API key |
GET /v1/sessions/:id | 30/min per IP |
POST /api/checkout/init, /api/checkout/complete | 20/min per IP |
POST /api/webhooks/* (inbound provider) | 100/min per IP |
GET /v1/webhook_subscriptions, /v1/webhook_subscriptions/:id, /v1/webhook_events/:id | 100/min per API key |
POST/PATCH/DELETE /v1/webhook_subscriptions/* (create / update / delete / rotate / test) | 30/min per API key |
See Rate Limits for the full bucket list.
Rate-limited responses return 429 with Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.
Error Format
All errors return JSON with a flat envelope. Every error also carries a selfHeal object — machine-readable retry guidance for SDKs and agents:
{
"error": "Human-readable error message",
"code": "validation_invalid_amount",
"fix": "Amount must be a positive integer in minor units (cents). 1499 = $14.99",
"docs": "https://docs.vonpay.com/integration/create-session#required-fields",
"selfHeal": {
"retryable": false,
"nextAction": "fix_request",
"llmHint": "Machine-readable guidance for SDKs and agents."
}
}
Every response includes an X-Request-Id header for debugging. See Error Codes for the full envelope and the selfHeal contract.
OpenAPI Spec
The full API specification is available at checkout.vonpay.com/openapi.yaml. Import it into Postman, Insomnia, or any OpenAPI-compatible tool.