https://sag-qa.efipay.co/api/v1
La versión va en la ruta. Hoy solo existe v1; cuando exista otra, v1 seguirá
respondiendo.
Dentro de una versión solo agregamos: campos nuevos en las respuestas, parámetros opcionales nuevos, valores nuevos en las enumeraciones. Nunca quitamos un campo ni cambiamos el significado de uno existente.
{warning} Por eso tu código no debe romperse si aparece un campo que no conocías, ni si una enumeración trae un valor nuevo. Ignora lo que no uses.
Content-Type: application/json.Accept: application/json. Sin él, un error de validación puede llegarte como
HTML en lugar de JSON.Authorization: Bearer. Ver
Autenticación.snake_case en lo que envías.La única excepción es crear una sucursal con
logo o RUT, que va como multipart/form-data porque lleva archivos.
{info} En las respuestas verás dos estilos:
snake_caseen la mayoría de los endpoints ycamelCaseen algunos de suscripciones. Cada página muestra el suyo; no lo adivines.
Los listados vienen paginados con el sobre estándar de Laravel:
{
"data": [ "..." ],
"links": {
"first": "https://sag-qa.efipay.co/api/v1/...?page=1",
"last": "https://sag-qa.efipay.co/api/v1/...?page=8",
"prev": null,
"next": "https://sag-qa.efipay.co/api/v1/...?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 8,
"per_page": 15,
"to": 15,
"total": 118
}
}
| Parámetro | Qué hace | Por defecto |
|---|---|---|
| page | Página a traer | 1 |
| per_page | Cuántos elementos por página | 15 en la mayoría de los endpoints |
{danger} Dos excepciones que muerden:
- Listar planes trae 2 por página. Si no envías
per_pageparecerá que tienes dos planes.- Reservas de cupo trae 25.
Para recorrer todo, sigue links.next hasta que sea null. No calcules las URLs a
mano.
| Contexto | Formato | Ejemplo |
|---|---|---|
| Filtros de fecha que envías | Y-m-d |
2026-07-31 |
| Vencimiento de tarjeta | Y-m |
2030-12 |
| Fecha tope de un plan | Y-m-d H:i:s |
2026-12-31 23:59:59 |
| Fechas que devolvemos | ISO 8601 en UTC | 2026-07-31T14:32:10.000000Z |
| Fechas en los webhooks | Hora de Colombia | 2026-07-31 09:32:10 |
{warning} La zona horaria de la operación es America/Bogotá (UTC−5). Un cobro de las 8 p.m. del 31 de julio en Colombia es
2026-08-01T01:00:00Zen UTC: si conviertes mal, te cambia de mes en la conciliación.
Los montos van como número decimal en la unidad principal de la moneda, no en
centavos: 120000 son ciento veinte mil pesos, y 1200.50 son mil doscientos pesos con
cincuenta centavos.
| Moneda | Código | Notas |
|---|---|---|
| Peso colombiano | COP |
La moneda de operación. Máximo 999.999.999.999 |
| Dólar | USD |
Se convierte a COP con la TRM del día. Máximo 200.000.000 |
| Euro | EUR |
Igual que USD |
En una transacción en moneda extranjera verás amount (moneda original), value_cop (el
equivalente en pesos) y currency_rate_conversion con la tasa aplicada. Concilia con
value_cop: es lo que efectivamente se movió.
{info} Las reservas de cupo solo operan en COP.
| Tipo | Aspecto | Dónde |
|---|---|---|
| UUID | 9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f |
Cobros, transacciones, planes, suscriptores, cupones, reservas |
| Consecutivo | 20481 |
transaction_id, el número que ve tu operador |
| Entero | 1 |
Sucursales |
Una transacción tiene los dos: id (UUID) y transaction_id (consecutivo). Los
endpoints de consulta aceptan cualquiera de los dos; guarda el que le vayas a mostrar a
una persona.
{warning} Los ids no se comparten entre ambientes. Un id de prueba da
404con token de producción, y al revés.
Las escrituras de suscripciones, pagos y reservas de cupo aceptan el header
Idempotency-Key. Si repites la misma llamada con la misma clave y los mismos
parámetros, te devolvemos la respuesta original con el header
Idempotency-Replayed: true, sin volver a ejecutar el cobro.
| Rutas que la aceptan | |
|---|---|
/api/v1/subscriptions/* |
Crear, cancelar, cambiar de plan, actualizar la tarjeta, pausar, reanudar |
/api/v1/payment/generate-payment |
Generar el cobro |
/api/v1/payment/transaction-checkout/* |
Checkout por API: tarjeta, efectivo, PSE, Bre-B |
/api/v1/payment/refund-transaction |
Devoluciones |
/api/v1/mit/pre-authorizations/* |
Crear, autorizar, cobrar y liberar reservas |
{info} Las consultas no la aceptan, aunque vayan por
POST:transaction-status,transaction/{id},all-transaction-statusy elsyncde una reserva. Ahí la clave no tendría sentido: se pide justamente el estado más reciente. Los pasos de 3DS tampoco, porque su resultado cambia entre llamadas.
curl -X POST \
'/api/v1/subscriptions/subscription' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-type: application/json' \
-H 'Idempotency-Key: 9b1f0e34-6b2a-4a7e-9d0a-uno-por-operacion' \
-d '{ "...": "..." }'
409.409.5xx no se memorizan, para que puedas reintentar un fallo transitorio.Detalle en Suscripciones.
No publicamos hoy un límite de peticiones por minuto. Lo que sí existe es un candado de concurrencia por cobro: no se procesan dos pagos del mismo cobro a la vez.
| Situación | Respuesta | Ventana |
|---|---|---|
| Otro pago del mismo cobro en curso (tarjeta, PSE, Bre-B) | 429 |
10 segundos |
| Otro pago en efectivo del mismo cobro en curso | 429 |
5 segundos |
Otra operación con la misma Idempotency-Key en curso |
409 |
Hasta que la primera termine |
{warning} Un
429no significa que hayas excedido una cuota: significa que esa misma operación ya se está procesando. Espera el resultado y consúltalo; no la reenvíes.
| Operación | Espera razonable | Nuestro tope contra la red |
|---|---|---|
| Catálogos y consultas | Menos de 1 s | — |
| Pago con tarjeta (sin 3DS) | 3 a 10 s | 45 s |
| Pago con tarjeta (con 3DS) | Depende del banco y del cliente | 45 s por llamada |
| Reserva de cupo | 3 a 10 s | 45 s |
Pon en tu cliente un timeout mayor a 45 segundos para las operaciones de cobro. Si cortas antes, no cancelas nada: la operación sigue su curso en la red y te quedas sin saber cómo terminó.
| Respuesta | ¿Reintentar? |
|---|---|
5xx, error.retryable: true |
Sí, con espera creciente |
error.retryable: false (fondos, tarjeta vencida, fraude) |
No. El resultado será el mismo |
202, T01, o un timeout de tu lado |
No a ciegas. Estado indeterminado: consulta primero |
409 de idempotencia |
No: ya hay una operación con esa clave |
422 de validación |
Solo después de corregir la petición |
{danger} La regla que evita cobros dobles: ante la duda, consulta antes de reenviar. Con estado de transacción o con la misma
Idempotency-Key, que te devuelve la respuesta original en vez de cobrar de nuevo.
491617******1313.api y el token de una tarjeta
se devuelven una sola vez, al crearse. De ahí en adelante solo guardamos su hash.{danger} Si necesitas volver a mostrar «con qué tarjeta pagó», usa el BIN y los últimos cuatro dígitos que ya te devolvemos. No hay forma de recuperar el número completo, y eso es deliberado.