Guarda data, ETag y requestId. No necesitas configurar un webhook para confirmar ni completar ninguna operación.
Formato
JSON UTF-8 y nombres de campo en camelCase.
Fechas
RFC 3339 en UTC. Las horas de servicio conservan Europe/Madrid.
Trazabilidad
Cada respuesta incluye requestId para soporte y auditoría.
Compatibilidad
Los cambios aditivos permanecen en v1. Los incompatibles abren una versión nueva.
Autenticación y permisos
Las integraciones usan credenciales de organización. No reutilizan la contraseña ni la sesión de una persona.
Clave visible una vez
La persona administradora copia el secreto al crearlo. Después sólo se conserva su hash.
Scopes mínimos
Cada credencial recibe permisos de lectura o escritura por recurso. Puede rotarse y revocarse sin afectar al resto.
Envía la clave en Authorization: Bearer hdr_live_.... No la incluyas en URLs, logs, archivos compartidos ni código que se ejecute en el navegador.
El administrador la crea desde Perfil → API e integraciones. El límite de claves activas depende del plan y una rotación invalida el secreto anterior inmediatamente.
account:read
usage:read
companies:read
companies:write
vehicles:read
vehicles:write
drivers:read
drivers:write
route_sheets:read
route_sheets:write
documents:read
webhooks:manage
Recursos y endpoints
Todos los paths parten de https://hojasderuta.com/api/v1 y devuelven JSON salvo la descarga del PDF.
Cuenta y uso
Consulta capacidades efectivas sin acceder a información de pago.
GET
/account
Organización, plan y capacidades
GET
/usage
Cuotas comerciales y límites técnicos
GET
/capabilities
Acciones disponibles para la credencial
Datos maestros
Mantén las referencias que usa la oficina al preparar servicios.
GET / POST
/drivers
Listar y crear cuentas de conductor
GET / PATCH / DELETE
/drivers/{id}
Consultar, actualizar o retirar un conductor
POST
/drivers/{id}/password
Cambiar la contraseña y cerrar sus sesiones
GET / POST
/companies
Empresas transportistas guardadas
GET / POST
/vehicles
Vehículos y matrículas
GET / PATCH / DELETE
/companies/{id}
Consultar, actualizar o retirar una empresa
GET / PATCH / DELETE
/vehicles/{id}
Consultar, actualizar o retirar un vehículo
Documentos
Emite, consulta y corrige DeCA con el mismo control que la aplicación.
GET / POST
/route-sheets
Listado y emisión de hojas
GET / PATCH
/route-sheets/{id}
Detalle y cambio de estado
POST
/route-sheets/{id}/revisions
Nueva versión inmutable
DELETE
/route-sheets/{id}
Borrado durante la ventana permitida
GET
/route-sheets/{id}/pdf
Descarga autenticada del PDF vigente
Opcional: webhooks
Sólo para sistemas que necesitan recibir cambios realizados fuera del ERP.
GET / POST
/webhooks
Listar y crear destinos
GET / PATCH / DELETE
/webhooks/{id}
Consultar, pausar o retirar un destino
POST
/webhooks/{id}/rotate-secret
Rotar el secreto de firma
POST
/webhooks/{id}/test
Enviar un evento de prueba
GET
/webhook-deliveries
Historial de entregas e intentos
Gestión completa de conductores
Crea cuentas activas, sincroniza la identidad del ERP, actualiza permisos y renueva contraseñas respetando las plazas del plan.
Alta
POST crea la cuenta y devuelve el conductor completo con ETag.
Edición
PATCH actualiza identidad, teléfono, externalId y permisos.
Acceso
El cambio de contraseña revoca todas las sesiones anteriores.
Baja
DELETE elimina al conductor; la cuenta administradora está protegida.
El alta requiere el scope drivers:write, una plaza disponible en el plan y una Idempotency-Key. Para actualizar, eliminar o cambiar la contraseña, lee primero el conductor y envía su ETag en If-Match. Un cambio de contraseña cierra todas sus sesiones.
externalId es el identificador estable del conductor en tu ERP. El email debe ser único globalmente; NIF y externalId deben ser únicos dentro de la organización. La contraseña nunca aparece en respuestas, logs de entrega ni webhooks.
Los conductores creados manualmente desde Gestión pueden no tener cuenta de acceso. También aparecen en los listados de la API con hasAccount: false y sin campo email; pueden asignarse a hojas de ruta y consumen una plaza del plan, pero no admiten cambios de contraseña ni permisos de acceso. Desde Gestión, un administrador puede concederles acceso más adelante o revocarlo sin eliminar el conductor.
Crear y revisar hojas
El servidor valida el plan, genera el PDF nativo, crea el QR y registra la auditoría antes de confirmar la emisión.
Validación
Comprueba campos, conductor, vehículo, horario y permisos.
Reserva de cuota
Bloquea una unidad mensual para evitar excesos concurrentes.
Documento
Genera PDF, hash, QR y primera versión inmutable.
Confirmación
Devuelve 201 sólo cuando el documento ya está disponible.
Las correcciones usan POST /route-sheets/{id}/revisions y exigen un motivo. Nunca sustituyen físicamente la versión anterior del PDF.
El borrado sólo se admite durante los 10 primeros minutos. Una hoja emitida sigue contando en la cuota mensual aunque después se elimine. La URL /deca/{token} es pública únicamente para entregar el PDF del QR y no funciona como API de integración.
Respuestas, polling e idempotencia
La respuesta HTTP es autoritativa. Para importar cambios externos, consulta las listas incrementalmente.
Respuesta autoritativa
Cada POST o PATCH devuelve el recurso confirmado. Guarda data, ETag y requestId directamente en el ERP.
Idempotency-Key
Obligatoria al crear conductores, emitir hojas y crear revisiones. Repetir la misma petición devuelve el resultado original.
externalId
Identificador propio del ERP, único dentro de la integración y el tipo de recurso.
Cursor
Las listas usan cursores opacos. No construyas ni modifiques su contenido.
updatedAfter
Permite hacer polling incremental: recupera sólo los cambios posteriores a la última sincronización y continúa con el cursor.
ETag e If-Match
GET devuelve ETag. PATCH, DELETE y las revisiones exigen enviarlo en If-Match para evitar sobrescrituras.
Si meta.hasMore es true, repite la misma consulta añadiendo cursor=meta.nextCursor. Avanza tu marca temporal sólo después de procesar todas las páginas; conserva un pequeño solapamiento para tolerar relojes y reintentos.
Cómo detectar eliminaciones
updatedAfter devuelve altas y modificaciones, no tombstones. Si otro usuario puede eliminar datos desde la app, realiza una reconciliación completa periódica o activa el webhook de eliminación.
Planes, cuotas y rate limits
La API comparte los límites comerciales de la cuenta. Además mantiene límites técnicos para proteger la disponibilidad.
Plan
Conductores
Hojas al mes
Claves API
Comportamiento API
Gratis
1
5
1
La cuota se comparte entre app y API
Base
5
40
2
Pensado para una oficina pequeña
Flota
15
Sin límite comercial
5
Mantiene protección técnica
Ilimitado
Sin límite comercial
Sin límite comercial
20
Mantiene protección técnica
Sin límite comercial no significa sin protección
Flota e Ilimitado mantienen límites de peticiones, escrituras y concurrencia. Un 429 incluye Retry-After.
Consulta GET /usage para mostrar uso, restante y fecha de renovación. Las hojas creadas desde la app y la API cuentan en el mismo periodo mensual UTC.
El límite técnico actual es de 300 peticiones API por minuto e IP, con un máximo general de 120 mutaciones por minuto. Las respuestas incluyen RateLimit-Limit, RateLimit-Remaining y RateLimit-Reset.
Errores predecibles
Los errores siguen application/problem+json. El código estable sirve para automatizar decisiones; detail es sólo informativo.
HTTP
Código
Significado
401
invalid_api_key
La credencial no existe, caducó o fue revocada.
403
insufficient_scope
La credencial no tiene permiso para la operación.
403
plan_driver_limit_reached
La cuenta agotó las plazas de conductor de su plan.
403
driver_management_forbidden
La API no puede modificar la cuenta administradora.
403
plan_route_sheet_monthly_limit_reached
La cuenta agotó su cuota mensual.
404
resource_not_found
El recurso no existe o pertenece a otra organización.
409
idempotency_conflict
La misma clave se reutilizó con otro contenido.
409
invalid_status_transition
El cambio de estado no es válido.
412
resource_version_mismatch
El recurso cambió desde la última lectura.
428
precondition_required
Falta el ETag vigente en If-Match.
422
validation_failed
Uno o más campos no cumplen el contrato.
429
rate_limit_exceeded
Se superó el límite técnico temporal.
Cuota agotada
application/problem+json
{
"type": "https://hojasderuta.com/problems/plan-route-sheet-monthly-limit-reached",
"title": "Acceso no permitido",
"status": 403,
"code": "plan_route_sheet_monthly_limit_reached",
"detail": "La cuenta ha agotado las hojas disponibles este mes.",
"requestId": "req_01J...",
"limit": 5,
"used": 5,
"resetsAt": "2026-11-01T00:00:00Z"
}
Webhooks opcionales
No determinan el resultado ni son necesarios para crear o gestionar recursos. Úsalos sólo si el ERP debe recibir cambios realizados desde la app.
Empieza sin webhooks
Para una integración de oficina sencilla, procesa la respuesta de cada operación y consulta GET con updatedAfter. Puedes activar webhooks más adelante.
route_sheet.created
route_sheet.updated
route_sheet.revised
route_sheet.deleted
driver.created
driver.updated
driver.deleted
company.created
company.updated
company.deleted
vehicle.created
vehicle.updated
vehicle.deleted
subscription.changed
usage.threshold_reached
Entrega verificable
Cada petición incluye X-Hojas-Evento-Id, X-Hojas-Timestamp y X-Hojas-Signature. Verifica la firma SHA-256 sobre timestamp.cuerpo antes de procesarlo.
Responde con 2xx después de persistir el evento. Cada entrega realiza hasta tres intentos con espera creciente y queda registrada en /webhook-deliveries.
El secreto whsec_ sólo se devuelve al crear o rotar el webhook. En el servidor se conserva cifrado con AES-256-GCM.