Guías
El cliente autoriza su tarjeta una vez. Después cobras desde tu servidor, sin él.
Las redes distinguen dos situaciones: el cliente está frente a la pantalla, o no está. Los nombres del contrato son initiator: "customer" y initiator: "merchant", y cada uno tiene reglas distintas. Confundirlos es la causa más común de rechazo en un cobro recurrente.
| Cliente presente | Cliente ausente | |
|---|---|---|
initiator | customer | merchant |
| CVV | Obligatorio | Prohibido — la API lo rechaza |
order_type | purchase y los de serie | Cualquiera menos purchase |
| Enlace al primer cobro | No aplica | Obligatorio en cobros de serie |
Una sesión de inscripción abre una pantalla donde el cliente entrega su tarjeta. No cobra nada: solo la deja autorizada para después.
/v1/enrollment/sessionsCrea la pantalla donde el cliente guarda su tarjeta.
Crear la inscripción
curl -X POST https://gxxazsplhgyezwxghrnn.supabase.co/functions/v1/blink-api/v1/enrollment/sessions \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"customer": { "email": "cliente@ejemplo.com" },
"success_url": "https://mitienda.com/tarjeta-guardada",
"expires_in": 3600
}'Respuesta 201
{
"id": "7d2b…",
"object": "enrollment.session",
"environment": "test",
"status": "pending",
"enrollment_url": "https://…"
}expires_in va entre 60 y 86400 segundos. Cuando el cliente termina, llega el evento instrument.enrolled y la tarjeta aparece en el listado de instrumentos.
Listar tarjetas guardadas
curl "https://gxxazsplhgyezwxghrnn.supabase.co/functions/v1/blink-api/v1/instruments" \
-H "Authorization: Bearer sk_test_…"Respuesta 200
{
"object": "list",
"data": [
{
"object": "payment.instrument",
"id": "c1a9f3e0-…",
"status": "active",
"customer": { "email": "cliente@ejemplo.com" },
"bin": "518617",
"last4": "4242",
"brand": "MASTERCARD",
"product": "CREDIT",
"supports_installments": true,
"enrolled_at": "2026-09-06T18:20:11.000Z"
}
]
}El primero de la serie lo inicia el cliente: está mirando la pantalla y escribe su CVV. Ese cobro es el que la red va a usar como referencia de todos los siguientes, así que guarda su identificador.
Primer cobro (CIT)
curl -X POST https://gxxazsplhgyezwxghrnn.supabase.co/functions/v1/blink-api/v1/payments \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"amount": 8900000,
"currency": "COP",
"instrument_id": "c1a9f3e0-…",
"initiator": "customer",
"cvv": "123",
"order_type": "recurring"
}'Un cobro de serie sin el cliente presente tiene que apuntar al primero. Manda parent_transaction_data con el first_payment_id que guardaste, o con los datos de red que devolvió aquel cobro. Sin eso la API responde 400, antes de intentar nada.
Cobro recurrente (MIT)
curl -X POST https://gxxazsplhgyezwxghrnn.supabase.co/functions/v1/blink-api/v1/payments \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{
"amount": 8900000,
"currency": "COP",
"instrument_id": "c1a9f3e0-…",
"initiator": "merchant",
"order_type": "recurring",
"parent_transaction_data": { "first_payment_id": "9b41d0c7-…" }
}'// El día 1 de cada mes, para cada suscripción activa.
async function cobrarMensualidad(sub) {
const res = await fetch("https://gxxazsplhgyezwxghrnn.supabase.co/functions/v1/blink-api/v1/payments", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LANE_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: sub.montoCentavos,
currency: "COP",
instrument_id: sub.instrumentId,
initiator: "merchant", // el cliente no está
order_type: "recurring",
parent_transaction_data: {
first_payment_id: sub.primerCobroId,
},
}),
});
const pago = await res.json();
if (!res.ok) throw new Error(pago.error);
return pago; // status: succeeded | failed | processing
}| `order_type` | Para qué | Quién lo inicia |
|---|---|---|
purchase | Una compra suelta. | Solo el cliente |
recurring | Mensualidad de monto fijo. | Ambos |
installment | Una compra dividida en pagos. | Ambos |
standing_order | Cobro periódico de monto variable. | Ambos |
unscheduled | Recarga automática, sin fecha fija. | Ambos |
deferred · delayed | Cobro que se hace después de la compra. | Ambos |
no_show · resubmission | Penalidad por no presentarse, reintento de un rechazo. | Solo el comercio |
Los cobros de serie —recurring, installment, standing_order, deferred, delayed— son los que exigen el enlace al primero. unscheduled, no_show y resubmission no.
Antes de un ciclo de cobros puedes preguntar si una tarjeta responde, sin cobrar nada: intent: "account-status" con amount: 0. Al tarjetahabiente no le aparece nada.
Verificación sin cobro
{
"amount": 0,
"instrument_id": "c1a9f3e0-…",
"intent": "account-status",
"initiator": "customer",
"cvv": "123"
}Una tarjeta reemitida deja de servir. Si al cliente le cambian la tarjeta por vencimiento o robo, el instrumento guardado queda muerto y no se actualiza solo. Cuando un cobro recurrente falle por eso, la salida es pedirle al cliente que vuelva a inscribir su tarjeta.
Esta página en markdown: /docs/guias/cobro-recurrente.md · Toda la documentación: /docs/llms-full.txt