Introducción
La API de HelppiuPay es REST, recibe y responde JSON y usa una sola URL base para pruebas y producción.
https://helppiupay.com/api/v1
Hay tres formas de integrar, según cuánto quieras construir:
| Camino | Cuándo usarlo | Endpoints |
|---|---|---|
| Checkout hospedado | Quieres cobrar sin construir el formulario de pago. Creas una sesión, rediriges al comprador a la URL que devuelve la API y HelppiuPay se encarga de los métodos de pago y de 3-D Secure. | POST /checkout-sessions |
| Cobro directo | Quieres controlar toda la experiencia de pago desde tu servidor (server-to-server). | POST /tokens, POST /charges |
| Payouts Bre-B | Necesitas enviar dinero desde el saldo de tu bolsillo a llaves Bre-B autorizadas. | POST /payouts |
En los tres casos recibes los cambios de estado por webhooks firmados y puedes consultar cada operación por su identificador.
Primeros pasos
En unos minutos puedes crear tu primer cobro de prueba.
- Crea tus llaves de API. En el panel de tu comercio, entra a Llaves de API y genera una llave secreta de prueba (
hp_sk_test_…). Desde ahí también puedes revocarlas. - Crea una sesión de checkout. Envía el siguiente request desde tu servidor, con tu llave en el formato
key_id:secret. - Abre el checkout. La respuesta trae el campo
url. Ábrelo en el navegador para ver el checkout hospedado. - Recibe el resultado. Registra un endpoint de webhooks para enterarte cuando el pago cambie de estado.
curl https://helppiupay.com/api/v1/checkout-sessions \
-H "Authorization: Bearer hp_sk_test_…:sk_…" \
-H "Idempotency-Key: 6f1c2b8e-4d1a-4c55-9f0e-2a7b1d3e9c10" \
-H "Content-Type: application/json" \
-d '{
"reference": "ORDER-1001",
"amount": 50000,
"currency": "COP",
"payment_method_types": ["card", "pse", "nequi"],
"customer_phone": "3001234567",
"success_url": "https://tutienda.com/ok",
"cancel_url": "https://tutienda.com/cancel"
}'
const res = await fetch('https://helppiupay.com/api/v1/checkout-sessions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.HELPPIU_KEY_ID}:${process.env.HELPPIU_SECRET}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
reference: 'ORDER-1001',
amount: 50000,
currency: 'COP',
payment_method_types: ['card', 'pse', 'nequi'],
customer_phone: '3001234567',
success_url: 'https://tutienda.com/ok',
cancel_url: 'https://tutienda.com/cancel',
}),
});
const session = await res.json();
// Redirige al comprador a session.url
$ch = curl_init('https://helppiupay.com/api/v1/checkout-sessions');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('HELPPIU_KEY_ID') . ':' . getenv('HELPPIU_SECRET'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'reference' => 'ORDER-1001',
'amount' => 50000,
'currency' => 'COP',
'payment_method_types' => ['card', 'pse', 'nequi'],
'customer_phone' => '3001234567',
'success_url' => 'https://tutienda.com/ok',
'cancel_url' => 'https://tutienda.com/cancel',
]),
]);
$session = json_decode(curl_exec($ch), true);
// Redirige al comprador a $session['url']
reference, amount, success_url y cancel_url son obligatorios. customer_phone lo es cuando ofreces PSE, Nequi, Daviplata, Bre-B o QR. La respuesta es 201 con la sesión creada.
Autenticación y llaves
Cada request se autentica con el header Authorization de tipo Bearer. El valor es el identificador de la llave y su secreto, separados por dos puntos:
Authorization: Bearer <key_id>:<secret>
Si falta el separador, la API responde 401 con Invalid API key format. Expected key_id:secret.
Tipos de llave
| Prefijo | Tipo | Uso |
|---|---|---|
hp_sk_test_ · hp_sk_live_ | Secreta | Todas las llamadas desde tu servidor. Nunca la expongas en el navegador ni en una app. |
hp_pk_test_ · hp_pk_live_ | Publicable | Para el navegador del comprador: úsala solo para tokenizar la tarjeta con POST /tokens. Todo lo demás, con la llave secreta desde tu servidor. |
Los endpoints de cobros (/charges), bancos PSE (/banks/pse) y tarjetas guardadas (/saved-cards) rechazan las llaves publicables con 403. Usa siempre la llave secreta para las llamadas de servidor.
Buenas prácticas
- Guarda el secreto en variables de entorno o en un gestor de secretos, nunca en el código ni en el repositorio.
- Usa llaves distintas para prueba y producción, y revoca desde el panel cualquier llave expuesta.
- Si tu comercio está suspendido, la llave sigue siendo válida pero la API responde
403.
Modo prueba y producción
No hay un servidor separado de pruebas. El ambiente lo define la llave, no la URL: todas las llamadas van a https://helppiupay.com/api/v1.
| Ambiente | Llaves | Resultado |
|---|---|---|
| Prueba | hp_*_test_* | Las operaciones se crean con environment: "test". |
| Producción | hp_*_live_* | Las operaciones se crean con environment: "live" y mueven dinero real. |
Tarjeta de prueba con 3-D Secure
Para probar el desafío 3-D Secure usa la tarjeta 4970110000001003, CVV 123 y cualquier fecha de vencimiento futura. Otras tarjetas de prueba válidas se aprueban sin desafío.
El comportamiento de cada método de pago en modo prueba puede variar. Si necesitas simular un caso específico, escríbenos a soporte@helppiupay.com.
Conceptos y estados
Objetos principales
- Checkout session: una página de pago hospedada por HelppiuPay para un monto y una referencia. Tiene su propio
urly una fecha de expiración. - Cobro (charge) y transacción: el intento de pago concreto. Un cobro directo crea una transacción; una checkout session también la crea cuando el comprador paga. Ambos comparten los mismos estados.
- Payout: un envío de dinero desde el saldo de tu bolsillo a una llave Bre-B autorizada.
Estados de un cobro
| Estado | Significado | Puede pasar a |
|---|---|---|
created | Creado, aún sin procesar. | processing, pending, approved, declined, error, expired |
processing | En proceso con el medio de pago. | pending, approved, declined, error, expired |
pending | Esperando una acción del comprador o la confirmación del medio de pago. | approved, declined, reversed, expired |
approved | Pago aprobado. | reversed, partially_refunded |
declined | Rechazado. | approved |
error | Error técnico al procesar. | approved, declined |
expired | El comprador no completó el pago a tiempo. | approved, declined |
reversed | Reversado o anulado. | — |
partially_refunded | Reembolsado en parte. | — |
declined, expired y error no siempre son definitivos. Un pago puede aprobarse después; por ejemplo, un pago Bre-B que el comprador completa cuando la llave ya había expirado. Toma como fuente de verdad el último evento que recibas, no el primero.
Estados de una checkout session
open (esperando el pago), completed (pagada), expired (venció o la expiraste con POST /checkout-sessions/{uuid}/expire) y cancelled.
Estados de un payout
pending, processing, completed, failed y cancelled.
Webhooks
HelppiuPay te avisa de cada cambio de estado con un POST HTTP firmado a la URL que registres. Puedes registrarla en el panel, en Configuración › Webhooks, o con POST /webhook-endpoints. La URL debe ser HTTPS y pública; para pruebas locales usa un túnel.
Eventos
| Evento | Cuándo se envía |
|---|---|
transaction.approved | Pago aprobado (alias: transaction.paid). |
transaction.declined | Pago rechazado. |
transaction.failed | Error técnico al procesar. |
transaction.reversed | Reverso o anulación. |
transaction.expired | La transacción expiró sin completarse. |
transaction.updated | Cambio de estado intermedio. |
payout.created | Payout Bre-B creado. |
payout.completed | Payout Bre-B liquidado en el destino. |
payout.failed | Payout Bre-B fallido. |
Suscríbete a * para recibir todos. Ignora los eventos que no reconozcas en lugar de responder con error.
Headers y payload
POST /webhooks/helppiu
Content-Type: application/json
X-Helppiu-Event: transaction.approved
X-Helppiu-Signature: 9f3a7c1e…
{
"event": "transaction.approved",
"created_at": "2026-05-09T19:14:55-05:00",
"data": {
"transaction_id": "70a24661-7fbd-4d71-bd5d-7b5a534d5e2d",
"reference": "ORDER-1001",
"checkout_session_reference": "cs_abc123",
"amount": 50000,
"currency": "COP",
"status": "approved",
"payment_method": "pse",
"customer_email": "cliente@example.com",
"paid_at": "2026-05-09T19:03:10-05:00"
}
}Verificar la firma
X-Helppiu-Signature es el HMAC-SHA256 en hexadecimal del cuerpo crudo del request, calculado con el secreto del endpoint (whsec_…). Ese secreto se entrega una sola vez, al crear el endpoint. Compara con una función de tiempo constante y rechaza la entrega si no coincide.
const crypto = require('crypto');
// Usa el cuerpo crudo, antes de parsear el JSON
const expected = crypto
.createHmac('sha256', process.env.HELPPIU_WEBHOOK_SECRET)
.update(req.rawBody)
.digest('hex');
const received = req.headers['x-helppiu-signature'] || '';
if (expected.length !== received.length ||
!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
return res.sendStatus(401);
}
res.sendStatus(200); // responde rápido y procesa después
$raw = file_get_contents('php://input');
$expected = hash_hmac('sha256', $raw, getenv('HELPPIU_WEBHOOK_SECRET'));
$received = $_SERVER['HTTP_X_HELPPIU_SIGNATURE'] ?? '';
if (!hash_equals($expected, $received)) {
http_response_code(401);
exit;
}
$event = json_decode($raw, true);
http_response_code(200); // responde rápido y procesa después
Reintentos
Tu endpoint debe responder con un código 2xx en menos de 10 segundos. Si no, HelppiuPay vuelve a intentar la entrega. En total son hasta 5 intentos: el original y 4 reintentos, a los 10 segundos, 1 minuto, 5 minutos y 30 minutos. Después, la entrega queda como fallida y puedes reenviarla manualmente desde el panel.
Procesamiento seguro
- El mismo evento puede llegar más de una vez. Deduplica con
data.transaction_id. - Responde primero y procesa en segundo plano para no superar los 10 segundos.
- Guarda el estado del último evento recibido: un pago rechazado o expirado puede aprobarse después.
Idempotencia
Para reintentar un POST sin riesgo de crear dos cobros o dos payouts, envía el header Idempotency-Key con un valor único, por ejemplo un UUID.
Idempotency-Key: 6f1c2b8e-4d1a-4c55-9f0e-2a7b1d3e9c10
- La llave se guarda 24 horas por comercio. Si repites un request con la misma llave, recibes la misma respuesta y el header
X-Idempotency-Replayed: true. - También se guardan las respuestas de error
4xx: si un request falló por validación, corrige los datos y usa una llave nueva. - La llave no depende del endpoint ni del cuerpo: usa una llave nueva para cada operación y nunca la reutilices entre endpoints distintos.
- Aplica a todos los endpoints autenticados, salvo
POST /tokens.
Errores y paginación
Los errores responden con un código HTTP y un cuerpo JSON con el mensaje en error:
{
"error": "Saldo insuficiente."
}| Código | Cuándo ocurre |
|---|---|
201 | Recurso creado. |
202 | El payout necesita un código OTP para continuar (requires_otp: true). |
401 | Falta la llave, es inválida o no tiene el formato key_id:secret. |
403 | Llave publicable en un endpoint que exige la secreta, comercio suspendido u OTP inválido. |
404 | El recurso no existe. |
422 | Datos inválidos, cobro declinado o saldo insuficiente. El cuerpo indica el detalle. |
Hoy los errores no traen un código interno estable: usa el código HTTP para decidir y registra el mensaje para soporte.
Paginación
Los listados (GET /charges, GET /transactions, GET /payouts…) reciben el parámetro page y devuelven los resultados en data y la paginación en meta. El tamaño de página es fijo: 20 en cobros y 25 en el resto.
{
"data": [ … ],
"meta": { "current_page": 1, "last_page": 4, "per_page": 20, "total": 73 }
}Glosario
| Bre-B | El sistema de pagos inmediatos de Colombia. En la API se identifica como brev (también se acepta breb). |
| Llave Bre-B | El identificador del destinatario en Bre-B (por ejemplo @maria o un celular). |
| Bolsillo | El saldo de tu comercio en HelppiuPay, desde el que salen los payouts. |
| Whitelist | La lista de llaves Bre-B autorizadas para recibir payouts de tu comercio. |
| Payout o dispersión | Un envío de dinero desde tu bolsillo a un tercero. |
| Checkout hospedado | La página de pago de HelppiuPay a la que rediriges al comprador. |
| Cobro directo | Un pago creado desde tu servidor con POST /charges, sin pasar por el checkout. |
| Token de tarjeta | El identificador tok_… que reemplaza los datos de la tarjeta. |
| 3-D Secure | La verificación adicional que algunos bancos exigen al pagar con tarjeta. |
| Idempotencia | La garantía de que repetir un request con la misma llave no duplica la operación. |
| OTP | El código de un solo uso que pueden exigir los payouts en producción. |
| Webhook | La notificación HTTP que HelppiuPay envía a tu servidor cuando algo cambia. |