External API

Documentación para desarrolladores

Integra pagos online y POS, consulta operaciones y recibe webhooks con la API externa de Avirato Payments.

Webhooks

Los webhooks son notificaciones HTTP POST que Avirato Payments envia automaticamente a tu sistema cuando ocurre un evento relevante: un pago se completa, un reembolso se procesa, una captura se confirma, etc.

Por que son importantes

Los webhooks son la forma mas fiable de saber que una operacion se ha completado. A diferencia del redirect (urlOk/urlKo), que depende de que el cliente vuelva a tu pagina:

  • Los webhooks llegan siempre, incluso si el cliente cierra el navegador
  • Llegan unos segundos despues de que el procesador confirme la operacion
  • No dependen del comportamiento del usuario

Recomendacion: Usa los webhooks como fuente principal de confirmacion de operaciones. Usa el redirect y el polling como complementos.

Como configurar tu URL de webhooks

Desde Integraciones > Configuracion Webhooks en el dashboard puedes registrar una URL publica por entorno (Live y Test). Cada URL se puede activar/desactivar por separado. Recomendamos:

  • URL HTTPS con certificado valido.
  • Endpoint dedicado a Avirato Payments (por ejemplo https://tu-dominio.com/avirato-payments/webhooks).
  • Necesitas tener una API key activa para el entorno antes de configurar su URL. Si no existe, el dashboard responde con 422.

Importante: solo se envian los webhooks generados a partir del momento en que la URL este configurada y activa. Eventos previos no se reenvian retroactivamente.

Verificacion de autenticidad (firma HMAC)

Todos los webhooks live llegan firmados con HMAC-SHA256 usando el mismo client_secret que se te muestra al crear (o rotar) la API key del entorno. Cabeceras:

CabeceraValor
X-Avirato-TimestampTimestamp Unix (segundos) del momento del envio
X-Avirato-Signaturet={timestamp},v1={hmac} — donde hmac = hash_hmac('sha256', timestamp + "." + body, client_secret)

Ejemplo de verificacion en PHP:

$timestamp = $_SERVER['HTTP_X_AVIRATO_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_AVIRATO_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');

if (!preg_match('/^t=(\d+),v1=([a-f0-9]+)$/', $signature, $m)) {
    http_response_code(400);
    exit;
}

$expected = hash_hmac('sha256', $timestamp . '.' . $body, $clientSecret);
if (!hash_equals($expected, $m[2])) {
    http_response_code(401);
    exit;
}

En Test, si tienes API key test creada, los webhooks de prueba se firman tambien con su secret. Si no, se envian sin firma para que puedas explorar el formato sin crear API key test todavia.

Politica de reintentos

Como funciona en una linea

Cada vez que Avirato Payments te envia un webhook y tu endpoint no responde con HTTP 200, lo reintenta mas tarde. La espera entre cada fallo y el siguiente reintento crece: empieza en 10 minutos y termina en 48 horas. Tras un total de 10 intentos sin exito Avirato Payments deja de reintentarlo automaticamente.

Cronograma completo

La tabla muestra, para un webhook que falla en cada intento, el momento exacto en el que tu endpoint recibe la siguiente llamada, contado desde el momento en el que se produjo el evento original (autorizacion, refund, etc.).

IntentoQue esCuando lo recibes (contado desde el evento)
1Envio inicialen el momento (≈ 0)
21.er reintento10 min despues
32.º reintento30 min despues
43.er reintento1 h 10 min despues
54.º reintento2 h 40 min despues
65.º reintento5 h 40 min despues
76.º reintento11 h 40 min despues
87.º reintento23 h 40 min despues
98.º reintento1 dia 23 h 40 min despues
109.º (y ultimo) reintento≈ 4 dias despues (95 h 40 min)
a partir de aqui ya no se reintenta

En total son 10 intentos (1 envio inicial + 9 reintentos) repartidos en una ventana de unos 4 dias. El reloj NO se reinicia en cada intento: cuanto mas tarde respondes correctamente, mas se han espaciado los siguientes reintentos.

Como saber en que intento vamos

En el dashboard, en Integraciones > Live > Webhooks, cada fila del historial muestra:

  • Intentos: numero de intentos consumidos hasta ahora (1 al 10).
  • Ultimo intento: la fecha y hora del ultimo envio.
  • HTTP: el codigo HTTP que devolvio tu endpoint en ese ultimo envio.
  • Estado: Entregado (success), Pendiente (todavia con reintentos por delante) o Fallido (no aplicable en el flujo live mientras queden reintentos).

Que pasa si el endpoint sigue cayendo

Si tras los 10 intentos (≈ 4 dias) tu endpoint no ha respondido correctamente NI UNA sola vez, Avirato Payments deja de reintentarlo automaticamente aunque mas tarde repares tu sistema. En ese caso:

  1. Reactiva tu endpoint y verifica que ya responde correctamente con webhooks normales.
  2. Para los eventos que quedaron pendientes, abre Integraciones > Live > Webhooks, identifica los webhooks con estado Pendiente y fuerza el reenvio manual desde el boton "Reenviar". Cada reenvio manual hace una llamada HTTP nueva a tu endpoint con el mismo payload.

Que pasa si desactivas o eliminas tu URL temporalmente

  • Mientras tu URL este desactivada (o no exista) Avirato Payments sigue encolando los webhooks de los eventos que se vayan produciendo.
  • El cron sigue contando reintentos: si reactivas la URL dentro de la ventana de ≈ 4 dias, los pendientes se entregaran automaticamente en el siguiente tick (siempre que aun queden intentos disponibles para ese webhook concreto).
  • Pasada esa ventana, los eventos quedan abandonados y NO se vuelven a enviar aunque vuelvas a activar la URL. Tendras que solicitarlos manualmente desde el dashboard si te interesan.

Comportamiento del reenvio manual

  • Si reenvias manualmente un webhook que estaba pendiente de reintentos y el reenvio tiene exito, los reintentos automaticos se detienen — el webhook ya se considera entregado.
  • Puedes reenviar un webhook que ya fue entregado correctamente. El dashboard te pedira confirmacion antes para evitar duplicados accidentales, pero el reenvio se ejecuta igualmente si lo confirmas.

Fuente de verdad del estado del pago (Live)

En el entorno Live, las notificaciones del procesador tienen la ultima palabra sobre el estado real del pago. Esto significa que un pago puede cambiar de estado despues de que tu sistema lo haya tratado como completado.

Casos tipicos en los que puede llegar un webhook posterior que revierte un exito previo:

  • Chargeback: el titular reclama el cargo a su banco
  • Fraude detectado a posteriori: el procesador identifica una transaccion fraudulenta dias despues
  • Reversion bancaria: el banco emisor revierte la operacion
  • Correccion del procesador: una notificacion previa contenia datos incompletos o incorrectos

Cuando recibimos uno de estos eventos en Live, actualizamos el estado del pago en nuestro sistema (por ejemplo, de AUTHORISED a FAILED) y te enviamos el webhook correspondiente. Tu integracion debe:

  • Aceptar webhooks asincronos que cambien el resultado de un pago previamente exitoso
  • Tratar los webhooks (no la respuesta inmediata ni el redirect) como la referencia para la conciliacion y el estado final
  • Volver a consultar la API (GET /payment/session/{sessionId}) cuando necesites el ultimo estado conocido

Test vs Live: en Test los webhooks los genera nuestro propio simulador y reflejan unicamente la simulacion que has lanzado. No hay chargebacks ni reverts en Test.

Formato general

Todos los webhooks llegan como POST a tu URL con este formato:

Cabeceras

CabeceraValor
Content-Typeapplication/json
webcodeEl webcode asociado al pago (ej: SHOP01)

Body

{
  "event_code": "AUTHORISATION",
  "data": {
    ...campos especificos del evento...
  }
}

Respuesta esperada

Tu endpoint debe responder con HTTP 200. El body de la respuesta no se evalua — basta con el codigo de estado.

Si tu endpoint no responde con HTTP 200, el webhook se reintentara automaticamente con backoff exponencial.

---

Tipos de evento

AUTHORISATION — Pago completado (online o POS)

Se envia cuando un pago (online o POS) se autoriza correctamente o falla.

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 15000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "paymentStatus": "AUTHORISED",
    "description": "Pedido #12345 - Servicio premium",
    "customReference": "ORD-2026-12345",
    "paymentSource": "external_api"
  }
}
CampoSiempre presenteDescripcion
amountSiImporte en centimos
currencySiCodigo ISO 4217
paymentReferenceSiReferencia del pago
paymentStatusSiAUTHORISED si exitoso, FAILED si fallo
descriptionSiDescripcion del pago
customReferenceNoTu referencia interna (si la proporcionaste al crear la sesion/pago)
paymentSourceNoOrigen del pago (ej: external_api)
failedReasonNoMotivo del fallo (solo si el pago fallo)

Como identificar el tipo de pago por la referencia:

Infijo en la referenciaTipoEntorno
-PXT-Pago onlineLive
-PXTT-Pago onlineTest
-POSX-Pago POSLive
-POSXT-Pago POSTest

Ejemplo de pago POS exitoso:

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 8500,
    "currency": "EUR",
    "paymentReference": "SHOP01-POSX-17195300001234",
    "paymentStatus": "AUTHORISED",
    "description": "Venta mostrador #205",
    "customReference": "VENTA-205-20260628",
    "paymentSource": "external_api"
  }
}

Ejemplo de pago fallido (rechazado):

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 15000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "paymentStatus": "FAILED",
    "description": "Pedido #12345",
    "failedReason": "Refused",
    "paymentSource": "external_api"
  }
}

Importante: Los webhooks se envian tanto para pagos exitosos como fallidos. Comprueba siempre el campo paymentStatus para determinar el resultado.

---

REFUND — Reembolso procesado

Se envia cuando un reembolso se completa (exito o fallo) por el procesador.

{
  "event_code": "REFUND",
  "data": {
    "amount": 5000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "refundReason": "CUSTOMER REQUEST",
    "refundReference": "SHOP01-RFX-17195234567890",
    "status": "success",
    "customReference": "ORD-2026-12345",
    "paymentSource": "external_api"
  }
}
CampoSiempre presenteDescripcion
amountSiImporte reembolsado en centimos
currencySiCodigo ISO 4217
paymentReferenceSiReferencia del pago original
refundReasonSiMotivo del reembolso (CUSTOMER REQUEST, FRAUD, RETURN, DUPLICATE, OTHER)
refundReferenceSiReferencia de esta operacion de reembolso
statusSisuccess o failed
customReferenceNoTu referencia interna
paymentSourceNoOrigen del pago
failedReasonNoMotivo del fallo (solo si status: "failed")

Ejemplo de reembolso fallido:

{
  "event_code": "REFUND",
  "data": {
    "amount": 5000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "refundReason": "CUSTOMER REQUEST",
    "refundReference": "SHOP01-RFX-17195234567890",
    "status": "failed",
    "failedReason": "Insufficient balance"
  }
}

---

PREAUTHORISATION — Resultado de captura, cancelacion o extension

Se envia cuando una operacion sobre una preautorizacion se completa. El campo action indica el tipo de operacion.

Captura completada

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "capture",
    "result": "success",
    "amount": 45000,
    "currency": "EUR",
    "customReference": "ORD-2026-67890",
    "paymentSource": "external_api"
  }
}

Cancelacion completada

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "cancellation",
    "result": "success",
    "customReference": "ORD-2026-67890",
    "paymentSource": "external_api"
  }
}

Extension completada

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "extend",
    "result": "success",
    "expirationDate": "2026-08-15T00:00:00Z",
    "customReference": "ORD-2026-67890",
    "paymentSource": "external_api"
  }
}
CampoSiempre presenteDescripcion
paymentReferenceSiReferencia del pago preautorizado
actionSicapture, cancellation o extend
resultSisuccess o failure
amountSolo captureImporte capturado en centimos
currencySolo captureCodigo ISO 4217
expirationDateSolo extend exitosoNueva fecha de expiracion
customReferenceNoTu referencia interna
paymentSourceNoOrigen del pago
failedReasonNoMotivo del fallo (solo si result: "failure")

Ejemplo de captura fallida (importe excede el autorizado):

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "capture",
    "result": "failure",
    "failedReason": "Payment already captured, cannot capture again"
  }
}

Nota sobre el flujo de modificaciones: Todas las modificaciones (reembolso, captura, cancelacion, extension) son asincronas. La respuesta inmediata de la API devuelve estado received, indicando que la peticion se ha aceptado para procesamiento. El resultado final (success o failed) llega posteriormente via webhook. El integrador no debe considerar la operacion como completada hasta recibir el webhook de confirmacion.

---

CHARGEBACK — Contracargo

Se envia cuando un titular de tarjeta inicia un contracargo contra un pago. Los contracargos son procesados por el emisor de la tarjeta y pueden tardar dias o semanas en resolverse.

{
  "event_code": "CHARGEBACK",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "chargebackReference": "SHOP01-CHB-17195123456789",
    "action": "chargeback",
    "result": "success",
    "amount": 15000,
    "currency": "EUR",
    "reason": "Fraudulent transaction",
    "chargebackReasonCode": "10.4",
    "chargebackSchemeCode": "VISA_10_4",
    "defensePeriodEndsAt": "2026-06-15",
    "defendable": true,
    "disputeStatus": "Undefended",
    "paymentSource": "external_api"
  }
}
CampoSiempre presenteDescripcion
paymentReferenceSiReferencia del pago original
chargebackReferenceSiReferencia unica del contracargo
actionSiSiempre chargeback
resultSisuccess o failure
amountSiImporte en centimos
currencySiMoneda ISO 4217
reasonSiMotivo del contracargo
chargebackReasonCodeNoCodigo de motivo del esquema de tarjeta
chargebackSchemeCodeNoCodigo del esquema (Visa, Mastercard, etc.)
defensePeriodEndsAtNoFecha limite para defender el contracargo
defendableNotrue si puedes disputar el contracargo
disputeStatusNoEstado de la disputa (Undefended, Defended, etc.)
failedReasonNoMotivo si result es failure
paymentSourceNoOrigen del pago (external_api, etc.)

---

NOTIFICATION_OF_CHARGEBACK — Aviso previo de contracargo

Aviso anticipado de que un contracargo puede estar en camino. No todos los procesadores lo envian. Te permite prepararte antes de que el contracargo formal se procese.

{
  "event_code": "NOTIFICATION_OF_CHARGEBACK",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "chargebackReference": "SHOP01-CHB-17195123456789",
    "action": "notification_of_chargeback",
    "result": "success",
    "amount": 15000,
    "currency": "EUR",
    "reason": "Cardholder disputes transaction",
    "chargebackReasonCode": "10.4",
    "chargebackSchemeCode": "VISA_10_4",
    "defensePeriodEndsAt": "2026-06-15",
    "defendable": true,
    "disputeStatus": "Undefended",
    "autoDefended": false,
    "arn": "74027600000012345678901",
    "paymentSource": "external_api"
  }
}

Contiene los mismos campos que CHARGEBACK mas dos campos adicionales opcionales:

CampoDescripcion
autoDefendedtrue si el procesador defendio automaticamente el contracargo
arnAcquirer Reference Number — identificador de la transaccion del adquirente

---

Webhooks en entorno Test

En el entorno Test, los webhooks no provienen del procesador de pagos real. Son generados automaticamente por el backend de Avirato Payments inmediatamente despues de completar la operacion simulada.

Diferencias con Live

AspectoLiveTest
Quien enviaEl procesador de pagosEl backend de Avirato Payments
Cuando llegaSegundos a minutos despues de la operacion1-3 segundos despues de la respuesta HTTP
FormatoIdenticoIdentico
CamposIdenticosIdenticos
Reintentos automaticosSi (backoff exponencial, hasta ~4 dias)No: el simulador hace un unico envio
Reenvio manualSi, desde el dashboardSi, desde el dashboard (mismo boton)
Criterio de exito HTTPHTTP 200HTTP 200

Lo que debes saber

  • El formato es exactamente el mismo: Puedes desarrollar tu logica de procesamiento de webhooks en Test y funcionara en Live sin cambios
  • Llegan para pagos exitosos Y fallidos: Tanto en Live como en Test, recibiras webhooks cuando un pago se rechaza o una operacion falla
  • URLs independientes por entorno: Los webhooks de Test se envian a la URL configurada para el entorno Test, y los de Live a la URL de Live. Configura ambas desde el panel de webhooks del dashboard
  • Las referencias usan sufijos Test: Las paymentReference y operationReference contendran los infijos de test (-PXTT-, -POSXT-, -RFXT-, etc.)
  • Criterio de exito simple: Tanto en Live como en Test, basta con que tu endpoint responda HTTP 200 para que el webhook se marque como entregado. Cualquier otro codigo de estado se considera fallo y activara los reintentos (en Live) o quedara como fallido en el dashboard (en Test).
  • Reenvio manual disponible en Test y Live: Desde el panel de webhooks del dashboard puedes reenviar manualmente un webhook concreto. Tanto en Test como en Live, el reenvio utiliza la URL actualmente configurada para ese entorno, no la URL que se uso en el envio original. Si reenvias un webhook ya entregado, el dashboard te pedira confirmacion explicita para evitar duplicados accidentales.

Ejemplo de webhook de test (pago online exitoso)

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 15000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXTT-17195000005678",
    "paymentStatus": "AUTHORISED",
    "description": "Pedido test #12345",
    "customReference": "TEST-ORD-12345",
    "paymentSource": "external_api"
  }
}

Ejemplo de webhook de test (POS rechazado)

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 10077,
    "currency": "EUR",
    "paymentReference": "SHOP01-POSXT-17195300001234",
    "paymentStatus": "FAILED",
    "description": "Venta test #100",
    "failedReason": "Refused",
    "paymentSource": "external_api"
  }
}

---

Referencia rapida

Operacionevent_codeaction (si aplica)Como identificar External API
Pago online completadoAUTHORISATIONpaymentReference contiene -PXT- (Live) o -PXTT- (Test)
Pago POS completadoAUTHORISATIONpaymentReference contiene -POSX- (Live) o -POSXT- (Test)
Reembolso procesadoREFUNDrefundReference contiene -RFX- (Live) o -RFXT- (Test)
Captura procesadaPREAUTHORISATIONcaptureOperacion sobre pago External API
Cancelacion procesadaPREAUTHORISATIONcancellationOperacion sobre pago External API
Extension procesadaPREAUTHORISATIONextendOperacion sobre pago External API
Contracargo recibidoCHARGEBACKContracargo iniciado por el titular de la tarjeta
Notificacion de contracargoNOTIFICATION_OF_CHARGEBACKAviso previo de un posible contracargo

---

Buenas practicas

Idempotencia en tu endpoint

Tu endpoint de webhook puede recibir la misma notificacion mas de una vez (por reintentos o duplicados del procesador). Asegurate de que procesar el mismo webhook dos veces no cause problemas: usa paymentReference o refundReference como clave de deduplicacion.

Respuesta rapida

Responde al webhook lo antes posible (idealmente en menos de 5 segundos). Si necesitas hacer procesamiento pesado, encola el trabajo y responde inmediatamente con HTTP 200.

No dependas de un solo canal

Usa los webhooks como canal principal, pero implementa tambien:

  1. Verificacion post-redirect: Cuando el cliente vuelva a urlOk, consulta GET /payment/session/{id} para confirmar
  2. Polling de seguridad: Un proceso periodico que consulte sesiones en estado pending antiguas para detectar pagos completados que no hayas procesado