Skip to content
Documentation menu

Vouchereto API · v1

API reference

Base URL https://api.vouchereto.com/v1. Every request needs a key and a signature; every POST an Idempotency-Key. Generated from openapi.yaml (OpenAPI 3.1): import it into Postman, Insomnia or your code generator.

Redemptions

Two-step redemption of a voucher code your customer typed in your site (reserve, then capture or cancel).

POST/v1/redemptions

Reserve a voucher (step 1 of 2). Locks the voucher's full value for ttl_seconds. Nothing is charged until you capture. If you neither capture nor cancel, the reservation expires and the voucher becomes usable again (redemption.expired webhook). Vouchers are single-use: the whole face value is redeemed. Invalid codes are rate limited per customer_ref, per customer IP and per merchant (5 failures / 15 min per customer, then exponential blocks). Send X-Customer-Ip so one abusive customer cannot block your server's IP.

Rate limit: 120 requests / minute / key.

Reserve a voucher (step 1 of 2) parameters
ParameterInDescription
Idempotency-KeyrequiredheaderUnique per logical operation (for example your order id). Reuse it on retries. string length 1–128
Vouchereto-Signaturerequiredheader string
X-Customer-IpheaderYour end customer's IP. Used for brute-force protection instead of your server's IP. string

Request body:

Reserve a voucher (step 1 of 2) request body
FieldTypeDescription
coderequiredstringCode as typed by the customer; dashes and spaces are ignored
length 16–40
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
customer_refrequiredstringYour id for the customer (no personal data)
length 1–128
ttl_secondsinteger
range 60–1800 · default 900
example request
{
  "code": "K7QM-4XPD-9TRW-2WNZ",
  "currency": "USD",
  "customer_ref": "user_8842",
  "ttl_seconds": 900
}

Response 201:

Reserve a voucher (step 1 of 2) response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"redemption"
statusrequiredreserved | captured | cancelled | expired
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
voucher_last4requiredstring
customer_refrequiredstring
livemoderequiredboolean
expires_atrequiredstring (date-time)When an uncaptured reservation lapses
captured_atrequiredstring | null (date-time)
created_atrequiredstring (date-time)

Errors: 400, 401, 403, 404, 409, 422, 429 · codes

GET/v1/redemptions

List redemptions. Newest first. Cursor pagination.

List redemptions parameters
ParameterInDescription
Vouchereto-Signaturerequiredheader string
statusquery reserved | captured | cancelled | expired
limitquery integer range 1–100 · default 20
cursorquerypagination.next_cursor from the previous page string

Response 200:

List redemptions response
FieldTypeDescription
datarequiredobject[]
paginationrequiredobject

Errors: 400, 401 · codes

GET/v1/redemptions/{id}

Retrieve a redemption.

Retrieve a redemption parameters
ParameterInDescription
idrequiredpath string (uuid)
Vouchereto-Signaturerequiredheader string

Response 200:

Retrieve a redemption response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"redemption"
statusrequiredreserved | captured | cancelled | expired
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
voucher_last4requiredstring
customer_refrequiredstring
livemoderequiredboolean
expires_atrequiredstring (date-time)When an uncaptured reservation lapses
captured_atrequiredstring | null (date-time)
created_atrequiredstring (date-time)

Errors: 404 · codes

POST/v1/redemptions/{id}/capture

Capture a reservation (step 2 of 2). Credits your merchant balance with the voucher's value. Credit your customer only after a 200 here (or the redemption.captured webhook).

Capture a reservation (step 2 of 2) parameters
ParameterInDescription
idrequiredpath string (uuid)
Idempotency-KeyrequiredheaderUnique per logical operation (for example your order id). Reuse it on retries. string length 1–128
Vouchereto-Signaturerequiredheader string

Response 200:

Capture a reservation (step 2 of 2) response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"redemption"
statusrequiredreserved | captured | cancelled | expired
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
voucher_last4requiredstring
customer_refrequiredstring
livemoderequiredboolean
expires_atrequiredstring (date-time)When an uncaptured reservation lapses
captured_atrequiredstring | null (date-time)
created_atrequiredstring (date-time)

Errors: 404, 409 · codes

POST/v1/redemptions/{id}/cancel

Cancel a reservation. Releases the voucher so the customer can use it again. Only reservations can be cancelled; a captured redemption is final.

Cancel a reservation parameters
ParameterInDescription
idrequiredpath string (uuid)
Idempotency-KeyrequiredheaderUnique per logical operation (for example your order id). Reuse it on retries. string length 1–128
Vouchereto-Signaturerequiredheader string

Response 200:

Cancel a reservation response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"redemption"
statusrequiredreserved | captured | cancelled | expired
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
voucher_last4requiredstring
customer_refrequiredstring
livemoderequiredboolean
expires_atrequiredstring (date-time)When an uncaptured reservation lapses
captured_atrequiredstring | null (date-time)
created_atrequiredstring (date-time)

Errors: 404, 409 · codes

Checkout

Hosted "Pay with voucher" checkout. The customer buys a voucher by card on pay.vouchereto.com and comes back.

POST/v1/checkout-sessions

Create a hosted checkout session. Redirect your customer to url. They buy a voucher by card (3D Secure) on pay.vouchereto.com. With auto_redeem: true (default) the voucher is reserved and captured for you in the same step and the session becomes completed with a redemption_id. The customer is sent back to return_url?vouchereto_session=<id>&status=<status>. Trust the checkout.completed webhook or GET /checkout-sessions/{id}, never the query string alone. Sessions expire after 60 minutes.

Rate limit: 300 requests / minute / key.

Create a hosted checkout session parameters
ParameterInDescription
Idempotency-KeyrequiredheaderUnique per logical operation (for example your order id). Reuse it on retries. string length 1–128
Vouchereto-Signaturerequiredheader string

Request body:

Create a hosted checkout session request body
FieldTypeDescription
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
customer_refrequiredstring
length 1–128
customer_emailstring (email)Prefills the email field
length 0–254
countrystringCustomer country (ISO 3166-1 alpha-2)
pattern ^[A-Z]{2}$
localeen | es | ja | ko | pt | it | de
default "en"
return_urlrequiredstring (uri)https:// (http://localhost allowed outside production)
cancel_urlrequiredstring (uri)
auto_redeembooleanApply the purchased voucher to your merchant in the same step
default true
metadataobject
max 20 keys
example request
{
  "amount_minor": 5000,
  "currency": "USD",
  "customer_ref": "user_8842",
  "locale": "en",
  "return_url": "https://shop.example.com/topup/done",
  "cancel_url": "https://shop.example.com/topup",
  "metadata": {
    "cart": "3141"
  }
}

Response 201:

Create a hosted checkout session response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"checkout_session"
urlrequiredstring (uri)
statusrequiredopen | paid | completed | expired | cancelled | failed
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
customer_refrequiredstring
localerequiredstring
auto_redeemrequiredboolean
livemoderequiredboolean
redemption_idrequiredstring | null (uuid)
metadatarequiredobject
expires_atrequiredstring (date-time)

Errors: 400, 403, 422, 429 · codes

GET/v1/checkout-sessions/{id}

Retrieve a checkout session.

Retrieve a checkout session parameters
ParameterInDescription
idrequiredpath string (uuid)
Vouchereto-Signaturerequiredheader string

Response 200:

Retrieve a checkout session response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"checkout_session"
urlrequiredstring (uri)
statusrequiredopen | paid | completed | expired | cancelled | failed
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
customer_refrequiredstring
localerequiredstring
auto_redeemrequiredboolean
livemoderequiredboolean
redemption_idrequiredstring | null (uuid)
metadatarequiredobject
expires_atrequiredstring (date-time)

Errors: 404 · codes

Redeem widget

Hosted page where the customer types an existing voucher code, so the code never touches your site.

POST/v1/redeem-sessions

Create a hosted redeem session. Redirect your customer to url; they type their code on pay.vouchereto.com. They return to return_url?vouchereto_redemption=<id>&status=<reserved|captured>. With auto_capture: false (default) you must capture or cancel the redemption yourself. Sessions expire after 30 minutes.

Create a hosted redeem session parameters
ParameterInDescription
Idempotency-KeyrequiredheaderUnique per logical operation (for example your order id). Reuse it on retries. string length 1–128
Vouchereto-Signaturerequiredheader string

Request body:

Create a hosted redeem session request body
FieldTypeDescription
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
customer_refrequiredstring
length 1–128
return_urlrequiredstring (uri)
auto_captureboolean
default false
example request
{
  "currency": "USD",
  "customer_ref": "user_8842",
  "return_url": "https://shop.example.com/wallet",
  "auto_capture": false
}

Response 201:

Create a hosted redeem session response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"redeem_session"
urlrequiredstring (uri)
statusrequiredstring
auto_capturerequiredboolean
livemoderequiredboolean
expires_atrequiredstring (date-time)

Errors: 400, 422 · codes

Sandbox

Test-mode helpers. Test keys only.

POST/v1/sandbox/vouchers

Create a test voucher. Test keys only (a live key gets 403 LIVEMODE_NOT_ALLOWED). Returns a real, valid code in the state you ask for, tied to your merchant.

Create a test voucher parameters
ParameterInDescription
Idempotency-KeyrequiredheaderUnique per logical operation (for example your order id). Reuse it on retries. string length 1–128
Vouchereto-Signaturerequiredheader string

Request body:

Create a test voucher request body
FieldTypeDescription
stateactive | reserved | redeemed | expired | risk_hold | void
default "active"
amount_minorinteger
range 100–10000000 · default 5000
currencystringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
example request
{
  "state": "active",
  "amount_minor": 5000,
  "currency": "USD"
}

Response 201:

Create a test voucher response
FieldTypeDescription
idrequiredstring (uuid)
objectrequired"sandbox_voucher"
coderequiredstring
staterequiredstring
amount_minorrequiredintegerAmount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000.
currencyrequiredstringISO 4217 code accepted by your merchant account
pattern ^[A-Z]{3}$
livemoderequiredfalse

Errors: 403, 422 · codes

Settlements

Weekly payouts of captured redemptions.

GET/v1/settlements

List settlements. Latest 100, newest first. Test keys always get an empty list (no money moves in the sandbox). The line-level CSV is in the merchant portal.

List settlements parameters
ParameterInDescription
Vouchereto-Signaturerequiredheader string

Response 200:

List settlements response
FieldTypeDescription
datarequiredobject[]
paginationrequiredobject

Webhook event

Sent to your endpoints; see Webhooks for signing and retries.

Webhook event
FieldTypeDescription
idrequiredstring (uuid)Same as the Vouchereto-Event-Id header; use it to deduplicate
typerequiredredemption.captured | redemption.cancelled | redemption.expired | checkout.completed | checkout.expired | checkout.failed
created_atrequiredstring (date-time)
livemoderequiredboolean
datarequiredobject

Problem (error)

Problem
FieldTypeDescription
typerequiredstring (uri)
titlerequiredstring
statusrequiredinteger
coderequiredUNAUTHENTICATED | INVALID_SIGNATURE | FORBIDDEN | MERCHANT_NOT_ACTIVE | LIVEMODE_NOT_ALLOWED | NOT_FOUND | VOUCHER_INVALID | REDEMPTION_NOT_FOUND | SESSION_NOT_FOUND | VOUCHER_RESERVED | VOUCHER_ALREADY_REDEEMED | REDEMPTION_NOT_CAPTURABLE | REDEMPTION_ALREADY_CAPTURED | IDEMPOTENCY_CONFLICT | IDEMPOTENCY_IN_PROGRESS | VOUCHER_EXPIRED | CURRENCY_MISMATCH | CURRENCY_NOT_ACCEPTED | UNIVERSAL_NOT_ACCEPTED | AMOUNT_OUT_OF_RANGE | COUNTRY_NOT_ALLOWED | PSP_PROGRAM_NOT_APPROVED | STATE_INVALID | VALIDATION_ERROR | IDEMPOTENCY_KEY_REQUIRED | RATE_LIMITED | TOO_MANY_INVALID_ATTEMPTS
detailstringFor INVALID_SIGNATURE: MALFORMED, TIMESTAMP_OUT_OF_RANGE or MISMATCH
request_idstring