# Enlaces de pago

Un enlace de pago es un cobro con su propia dirección (`https://pay.pagaconquickpay.com/l/…`). Tu cliente lo abre, elige su banco y autoriza con la clave de 8 dígitos que le manda su banco (por SMS, notificación o correo). La página la aloja QuickPay: tú no manejas datos bancarios.

Sirve para cobrar por WhatsApp, correo, SMS o QR: creas el enlace, lo envías y te enteras cuando lo pagan.

## 1. Crear un enlace

```http
POST https://pay.pagaconquickpay.com/switch/v1/links
x-switch-key: tu-comercio:sk_test_…
Content-Type: application/json

{
  "monto": 450.00,
  "concepto": "Servicio de consultoría",
  "expira_horas": 72,
  "success_url": "https://tu-dominio.com/gracias?pedido=100",
  "metadata": { "cliente_id": "CLI-001", "factura": "FAC-2026-100" },
  "idempotency_key": "factura-FAC-2026-100"
}
```

Respuesta `201`:

```json
{
  "id": "3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40",
  "url": "https://pay.pagaconquickpay.com/l/3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40",
  "wa_deeplink": null,
  "qr_png": null,
  "monto": 450,
  "moneda": "VES",
  "concepto": "Servicio de consultoría",
  "estado": "pendiente",
  "expires_at": "2026-10-11T14:00:00.000Z",
  "success_url": "https://tu-dominio.com/gracias?pedido=100",
  "failure_url": null,
  "metadata": { "cliente_id": "CLI-001", "factura": "FAC-2026-100" },
  "mode": "test"
}
```

Guarda el `id` junto a tu pedido: con él consultas el cobro y reconoces su webhook. Para mandarle el cobro a tu cliente usa `url`.

### Campos que puedes enviar

| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
| `monto` | número | Sí | Mayor que cero, en bolívares. |
| `concepto` | texto | Sí | Lo que ve tu cliente al pagar. Hasta 140 caracteres. |
| `moneda` | texto | No | `VES` (la única hoy). |
| `expira_horas` | número entero | No | De 1 a 720 (30 días). Por omisión, 24. |
| `expira_en` | fecha ISO 8601 | No | Vencimiento exacto; si lo envías, manda sobre `expira_horas`. Tiene que ser futuro. |
| `success_url` | texto | No | A dónde vuelve tu cliente al pagar. Empieza con `https://`, hasta 400 caracteres. → [Volver a tu web](/developers/volver-a-tu-web) |
| `failure_url` | texto | No | A dónde vuelve tu cliente si el pago no puede continuar. Empieza con `https://`, hasta 400 caracteres. → [Volver a tu web](/developers/volver-a-tu-web) |
| `metadata` | objeto | No | Tus datos: hasta 20 claves (nombre ≤ 40, valor ≤ 200 caracteres). Te los devuelve la respuesta de crear; **no viajan en el webhook**, así que guarda la relación `id` ↔ pedido en tu sistema. |
| `idempotency_key` | texto | No | Hasta 64 caracteres. Ver abajo. |

> Si el banco rechaza, tu cliente **no** sale de la página de pago: puede intentarlo otra vez con una clave nueva. Sólo vuelve a tu `failure_url` si el cobro ya no se puede pagar (venció o lo cancelaste) o si él elige **Cancelar y volver**.

## 2. No duplicar cobros: `idempotency_key`

Va **en el cuerpo** de la petición. Si repites la creación con la misma `idempotency_key` (por ejemplo, porque se cortó la red y no sabes si llegó), recibes el **mismo** enlace en vez de uno nuevo:

- Primera vez: `201` y el enlace nuevo.
- Repetición: `200`, el mismo enlace y `"idempotent_replay": true`.

La llave vale **dentro del modo**: la misma `idempotency_key` con tu llave de prueba y con la de producción son dos enlaces distintos (uno `test` y otro `live`); nunca recibes con `sk_live_` un enlace creado con `sk_test_`. Si recibes `409` con `"error": "idempotency_key_en_uso"`, esa llave ya la usaste en el otro modo: usa otra.

Usa algo que identifique tu pedido (`factura-FAC-2026-100`), no un valor al azar por intento.

## 3. Compartir el enlace

Mándale `url` a tu cliente. En WhatsApp, lo mejor es un mensaje con botón (`cta_url` en la API de WhatsApp Cloud): abre la página de pago con un toque.

```json
{
  "messaging_product": "whatsapp",
  "to": "584141234567",
  "type": "interactive",
  "interactive": {
    "type": "cta_url",
    "body": { "text": "Tienes un pago de Bs 450 pendiente. Puedes pagarlo desde cualquier banco." },
    "action": {
      "name": "cta_url",
      "parameters": { "display_text": "Pagar ahora", "url": "https://pay.pagaconquickpay.com/l/3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40" }
    }
  }
}
```

El mensaje sale de **tu** número de WhatsApp, y su costo en Meta es tuyo.

## 4. Lo que hace tu cliente

1. Abre el enlace. Ve tu nombre, el concepto y el monto.
2. Elige su banco y escribe el teléfono y la cédula afiliados a ese banco. Si quiere, escribe su nombre.
3. Escribe la clave de 8 dígitos que le manda su banco.
4. Mientras el banco confirma, la página muestra **Procesando tu pago** y no deja reenviar el pago. Si tu cliente intenta salir o recargar, el navegador le pregunta antes; si recarga igual, vuelve a esa misma pantalla, no al formulario. Si el banco tarda más de lo normal (90 segundos), se lo dice sin invitarlo a pagar de nuevo, y la página se actualiza sola cuando el banco responde.
5. Ve la confirmación. Si enviaste `success_url`, vuelve a tu web.

Un enlace se paga **una sola vez**. Sólo tras un rechazo del banco puede intentarlo otra vez, con una clave nueva.

### Cierre diario de los bancos

Todas las noches, de **11:45 p. m. a 1:30 a. m.** (hora de Venezuela), los bancos hacen su cierre diario y no atienden pagos. En esa franja la página de pago:

- Muestra arriba el aviso **Bancos en mantenimiento** con el texto "Los bancos están en su mantenimiento diario y no se pueden hacer pagos. Podrás pagar a partir de la 1:30 a. m. (hora de Venezuela)." y no deja pedir la clave de pago. No se le cobra nada a tu cliente.
- Desde **15 minutos antes** (11:30 p. m.) muestra un aviso que no bloquea: "En 12 minutos los bancos entran en mantenimiento (de 11:45 p. m. a 1:30 a. m.). Si vas a pagar, hazlo ahora." Los minutos se actualizan solos.
- Se actualiza sola cada 30 segundos: una página abierta antes de la franja se bloquea al empezar y se desbloquea a la 1:30 a. m. sin recargar.

Si alguien pide la clave dentro de la franja, la página recibe `503` con `{ "error": "cierre_bancario", "motivo": "Los bancos están en su mantenimiento diario y no se pueden hacer pagos. Podrás pagar a partir de la 1:30 a. m. (hora de Venezuela).", "reintentar_en": 5400 }` (`reintentar_en`, en segundos, y la cabecera `Retry-After` dicen cuánto falta para que termine) y muestra el mismo aviso.

Lo que ya estaba en curso no se corta: un pago con la clave ya pedida sigue su camino y los avisos `link.pagado` y `link.acreditado` llegan como siempre. El enlace sigue `pendiente` y tu cliente lo paga después de la 1:30 a. m. con el mismo enlace, si no vence antes. Los enlaces de **prueba** no tienen esta franja: no pasan por el banco.

### Pagar con tarjeta (piloto)

Está en **piloto** y apagado: QuickPay lo enciende por comercio. Si no está activo para tu cuenta, tu página de pago se ve exactamente como arriba.

Con el piloto activo, debajo de los bancos tu cliente ve **Paga con tarjeta de débito o crédito**: se aceptan tarjetas de crédito y las tarjetas de débito de Banco de Venezuela, Bancaribe, Bancrecer, Banco del Tesoro, Bancamiga, Banco Digital de los Trabajadores, BANFANB, Banco Fondo Común, Banco Plaza y R4. Antes del botón **Pagar con tarjeta** ve cuánto pagará: «Con tarjeta pagas Bs 103,00 (incluye recargo de 3 % por pago con tarjeta)» para un cobro de Bs 100. Al tocarlo pasa a la página de pago de Credicard, que es donde escribe su tarjeta: QuickPay no ve ni guarda los datos de la tarjeta. Ese formulario dura 6 minutos.

- **El recargo lo paga tu cliente**, no tú: se cobra a la tarjeta el monto (con la propina, si agregó una) más el recargo. A ti se te liquida lo mismo que si te hubiera pagado con débito inmediato: el monto (con propina) menos tu comisión de siempre.
- Sólo en cobros en bolívares de **producción**, desde Bs 5 (el mínimo de Credicard) y hasta el tope del piloto, contando el recargo. No aparece en enlaces de prueba ni en enlaces con [pago dividido](/developers/pago-dividido).
- El enlace se sigue pagando **una sola vez**: mientras el formulario de la tarjeta está abierto, el enlace queda `cobrando` y no se puede pagar con débito inmediato (ni abrir otro formulario); mientras un pago con débito inmediato está en curso, no se puede pagar con tarjeta.
- El enlace pasa a `pagado` sólo cuando Credicard confirma el cobro aprobado. Si lo rechaza o el formulario vence sin pago, el enlace vuelve a `pendiente` y tu cliente puede pagarlo otra vez (con tarjeta o con débito inmediato).
- Te llega el mismo aviso `link.pagado`: `monto`, `propina` y `total` son los del cobro (sin el recargo), con `"metodo": "tarjeta"`, `recargo_tarjeta` (lo que pagó de más tu cliente), en `referencia` la referencia del recibo de la tarjeta y en `txn_id` el id del pago con tarjeta. → [Webhooks](/developers/webhooks-referencia)
- **La liquidación de los pagos con tarjeta no es inmediata**: Credicard abona los pagos con tarjeta en su cierre nocturno. Cuando el abono llega, QuickPay te liquida ese pago y te llega `link.acreditado`, como con cualquier otro pago.

### Quiero ser cliente

Debajo de la cédula, tu cliente ve el campo **Tu nombre** (opcional) y la casilla **"Quiero ser cliente de *tu comercio* y recibir sus novedades."** La casilla viene **desmarcada**: sólo la marca quien quiere. Si la marca, el nombre es obligatorio.

Cuando el cobro queda `pagado` (no antes), esa persona aparece en **Clientes** del portal con la etiqueta **Se registró al pagar** y **Acepta novedades**. Si ya la tenías (misma cédula, o mismo WhatsApp sin cédula), no se duplica ni se le cambia el nombre que le pusiste: sólo se marca que acepta novedades. En **Clientes** puedes filtrar por **Aceptan novedades**.

Si quien paga ya está registrado en QuickPay por WhatsApp con esa cédula, se usa el nombre de su registro: no tiene que registrarse dos veces.

Si quien cobra es una **cuenta personal**, la casilla dice **"Guardar mis datos para pagarle más rápido a *su nombre*."** y marcarla no vuelve obligatorio el nombre; sin nombre, el contacto se guarda con el teléfono de quien pagó. Esa casilla no es permiso para enviarle novedades.

Con un enlace de **prueba** se ve igual, pero el cliente queda marcado **Se registró al pagar (prueba)** y no cuenta como permiso para enviarle novedades.

Por la API sólo te llega si lo pidió: `pagador.alta_cliente` al consultar el enlace y en el aviso `link.pagado`. Nunca su cédula, teléfono ni nombre.

## 5. Enterarte del pago

- **Webhook `link.pagado`** (recomendado): registra tu URL en el portal (**Integraciones › Webhooks**) o con `POST /switch/v1/webhooks`. → [Webhooks](/developers/webhooks-referencia)
- **Consultar el enlace**:

```bash
curl -s https://pay.pagaconquickpay.com/switch/v1/links/3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40 \
  -H "x-switch-key: $QP_KEY"
```

```json
{
  "id": "3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40",
  "url": "https://pay.pagaconquickpay.com/l/3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40",
  "wa_deeplink": null,
  "qr_png": null,
  "comercio": "tu-comercio",
  "monto": 450,
  "moneda": "VES",
  "concepto": "Servicio de consultoría",
  "estado": "pagado",
  "expires_at": "2026-10-11T14:00:00.000Z",
  "txn_id": "b639fac6-1d2e-4f00-9a1b-3c4d5e6f7a8b",
  "created_at": "2026-10-08T14:00:00.000Z",
  "paid_at": "2026-10-08T14:03:22.000Z",
  "propina": 0,
  "total": 450,
  "pagador": { "alta_cliente": false },
  "codigo_verificacion": "QP-7K3M9-XQ4TA"
}
```

`pagador.alta_cliente` es `true` si quien pagó marcó "Quiero ser cliente de *tu comercio* y recibir sus novedades" en la página de pago. → [Página de pago](/developers/enlaces-de-pago#quiero-ser-cliente)

`propina` y `total` vienen siempre: si activaste [propinas](/developers/propinas) y tu cliente agregó una, `total` = `monto` + `propina` es lo que se le debitó. `monto` no cambia.

Cuando el enlace está `pagado`, la respuesta trae `codigo_verificacion`: el mismo código que ve tu cliente en su comprobante. Cualquiera puede [verificarlo](/developers/enlaces-de-pago#verificar-un-comprobante).

Sólo consultas los enlaces del modo de tu llave: un enlace real consultado con `sk_test_` (o uno de prueba con `sk_live_`) responde `404`.

Qué significa cada `estado`: → [Estados de un cobro](/developers/ciclo-de-vida)

## 6. Listar tus enlaces

```bash
curl -s "https://pay.pagaconquickpay.com/switch/v1/links?estado=pagado&limit=20" \
  -H "x-switch-key: $QP_KEY"
```

Devuelve una **lista** de enlaces (cada uno con la forma de la consulta, incluido `codigo_verificacion` si está pagado), del más nuevo al más viejo.

Los filtros se combinan entre sí (todos tienen que cumplirse). Por ejemplo, los pagados o en proceso del 8 de octubre en Venezuela que digan "mensualidad":

```bash
curl -s "https://pay.pagaconquickpay.com/switch/v1/links?estado=pagado,procesando&desde=2026-10-08T04:00:00Z&hasta=2026-10-09T04:00:00Z&q=mensualidad" \
  -H "x-switch-key: $QP_KEY"
```

| Parámetro | Notas |
|---|---|
| `estado` | Opcional. Uno o varios separados por coma: `pendiente`, `cobrando`, `procesando`, `revision`, `pagado`, `expirado`, `cancelado`. Un valor que no es un estado se ignora. |
| `desde` · `hasta` | Opcionales. Fecha ISO 8601 (`2026-10-08T04:00:00Z`) o milisegundos desde 1970. Se compara con la fecha del pago o, si aún no se pagó, con la de creación. `desde` entra y `hasta` no. Un día de Venezuela va de las 04:00 Z de ese día a las 04:00 Z del siguiente. |
| `q` | Opcional. Texto a buscar en el concepto, el nombre de quien pagó, la referencia bancaria del pago, el `id` del enlace o su `codigo_verificacion`. Con varias palabras, cada una tiene que aparecer en alguno de esos campos. No distingue mayúsculas ni tildes. |
| `min` · `max` | Opcionales. Monto del enlace en Bs (sin propina), ambos incluidos. |
| `con_propina` | Opcional. `true`: sólo los que tienen propina. `false`: sólo los que no. |
| `mode` | Opcional. `test` o `live`. Sólo ves los enlaces del modo de tu llave: con `sk_test_`, los de prueba; con `sk_live_`, los reales. Si pides el otro modo, la lista viene vacía. |
| `origen` | Opcional. Cómo se creó: `api`, `panel`, `mi_pagina`, `boton` o `whatsapp`. |
| `limit` | Cuántos traer. Por omisión 50, máximo 200. |
| `offset` | Cuántos saltar, para paginar. |

Si `desde`, `hasta`, `min`, `max`, `con_propina`, `mode` u `origen` traen un valor que no se entiende, responde `400` con `{ "error": "validation", "parametro": "…", "detail": "…" }` en lugar de ignorarlo.

## 7. Cancelar un enlace

Si el pedido ya no va (el cliente se arrepintió, te equivocaste en el monto), cancela el enlace:

```bash
curl -s -X POST https://pay.pagaconquickpay.com/switch/v1/links/3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40/cancelar \
  -H "x-switch-key: $QP_KEY"
```

```json
{ "id": "3f6c2a9e-8b1d-4c7a-9e2f-5a1b7c3d9e40", "estado": "cancelado" }
```

Sólo se puede cancelar un enlace **`pendiente`**. Si tu cliente ya está pagando (`cobrando`, `procesando`, `revision`) o ya pagó, responde `409` con `{ "error": "no_cancelable", "estado": "…" }` y no se toca nada: cancelar a mitad de un pago dejaría el dinero sin dueño. Si el `id` no es tuyo, no existe o es del otro modo (un enlace real con tu llave de prueba, o al revés), `404`. Cuando alguien abre un enlace cancelado ve que fue cancelado (y, si pusiste `failure_url`, vuelve a tu web).

## 8. Muchos cobros de una vez

Si le cobras a una lista de personas (mensualidades, cuotas), crea hasta 500 enlaces en una sola petición: → [Cobro por lote](/developers/cobro-por-lote)

## Verificar un comprobante

El comprobante de un pago exitoso lleva un **código de verificación** (por ejemplo `QP-7K3M9-XQ4TA`) y la línea "Verifícalo en pagaconquickpay.com/verificar". Con ese código, tú o cualquier persona pueden comprobar que el comprobante es auténtico. Una captura con el monto editado no pasa la verificación, porque el código depende del monto, la moneda y la fecha del pago.

- **En la web:** `https://docs.pagaconquickpay.com/verificar` (también acepta `?codigo=QP-…`, para ponerlo en un QR o un enlace).
- **Por API, sin llave:**

```bash
curl -s "https://pay.pagaconquickpay.com/switch/v1/verificar/QP-7K3M9-XQ4TA"
```

```json
{
  "valido": true,
  "estado": "válido",
  "monto": 150,
  "moneda": "VES",
  "comercio": "Tu Comercio",
  "fecha_hora": "2026-10-09T18:03:22.000Z",
  "fecha_hora_caracas": "09/10/2026, 02:03 p. m.",
  "referencia_bancaria": "****2808",
  "prueba": false,
  "mensaje": "Comprobante auténtico emitido por QuickPay.",
  "concepto": "Mensualidad de octubre",
  "referencia_externa": null,
  "verificaciones": 1,
  "primera_verificacion": "2026-10-09T18:05:10.000Z",
  "primera_verificacion_caracas": "09/10/2026, 02:05 p. m."
}
```

- `concepto` es el del enlace que se pagó y `referencia_externa` la referencia de tu pedido si el enlace vino de un [lote](/developers/cobro-por-lote) (`null` si no). Sirven para comprobar que el comprobante es del pedido que te están presentando, y no de otro del mismo monto.
- `verificaciones` dice cuántas veces se ha verificado ese código, **contando esta consulta**, y `primera_verificacion` cuándo fue la primera (en UTC y en hora de Caracas). Si te presentan un comprobante que ya se verificó antes, lo verás aquí. Pueden venir `null` si por ahora no se pudo registrar la consulta.

- Si el código no existe responde `404` con `"estado": "no_encontrado"` y el mensaje "No encontramos un comprobante con ese código.".
- Los pagos de **prueba** también tienen código, y la verificación los marca con `"prueba": true` y el mensaje "Pago de prueba (no movió dinero).".
- Nunca se muestran datos de quien pagó (teléfono, cédula ni nombre). La referencia bancaria sale enmascarada, con sólo los últimos 4 dígitos.
- Límite: 20 consultas por minuto por IP (`429` si te pasas).
- Tu servidor recibe el mismo código en `codigo_verificacion`, al consultar el enlace `pagado` y en el aviso `link.pagado`.
