Índice de la documentación

Pagos Recurrentes

Cobra a tus clientes de forma periodica (mensual, semanal, cada N dias, anual, un dia concreto de cada mes, con o sin fecha de fin) y gestiona todo el ciclo de vida desde tu sistema: alta, consulta, cambios, pausa, reactivacion, cambio de tarjeta y cancelacion.

Nombre tecnico: en la API cada pago recurrente es un recurso subscription (rutas /subscriptions, ids WEBCODE-SB-xxxxxxxx). En el panel aparecen en Transacciones > Pagos Recurrentes.

LiveTest
URL base/external/v1/subscriptions/external/v1/test/subscriptions
API keyKey LiveKey Test
Pago inicialPagina segura real (/pay/...)Pagina simulada (/pay-subscription-test/...)
Cobros recurrentesReales, en su fechaSimulados (en su fecha o al momento con simulate-renewal)
WebhooksURL LiveURL Test (con environment: "test")
Visible en el panelSi (Pagos Recurrentes)No

Reglas generales

  • webcode obligatorio: en el body en POST/PATCH y en la query en GET. Debe coincidir con el de tu API key.
  • Solo veras y modificaras los pagos recurrentes de tu webcode y de ese entorno. Cualquier recurso ajeno o del otro entorno responde 404.
  • Importes siempre en centimos (2990 = 29,90 EUR). Monedas: EUR, USD, GBP.
  • Idempotency-Key recomendada en todos los POST y PATCH (ver Autenticacion).

Flujo

ClienteAvirato PaymentsTu sistemaCada periodo cobra automaticamentePOST /subscriptions201 { linkId, paymentUrl }Redirige a paymentUrlPaga el primer importe (se guarda la tarjeta)Redirige a returnUrlWebhook SUBSCRIPTION_CREATED { subscriptionId }Webhook SUBSCRIPTION_RENEWED / SUBSCRIPTION_FAILED
  1. POST /subscriptions crea un link de pago recurrente y devuelve paymentUrl.
  2. Rediriges a tu cliente a paymentUrl. Paga el primer importe y se guarda su tarjeta.
  3. Se crea el pago recurrente (subscriptionId) y recibes SUBSCRIPTION_CREATED. Tambien puedes consultarlo en GET /subscriptions/links/{linkId} (campo subscriptionId).
  4. Avirato cobra cada periodo. Si un cobro falla se reintenta 3 veces (5 h, 8 h y 11 h despues); si sigue fallando el pago recurrente queda pausado (SUBSCRIPTION_ERROR).

Si el primer pago se rechaza

Se crea igualmente el pago recurrente en estado error (statusReason: initial_payment_failed) y recibes SUBSCRIPTION_FAILED. El link sigue pending y tu cliente puede reintentar con el mismo paymentUrl: cada intento crea un pago recurrente nuevo. El anterior queda en error, nunca se cobra y puedes ignorarlo. El valido es el del webhook SUBSCRIPTION_CREATED, que es tambien el que devuelve el detalle del link. El motivo del rechazo esta en refusalReason de GET /subscriptions/{id}/payments. Igual en Live y en Test.

Intervalos

QuieresintervalUnitintervalCountExtra
Mensualmonth1—
Cada 15 diasday15—
Cada 2 semanasweek2—
Trimestralmonth3—
Anualyear1—
El dia 5 de cada mesmonth1billingDay: 5
Mensual hasta el 31/12/2027month1endAt: "2027-12-31"
  • intervalCount minimo 1.
  • billingDay (1-31) solo con month. En meses mas cortos se cobra el ultimo dia del mes.
  • endAt futura (Y-m-d o Y-m-d H:i:s): el dia de fin ya no se cobra; esa noche el pago recurrente se cancela (statusReason: end_date_reached).
  • initialAmount: primer pago distinto al recurrente (puede ser 0 para solo guardar la tarjeta).

Crear un pago recurrente

POST /external/v1/subscriptions → 201

json
{
  "webcode": "SHOP01",
  "amount": { "value": 2990, "currency": "EUR" },
  "intervalUnit": "month",
  "intervalCount": 1,
  "billingDay": 5,
  "endAt": "2027-06-30",
  "initialAmount": { "value": 990 },
  "returnUrl": "https://tu-web.com/pago-recurrente/ok",
  "description": "Plan Gold",
  "customReference": "PEDIDO-123",
  "planCode": "GOLD",
  "customerInternalId": "CLI-42",
  "customerInternalFolder": "EXP-2026-7",
  "customerExtraInfo": "Juan Perez",
  "metadata": { "contrato": "C-99" },
  "expiresAt": "2026-11-30 23:59:59",
  "countryCode": "ES",
  "shopperLocale": "es-ES"
}

Obligatorios: webcode, amount, intervalUnit, intervalCount, returnUrl (http/https). description maximo 255 caracteres; metadata debe ser un objeto JSON.

json
{
  "success": true,
  "data": {
    "linkId": "SHOP01-LK-1792068995050",
    "environment": "live",
    "status": "pending",
    "paymentUrl": "https://aviratopayments.com/pay/eyJ0eXAi...",
    "subscriptionId": null,
    "amount": { "value": 2990, "currency": "EUR" },
    "initialAmount": { "value": 990, "currency": "EUR" },
    "intervalUnit": "month",
    "intervalCount": 1,
    "billingDay": 5,
    "endAt": "2027-06-30 23:59:59",
    "planCode": "GOLD",
    "returnUrl": "https://tu-web.com/pago-recurrente/ok",
    "expiresAt": "2026-11-30 23:59:59",
    "createdAt": "2026-10-15 14:56:35"
  }
}

Al terminar el pago el cliente vuelve a returnUrl con ?linkId=...&subscriptionId=...&status=success|refused|error. No te fies solo del redirect: confirma con el webhook o consultando el link.

Endpoints

Consultas

MetodoRutaDescripcion
GET/subscriptions?webcode=Listado. Filtros: status, plan_code, customer_internal_id, customer_internal_folder, created_at_start, created_at_end. Paginacion: take (1-100, def. 20), cursor, order
GET/subscriptions/{id}?webcode=Detalle. Incluye paymentRetryInfo si hay reintentos en curso y failedPaymentInfo si se pauso por cobro fallido
GET/subscriptions/{id}/payments?webcode=Historial de pagos (inicial, cambios de tarjeta y recurrentes) con refusalReason si fallaron
GET/subscriptions/{id}/charges?webcode=&status=Cola de cobros: pendientes, realizados, fallidos, reintentos
GET/subscriptions/links?webcode=&status=Links de pago recurrente (pending, redeemed, expired, cancelled)
GET/subscriptions/links/{linkId}?webcode=Detalle del link (tras el pago incluye subscriptionId)

Ciclo de vida (body siempre con webcode)

MetodoRutaBodyReglas
PATCH/subscriptions/{id}amount, intervalUnit, intervalCount, billingDay, endAt (null = sin fin), nextChargeDate, planCode, customerExtraInfo, customerInternalId, customerInternalFolder, autoRenew, metadataNo se puede modificar uno cancelado. Al cambiar importe o fechas se ajusta el siguiente cobro y la baja programada
POST/subscriptions/{id}/pause—Solo activos. Anula el cobro pendiente
POST/subscriptions/{id}/reactivatechargeImmediately (bool, def. true)Desde paused o error. Uno cancelado no se reactiva
POST/subscriptions/{id}/update-cardreturnUrl, countryCode? (def. ES), shopperLocale? (def. es-ES)Desde paused, error o pendingNewCard. Devuelve paymentUrl para que el cliente pague con su nueva tarjeta; al pagar se reactiva
POST/subscriptions/{id}/cancelreason? (a-z, 0-9 y _; def. cancelled_by_client)Definitivo: anula cobros pendientes y no se puede reactivar
POST/subscriptions/links/{linkId}/cancel—Solo links no pagados

Estados y acciones permitidas

EstadoSignificadoPuedes
activeCobrando con normalidadModificar, pausar, cancelar
pausedPausado por ti (paused_by_client) o tras agotar los reintentos (payment_failed_max_retries)Reactivar (tarjeta actual), cambiar tarjeta, modificar, cancelar
errorFallo el primer pago o el pago con la nueva tarjetaReactivar, cambiar tarjeta, cancelar
pendingNewCardEsperando a que el cliente pague con su nueva tarjetaGenerar otro link (update-card), cancelar
cancelledCancelado por ti o fin por endAt (end_date_reached)Nada (definitivo)

Entorno Test

Todo funciona igual que en Live pero sin dinero real. Los pagos recurrentes de test no aparecen en el panel; consultalos con la API.

Pago inicial: abre paymentUrl (/pay-subscription-test/...) y usa cualquier tarjeta valida (p. ej. 4111 1111 1111 1111, fecha futura en formato MM/AA, CVC 737). El titular decide el resultado:

TitularResultado
Cualquier nombrePago correcto
DECLINED, CARD_EXPIRED, NOT_ENOUGH_BALANCE, CVC_DECLINED, FRAUD, INVALID_CARDRechazado
ERRORError del procesador

Simuladores (solo /external/v1/test/...), body { "webcode", "result" } con result: success (def.), declined, not_enough_balance, card_expired, error:

MetodoRutaQue hace
POST/test/subscriptions/links/{linkId}/simulate-checkoutCompleta el pago inicial (o el de cambio de tarjeta) sin abrir la pagina
POST/test/subscriptions/{id}/simulate-renewalEjecuta ya el siguiente cobro con ese resultado (reintentos, pausa tras 3 fallos, siguiente ciclo y webhooks como en Live)
POST/test/subscriptions/{id}/simulate-endDa de baja el pago recurrente como si hubiera llegado su endAt

Webhooks

Eventos SUBSCRIPTION_CREATED, SUBSCRIPTION_RENEWED, SUBSCRIPTION_FAILED, SUBSCRIPTION_ERROR, SUBSCRIPTION_PAUSED, SUBSCRIPTION_REACTIVATED, SUBSCRIPTION_CANCELLED y SUBSCRIPTION_CARD_UPDATED. Formato y ejemplos en Webhooks.

Errores habituales

Ver Errores > Pagos recurrentes. Resumen: 400 validacion o accion no permitida en el estado actual, 403 key/webcode/entorno, 404 no existe para tu webcode y entorno, 409 Idempotency-Key reutilizada.