Suscripciones de eventos
Las suscripciones funcionan en producción, pero su contrato todavía no está en la referencia OpenAPI y puede sumar campos. Ignora los campos que no conozcas y no dependas del orden de las propiedades.
Además del aviso checkout.sesion, que llega a la webhookUrl de cada sesión, el Merchant puede avisar a varios sistemas tuyos (ERP, sistema de despacho, back office) cuando se resuelve un cobro creado desde la API de pagos o cambia un vale de salida. Cada sistema se da de alta como una suscripción con su URL, sus eventos y su propio secreto de firma.
Eventos
| Evento | Cuándo llega |
|---|---|
intencion.resultado | Se resolvió el cobro de una intención creada con externalOrderId desde la API de pagos. |
vale.cobro | Se resolvió un cobro asociado a un vale de salida. |
vale.estado | El vale cambió de estado: ANCLADO, CONSUMIDO, ANULADO o VENCIDO. |
vale.comprobante.emitido | Se emitió el comprobante de pago de la venta. |
vale.factura.pedida | El cliente pidió factura y la emite el comercio. |
Los eventos factura.solicitada, factura.emitida y factura.rechazada ya se aceptan al suscribirse, pero todavía no se envían.
Crear una suscripción
Necesitas una clave API de alcance INTEGRACION o COMPLETO. Una clave EQUIPOS no puede administrar a quién se envían los datos del comercio.
curl -s -X POST https://pos.finoracore.com/api/v1/pagos/webhooks/suscripciones \
-H "X-API-Key: $FINORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"merchantCode": "COM00042",
"nombre": "ERP central",
"url": "https://erp.mitienda.example/finora/eventos",
"eventos": ["intencion.resultado", "vale.cobro"]
}'
Respuesta 201:
{
"id": 12,
"nombre": "ERP central",
"url": "https://erp.mitienda.example/finora/eventos",
"eventos": ["intencion.resultado", "vale.cobro"],
"activo": true,
"secretoConfigurado": true,
"creadaEn": "2026-10-15T14:02:11.000+00:00",
"secreto": "<secreto, se muestra una sola vez>",
"aviso": "Guarda el secreto: no se vuelve a mostrar. Verifica X-Finora-Signature (t, v1) con él."
}
Reglas:
nombre: de 1 a 60 caracteres.url:httpshacia un nombre de dominio público, hasta 500 caracteres. Se rechazan las IP,localhost, los dominios.localo.internaly las URL con credenciales.eventos: lista de la tabla anterior. Si la omites, o envías["*"], la suscripción recibe todos.- Máximo 5 suscripciones activas por comercio.
- El
secretosolo aparece en esta respuesta. Si lo pierdes, borra la suscripción y crea otra.
Listar y borrar
curl -s "https://pos.finoracore.com/api/v1/pagos/webhooks/suscripciones?merchantCode=COM00042" \
-H "X-API-Key: $FINORA_API_KEY"
curl -s -X DELETE "https://pos.finoracore.com/api/v1/pagos/webhooks/suscripciones/12?merchantCode=COM00042" \
-H "X-API-Key: $FINORA_API_KEY"
# → 204 sin cuerpo
El listado devuelve las suscripciones activas sin el secreto. Borrar desactiva la suscripción: deja de recibir eventos al instante.
Qué llega
Cada entrega es un POST con el cuerpo en JSON y las mismas cabeceras del aviso del checkout:
POST /finora/eventos HTTP/1.1
Content-Type: application/json
X-Finora-Evento: intencion.resultado
X-Finora-Entrega: 9310
X-Finora-Signature: t=1760536931,v1=5d0c…,v0=91ab…
Cuerpo de intencion.resultado y vale.cobro (ejemplo con datos ficticios):
{
"evento": "intencion.resultado",
"valeNumero": null,
"externalId": "PED-8841",
"referenciasExternas": null,
"sucursal": { "storeCode": "SUC001" },
"referenciaFinora": "FNR8Q2LM4K",
"estado": "APROBADA",
"monto": 2499.00,
"moneda": "VES",
"riel": "TARJETA",
"autorizacion": "A1B2C3",
"rrn": "622916125320",
"stan": 125320,
"terminalId": "TERM0042",
"lote": "000052",
"aprobadaEn": "2026-10-15T14:05:40.000+00:00",
"tarjeta": { "marca": "VISA", "ultimos4": "0015", "tipoCuenta": null },
"recibo": { "lineas": ["…", "COMPROBANTE DE PAGO - NO ES FACTURA FISCAL", "REF FNR8Q2LM4K", "MONTO VES 2499.00", "VISA ****0015", "AUT A1B2C3 RRN 622916125320", "APROBADA"] }
}
| Campo | Notas |
|---|---|
estado | APROBADA, RECHAZADA, EN_DUDA, ANULADA, EN_CURSO o PENDIENTE. Como en el checkout, EN_DUDA no es un rechazo. |
referenciaFinora | Referencia de la intención en FINORA. |
externalId | Tu número de pedido (externalOrderId de la intención o el del vale). |
autorizacion, rrn, stan, lote | Datos de la transacción con tarjeta; nulos si el cobro no fue con tarjeta. |
tarjeta | Solo marca, últimos cuatro dígitos y tipo de cuenta. Nunca viaja el número de la tarjeta, ni enmascarado. |
recibo.lineas | Texto listo para imprimir un comprobante (no es factura fiscal). |
vale.cobro y vale.estado traen además los datos del vale: valeNumero, merchantCode, origen y la sucursal con su nombre. vale.estado agrega estado, terminal y en (fecha del cambio). El cuerpo de vale.comprobante.emitido y de vale.factura.pedida se documentará en la referencia cuando el contrato se formalice.
Firma, reintentos y duplicados
Iguales a los del aviso del checkout; los ejemplos en cinco lenguajes están en Webhooks. Lo único que cambia es el secreto: cada suscripción firma con el suyo.
- Verifica
v1 = hex(HMAC-SHA256(secreto, t + "." + cuerpo))sobre el cuerpo crudo, en tiempo constante, y rechaza si|ahora − t| > 300 s. - Responde
2xxrápido. Si no, se reintenta a 1, 5, 25 y 125 minutos. - Deduplica por
X-Finora-Entrega. - Un error en tu sistema nunca deshace un cobro: los eventos se publican después de registrar el veredicto.