Customer API
Emisión de documentos de control administrativo desde tu TMS o ERP. REST sobre HTTPS, JSON en ambos sentidos. Tres llamadas de escritura y una de consulta.
El modelo: un borrador que se rellena
El DeCA se constituye por partes: nace como un borrador incompleto, se rellena con tantas llamadas como necesites y se cierra al llamar a generar QR. Mientras está abierto está en modo borrador, y no tiene validez legal.
POST /v1/decas
(constituye, N veces)
↺
│
──────────► borrador ──────────────► emitido
crear ▲ generar_QR │
│ │
└────── regenerar ────────┘
(abre borrador nuevo,
sembrado con lo emitido)Cada llamada de escritura corresponde a una transición: constituir se puede repetir, generar consume un número de tu serie legal y produce el PDF, y regenerar abre una corrección que queda registrada. Ninguna de las dos últimas ocurre como efecto de la primera.
Todas las llamadas identifican el documento por referenciaExterna: tu número de orden, expedición o pedido. No hay que guardar ningún identificador nuestro en tu base de datos.
Autenticación
Clave estática por cabecera, en las cuatro llamadas. Se emite al dar de alta la integración y es revocable en caliente, sin desplegar nada de tu lado.
x-api-key: dk_live_a1b2c3d4e5f6g7h8i9j0 Content-Type: application/json
| Entorno | base_url | Prefijo de clave |
|---|---|---|
| Producción | https://decatransporte.app/api | dk_live_ |
| Pruebas | https://sandbox.decatransporte.app/api | dk_test_ |
La clave identifica una cuenta y una empresa. Lo que emitas queda bajo esa empresa, con su serie de numeración propia, y solo esa cuenta lo consulta. La referenciaExterna es única dentro de esa empresa, no globalmente: dos clientes pueden usar el mismo OC-100425 sin cruzarse.
No la incrustes en clientes ni la subas a un repositorio. Si se compromete, se revoca al momento y se emite otra: las integraciones activas solo cambian el valor de la cabecera.
Constituir DeCA
Abre el borrador si referenciaExterna es nueva; si ya hay uno abierto, funde los campos recibidos con los que hubiera. Es la misma llamada en los dos casos.
Entrada
| campo | Tipo | Descripción |
|---|---|---|
| referenciaExternareq | string ≤255 | Tu identificador del transporte. Único dentro de tu empresa. |
| …campos opc | string | Cualquier subconjunto de los 19 campos del documento, en cualquier orden y repartidos en cuantas llamadas quieras. |
{
"referenciaExterna": "OC-100425",
"cargadorNombre": "Segura SL",
"cargadorNif": "B12345678",
"cargadorDomicilio": "Pol. Fuente del Jarro, 46988 Paterna",
"origen": "Valencia",
"destino": "Irún",
"mercanciaNatura": "Palés de cerámica",
"mercanciaPeso": "18500 kg"
}{
"id": "3f9a2b1c-8d5e-4f2a-9c1b-7e6d5a4b3c2d",
"referenciaExterna": "OC-100425",
"estado": "borrador",
"faltan": ["transportistaNombre", "transportistaNif",
"matriculaTractor", "fechaTransporte"]
}{ "referenciaExterna": "OC-100425",
"transportistaNombre": "Logística Ríos SL",
"transportistaNif": "B98765432",
"matriculaTractor": "4521 KLM",
"matriculaRemolque": "R-8830" }
// → 200 { "estado":"borrador", "faltan":["fechaTransporte"] }
// Los campos de la llamada 1 siguen ahí. Esto suma, no reemplaza.faltan enumera los obligatorios que quedan por rellenar. Aunque la lista quede vacía, el documento sigue en borrador: se emite cuando llamas a generar_QR, nunca solo.
Si tu sistema envía centroCoste o numeroExpedicion, la llamada no falla: se guardan y se ignoran.
| código | Cuándo |
|---|---|
| 200 | Borrador abierto o actualizado |
| 400 | JSON mal formado, falta referenciaExterna o un campo supera el límite |
| 409 | El documento ya está emitido: abre una corrección con regenerar |
Generar QR
Cierra el borrador. Valida los once obligatorios, asigna el siguiente número de la serie de tu empresa y genera el PDF con su código QR de verificación incrustado.
Entrada
La referenciaExterna en la ruta y la clave en la cabecera. Sin cuerpo.
{ "id": "3f9a2b1c-8d5e-4f2a-9c1b-7e6d5a4b3c2d",
"referenciaExterna": "OC-100425",
"estado": "emitiendo" }Esta llamada no admite datos. Todo lo que sale en el PDF ha entrado por POST /v1/decas.
202 y no 200: la generación es asíncrona y tarda unos segundos. Sondea la consulta hasta que el estado sea emitido, o pide que te configuremos un webhook de aviso.
{ "error": "campos_obligatorios",
"detalle": "no se puede emitir sin todos los apartados del art. 6",
"faltan": ["fechaTransporte"] }Un 422 no toca nada: el borrador sigue abierto y con su contenido intacto. Completa lo que falte y vuelve a llamar.
Si la llamas dos veces
Después de la primera llamada ya no queda borrador que emitir. La segunda encuentra el documento en curso o terminado y te lo devuelve.
| Cuándo llega la segunda | Qué encuentra | Respuesta |
|---|---|---|
| El worker sigue trabajando | emitiendo | 202 · mismo id, mismo trabajo |
| Ya terminó | emitido | 200 · referencia y pdfUrl |
| La generación falló | error | 202 · reintenta, sin consumir número |
Ni segundo PDF, ni segundo número de serie, ni segunda versión. Para que exista una v2 hay que pasar por regenerar, que es una llamada distinta y exige un motivo.
Generar consume un número de la serie legal de tu empresa y produce un documento con valor probatorio, archivado y verificable por QR. A partir de ahí no se edita: se corrige emitiendo una versión nueva, y la anterior se conserva accesible.
Regenerar
El documento emitido no se edita. Regenerar abre un borrador nuevo sembrado con los campos del documento vigente, ya enlazado al anterior: es la vía para un cambio de vehículo a mitad de ruta o un error en el peso.
Entrada
| campo | Tipo | Descripción |
|---|---|---|
| motivoreq | string ≤255 | Circunstancia que obliga a corregir. Sale impreso en la versión nueva. |
Ningún campo del transporte: los cambios entran después por POST /v1/decas, la única puerta de escritura.
{ "motivo": "cambio de vehículo por avería en ruta" }
// → 200
{ "id": "7d2e9f04-…", // el DeCA nuevo, todavía sin emitir
"estado": "borrador",
"version": 2,
"regeneradoDe": "3f9a2b1c-…", // el DeCA vigente hasta ahora
"faltan": [] } // viene completo: se sembró de uno emitidoEl ciclo de corrección
POST /v1/decas/OC-100425/regenerar { motivo } → 200 borrador, faltan:[]
POST /v1/decas { matriculaTractor } → 200 borrador
POST /v1/decas/OC-100425/generar_QR → 202 → v2, referencia 47- La versión nueva hereda la
referencialegal. Tu numeración no salta: sigue siendo el DeCA nº 47, corregido. - La anterior queda marcada como reemplazada y sigue descargable.
- El QR del PDF nuevo apunta al anterior: la cadena v1 → v2 → v3 queda trazada.
- Tu
referenciaExternano cambia nunca y siempre resuelve a la versión vigente.
Un POST sobre un documento emitido devuelve 409. La corrección solo se abre llamando a /regenerar, con su motivo.
No recibe el id del documento a corregir: una sola línea de sucesión, sin ramas.
La circunstancia que obliga a corregir consta en el documento (art. 6.g) y sale impresa en la versión nueva.
| código | Cuándo |
|---|---|
| 200 | Borrador nuevo abierto, sembrado con la versión vigente |
| 400 | Falta motivo |
| 404 | Esa referenciaExterna no existe |
| 409 | Ya hay un borrador abierto: no se corrigen dos versiones en paralelo |
Consultar documento
Válido en cualquier fase. En borrador devuelve lo acumulado y lo que falta; emitido, el número legal, el PDF vigente y la cadena de versiones.
{
"id": "7d2e9f04-…",
"referenciaExterna": "OC-100425",
"estado": "emitido",
"referencia": 47, // nº de DeCA de tu empresa
"version": 2,
"emitidoEl": "2026-08-18T14:31:07Z",
"pdfUrl": "https://f003.backblazeb2.com/…?X-Amz-Signature=…",
"versiones": [
{ "version": 1, "emitidoEl": "2026-08-18T11:04:22Z",
"reemplazado": true, "motivo": null, "pdfUrl": "https://…" },
{ "version": 2, "emitidoEl": "2026-08-18T14:31:07Z",
"reemplazado": false, "motivo": "cambio de vehículo por avería en ruta",
"pdfUrl": "https://…" }
],
"documento": { /* todos los campos tal y como se imprimieron */ }
}Es una URL firmada con caducidad. Si archivas el DeCA en tu gestor documental, descarga el fichero al recibirlo en lugar de guardar el enlace. La consulta emite un enlace nuevo cada vez que lo pidas.
Campos del documento
Los nombres son los del contrato y no cambian dentro de v1. Los once obligatorios son los apartados del artículo 6 y son condición para generar, no para constituir.
Obligatorios para generar
| campo | Formato | Ejemplo |
|---|---|---|
| cargadorNombre | string | Segura SL |
| cargadorNif | string | B12345678 |
| cargadorDomicilio | string | Pol. Fuente del Jarro, Paterna |
| transportistaNombre | string | Logística Ríos SL |
| transportistaNif | string | B98765432 |
| origen | string | Valencia |
| destino | string | Irún |
| mercanciaNatura | string | Palés de cerámica |
| mercanciaPeso | string | 18500 kg |
| fechaTransporte | AAAA-MM-DD | 2026-08-18 |
| matriculaTractor | string | 4521 KLM |
mercanciaPeso es texto, no número: la norma admite expresar la cantidad en otra magnitud. Manda la unidad dentro del valor.
Opcionales
| campo | Descripción |
|---|---|
| matriculaRemolque | Solo en conjunto articulado |
| bultos | Número y clase de bultos |
| destinatarioNombre | Destinatario de la mercancía |
| destinatarioDomicilio | Domicilio de entrega |
| numeroAlbaran | Nº de tu albarán de origen, informativo |
| observaciones | Observaciones generales del transporte |
| observacionesCargador | Reservas del cargador (art. 6.h) |
| observacionesTransportista | Reservas del transportista (art. 6.h) |
id, referencia, version, pdfUrl y regeneradoDe se descartan si los mandas. Son resultado de la emisión, no entrada.
Estados y transiciones
| estado | Significa | Siguiente |
|---|---|---|
| borrador | Borrador abierto, admite campos | generar_QR → emitiendo |
| emitiendo | Validado, generándose el PDF | automático → emitido | error |
| emitido | PDF disponible, número asignado | regenerar → borrador |
| error | La generación falló; vuelve detalle | generar_QR → reintenta |
Qué admite cada estado
| Estado actual | POST /decas | generar_QR | regenerar |
|---|---|---|---|
| (no existe) | abre el borrador | 404 | 404 |
| borrador | funde campos | emite | 409 |
| emitiendo | 409 | 202, mismo trabajo | 409 |
| emitido | 409 | 200, el ya emitido | abre borrador v+1 |
Dos invariantes al integrar: hay como mucho un borrador abierto por referencia (de ahí el 409 de regenerar sobre un borrador) y un documento en error no ha consumido número de serie, así que reintentar no deja huecos en tu numeración.
Reintentos
Las cuatro llamadas se pueden repetir. La unicidad la impone una restricción en base de datos, no una comprobación de la aplicación.
| Repetir | Efecto |
|---|---|
| POST /v1/decas | Funde los mismos valores otra vez. No abre un segundo borrador. |
| POST …/generar_QR | Devuelve el documento en curso o emitido. Ni segundo PDF ni segundo número. |
| POST …/regenerar | 409: ya hay un borrador abierto por la primera llamada. |
| GET … | Sin efectos. Lectura pura. |
Ante un timeout o un 5xx, repite la misma llamada con la misma referenciaExterna, con espera creciente. Una referencia distinta es otro transporte y produce un documento duplicado.
Códigos de error
Formato único en todas las rutas. El texto de detalle es explicativo y puede cambiar: para tu lógica usa el código HTTP y el campo error, que sí es estable.
{ "error": "ya_emitido", "detalle": "usa /regenerar para abrir una corrección" }| HTTP | error | Causa | Acción |
|---|---|---|---|
| 400 | peticion_invalida | JSON mal formado o campo fuera de límite | Corregir; reintentar no ayuda |
| 401 | no_autorizado | Clave ausente, errónea o revocada | Revisar x-api-key |
| 403 | cuenta_solo_consulta | La cuenta no puede emitir | Pedir clave con permiso de emisión |
| 404 | no_encontrado | Esa referenciaExterna no existe | Comprobar el valor exacto |
| 409 | ya_emitido | Constituir sobre un documento emitido | Llamar a /regenerar |
| 409 | borrador_abierto | Regenerar con un borrador ya abierto | Cerrarlo con /generar_QR |
| 422 | campos_obligatorios | Faltan apartados del art. 6 | Leer faltan y completar |
| 429 | demasiadas_peticiones | Límite de ritmo | Esperar lo que indique Retry-After |
| 5xx | error_interno | Fallo nuestro | Reintentar con espera creciente; es seguro |
Límites y alcance
| Límite | valor |
|---|---|
| Longitud de campo | 255 caracteres · 2000 en observaciones |
| Cuerpo de la petición | 64 KB |
| Ritmo por clave | 60 peticiones / minuto |
| Caducidad de un borrador abierto | 30 días sin actividad |
Vigencia de pdfUrl | 7 días desde la consulta |
Fuera de alcance en v1
- Sin EDI ni SFTP. Solo HTTPS con JSON. Si tu operativa es de ficheros por lotes, escríbenos y lo vemos aparte.
- Sin OCR por API. La extracción de campos desde una foto del albarán vive en el panel web. La API recibe los datos ya estructurados.
- Sin firma electrónica cualificada. El DeCA no la exige.
- Sin borrado de documentos emitidos. Se corrigen, no se eliminan.
- Una empresa por clave. Si emites en nombre de varias sociedades, una clave por cada una.
Lanzar llamadas HTTP desde tu TMS y guardar el PDF que devolvemos. El documento se localiza siempre por una referencia que ya tienes, así que no hay que añadir campos a tu base de datos.