Para desarrolladores · Plan ESCALA
API REST y Webhooks para tu ERP o TMS
Crea documentos de control (DeCA) directamente desde tu sistema y recibe avisos firmados en cada cambio de estado. Integración bidireccional con el patrón estándar REST + webhooks, sin tarifa por integración.
1. Cómo empezar
- Necesitas el plan ESCALA.
- En el panel, ve a Ajustes → API y crea una clave con permiso de escritura.
- Guarda la clave (
tcr_…): solo se muestra una vez. - Empléala en la cabecera
Authorizationde cada petición.
2. Autenticación
Todas las llamadas requieren tu clave como Bearer token:
Authorization: Bearer tcr_TU_CLAVE
Base de la API: https://app.tucontrolderutas.com
3. Crear un DeCA
/api/v1/documentos
Crea un documento de control. Queda emitido y válido ante inspección al instante.
Campos obligatorios (los datos del art. 6 · Orden FOM/2861/2012)
expedidor_nombreCargador contractual (razón social)expedidor_nifNIF/CIF del cargadortransportista_nombreTransportista efectivotransportista_nifNIF/CIF del transportistaorigen_direccionDirección de origenorigen_ciudadCiudad de origendestino_direccionDirección de destinodestino_ciudadCiudad de destinodescripcion_mercanciasNaturaleza de la mercancíafecha_hora_previstaFecha/hora del transporte (ISO 8601)matricula_vehiculoMatrícula del vehículoCampos opcionales
referencia_externaTu nº de pedido. Clave de idempotencia (ver abajo)precio_referenciaPrecio o referencia al contrato. NO es dato del DeCA (es de la carta de porte)expedidor_direccionDomicilio del cargadororigen_cp / destino_cpCódigos postalespeso_kgPeso bruto en kgremolque_matriculaMatrícula del remolquetipo_vehiculo"rigido" (def.) o "articulado"conductor_nombre / conductor_dni_nieDatos del conductor (opcional, no es dato del art. 6)num_bultosNúmero de bultosreferencia_clienteTu referencia interna (libre)tipo_mercancia / numero_onu / clase_adrMercancías peligrosas (ADR)observaciones / instrucciones_entregaTexto libreEjemplo
curl -X POST https://app.tucontrolderutas.com/api/v1/documentos \
-H "Authorization: Bearer tcr_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"referencia_externa": "PEDIDO-2026-00123",
"expedidor_nombre": "Logística Ebro SL",
"expedidor_nif": "B12345678",
"transportista_nombre": "Trans López SL",
"transportista_nif": "B87654321",
"origen_direccion": "Pol. Ind. Malpica, nave 7",
"origen_ciudad": "Zaragoza",
"destino_direccion": "C/ Embajadores 120",
"destino_ciudad": "Madrid",
"descripcion_mercancias": "22 palés de bebidas",
"fecha_hora_prevista": "2026-06-20T08:15",
"matricula_vehiculo": "4521KTM",
"precio_referencia": "870 €"
}'Respuesta 201 Created
{
"ok": true,
"idempotente": false,
"documento": {
"id": "a846a916-7b39-4d81-b5d7-dede94a25702",
"numero_control": "70268072",
"estado": "emitido",
"referencia_externa": "PEDIDO-2026-00123",
"pdf_url": "https://.../documentos/.../70268072.pdf",
"url_inspeccion": "https://app.tucontrolderutas.com/inspeccion/a846a916-...",
"url_pdf_publico": "https://app.tucontrolderutas.com/api/pdf/v/a846a916-...",
"created_at": "2026-06-20T06:15:02Z"
}
}Tipos de documento (campo modo)
El mismo endpoint crea los tres tipos. modo_b (carta de porte como DeCA) queda pendiente de firma AdES y no es válido hasta que firman expedidor y transportista. eCMR es para transporte internacional.
# Por defecto crea un DeCA. Para otros tipos, añade "modo":
# modo_b · carta de porte como DeCA (requiere firma AdES)
{ "modo": "modo_b", ...campos del DeCA...,
"destinatario_nombre": "Distribuciones Sur SL",
"destinatario_direccion": "C/ Sevilla 10, Madrid",
"email_expedidor": "firma@ebro.com",
"email_transportista": "firma@translopez.com" }
# → queda "pendiente_firma_aes"; se envían los enlaces de firma a ambas partes.
# eCMR · carta de porte internacional (requiere firma AdES)
{ "modo": "ecmr", ...campos del DeCA...,
"pais_origen": "ES", "pais_destino": "FR",
"valor_mercancias": 18000, "moneda": "EUR",
"email_expedidor": "firma@ebro.com",
"email_transportista": "firma@translopez.com" }
# → queda "pendiente_firma_aes"; se envían los enlaces de firma a ambas partes.4. Idempotencia
Envía tu número de pedido en referencia_externa. Si repites la llamada con la misma referencia, la API no duplica el documento: devuelve el ya creado con 200 OK e idempotente: true. Así tu ERP puede reintentar tras un timeout sin riesgo de crear DeCAs duplicados.
5. Consultar
/api/v1/documentos?estado=&desde=&hasta=&pagina=&limite=
Lista paginada de documentos (máx. 200 por página).
/api/v1/documentos/:id
Un documento con todos sus campos y firmas.
/api/v1/conductores
Conductores de la empresa.
/api/v1/vehiculos
Vehículos de la empresa.
6. Sincronizar maestros
Da de alta conductores y vehículos desde tu ERP. Idempotente por la clave natural (dni_nie / matricula): si ya existen, se devuelven sin duplicar. Los vehículos respetan el límite de tu plan.
/api/v1/conductores
Alta de conductor (nombre, apellidos, dni_nie obligatorios).
/api/v1/vehiculos
Alta de vehículo (matricula obligatoria; tipo: rigido/articulado/furgon).
# Alta de conductor (idempotente por dni_nie)
curl -X POST https://app.tucontrolderutas.com/api/v1/conductores \
-H "Authorization: Bearer tcr_TU_CLAVE" -H "Content-Type: application/json" \
-d '{ "nombre": "Juan", "apellidos": "Martín Ruiz",
"dni_nie": "51234829V", "telefono": "612345678" }'
# Alta de vehículo (idempotente por matrícula)
curl -X POST https://app.tucontrolderutas.com/api/v1/vehiculos \
-H "Authorization: Bearer tcr_TU_CLAVE" -H "Content-Type: application/json" \
-d '{ "matricula": "4521KTM", "tipo": "articulado" }'7. Webhooks
Registra una URL en Ajustes → API → Webhooks y te enviaremos un POST cada vez que un documento cambie de estado, sin que tengas que sondear la API.
Eventos
documento.emitidoDeCA creado y válido ante inspeccióndocumento.firmado_cargadorEl cargador ha firmadodocumento.firmado_conductorEl conductor ha firmadodocumento.firmado_receptorEl destinatario ha firmadodocumento.completadoEntrega completadadocumento.entrega_rechazadaEl destinatario rechazó la entregadocumento.finalizadoServicio finalizado (arranca el plazo de cierre del QR; la ley permite cerrarlo a partir de 7 días)Qué recibes
POST https://tu-erp.com/webhooks/tcr
X-TCR-Evento: documento.completado
X-TCR-Firma: sha256=2b1c... ← HMAC-SHA256 del cuerpo con tu secret
{
"evento": "documento.completado",
"enviado_at": "2026-06-20T14:32:10Z",
"documento": {
"id": "a846a916-...",
"numero_control": "70268072",
"estado": "completado",
"referencia_externa": "PEDIDO-2026-00123",
"pdf_url": "https://.../70268072.pdf",
"url_inspeccion": "https://app.tucontrolderutas.com/inspeccion/a846a916-...",
"origen_ciudad": "Zaragoza",
"destino_ciudad": "Madrid"
}
}Verificar la firma
Cada envío incluye X-TCR-Firma: sha256=…, el HMAC-SHA256 del cuerpo crudo con el secret de tu webhook. Compáralo antes de procesar:
// Node.js (Express)
const crypto = require('crypto')
app.post('/webhooks/tcr', express.raw({ type: '*/*' }), (req, res) => {
const firma = req.headers['x-tcr-firma']
const esperado = 'sha256=' + crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(req.body) // cuerpo crudo, sin parsear
.digest('hex')
if (!crypto.timingSafeEqual(Buffer.from(firma), Buffer.from(esperado)))
return res.status(401).end()
const evento = JSON.parse(req.body)
// … actualiza tu ERP …
res.status(200).end()
})<?php // PHP
$cuerpo = file_get_contents('php://input');
$firma = $_SERVER['HTTP_X_TCR_FIRMA'] ?? '';
$esperado = 'sha256=' . hash_hmac('sha256', $cuerpo, $WEBHOOK_SECRET);
if (!hash_equals($esperado, $firma)) { http_response_code(401); exit; }
$evento = json_decode($cuerpo, true);
// … actualiza tu ERP …
http_response_code(200);8. Errores y límites
400Cuerpo JSON no válido401API key ausente, inválida o revocada403La empresa no es ESCALA, o la clave es de solo lectura422Validación: faltan campos obligatorios (campo detalles[])429Límite de 120 creaciones/minuto por clave superado¿List@ para integrar?
Crea tu cuenta, activa el plan ESCALA y genera tu primera clave en minutos.