Documento de control (DeCA)
Emite desde la API el documento electrónico de control administrativo del transporte de mercancías por carretera — ámbito y exenciones, el flujo emitir → copia al conductor → modificar → cerrar, la URL pública permanente para la inspección, albaranes y peso bruto.
Desde el 5 de octubre de 2026 el documento de control administrativo del transporte público de mercancías por carretera tiene que ser digital. El DeCA (documento de control) identifica las partes, los envíos, la mercancía, el vehículo y las fechas de un transporte, y viaja con el conductor como un PDF cuyo código QR abre una URL pública permanente. Tanto el cargador contractual como el transportista efectivo están obligados a formalizarlo (Orden FOM/2861/2012, art. 4).
El recurso transport_documents cubre toda la vida de ese documento: borradores
(también prerrellenados desde tus albaranes), emisión, la copia para el conductor,
modificaciones durante el servicio, cierre, anulación y conservación de los ficheros
para la inspección. Un DeCA no es una factura ni un registro VeriFactu, y nunca
cambia la numeración, el stock ni la facturación de tus albaranes.
Todos los endpoints siguientes cuelgan de https://api.factuarea.com/v1 y usan el
mismo envoltorio de error, la misma
paginación por cursor, la misma
idempotencia y los mismos
scopes que el resto de la API.
Cuándo lo necesitas
Se exige en el transporte público de mercancías por carretera, nacional o de
cabotaje, con origen y destino en España. El transporte internacional se documenta con
la carta de porte CMR: un envío con origen o destino fuera de España no se puede emitir
(transport_outside_spain).
No se exige, con la redacción de la Orden:
- en el transporte privado complementario, con vehículos y conductores propios de la empresa; la documentación a bordo debe acreditar igualmente que la mercancía, el vehículo y el conductor son de la empresa;
- en la paquetería de pocos bultos;
- en las mudanzas;
- en el transporte de vehículos accidentados o averiados en vehículos especiales;
- en los transportes que no necesitan una autorización de transporte previa.
Fuentes oficiales: Orden FOM/2861/2012, Resolución de 5 de junio de 2026, página del Ministerio sobre el DeCA y sus preguntas frecuentes.
El módulo transport_documents está incluido allí donde lo están los albaranes
(planes Profesional, Avanzado y Enterprise) y requiere el módulo delivery_notes. Scopes:
transport_documents:read, transport_documents:write (borradores y envío por
email), transport_documents:delete (solo borradores) y
transport_documents:transition (emitir, modificar, cerrar, reabrir, anular y
sustituir). El PDF de cada versión exige pdfs:read; el justificante de emisión
exige transport_documents:read, como el registro de emisión que contiene.
Tu papel y las partes
Cada documento declara si tu empresa actúa como cargador contractual
(company_role: "shipper") o como transportista efectivo ("carrier"), incluido el
transportista que subcontrata el transporte. Tu propia parte se rellena con los datos de
tu empresa; la otra sale de contact_id o de los campos que envíes. Un transportista
extranjero (cabotaje) se identifica con su propio tax_id y su tax_id_country.
Un NIF o un domicilio que no supera la validación en los datos de tu empresa o en el contacto se deja vacío: el borrador lo admite y la emisión lo pide. Lo que envías en la petición se valida al guardarlo. Un domicilio español copiado de tu empresa o de un contacto sin provincia toma la de su código postal (sus dos primeras cifras: 28001 es Madrid); un domicilio que envías se guarda tal como lo envías.
Mientras el documento es un borrador, cada parte copiada sigue a su origen, sin volver a guardar el borrador:
- Al actualizar un contacto, su nombre, su NIF (o identificador extranjero con su país) y su domicilio se vuelven a copiar en los borradores cuya otra parte está enlazada a él.
- Al cambiar el nombre fiscal, la razón social, el NIF o el domicilio fiscal de tu empresa, se vuelven a copiar en tu propia parte de todos los borradores. Los demás cambios en los datos de tu empresa (email, teléfono, web, cuenta bancaria, idioma) no tocan ningún borrador.
- Lo que el origen tiene válido manda. Un NIF vacío o no válido o un domicilio incompleto en el origen nunca borra lo que el borrador ya tenía, por ejemplo lo que enviaste en la petición. Una parte escrita a mano o enlazada a otro contacto no cambia.
- El refresco se hace unos segundos después del cambio y, si algo cambia, publica
transport_document.updated, así que puedes recibirlo de un borrador que no has tocado por la API. Archivar o borrar el contacto deja sus borradores como estaban.
Un documento emitido nunca sigue a sus orígenes: conserva los datos con los que se emitió.
Una vez emitido, las partes no pueden cambiar: una modificación que las toque devuelve
422 transport_document_parties_immutable. Anula el documento y emite otro.
El flujo: emitir, entregar la copia, modificar, cerrar
Crea un borrador. Solo company_role es obligatorio: un borrador admite datos
incompletos y cualquier fecha. Pasa delivery_note_ids (de 1 a 50 de tus albaranes)
para obtener un envío por albarán, con su destino, su fecha y su mercancía, sin
servicios y con los pesos congelados. Un envío que omite origin toma tu lugar de carga
por defecto o, si no tienes ninguno, tu domicilio fiscal (como transportista, la
dirección del contacto cargador); un "origin": null explícito lo deja sin origen. Un
albarán de otra empresa devuelve 422 en delivery_note_ids.N.
curl -X POST https://api.factuarea.com/v1/transport_documents \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"company_role": "shipper",
"carrier": { "contact_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a10" },
"vehicle": { "tractor_plate": "1234BCD", "trailer_plate": "R1234BCD" },
"transport_date": "2026-10-06",
"delivery_note_ids": [
"01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a11",
"01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a12"
]
}'Edita el borrador con PUT /v1/transport_documents/{id} (un campo ausente se conserva,
un null explícito lo borra y shipments sustituye la lista completa) o bórralo con DELETE /v1/transport_documents/{id}.
El id del documento lo genera el servidor. shipments[].id es opcional: al crear,
un identificador que ya está en uso, en tu empresa o en cualquier otra, devuelve 422
en shipments.N.id; en PUT y en modify solo identifica un envío de ese mismo
documento (cualquier otro devuelve 422 parameter_invalid_value en
shipments.N.id), y un envío nuevo va sin id. Todo UUID que envíes se normaliza a
minúsculas. Los envíos, y las líneas de mercancía de cada envío, se guardan en el orden
en que los envías al crear, editar, modificar y en la vista previa. Una línea de mercancía cuyo quantity × gross_weight_kg redondea a
0 kg o supera 9.999.999.999,9999 kg devuelve 422 invalid_gross_weight en
shipments.N.goods.M.gross_weight_kg al guardarla, no al emitir. Si una petición
simultánea ocupa el mismo identificador entre la comprobación y el guardado, la API
devuelve 409 resource_conflict: no se guardó nada y la petición se puede reintentar
tal cual.
Emítelo antes de que empiece el transporte. POST /v1/transport_documents/{id}/issue
comprueba los datos mínimos: nombre, NIF y domicilio completo del cargador; nombre y NIF
del transportista; matrícula de la tractora; y en cada envío, origen, destino,
mercancía, magnitud declarada y una fecha de transporte de hoy o posterior
(Europe/Madrid). En una sola operación atómica asigna el siguiente número de la serie
DC (creada en la primera emisión), la URL pública permanente y la versión 1 del PDF.
Es irreversible: envía un Idempotency-Key.
Cuando falta algo, el error lo enumera en error.details.missing:
{
"error": {
"type": "invalid_request_error",
"code": "transport_document_not_issuable",
"message": "No se puede emitir el DeCA. Faltan 3 datos: el NIF del transportista efectivo; la matrícula de la tractora o del vehículo rígido; la magnitud declarada del envío 1 (peso u otra).",
"details": {
"missing": ["carrier.tax_id", "vehicle.tractor_plate", "shipments.1.measure"]
}
}
}missing usa un vocabulario cerrado: shipper.name, shipper.tax_id,
shipper.address, carrier.name, carrier.tax_id, vehicle.tractor_plate,
transport_date, shipments (ningún envío) y shipments.N.origin,
shipments.N.destination, shipments.N.goods o shipments.N.measure, donde N
cuenta desde 1 (a diferencia del param de un error de validación, que cuenta desde
0). Si el PDF superara 5 MB (5.000.000 bytes), la petición devuelve
422 transport_document_pdf_too_large y no se emite nada: acorta el contenido o
reparte los envíos en varios documentos.
Una fecha de transporte pasada devuelve transport_date_in_past: el documento se crea
antes del servicio y no hay forma de regularizarlo después.
Entrega la copia al conductor. Vale cualquiera de estas: el enlace public_url, el
código QR (GET /v1/transport_documents/{id}/qr?format=svg|png, con la zona de silencio
estándar de 4 módulos de la ISO/IEC 18004, para que se lea tal como se descarga al
imprimirlo o pegarlo en otro documento), el PDF
(GET /v1/transport_documents/{id}/pdf) o un email al transportista con
POST /v1/transport_documents/{id}/send (hasta 5 direcciones distintas entre to, cc y bcc; una dirección repetida en
cualquier lista, sin distinguir mayúsculas, cuenta y se envía una sola vez;
sin to, el email del contacto transportista). El envío es irreversible y queda en el
registro de emisión. Si el proveedor de correo rechaza el mensaje o no puede aceptarlo,
la API devuelve 500 send_failed y no se anota nada en el registro: reintenta con una
Idempotency-Key nueva.
Modifícalo durante el servicio. POST /v1/transport_documents/{id}/modify conserva
el mismo número, la misma URL y el mismo QR, y guarda una versión nueva y completa del
PDF con los datos nuevos, el motivo y los datos anteriores marcados como ya no válidos.
Envía solo lo que cambia, más reason (de 3 a 500 caracteres) y data_origin:
company, o carrier_reported cuando el cambio lo comunicó el transportista. Una petición que no cambia nada devuelve transport_document_no_changes. Un
documento tiene como máximo 50 versiones y la última se reserva para anularlo o
sustituirlo: con 49 versiones, una modificación devuelve
422 transport_document_version_limit_reached, así que emite un documento nuevo y
marca este como sustituido. Una modificación que deja sin algún dato mínimo devuelve
422 transport_document_cannot_be_modified con el mismo error.details.missing. Vuelve a enviar el
PDF modificado al conductor.
{
"reason": "Avería de la tractora",
"data_origin": "carrier_reported",
"vehicle": { "tractor_plate": "5678FGH" }
}Ciérralo. POST /v1/transport_documents/{id}/close lo cierra a mano. Si no, un
proceso diario lo cierra automáticamente 7 días después del final de su última fecha de
transporte (Europe/Madrid). Un documento cerrado a mano se puede reabrir con un reason
hasta reopen_deadline; un cierre automático no se puede reabrir.
Un documento emitido tiene dos salidas terminales, ambas irreversibles y ambas
conservando el original: POST /v1/transport_documents/{id}/cancel (con reason)
guarda una versión final marcada «ANULADO», y
POST /v1/transport_documents/{id}/supersede (con reference y reason) deja constancia
de que el documento propio del transportista lo sustituye. Un documento emitido nunca se borra. Igual que emitir y modificar, anular y sustituir
devuelven 422 transport_document_pdf_too_large sin cambiar nada cuando el PDF
superaría 5 MB.
La URL pública y la inspección
La public_url tiene la forma https://app.factuarea.com/api/public/deca/{token},
con un token opaco de 43 caracteres. Es la URL que codifica el código QR (el PDF y el
justificante de emisión no la imprimen como texto) y no cambia entre versiones.
GETyHEADresponden sin login, sin credenciales y sin página intermedia:200con el PDF de la versión vigente yContent-Type: application/pdf.- El fichero se sirve exactamente como se guardó, nunca se renderiza en la petición. El
ETages su sha256, que coincide conversions[].sha256. - Las peticiones tienen dos límites, y ninguno depende solo de la IP, porque la
inspección puede llegar a la URL a través de una pasarela con una dirección
compartida: uno por token y prefijo de red (/24 en IPv4, /48 en IPv6; 60 por minuto
por defecto), que se comprueba primero, y otro por token (600 por minuto por defecto,
diez veces el de una red, para que dos redes que agotan el suyo no dejen sin el
documento a una tercera). Una dirección IPv4 mapeada en IPv6 (
::ffff:a.b.c.d) cuenta como su /24. Superar cualquiera de los dos devuelve429conRetry-After. - Las peticiones con un token que no corresponde a ningún documento, también uno mal
formado (de otra longitud o con caracteres fuera de base64url), cuentan en un límite
por prefijo de red (30 por minuto por defecto), nunca por token: desde una red, el
intento 31 del minuto recibe
429. - Una descarga se anota en el registro solo después de comprobar que el fichero
existe, con la versión que se sirvió de verdad.
HEADno se anota. - Un token desconocido devuelve
404, y un documento cuyos ficheros se purgaron,410.
Cada versión es un PDF de hasta 5 MB (5.000.000 bytes) cuya CreationDate es la primera emisión y cuya
ModDate es la fecha de la versión. Su historial muestra la fecha, el motivo, el origen del dato y
los datos anteriores de cada modificación, pero no quién la hizo: el autor de cada
versión solo está en el recurso autenticado, el registro y el justificante de emisión. La URL sigue sirviendo el documento como mínimo un
año después de cerrarse, anularse o sustituirse (retention_until), aunque la empresa
cambie de plan. Pasado ese plazo, los ficheros solo se purgan si la cuenta está cerrada: la suscripción
está cancelada, o la empresa gestionada fue archivada por su gestoría. Una cuenta
bloqueada (impago, prueba caducada) no está cerrada. Tras la purga,
el documento y sus datos se conservan, y los endpoints del PDF devuelven
410 transport_document_file_unavailable. Pedir
GET /v1/transport_documents/{id}/pdf?version=N con una versión que el documento no
tiene devuelve 404 transport_document_version_not_found con error.param = version.
Prueba de emisión
GET /v1/transport_documents/{id}/evidence enumera, en orden cronológico, las versiones emitidas o modificadas, los cierres manuales (closed) y automáticos
(auto_closed), las reaperturas, la anulación o sustitución, los
envíos por email con sus destinatarios y las descargas públicas con la IP truncada y el
agente de usuario. La respuesta es { data, meta: { downloads_total, downloads_listed } }:
- Cada entrada nombra a su actor en
actor_name, congelado con el nombre que tenía en ese momento: el usuario en la app, la clave de API en la API REST y en MCP con clave de API, y el cliente OAuth en MCP por OAuth. Una clave nunca toma el nombre del usuario que la creó.actor_nameesnullsolo enauto_closedy en las descargas públicas;user_namees el nombre actual de la persona, cuando la hay.occurred_ates ISO 8601 con su desplazamiento UTC. - Una descarga pública se anota una vez por hora para cada combinación de versión y prefijo de red. El agente de usuario se guarda pero no cuenta, así que cambiarlo no añade entradas y escanear varias veces el QR no las multiplica.
datatrae siempre todas las entradas que no son descargas y, como máximo, las 100 primeras descargas en orden cronológico.meta.downloads_totales el número de descargas registradas ymeta.downloads_listed, cuántas de ellas hay endata.
La tool MCP get_transport_document_evidence devuelve la misma forma.
GET /v1/transport_documents/{id}/issuance_proof exporta el registro como un PDF generado bajo demanda, con el autor de cada versión.
Exige transport_documents:read: una clave con solo pdfs:read recibe
403 insufficient_scope. Es la prueba que exime al cargador que demuestra haberlo
emitido (art. 7.1 de la Orden). Cada versión se verifica recalculando el sha256 de su
PDF.
Albaranes y peso bruto
- Envíos desde albaranes. Filtra los documentos de un albarán con
GET /v1/transport_documents?delivery_note_id=…. Cuando el albarán cambia después de la versión vigente en algo que declara el envío (líneas, cantidades, unidad, peso, dirección de entrega o fecha), su envío informasource_changed: truecon las diferencias ensource_changes; entregarlo o facturarlo no cuenta, ni tampoco un peso añadido después al catálogo. Un albarán anulado o borrado marcasource_missing: true. Un albarán anulado no puede ser el origen de un borrador nuevo (delivery_note_cancelled). - Peso bruto en el catálogo. Los productos, las variantes y las presentaciones fijas
aceptan
gross_weight_kg, lo que pesa una unidad tal como se carga, embalaje incluido. Es opcional y solo ayuda a rellenar la magnitud declarada de cada envío. - Peso en los albaranes. Cada línea de albarán congela su peso al crearse o
editarse en borrador (
gross_weight_kgde la línea); el albarán publicatotal_gross_weight_kgylines_without_weight_count, e imprime el total en su PDF. Duplicar un albarán copia tal cual el peso congelado de cada línea.
Eventos
transport_document.created, .updated, .issued, .modified, .closed,
.reopened, .cancelled y .superseded llevan el recurso completo en data.object.
transport_document.closed distingue un cierre manual de uno automático con
close_mode. transport_document.updated llega también cuando un borrador sigue un
cambio de su contacto o de los datos de tu empresa (partes).
transport_document.email_sent y .email_failed informan de cada email
del documento con sus destinatarios y la versión del PDF adjunta. Consulta Eventos.
Lo que la API pública no cubre
Esto se queda en la app a propósito:
- Los lugares de carga. Son ajustes de la empresa. La API pública y MCP identifican el origen de un envío por su dirección.
- La vista previa en vivo de un documento sin guardar, una ayuda del editor de la app.
- WebMCP, las acciones de automatización sobre el DeCA, los asistentes de IA y la importación masiva.
Relacionados
Referencia de la API.
las 15 tools del documento de control.
causas y acciones de cada error del documento de control.
eventos transport_document.* y sus payloads.