Desarrolla con la API de Vouchereto
Una API REST pequeña para una sola tarea: recibir un voucher, bloquearlo para un cliente y convertirlo en saldo en tu plataforma.
- URL base
- api.vouchereto.com/v1
- Prueba y producción
- claves vch_test_… y vch_live_…
- Autenticación
- Bearer key + HMAC-SHA256
- Formato
- JSON · importes en unidades menores
Tu primer canje
Consigue tus claves
Crea una clave de prueba en el portal de comercios. Verás la clave completa una sola vez; su última parte es también el secreto con el que firmas las peticiones.
Reserva el voucher
Envía el código, la moneda y la referencia de tu cliente. El voucher queda bloqueado para ese cliente y no se puede usar en ningún otro sitio.
Abona y después captura
Abona el saldo en tu sistema y después captura. Si la recarga falla, cancela en su lugar y el voucher se libera.
Escucha los webhooks
Registra un endpoint para recibir eventos firmados de capturas, cancelaciones, caducidades y checkouts.
POST /v1/redemptions
Authorization: Bearer vch_test_…
Idempotency-Key: topup-88213
Vouchereto-Signature: t=1790500000,v1=9c1e5f07…
Content-Type: application/json
{ "code": "7K2M-9QXR-4HTB-2WNZ", "customer_ref": "acct_48213", "currency": "USD" }
# 201 Created
{ "id": "5f0c2a7e-…", "object": "redemption", "status": "reserved",
"amount_minor": 5000, "currency": "USD", "voucher_last4": "2WNZ",
"customer_ref": "acct_48213", "livemode": false,
"expires_at": "2026-09-27T14:12:00Z", "captured_at": null }
# Credit the customer first, then capture. Irreversible.
POST /v1/redemptions/5f0c2a7e-…/capture
Authorization: Bearer vch_test_…
Idempotency-Key: topup-88213-capture
Vouchereto-Signature: t=1790500012,v1=4b7d2e91…
# 200 OK
{ "id": "5f0c2a7e-…", "object": "redemption", "status": "captured",
"captured_at": "2026-09-27T14:02:31Z", … }
# The top-up failed: release the voucher back to the customer
POST /v1/redemptions/5f0c2a7e-…/cancel
Authorization: Bearer vch_test_…
Idempotency-Key: topup-88213-cancel
Vouchereto-Signature: t=1790500015,v1=77aa01c3…
# 200 OK
{ "id": "5f0c2a7e-…", "object": "redemption", "status": "cancelled", … }
// Vouchereto-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, t + "." + rawBody)>
// secret = the whsec_… signing secret of your webhook endpoint
import crypto from "node:crypto";
export function verifyWebhook(rawBody, header, secret) {
const parts = header.split(",").map((p) => p.trim().split("="));
const t = Number(parts.find(([k]) => k === "t")?.[1]);
const sigs = parts.filter(([k]) => k === "v1").map(([, v]) => Buffer.from(v, "hex"));
if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
return sigs.some((s) => s.length === expected.length && crypto.timingSafeEqual(s, expected));
}
El ciclo de vida de un canje
- capturadoEl voucher se ha gastado. Es irreversible.
- canceladoLo has cancelado. El voucher vuelve a estar activo.
- reserva caducadaNo se capturó a tiempo (15 minutos por defecto). El voucher vuelve a estar activo.
Con qué vas a trabajar
Firma de peticiones
Cada petición lleva una cabecera Vouchereto-Signature: una marca de tiempo y un HMAC-SHA256 de la marca de tiempo, el método, la ruta y el cuerpo, con el secreto de tu clave de API como clave. Aceptamos un desfase de reloj de hasta 300 segundos.
// Sign every request with the secret part of your API key (the text after the last "_")
const t = Math.floor(Date.now() / 1000);
const payload = `${t}.${method} ${pathWithQuery}\n${body}`;
const v1 = crypto.createHmac("sha256", keySecret).update(payload).digest("hex");
headers["Vouchereto-Signature"] = `t=${t},v1=${v1}`;
Idempotencia
Cada POST necesita una cabecera Idempotency-Key. Si repites una petición con la misma clave, recibes la respuesta original, marcada con Idempotent-Replayed: true. Las claves se conservan durante al menos 30 días.
Vouchers del sandbox
Con una clave de prueba, POST /v1/sandbox/vouchers crea un voucher de prueba en el estado que pidas (active, reserved, redeemed, expired, risk_hold o void) y devuelve su código. Las claves de prueba solo ven datos de prueba.
Eventos de webhook
| Evento | Cuándo se envía |
|---|---|
| redemption.captured | Se capturó un voucher reservado. Puedes conservar el saldo abonado con seguridad. |
| redemption.cancelled | Se canceló una reserva. El voucher vuelve a estar activo. |
| redemption.expired | Una reserva se quedó sin tiempo sin ser capturada. |
| checkout.completed | Se pagó un checkout alojado y se aplicó el voucher. |
| checkout.expired | Una sesión de checkout alojado caducó sin pago. |
| checkout.failed | Se revirtió un checkout pagado, por ejemplo tras un reembolso. |
Errores
| Estado | Código | Qué decirle al cliente |
|---|---|---|
| 404 | VOUCHER_INVALID | No encontramos ese código. Revísalo e inténtalo de nuevo. |
| 409 | VOUCHER_ALREADY_REDEEMED | Este voucher ya se ha usado. |
| 409 | VOUCHER_RESERVED | Este voucher se está usando ahora mismo en otro pago. |
| 422 | VOUCHER_EXPIRED | Este voucher ha caducado. |
| 422 | UNIVERSAL_NOT_ACCEPTED | No aceptamos vouchers universales. Usa un voucher de este sitio. |
| 422 | CURRENCY_MISMATCH | Este voucher es de otra moneda. |
| 429 | TOO_MANY_INVALID_ATTEMPTS | Demasiados intentos. Espera unos minutos e inténtalo de nuevo. |
Los errores siguen RFC 7807 (application/problem+json) con un código estable y un request_id.
Esta página resume la API. La referencia completa, con todos los campos, está publicada en www.vouchereto.com/docs/reference.
¿Te has atascado?
Escribe a [DEVELOPER SUPPORT EMAIL]. Un desarrollador lee cada mensaje.
- Especificación OpenAPI
- Colección de Postman
- Estado de la API · [URL]
- Registro de cambios