Todas las guías

API y webhooks

Si llevas la contabilidad o el ERP en otro programa y quieres que hable con Recua, lo haces con la API REST y los webhooks. Esta página es técnica: pásasela a quien te lleve la informática.

Dónde está

En el menú de tu cuenta, al pie de la barra de la izquierda.

Panel de Recua con el menú de la cuenta abierto y la opción API e integraciones
  1. Pulsa el nombre de tu empresa, abajo del todo.
  2. Pulsa API e integraciones.
Pantalla API e integraciones con la lista de API keys, la lista de webhooks y la documentación rápida
  1. Nueva API key: para que tu programa lea o cree portes.
  2. Tus claves, con su prefijo, sus permisos, el último uso y si están activas.
  3. Nuevo webhook: para que Recua avise a tu programa cuando pasa algo.

Cuándo usar cada cosa

  • API (tu programa pregunta): tu ERP necesita la lista de portes o crear portes. Usa una API key.
  • Webhooks (Recua avisa): quieres enterarte en tu sistema cuando un porte se asigna, se firma o se entrega. Usa un webhook.

Si solo quieres ver datos en otra herramienta, sin conexión en directo, exporta un CSV desde Analítica: es más sencillo.

Crear una API key

  1. Pulsa Nueva API key.
  2. Ponle un nombre que diga qué programa la usa.
  3. Marca los permisos.
  4. Pulsa Generar.
Formulario de nueva API key con el nombre escrito, los permisos portes:read y portes:write y el botón Generar
  1. Nombre: por ejemplo «ERP Sage 50» o «Power BI».
  2. Permisos: portes:read (leer portes, marcado de serie) y portes:write (crear portes). Si necesitas otros (clientes, facturas), pídenoslo.
  3. Pulsa Generar.

Al generarla, Recua te enseña el token completo UNA SOLA VEZ, algo como ta_a1b2c3d4e5f6_<44 caracteres>, con un botón Copiar. Guárdalo en tu gestor de secretos: Recua solo guarda una huella, así que si lo pierdes no se puede recuperar y hay que generar otra.

Usar la API

Pasa la key en la cabecera Authorization: Bearer <token>:

curl -H "Authorization: Bearer ta_..." \
  https://recua.app/api/v1/portes?desde=2026-05-01

Endpoints:

  • GET /api/v1/portes: lista los portes de tu empresa, los más recientes primero. Filtros: estado, desde y hasta (sobre la fecha de carga) y limit (50 por defecto, hasta 200).
  • GET /api/v1/portes/{id}: el detalle de un porte, con conductor, cargador, destinatario, vehículo, sus eventos y las reservas (las observaciones sobre el estado de la mercancía, art. 8 del Convenio CMR).
  • POST /api/v1/portes: crea un porte (necesita portes:write). Son obligatorios conductor_id y el peso: peso_bruto_kg o, si la mercancía no se puede pesar, volumen_m3 (es dato obligatorio del documento de control). cargador_id, destinatario_id y vehiculo_id son opcionales, pero si los mandas tienen que ser de tu empresa. Si el vehículo circula con autorización especial, manda su número en autorizacion_especial.

Respuestas en JSON. Errores:

  • 401: falta la cabecera, el token no tiene el formato o está revocado.
  • 402: tu empresa no puede operar ahora (prueba terminada o suscripción impagada o cancelada). Solo bloquea crear portes; leer sigue funcionando.
  • 403: el token no tiene el permiso que hace falta.
  • 404: el porte no existe o no es de tu empresa.
  • 422: falta el peso al crear un porte.

Revocar una API key

Si crees que la key se ha filtrado, o el programa que la usaba ya no funciona, pulsa Revocar en su fila. Deja de valer al momento: las siguientes llamadas dan 401. No se puede deshacer; si la necesitas, genera otra.

Las revocadas siguen en la lista con la etiqueta Revocada, para que quede constancia de las claves que ha tenido la empresa.

Crear un webhook

  1. Pulsa Nuevo webhook.
  2. Escribe la URL de tu sistema.
  3. Marca los eventos que te interesan.
  4. Pulsa Crear webhook.
Formulario de nuevo webhook con la URL escrita, la lista de eventos con porte.firmado y porte.entregado marcados, y el botón Crear webhook
  1. URL de tu sistema (http o https). Tiene que ser pública: Recua no llama a localhost, a direcciones privadas (192.168.x, 10.x.x.x...) ni a las de metadatos de la nube.
  2. Eventos suscritos: porte.creado, porte.asignado, porte.cargando, porte.en_ruta, porte.descargando, porte.firmado, porte.entregado, porte.incidencia y porte.cancelado.
  3. Pulsa Crear webhook.

Al crearlo, Recua te enseña el secret del webhook (empieza por whsec_) una sola vez. Guárdalo: con él compruebas que cada aviso viene de Recua (ver abajo).

Un webhook no se edita. Para cambiar la URL o los eventos, elimínalo y crea otro.

Lista de webhooks con uno en estado Pausado y los botones Reactivar y Eliminar
  1. El estado: Activo o Pausado. En Último envío ves la fecha y el código que devolvió tu servidor.
  2. Pausar o Reactivar: para los avisos sin borrar el webhook. Al lado, Eliminar lo borra.

porte.firmado llega más de una vez

Un porte lanza porte.firmado en cada firma: conductor en la recogida, cargador, conductor en la entrega. El campo campo del mensaje dice cuál fue.

Qué trae cada aviso

{
  "evento": "porte.entregado",
  "enviado_at": "2026-08-03T10:00:00.000Z",
  "data": { "porte_id": "...", "campo": "firma_destinatario" }
}

El contenido de data cambia según el evento y de dónde venga: si viene de POST /api/v1/portes trae el porte completo; si viene de una firma o de un cambio de estado trae, como mínimo, porte_id.

Comprobar la firma del webhook

Recua manda la cabecera X-Recua-Signature con este formato:

t=<timestamp>,v1=<hmac>

Tu servidor:

  1. Lee timestamp y hmac de la cabecera.
  2. Calcula HMAC-SHA256(secret, timestamp + "." + body).
  3. Si no coincide con hmac, rechaza el aviso: no viene de Recua.
  4. Si el timestamp tiene más de 5 minutos, recházalo también (evita que te reenvíen un aviso viejo).

Ejemplo en Node.js:

import { createHmac } from "node:crypto";

const [tsPart, sigPart] = req.headers["x-recua-signature"].split(",");
const ts = tsPart.split("=")[1];
const recibido = sigPart.split("=")[1];

const calculado = createHmac("sha256", SECRET)
  .update(`${ts}.${rawBody}`)
  .digest("hex");

if (calculado !== recibido) return res.status(401).end();
if (Date.now() / 1000 - parseInt(ts) > 300) return res.status(401).end();

Sin reintentos

Recua intenta cada aviso una sola vez, con 5 segundos de margen. Si tu servidor no contesta o devuelve un error, no se repite: solo se apuntan la fecha y el código en Último envío. Contesta rápido con un 2xx y, si tienes que hacer algo lento, déjalo en una cola y contesta enseguida.

Errores habituales

  • «Último envío» tiene fecha pero ningún código: Recua no llegó a recibir respuesta. La URL estaba bloqueada (dirección privada), no se encontró el dominio, o tu servidor no contestó en 5 segundos o rechazó la conexión.
  • El código sale en rojo: tu servidor contestó con un error (4xx o 5xx). Ese aviso no se repite: corrige tu servidor o consulta el porte con GET /api/v1/portes/{id}.
  • Falta un aviso: como no hay reintentos, un fallo puntual de tu servidor lo pierde. Si no te lo puedes permitir, usa el webhook como señal para ir a buscar el estado real por la API.

¿Necesitas un permiso, un evento o un endpoint que no existe (clientes, facturas, cambiar un porte por API)? Cuéntanoslo en hola@recua.app.