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": "wsub_abc123",
"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 event types (session.*, dispute.*, application.*, payout.*, merchant.ready_for_payments) are delivered by Von Payments as platform-level events — they are not selectable via enabledEvents (you can't turn them on or off), but your endpoint may still receive them. The SDK's WebhookEvent type models them so your handler can switch on type. 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/wsub_abc123 \
-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/wsub_abc123/rotate_signing_secret \
-H "Authorization: Bearer vp_sk_live_xxx"
# Delete
curl -X DELETE https://checkout.vonpay.com/v1/webhook_subscriptions/wsub_abc123 \
-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/wsub_abc123/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": "no_action",
"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.