Firux Partner API
Crea cobros Bre-B por API y recibe la confirmación por webhook firmado.
- El dinero es del comercio. Cada cobro se paga a su cuenta Bre-B. La API crea y consulta cobros; nunca mueve ni retiene fondos, ni permite retiros.
- Montos en pesos COP enteros. El peso no tiene centavos:
amountva y vuelve como entero (50000= $50.000). - URL base:
https://api.firux.co/v1
Autenticación
Cada llamada lleva la API key del comercio en el header Authorization:
Authorization: Bearer firux_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- Se genera y se muestra una sola vez desde el panel del comercio (Ajustes → Conexiones API).
- Prefijos:
firux_live_(producción) yfirux_test_(pruebas). - Es una credencial de servidor: nunca la pongas en el navegador ni en apps de cliente.
Crear un cobro
POST/charges · requiere el header Idempotency-Key.
curl -X POST https://api.firux.co/v1/charges \
-H "Authorization: Bearer firux_test_..." \
-H "Idempotency-Key: 5f3c9b2a-1e77-4a10-9a1c-abc123" \
-H "Content-Type: application/json" \
-d '{
"amount": 50000,
"external_reference": "FACT-2026-00123",
"description": "Mensualidad julio - Club Deportivo"
}'
Respuesta 201
{
"id": "chg_9f8c1d2e...",
"object": "charge",
"status": "PENDING",
"amount": 50000,
"currency": "COP",
"external_reference": "FACT-2026-00123",
"reference": "API-8F3K2M1Q",
"payment_url": "https://firux.co/pay/API-8F3K2M1Q",
"qr_emv": "000201...",
"payment_method": "BRE_B",
"created_at": "2026-07-25T14:03:00-05:00"
}
Muéstrale al pagador el qr_emv (como QR Bre-B) o el payment_url. La confirmación llega por webhook; no hace falta poletear.
Idempotencia y external_reference
Idempotency-Keyprotege contra reintentos de red del mismo request: la misma clave con el mismo cuerpo devuelve el mismo cobro (nunca duplica). Reusarla con otro cuerpo devuelve422.external_referencees tu llave de negocio. Si vuelves a crear un cobro con la misma referencia: si sigue pendiente y con el mismo monto se devuelve ese cobro (200); si ya está pagado,409. Cubre el caso "abre la deuda hoy, paga mañana" sin duplicar.
Consultar cobros
# Por id curl https://api.firux.co/v1/charges/chg_9f8c1d2e... \ -H "Authorization: Bearer firux_test_..." # Por tu referencia curl "https://api.firux.co/v1/charges?external_reference=FACT-2026-00123" \ -H "Authorization: Bearer firux_test_..."
Una key solo ve los cobros que esa conexión creó (aislamiento por integración).
Webhooks
Cuando un cobro se paga, Firux hace POST a la URL de webhook del comercio con el evento charge.paid. Debe ser https y pública. Headers de cada envío:
| Header | Descripción |
|---|---|
Firux-Event-Id | Id del evento (estable; úsalo para deduplicar). |
Firux-Event-Type | charge.paid |
Firux-Timestamp | Unix timestamp del envío. |
Firux-Signature | Una o más firmas v1=<hex> separadas por coma. |
Cuerpo (data)
{
"id": "evt_...",
"type": "charge.paid",
"livemode": true,
"data": {
"charge_id": "chg_...",
"status": "PAID",
"amount": 50000,
"amount_paid": 50000,
"currency": "COP",
"external_reference": "FACT-2026-00123",
"paid_at": "2026-07-25T14:05:11-05:00",
"detected_at": "2026-07-25T14:05:14-05:00",
"payment_method": "BRE_B"
}
}
paid_at = cuándo se movió la plata en el banco; detected_at = cuándo lo vio Firux. Responde 2xx para confirmar; si respondes error o hay timeout, Firux reintenta con backoff (aprox. 1m, 5m, 30m, 2h, 6h).
Verificar la firma (obligatorio)
Reconstruye HMAC-SHA256(secreto, "{timestamp}.{cuerpo_crudo}") y compáralo en tiempo constante con alguna de las firmas del header. El secreto de firma se muestra al crear o rotar la conexión (distinto de la API key). Rechaza timestamps de más de 5 minutos.
Node.js
const crypto = require("crypto");
function verify(rawBody, headers, secret) {
const ts = headers["firux-timestamp"];
const expected = crypto.createHmac("sha256", secret)
.update(`${ts}.${rawBody}`).digest("hex");
const sigs = (headers["firux-signature"] || "")
.split(",").map(s => s.trim().replace(/^v1=/, ""));
const ok = sigs.some(s => s.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)));
return ok && Math.abs(Date.now()/1000 - Number(ts)) < 300;
}
PHP
function firux_verify(string $rawBody, array $headers, string $secret): bool {
$ts = $headers['Firux-Timestamp'] ?? '';
$expected = hash_hmac('sha256', $ts.'.'.$rawBody, $secret);
foreach (explode(',', $headers['Firux-Signature'] ?? '') as $s) {
if (hash_equals($expected, trim(str_replace('v1=', '', $s)))) {
return abs(time() - (int) $ts) < 300;
}
}
return false;
}
Firux-Signature puede traer dos firmas durante una rotación de secreto (v1=A,v1=B). Acepta si cualquiera cuadra: así el comercio rota su secreto sin cortarte los webhooks. En el OpenAPI está también el ejemplo en Python.Errores
Formato uniforme: {"error":{"type":"...","message":"..."}}
| HTTP | Cuándo |
|---|---|
400 | Falta Idempotency-Key. |
401 | Credenciales inválidas o revocadas. |
409 | external_reference pagada/en conflicto, o solicitud en proceso. |
422 | Validación (monto, reglas de negocio). |
503 | Bre-B no disponible momentáneamente; reintenta. |
Modo prueba
Con una key firux_test_... y una URL de webhook configurada puedes simular el pago sin mover dinero real y ver llegar tu webhook firmado:
curl -X POST https://api.firux.co/v1/charges/chg_.../simulate_payment \ -H "Authorization: Bearer firux_test_..."
simulate_payment no funciona con keys live.
Soporte
¿Dudas con la integración? Escríbenos a soporte@firux.co. La especificación completa (con el ejemplo en Python y todos los esquemas) está en el OpenAPI, listo para importar en Postman o Insomnia.