Firux Pay Partner API v2026-07-25 Descargar OpenAPI

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: amount va 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) y firux_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-Key protege contra reintentos de red del mismo request: la misma clave con el mismo cuerpo devuelve el mismo cobro (nunca duplica). Reusarla con otro cuerpo devuelve 422.
  • external_reference es 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:

HeaderDescripción
Firux-Event-IdId del evento (estable; úsalo para deduplicar).
Firux-Event-Typecharge.paid
Firux-TimestampUnix timestamp del envío.
Firux-SignatureUna 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;
}
El header 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":"..."}}

HTTPCuándo
400Falta Idempotency-Key.
401Credenciales inválidas o revocadas.
409external_reference pagada/en conflicto, o solicitud en proceso.
422Validación (monto, reglas de negocio).
503Bre-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.