Skip to main content

Capabilities

GET /v1/capabilities returns the effective capability matrix for the authenticated merchant: which payment-intent operations are supported, which settlement currencies are available, and the payment-intent rate limit. The matrix is processor-agnostic — it never identifies which underlying provider supplies a capability, so you branch on the capability, not on a processor name.

Read it once at integrator startup and cache it for the process lifetime. Branch on it before invoking optional operations (separate capture, partial refund, void-after-capture) so you fail early in your own code instead of round-tripping to a 501 from the API.

Authentication: any valid API key — both publishable (vp_pk_*) and secret (vp_sk_*) keys are accepted, since the matrix is read-only metadata.

Request​

curl https://checkout.vonpay.com/v1/capabilities \
-H "Authorization: Bearer vp_sk_test_YOUR_KEY"
const caps = await client.capabilities.get();

Response​

{
"supported_operations": {
"auth_capture_separation": true,
"partial_capture": true,
"partial_refund": true,
"unreferenced_refund": false,
"void_after_capture": "not_supported",
"mit": true,
"network_tokens": true,
"three_d_secure_2": false,
"ach": false,
"payouts_api": false
},
"settlement_currencies": ["USD", "EUR", "GBP", "CAD", "AUD"],
"rate_limits": {
"payment_intents_per_minute": 300
}
}

In the Node SDK the keys are camelCase (caps.supportedOperations.partialCapture); on the wire they are snake_case as shown above.

supported_operations​

FlagTypeMeaning
auth_capture_separationbooleanAuthorize and capture can be separate steps (capture_method: "manual" on the payment intent, then POST /v1/payment_intents/:id/capture).
partial_capturebooleanCapture less than the authorized amount.
partial_refundbooleanRefund less than the captured amount via POST /v1/refunds with an amount.
unreferenced_refundbooleanIssue a refund that does not reference an original charge.
void_after_capturestring enumWhether POST /v1/payment_intents/:id/void works once the intent is captured. Every processor returns not_supported today — reverse a captured payment with refunds.create instead. The enum also carries supported (void works after capture) and rerouted_to_refund (the void call is handled through the refund pathway for you); no processor returns either at present. See branching below.
mitbooleanMerchant-initiated transactions (e.g. recurring, unscheduled).
network_tokensbooleanNetwork tokenization is available for the merchant's processor.
three_d_secure_2boolean3-D Secure 2 is available.
achbooleanACH bank-transfer payments.
payouts_apibooleanPayouts API.
dispute_reportingstring enumWhether a chargeback against one of your payments reaches Von Payments. tracked: we are notified and emit a dispute.created webhook. not_tracked: we are not notified. The payment's status never becomes disputed on either value — see below.

settlement_currencies​

Array of ISO 4217 currency codes the merchant can settle in.

rate_limits​

FieldTypeMeaning
payment_intents_per_minuteintegerPer-minute ceiling per secret key, shared by the payment routes (/v1/payment_intents, /v1/refunds, /v1/tokens, /v1/buyers, /v1/payment_methods). See Rate Limits.

succeeded is not evidence a payment was not disputed​

A payment's status is a closed set (requires_action, authorized, captured, succeeded, voided, failed) and none of them means "disputed" — a disputed payment keeps reading succeeded on either value of dispute_reporting, so polling a payment can never reveal a dispute.

  • tracked — we are notified and send dispute.created (then dispute.won / dispute.lost). dispute.* is delivered to every active webhook subscription, whichever events it registered for — you need at least one active endpoint, and the webhook is the only signal.
  • not_tracked — we are not notified and nothing in this API will tell you the dispute exists. Monitor and answer disputes in your processor's own dashboard; the card network's response deadline is shown there, and a dispute you do not answer in time is lost.

You answer your own disputes on either value; this field only changes whether we can tell you one was raised.

Branching on the matrix​

Check the matrix before an optional operation instead of catching a 501:

const caps = await client.capabilities.get();

if (caps.supportedOperations.voidAfterCapture === "supported") {
// The processor can void the intent directly after capture.
await client.paymentIntents.void(pi.id, { idempotencyKey: `${pi.id}_void` });
} else {
// Every processor today. Reverse a captured payment with a refund.
const refund = await client.refunds.create({ paymentIntent: pi.id });
// ⛔ Not throwing is not the same as the buyer being repaid — `canceled` is a
// `200` that moved no money. See [Refunds](refunds.md#status).
if (refund.status === "canceled") throw new Error("refund canceled before settlement");
}

Branch so the refund is the fallback, not a special case — a branch that handles only supported and rerouted_to_refund reverses nothing (Refunds → Void-after-capture). An operation the active binder does not support returns 501 endpoint_not_implemented. An operation that is supported but invalid for the intent's current state returns 409 invalid_transition.

  • Payment Intents — the operations gated by this matrix
  • Refunds — partial-refund and void-after-capture behavior
  • Error Codes — endpoint_not_implemented, invalid_transition