FITALAPI

Cobros

Crear un cobro y seguirlo hasta que se pague.

Un cobro genera la instrucción que tu cliente usa para pagarte. Eliges método y monto; FITAL devuelve la instrucción y el estado.

1. Consulta los métodos

GET /v1/collection-methods da país, moneda, método, rango de monto y payer_fields, lo que el método pide de quien paga. Usa el valor de method tal cual.

2. Estima, si quieres

POST /v1/collections/estimate devuelve lo que recibirías y la comisión. Lleva firma, sin clave de idempotencia.

3. Crea el cobro

Con POST /v1/collections, envía amount, lo que paga tu cliente, o destination_amount, lo que quieres recibir, y en payer lo que pida el método.

Variables de estas muestras: simulador público, sin cuenta

Define esto en tu terminal. Con estos valores las muestras corren tal cual contra el simulador público:

export FITAL_API="https://widget.fital.xyz/explorar/v1"
export FITAL_KEY="sk_test_sandbox_publica"
export FITAL_SIGNING_SECRET="secreto_de_firma_de_prueba_publico"

En la cuenta de prueba o en producción cambia la base, la llave y el secreto, y sustituye los id de ejemplo por los tuyos. Ver Ambientes.

crear-cobro.sh
CUERPO='{"currency":"MXN","method":"spei","amount":"1250.00","payer":{"firstName":"CLIENTE","lastName":"FICTICIO","email":"pagos@empresa-ejemplo.com"},"external_ref":"pedido-7731"}'
CLAVE="cobro-pedido-7731"
TS=$(date +%s)
HASH=$(printf '%s' "$CUERPO" | openssl dgst -sha256 -r | cut -d' ' -f1)
FIRMA=$(printf '%s\n%s\n%s\n%s\n%s' "$TS" POST /v1/collections "$HASH" "$CLAVE" \
  | openssl dgst -sha256 -hmac "$FITAL_SIGNING_SECRET" -r | cut -d' ' -f1)
curl -sS -X POST "$FITAL_API/collections" \
  -H "Authorization: Bearer $FITAL_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $CLAVE" \
  -H "X-Fital-Timestamp: $TS" \
  -H "X-Fital-Signature: v1=$FIRMA" \
  -d "$CUERPO"

La respuesta trae instruction, con type y value, y expires_at. GET /v1/collections/{id} devuelve lo mismo. Con 202, el alta aún no se confirma y ambos llegan en null: repite con la misma clave, y en cuanto exista el resultado lo recibes.

Los datos de quien paga van en payer, y payer_fields manda: cada fila da la clave en name, si es obligatoria en required, los valores admitidos en options y el prefijo telefónico en phone_prefix. El país se deduce de la moneda: envía countrySymbol, en 2 letras, sólo si quien paga es de otro país.

Sin un campo required, o con un valor fuera de options, la respuesta es 400 invalid_request, sin crear nada:

{
  "error": {
    "code": "invalid_request",
    "message": "Faltan datos de quien paga",
    "request_id": "0123456789abcdef0123456789abcdef",
    "details": { "fields": { "payer.email": "Obligatorio en este método, o con un valor no admitido" } },
    "retryable": false,
    "docs_url": "https://merchants.fital.xyz/docs/errores/#invalid_request"
  }
}

Ese rechazo no cierra la clave, pero la clave conserva su cuerpo: repetir el mismo cuerpo da el mismo 400, y el cuerpo corregido necesita otra Idempotency-Key. Con la misma responde 422 idempotency_key_reused. Si la comprobación no se puede hacer a tiempo en producción, el cobro sigue y decide el riel.

4. Sigue el estado

EstadoSignificado
processingEl alta sigue en curso
pendingEspera el pago
paidPagado
expiredVenció sin pago
failedNo se pudo crear o completar

Consulta GET /v1/collections/{id}. Los eventos collection.paid y collection.expired llegan por webhook.

Errores comunes

  • 403 not_enabled: el método no está habilitado para tu cuenta.
  • 422 amount_out_of_range: revisa min_amount y max_amount.
  • 400 invalid_request: falta amount o destination_amount, o details.fields nombra un campo payer.<campo>.
  • Corregir payer y repetir con la misma clave: responde 422 idempotency_key_reused.

Qué sigue

Quién pagó.

Cobros en efectivo

efectivo cobra en tiendas de México, en MXN, de 20.00 a 10,000.00 por operación. Está disponible bajo solicitud: pídelo a FITAL. Sale en GET /v1/collection-methods cuando tu empresa lo tiene activado; sin activación, crear el cobro responde 403 not_enabled.

  • Se pide con amount, no con destination_amount. payer no lleva nada: quien paga no da datos.
  • instruction.type llega en REFERENCE, y instruction.value es la referencia que quien paga da en la tienda. Se entrega sólo la referencia.
  • Sin expires_at, el cobro vence a los 3 días.
  • paid y collection.paid dicen que la tienda confirmó el pago. El abono a tu cuenta llega después, y POST /v1/collections/estimate no promete cuánto recibirás: receive_amount llega en null.

Ver esta página en Markdown

En esta página