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.
| Parameter | In | Description |
|---|---|---|
Idempotency-Keyrequired | header | Unique per logical operation (for example your order id). Reuse it on retries. string length 1–128 |
Vouchereto-Signaturerequired | header | string |
X-Customer-Ip | header | Your end customer's IP. Used for brute-force protection instead of your server's IP. string |
Request body:
| Field | Type | Description |
|---|---|---|
coderequired | string | Code as typed by the customer; dashes and spaces are ignored length 16–40 |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
customer_refrequired | string | Your id for the customer (no personal data) length 1–128 |
ttl_seconds | integer | range 60–1800 · default 900 |
{
"code": "K7QM-4XPD-9TRW-2WNZ",
"currency": "USD",
"customer_ref": "user_8842",
"ttl_seconds": 900
}
Response 201:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "redemption" | |
statusrequired | reserved | captured | cancelled | expired | |
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
voucher_last4required | string | |
customer_refrequired | string | |
livemoderequired | boolean | |
expires_atrequired | string (date-time) | When an uncaptured reservation lapses |
captured_atrequired | string | null (date-time) | |
created_atrequired | string (date-time) |
Errors: 400, 401, 403, 404, 409, 422, 429 · codes
GET/v1/redemptions
List redemptions. Newest first. Cursor pagination.
| Parameter | In | Description |
|---|---|---|
Vouchereto-Signaturerequired | header | string |
status | query | reserved | captured | cancelled | expired |
limit | query | integer range 1–100 · default 20 |
cursor | query | pagination.next_cursor from the previous page string |
Response 200:
| Field | Type | Description |
|---|---|---|
datarequired | object[] | |
paginationrequired | object |
Errors: 400, 401 · codes
GET/v1/redemptions/{id}
Retrieve a redemption.
| Parameter | In | Description |
|---|---|---|
idrequired | path | string (uuid) |
Vouchereto-Signaturerequired | header | string |
Response 200:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "redemption" | |
statusrequired | reserved | captured | cancelled | expired | |
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
voucher_last4required | string | |
customer_refrequired | string | |
livemoderequired | boolean | |
expires_atrequired | string (date-time) | When an uncaptured reservation lapses |
captured_atrequired | string | null (date-time) | |
created_atrequired | string (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).
| Parameter | In | Description |
|---|---|---|
idrequired | path | string (uuid) |
Idempotency-Keyrequired | header | Unique per logical operation (for example your order id). Reuse it on retries. string length 1–128 |
Vouchereto-Signaturerequired | header | string |
Response 200:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "redemption" | |
statusrequired | reserved | captured | cancelled | expired | |
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
voucher_last4required | string | |
customer_refrequired | string | |
livemoderequired | boolean | |
expires_atrequired | string (date-time) | When an uncaptured reservation lapses |
captured_atrequired | string | null (date-time) | |
created_atrequired | string (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.
| Parameter | In | Description |
|---|---|---|
idrequired | path | string (uuid) |
Idempotency-Keyrequired | header | Unique per logical operation (for example your order id). Reuse it on retries. string length 1–128 |
Vouchereto-Signaturerequired | header | string |
Response 200:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "redemption" | |
statusrequired | reserved | captured | cancelled | expired | |
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
voucher_last4required | string | |
customer_refrequired | string | |
livemoderequired | boolean | |
expires_atrequired | string (date-time) | When an uncaptured reservation lapses |
captured_atrequired | string | null (date-time) | |
created_atrequired | string (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.
| Parameter | In | Description |
|---|---|---|
Idempotency-Keyrequired | header | Unique per logical operation (for example your order id). Reuse it on retries. string length 1–128 |
Vouchereto-Signaturerequired | header | string |
Request body:
| Field | Type | Description |
|---|---|---|
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
customer_refrequired | string | length 1–128 |
customer_email | string (email) | Prefills the email field length 0–254 |
country | string | Customer country (ISO 3166-1 alpha-2) pattern ^[A-Z]{2}$ |
locale | en | es | ja | ko | pt | it | de | default "en" |
return_urlrequired | string (uri) | https:// (http://localhost allowed outside production) |
cancel_urlrequired | string (uri) | |
auto_redeem | boolean | Apply the purchased voucher to your merchant in the same step default true |
metadata | object | max 20 keys |
{
"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:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "checkout_session" | |
urlrequired | string (uri) | |
statusrequired | open | paid | completed | expired | cancelled | failed | |
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
customer_refrequired | string | |
localerequired | string | |
auto_redeemrequired | boolean | |
livemoderequired | boolean | |
redemption_idrequired | string | null (uuid) | |
metadatarequired | object | |
expires_atrequired | string (date-time) |
Errors: 400, 403, 422, 429 · codes
GET/v1/checkout-sessions/{id}
Retrieve a checkout session.
| Parameter | In | Description |
|---|---|---|
idrequired | path | string (uuid) |
Vouchereto-Signaturerequired | header | string |
Response 200:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "checkout_session" | |
urlrequired | string (uri) | |
statusrequired | open | paid | completed | expired | cancelled | failed | |
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
customer_refrequired | string | |
localerequired | string | |
auto_redeemrequired | boolean | |
livemoderequired | boolean | |
redemption_idrequired | string | null (uuid) | |
metadatarequired | object | |
expires_atrequired | string (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.
| Parameter | In | Description |
|---|---|---|
Idempotency-Keyrequired | header | Unique per logical operation (for example your order id). Reuse it on retries. string length 1–128 |
Vouchereto-Signaturerequired | header | string |
Request body:
| Field | Type | Description |
|---|---|---|
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
customer_refrequired | string | length 1–128 |
return_urlrequired | string (uri) | |
auto_capture | boolean | default false |
{
"currency": "USD",
"customer_ref": "user_8842",
"return_url": "https://shop.example.com/wallet",
"auto_capture": false
}
Response 201:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "redeem_session" | |
urlrequired | string (uri) | |
statusrequired | string | |
auto_capturerequired | boolean | |
livemoderequired | boolean | |
expires_atrequired | string (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.
| Parameter | In | Description |
|---|---|---|
Idempotency-Keyrequired | header | Unique per logical operation (for example your order id). Reuse it on retries. string length 1–128 |
Vouchereto-Signaturerequired | header | string |
Request body:
| Field | Type | Description |
|---|---|---|
state | active | reserved | redeemed | expired | risk_hold | void | default "active" |
amount_minor | integer | range 100–10000000 · default 5000 |
currency | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
{
"state": "active",
"amount_minor": 5000,
"currency": "USD"
}
Response 201:
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
objectrequired | "sandbox_voucher" | |
coderequired | string | |
staterequired | string | |
amount_minorrequired | integer | Amount in minor units (cents). JPY and KRW have no decimals: 1000 = ¥1,000. |
currencyrequired | string | ISO 4217 code accepted by your merchant account pattern ^[A-Z]{3}$ |
livemoderequired | false |
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.
| Parameter | In | Description |
|---|---|---|
Vouchereto-Signaturerequired | header | string |
Response 200:
| Field | Type | Description |
|---|---|---|
datarequired | object[] | |
paginationrequired | object |
Webhook event
Sent to your endpoints; see Webhooks for signing and retries.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | Same as the Vouchereto-Event-Id header; use it to deduplicate |
typerequired | redemption.captured | redemption.cancelled | redemption.expired | checkout.completed | checkout.expired | checkout.failed | |
created_atrequired | string (date-time) | |
livemoderequired | boolean | |
datarequired | object |
Problem (error)
| Field | Type | Description |
|---|---|---|
typerequired | string (uri) | |
titlerequired | string | |
statusrequired | integer | |
coderequired | UNAUTHENTICATED | 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 | |
detail | string | For INVALID_SIGNATURE: MALFORMED, TIMESTAMP_OUT_OF_RANGE or MISMATCH |
request_id | string |