{"openapi":"3.1.0","info":{"title":"DeCAFacil API","description":"Emite y gestiona el DeCA desde tu propio ERP o software de gestión, sin tocar la PWA. Documentación completa (autenticación, cómo solicitar tu clave, límites y condiciones): https://decafacil.es/desarrolladores.","version":"1.0.0"},"paths":{"/yo":{"get":{"tags":["gestion"],"summary":"Verificar la clave y ver qué puede hacer","description":"Confirma que la clave de autenticación es válida y devuelve la cuenta a la que pertenece, sus permisos (scopes) y su modo (`real` o `pruebas`). No exige ningún scope concreto: cualquier clave válida puede consultarlo. Es el primer paso recomendado al integrar, antes de emitir nada.","operationId":"verificarClave","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/YoResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca":{"post":{"tags":["gestion"],"summary":"Emitir un DeCA","description":"Crea un DeCA a partir de los datos del envío (o envíos agrupados) y genera su PDF con el código QR. Acepta la cabecera opcional `Idempotency-Key`: repetir la misma petición con la misma clave de idempotencia devuelve la respuesta ya emitida en vez de crear un documento duplicado; con la misma clave y un cuerpo distinto, responde 409. Si envías `external_id`, debe ser único dentro de tu cuenta.","operationId":"emitirDeca","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaCreateRequest"},"examples":{"envio_unico":{"summary":"Envío único","value":{"datos":{"cargador_contractual":{"nombre":"Cargas Ejemplo SA","nif":"A76543214","direccion":{"empresa":"Cargas Ejemplo SA","via":"Polígono Industrial El Álamo, nave 12","localidad":"Getafe","provincia":"Madrid","codigo_postal":"28906","pais":"España"}},"transportista_efectivo":{"nombre":"Transportes Ejemplo SL","nif":"B12345674","direccion":{"empresa":"Transportes Ejemplo SL","via":"Calle del Transporte, 8","localidad":"Valencia","provincia":"Valencia","codigo_postal":"46013","pais":"España"}},"matricula_vehiculo":"1234ABC","envios":[{"ref":"PED-2026-0842","origen":{"via":"Polígono Industrial El Álamo, nave 12","localidad":"Getafe","provincia":"Madrid","codigo_postal":"28906","pais":"España"},"destino":{"via":"Avenida del Puerto, 45","localidad":"Valencia","provincia":"Valencia","codigo_postal":"46023","pais":"España"},"mercancia":{"naturaleza":"Palets de material de construcción","peso_kg":8200,"bultos":12},"fecha_efectiva_servicio":"2026-08-28"}]},"ejecutado_por":"Integración ERP - Transportes Ejemplo SL","external_id":"PED-2026-0842"}}}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaCreateResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"external_id ya usado por otro DeCA de tu cuenta, o la misma Idempotency-Key con un cuerpo distinto al de la petición original.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"get":{"tags":["gestion"],"summary":"Listar tus DeCA","description":"Listado paginado de todos los DeCA de tu cuenta, en cualquier estado, más recientes primero. Admite paginación por cursor (`cursor`, tomado del `next_cursor` de la respuesta anterior — opaco, no lo interpretes) y los filtros `externalId`, `estado` y `modificado_desde`.\n\n**Feed de cambios (sin webhook):** para saber qué DeCA han sido corregidos en ruta o finalizados desde tu última consulta, sin sondear todo el listado, combina `modificado_desde` con `estado` y los campos `n_version`/`actualizado_en` de cada resumen:\n- `estado=finalizado&modificado_desde=<cursor>` → finalizados desde entonces.\n- `estado=emitido&modificado_desde=<cursor>` → quédate solo con los `n_version > 1` (los `n_version = 1` son emisiones nuevas, no correcciones).\n\nGuarda el mayor `actualizado_en` que veas en cada página como el `modificado_desde` de tu próxima consulta (no uses tu propio reloj, para no perder eventos por desfase de reloj); vuelve a pedir con un pequeño margen hacia atrás y deduplica por `(id, n_version)` si te preocupa algún empate al segundo.","operationId":"listarDecas","parameters":[{"name":"limite","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limite"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"externalId","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Externalid"}},{"name":"estado","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/DecaEstado"},{"type":"null"}],"title":"Estado"}},{"name":"modificado_desde","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Modificado Desde"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaListaResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/vivos":{"get":{"tags":["gestion"],"summary":"Listar los DeCA con URL pública activa ahora mismo","description":"Devuelve los DeCA de tu cuenta cuya URL pública (la que lee el código QR) es accesible sin autenticación en este instante, más recientes primero. Usa `limite` (por defecto 50, máximo 500) para acotar el tamaño de la respuesta.","operationId":"listarDecasVivos","parameters":[{"name":"limite","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limite"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DecaResumen"},"title":"Response Listardecasvivos"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/por-token/{token}":{"get":{"tags":["gestion"],"summary":"Buscar un DeCA por su token público","description":"Resuelve un DeCA de tu cuenta a partir del token que lleva impreso en su PDF, código QR y URL pública — útil cuando ya no conservas su identificador interno.","operationId":"obtenerDecaPorToken","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaDetailResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}":{"get":{"tags":["gestion"],"summary":"Consultar un DeCA","description":"Estado, metadatos y versión vigente de un DeCA de tu cuenta.","operationId":"obtenerDeca","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaDetailResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}/pdf":{"get":{"tags":["gestion"],"summary":"Descargar el PDF vigente de un DeCA","description":"Devuelve el PDF de la versión actualmente vigente del DeCA, sin necesidad de conocer su número de versión: si el documento se modifica, este mismo endpoint sigue sirviendo siempre la versión más reciente.","operationId":"descargarPdfVigente","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"El DeCA existe pero no tiene ninguna versión vigente.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}/versiones":{"get":{"tags":["gestion"],"summary":"Historial de versiones de un DeCA","description":"Lista todas las versiones de un DeCA — la vigente y las que quedaron superadas por una modificación — con quién hizo cada cambio y cuándo.","operationId":"listarVersiones","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DecaVersionSummary"},"title":"Response Listarversiones"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}/versiones/{n_version}/pdf":{"get":{"tags":["gestion"],"summary":"Descargar el PDF de una versión concreta","description":"Devuelve el PDF de una versión específica de un DeCA, esté o no vigente. A diferencia de la URL pública del QR, este endpoint no comprueba el estado del documento: también sirve versiones anuladas o reemplazadas, para que puedas recuperar tu propio historial.","operationId":"descargarPdfDeVersion","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"n_version","in":"path","required":true,"schema":{"type":"integer","title":"N Version"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}/modificacion":{"post":{"tags":["gestion"],"summary":"Modificar un DeCA en curso","description":"Corrige o cambia los datos de un DeCA durante el servicio. Con `metodo=in_place` corrige un dato del propio documento (matrícula, fecha…): misma URL y QR, se crea una nueva versión vigente, responde 200. Con `metodo=nuevo_fichero` el servicio real ha cambiado (cargador, transportista, origen/destino, mercancía…): se emite un DeCA nuevo con su propio token y QR, el original queda marcado como reemplazado, responde 201 con `reemplaza_a_id`. Admite la cabecera opcional `Idempotency-Key`, igual que la emisión.","operationId":"modificarDeca","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModificacionRequest"},"examples":{"in_place":{"summary":"in_place — corregir un dato (200)","value":{"campos":{"matricula_vehiculo":"5678XYZ"},"motivo":"Corrección de matrícula: error de transcripción","metodo":"in_place","ejecutado_por":"Integración ERP - Transportes Ejemplo SL"}},"nuevo_fichero":{"summary":"nuevo_fichero — cambia el servicio real (201)","value":{"campos":{"transportista_efectivo":{"nombre":"Subcontratas Ejemplo SL","nif":"B98765431","direccion":{"via":"Calle Nueva, 2","localidad":"Alicante","provincia":"Alicante","codigo_postal":"03001","pais":"España"}}},"motivo":"Cambio de transportista efectivo: subcontratación del servicio","metodo":"nuevo_fichero","ejecutado_por":"Integración ERP - Transportes Ejemplo SL"}}}}}},"responses":{"200":{"description":"Modificado in_place: mismo DeCA, misma URL/QR.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaModificacionResponse"}}}},"201":{"description":"Modificado con nuevo_fichero: DeCA nuevo, reemplaza_a_id apunta al original.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaModificacionNuevoFicheroResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"Conflicto de idempotencia (misma Idempotency-Key, cuerpo distinto).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}/finalizar":{"post":{"tags":["gestion"],"summary":"Finalizar el servicio de un DeCA","description":"Marca el DeCA como finalizado y fija su fecha de fin de servicio efectivo, lo que arranca la cuenta atrás de la ventana en la que la URL pública del QR sigue siendo accesible.","operationId":"finalizarDeca","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalizarRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecaFinalizarResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"El DeCA no está en estado 'emitido' (solo se puede finalizar desde ahí).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}/aviso":{"post":{"tags":["gestion"],"summary":"Registrar el aviso al conductor","description":"Deja constancia de que el PDF del DeCA se hizo llegar al conductor — trazabilidad obligatoria. No reenvía ni notifica nada por sí mismo: solo registra que ya ocurrió.","operationId":"registrarAviso","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvisoRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvisoResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"El DeCA no tiene versión vigente sobre la que registrar el aviso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/deca/{deca_id}/anular":{"post":{"tags":["gestion"],"summary":"Anular un DeCA","description":"Anula un DeCA con motivo. Su URL pública pasa a devolver 410 Gone; el historial de versiones conserva constancia de quién lo anuló, cuándo y por qué.","operationId":"anularDeca","parameters":[{"name":"deca_id","in":"path","required":true,"schema":{"type":"integer","title":"Deca Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnularRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnularResponse"}}}},"401":{"description":"No autenticado: falta la cabecera Authorization, o la clave no existe, está revocada o ha caducado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"La clave es válida pero no tiene el permiso (scope) que exige esta operación.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"422":{"description":"Los datos enviados no son válidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"No existe un DeCA con ese identificador para esta clave (incluye el de otra cuenta: nunca se distingue de \"no existe\", ver la nota de aislamiento por inquilino más arriba).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"El DeCA ya está anulado, o ya fue reemplazado por otro (metodo=nuevo_fichero) y no se puede anular por separado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}}},"components":{"schemas":{"AnularRequest":{"properties":{"motivo":{"type":"string","maxLength":2000,"minLength":1,"title":"Motivo"},"ejecutado_por":{"type":"string","maxLength":200,"minLength":1,"title":"Ejecutado Por","description":"Operador que anula el DeCA"}},"type":"object","required":["motivo","ejecutado_por"],"title":"AnularRequest","example":{"ejecutado_por":"Integración ERP - Transportes Ejemplo SL","motivo":"Transporte cancelado por el cliente antes de la carga"}},"AnularResponse":{"properties":{"id":{"type":"integer","title":"Id"},"estado":{"$ref":"#/components/schemas/DecaEstado"}},"type":"object","required":["id","estado"],"title":"AnularResponse","description":"`POST /deca/{id}/anular` — 200.","example":{"estado":"anulado","id":4213}},"ApiErrorDetalle":{"properties":{"code":{"type":"string","title":"Code","description":"Identificador estable del error — compara esto, no `mensaje`."},"mensaje":{"type":"string","title":"Mensaje","description":"Texto en español, puede reformularse entre versiones."}},"type":"object","required":["code","mensaje"],"title":"ApiErrorDetalle"},"ApiErrorResponse":{"properties":{"detail":{"$ref":"#/components/schemas/ApiErrorDetalle"}},"type":"object","required":["detail"],"title":"ApiErrorResponse"},"AvisoRequest":{"properties":{"canal":{"$ref":"#/components/schemas/DecaCanal"},"destino":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Destino"},"nota":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Nota"}},"type":"object","required":["canal"],"title":"AvisoRequest","example":{"canal":"whatsapp","destino":"+34600111222","nota":"Enviado antes de la carga"}},"AvisoResponse":{"properties":{"id":{"type":"integer","title":"Id"},"deca_id":{"type":"integer","title":"Deca Id"},"version_id":{"type":"integer","title":"Version Id"},"canal":{"$ref":"#/components/schemas/DecaCanal"},"destino":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Destino"},"enviado_en":{"type":"string","format":"date-time","title":"Enviado En"}},"type":"object","required":["id","deca_id","version_id","canal","enviado_en"],"title":"AvisoResponse","description":"`POST /deca/{id}/aviso` — 201. Confirma el registro del aviso al\nconductor (trazabilidad obligatoria), no reenvía nada.","example":{"canal":"whatsapp","deca_id":4213,"destino":"+34600111222","enviado_en":"2026-08-28T09:20:00Z","id":991,"version_id":8841}},"DatosDeCA":{"properties":{"cargador_contractual":{"allOf":[{"$ref":"#/components/schemas/Parte"}],"description":"Art. 6a (común)"},"transportista_efectivo":{"allOf":[{"$ref":"#/components/schemas/Parte"}],"description":"Art. 6b (común)"},"matricula_vehiculo":{"type":"string","minLength":4,"title":"Matricula Vehiculo","description":"Art. 6g — tractor (común)"},"matricula_remolque":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula Remolque","description":"remolque/semirremolque (común)"},"autorizacion_especial_circulacion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Autorizacion Especial Circulacion","description":"Art. 6e — solo cuando el servicio la requiera (común)"},"observaciones":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Observaciones","description":"Art. 6h — una global por DeCA"},"envios":{"items":{"$ref":"#/components/schemas/Envio"},"type":"array","maxItems":50,"minItems":1,"title":"Envios","description":"Uno o varios envíos agrupados (mismo cargador/transportista/vehículo)"}},"type":"object","required":["cargador_contractual","transportista_efectivo","matricula_vehiculo","envios"],"title":"DatosDeCA","description":"Contenido completo de un DeCA, con los apartados del artículo 6 de la\nOrden FOM/2861/2012.\n\nComunes a todo el grupo:\n  a) cargador_contractual (Art. 6a)\n  b) transportista_efectivo (Art. 6b)\n  g) matricula_vehiculo (Art. 6g, tractor); matricula_remolque por utilidad\n  e) autorizacion_especial_circulacion (Art. 6e, cuando sea exigible)\n  h) observaciones (Art. 6h) — una sola, global al DeCA\nPor envío (lista `envios`, 1..N):\n  c) origen, destino\n  d) mercancia\n  f) fecha_efectiva_servicio\n\nNo se exige identificación del conductor. La regla legal de agrupación\n(Resolución de 5 de junio de 2026, Sexto.1: mismo cargador y transportista)\nes estructural: ambos viven a nivel de grupo, no pueden diferir entre envíos."},"DecaCanal":{"type":"string","enum":["telefono","email","whatsapp","sms","presencial","otro"],"title":"DecaCanal"},"DecaCreateRequest":{"properties":{"datos":{"$ref":"#/components/schemas/DatosDeCA"},"ejecutado_por":{"type":"string","maxLength":200,"minLength":1,"title":"Ejecutado Por","description":"Operador que crea el DeCA"},"external_id":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"External Id","description":"Referencia opaca del sistema del integrador (única por cuenta)"}},"type":"object","required":["datos","ejecutado_por"],"title":"DecaCreateRequest"},"DecaCreateResponse":{"properties":{"id":{"type":"integer","title":"Id"},"token":{"type":"string","title":"Token"},"url":{"type":"string","title":"Url"},"n_version":{"type":"integer","title":"N Version"},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id"}},"type":"object","required":["id","token","url","n_version"],"title":"DecaCreateResponse","example":{"external_id":"PED-2026-0842","id":4213,"n_version":1,"token":"a1b2c3d4e5f6","url":"https://decafacil.es/d/a1b2c3d4e5f6"}},"DecaDetailResponse":{"properties":{"id":{"type":"integer","title":"Id"},"token":{"type":"string","title":"Token"},"estado":{"$ref":"#/components/schemas/DecaEstado"},"url":{"type":"string","title":"Url"},"fin_servicio":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Fin Servicio"},"url_expira_en":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Url Expira En"},"retencion_hasta":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Retencion Hasta"},"creado_en":{"type":"string","format":"date-time","title":"Creado En"},"actualizado_en":{"type":"string","format":"date-time","title":"Actualizado En"},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id"},"version_vigente":{"anyOf":[{"$ref":"#/components/schemas/DecaVersionSummary"},{"type":"null"}]}},"type":"object","required":["id","token","estado","url","fin_servicio","url_expira_en","retencion_hasta","creado_en","actualizado_en","version_vigente"],"title":"DecaDetailResponse","example":{"actualizado_en":"2026-08-28T09:15:00Z","creado_en":"2026-08-28T09:00:00Z","estado":"emitido","external_id":"PED-2026-0842","id":4213,"token":"a1b2c3d4e5f6","url":"https://decafacil.es/d/a1b2c3d4e5f6","version_vigente":{"creado_en":"2026-08-28T09:15:00Z","ejecutado_por":"Integración ERP - Transportes Ejemplo SL","id":8841,"metodo":"in_place","motivo_cambio":"Corrección de matrícula: error de transcripción","n_version":2,"pdf_bytes":214532,"pdf_path":"/data/storage/4213/v2.pdf","vigente":true}}},"DecaEstado":{"type":"string","enum":["emitido","finalizado","expirado","reemplazada","anulado"],"title":"DecaEstado"},"DecaFinalizarResponse":{"properties":{"id":{"type":"integer","title":"Id"},"estado":{"$ref":"#/components/schemas/DecaEstado"},"fin_servicio":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Fin Servicio"},"url_expira_en":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Url Expira En"}},"type":"object","required":["id","estado"],"title":"DecaFinalizarResponse","description":"`POST /deca/{id}/finalizar` — 200.","example":{"estado":"finalizado","fin_servicio":"2026-08-28T17:30:00Z","id":4213,"url_expira_en":"2026-09-04T17:30:00Z"}},"DecaListaResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DecaResumen"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"DecaListaResponse","description":"Envoltura paginada de `GET /deca`. `next_cursor` es opaco — no lo\ninterpretes, solo devuélvelo tal cual en la siguiente petición como\nparámetro `cursor` — y sale `None` cuando esta página es la última.","example":{"items":[{"creado_en":"2026-08-28T09:00:00Z","estado":"emitido","external_id":"PED-2026-0842","fecha_efectiva_servicio":"2026-08-28","id":4213,"matricula_vehiculo":"1234ABC","n_envios":1,"token":"a1b2c3d4e5f6","url":"https://decafacil.es/d/a1b2c3d4e5f6"}]}},"DecaMetodoModificacion":{"type":"string","enum":["in_place","nuevo_fichero"],"title":"DecaMetodoModificacion"},"DecaModificacionNuevoFicheroResponse":{"properties":{"id":{"type":"integer","title":"Id"},"token":{"type":"string","title":"Token"},"url":{"type":"string","title":"Url"},"n_version":{"type":"integer","title":"N Version"},"reemplaza_a_id":{"type":"integer","title":"Reemplaza A Id"}},"type":"object","required":["id","token","url","n_version","reemplaza_a_id"],"title":"DecaModificacionNuevoFicheroResponse","description":"`POST /deca/{id}/modificacion`, método `nuevo_fichero` — 201. DeCA\nnuevo (token/URL/QR propios); `reemplaza_a_id` apunta al original, que\npasa a estado 'reemplazada'.","example":{"id":4298,"n_version":1,"reemplaza_a_id":4213,"token":"f6e5d4c3b2a1","url":"https://decafacil.es/d/f6e5d4c3b2a1"}},"DecaModificacionResponse":{"properties":{"id":{"type":"integer","title":"Id"},"token":{"type":"string","title":"Token"},"url":{"type":"string","title":"Url"},"n_version":{"type":"integer","title":"N Version"}},"type":"object","required":["id","token","url","n_version"],"title":"DecaModificacionResponse","description":"`POST /deca/{id}/modificacion`, método `in_place` — 200. Mismo DeCA,\nmisma URL/QR: solo cambia la versión vigente.","example":{"id":4213,"n_version":2,"token":"a1b2c3d4e5f6","url":"https://decafacil.es/d/a1b2c3d4e5f6"}},"DecaResumen":{"properties":{"id":{"type":"integer","title":"Id"},"token":{"type":"string","title":"Token"},"url":{"type":"string","title":"Url"},"estado":{"$ref":"#/components/schemas/DecaEstado"},"matricula_vehiculo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matricula Vehiculo"},"fecha_efectiva_servicio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fecha Efectiva Servicio"},"n_envios":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N Envios"},"n_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N Version"},"fin_servicio":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Fin Servicio"},"url_expira_en":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Url Expira En"},"creado_en":{"type":"string","format":"date-time","title":"Creado En"},"actualizado_en":{"type":"string","format":"date-time","title":"Actualizado En"},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id"}},"type":"object","required":["id","token","url","estado","creado_en","actualizado_en"],"title":"DecaResumen","description":"Resumen ligero de un DeCA (id, token, url, estado + datos clave de la versión\nvigente). Lo devuelven `GET /deca/vivos`, `GET /deca` y `GET /deca/por-token`.\n\n`fecha_efectiva_servicio` es la del ÚLTIMO envío del grupo (la que\ndetermina la caducidad); `n_envios` indica cuántos envíos agrupa.","example":{"actualizado_en":"2026-08-28T09:00:00Z","creado_en":"2026-08-28T09:00:00Z","estado":"emitido","external_id":"PED-2026-0842","fecha_efectiva_servicio":"2026-08-28","id":4213,"matricula_vehiculo":"1234ABC","n_envios":1,"n_version":1,"token":"a1b2c3d4e5f6","url":"https://decafacil.es/d/a1b2c3d4e5f6"}},"DecaVersionSummary":{"properties":{"id":{"type":"integer","title":"Id"},"n_version":{"type":"integer","title":"N Version"},"vigente":{"type":"boolean","title":"Vigente"},"metodo":{"anyOf":[{"$ref":"#/components/schemas/DecaMetodoModificacion"},{"type":"null"}]},"motivo_cambio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motivo Cambio"},"ejecutado_por":{"type":"string","title":"Ejecutado Por"},"pdf_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pdf Path"},"pdf_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pdf Bytes"},"creado_en":{"type":"string","format":"date-time","title":"Creado En"}},"type":"object","required":["id","n_version","vigente","metodo","motivo_cambio","ejecutado_por","pdf_path","pdf_bytes","creado_en"],"title":"DecaVersionSummary","description":"Una versión del historial de un DeCA. `pdf_path` es la ruta interna\ndonde se guarda el PDF de esta versión (informativa: no es accesible\ndirectamente — usa `GET /deca/{id}/versiones/{n_version}/pdf` para\ndescargarlo).","example":{"creado_en":"2026-08-28T09:15:00Z","ejecutado_por":"Integración ERP - Transportes Ejemplo SL","id":8841,"metodo":"in_place","motivo_cambio":"Corrección de matrícula: error de transcripción","n_version":2,"pdf_bytes":214532,"pdf_path":"/data/storage/4213/v2.pdf","vigente":true}},"Direccion":{"properties":{"empresa":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Empresa","description":"Nombre de la empresa o titular de la dirección (primera línea)"},"via":{"type":"string","maxLength":200,"minLength":1,"title":"Via","description":"Calle, número, polígono, etc."},"localidad":{"type":"string","maxLength":120,"minLength":1,"title":"Localidad"},"provincia":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Provincia"},"codigo_postal":{"anyOf":[{"type":"string","maxLength":6,"minLength":4},{"type":"null"}],"title":"Codigo Postal"},"pais":{"type":"string","maxLength":80,"title":"Pais","default":"España"}},"type":"object","required":["via","localidad"],"title":"Direccion","description":"Dirección estructurada, reutilizada en cargador/transportista (domicilio,\nArt. 6a) y en origen/destino de cada envío (Art. 6c).\n\n`empresa` (opcional) identifica al titular de la dirección — se usa como\nprimera línea del bloque de dirección en origen/destino. En el domicilio de\ncargador/transportista el titular ya viene por `Parte.nombre`, así que ahí\nqueda vacío."},"Envio":{"properties":{"ref":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Ref","description":"Identidad estable del envío (p. ej. 'C123-D456')"},"origen":{"allOf":[{"$ref":"#/components/schemas/Direccion"}],"description":"Art. 6c"},"destino":{"allOf":[{"$ref":"#/components/schemas/Direccion"}],"description":"Art. 6c"},"mercancia":{"allOf":[{"$ref":"#/components/schemas/Mercancia"}],"description":"Art. 6d"},"fecha_efectiva_servicio":{"type":"string","format":"date","title":"Fecha Efectiva Servicio","description":"Art. 6f"}},"type":"object","required":["origen","destino","mercancia","fecha_efectiva_servicio"],"title":"Envio","description":"Un envío dentro del grupo. Cada envío aporta sus propios origen, destino,\nmercancía y fecha efectiva; los datos comunes (cargador, transportista,\nvehículo) viven a nivel de `DatosDeCA`.\n\n`ref` es la identidad estable del envío dentro del grupo — cualquier\nreferencia propia que te sirva para direccionar correcciones por envío en\nruta (p. ej. \"C123-D456\") y como puente de trazabilidad con tu propio\nsistema. Opcional pero recomendado."},"FinalizarRequest":{"properties":{"fin_servicio":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Fin Servicio","description":"Si se omite, se usa now(). Siempre en UTC."}},"type":"object","title":"FinalizarRequest","example":{"fin_servicio":"2026-08-28T17:30:00Z"}},"Mercancia":{"properties":{"naturaleza":{"type":"string","minLength":1,"title":"Naturaleza"},"peso_kg":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Peso Kg","description":"Peso en kg"},"bultos":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Bultos","description":"Número de bultos (alternativa al peso)"},"volumen_m3":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Volumen M3","description":"Volumen en m³ (alternativa al peso)"}},"type":"object","required":["naturaleza"],"title":"Mercancia","description":"Naturaleza y cantidad de la mercancía (Art. 6d). El reglamento admite indicar\nel peso o, en su defecto, otra magnitud (bultos o volumen); las tres son\nopcionales pero se exige al menos una."},"ModificacionRequest":{"properties":{"campos":{"type":"object","title":"Campos","description":"Campos a modificar (lista blanca)"},"motivo":{"type":"string","maxLength":2000,"minLength":1,"title":"Motivo"},"metodo":{"$ref":"#/components/schemas/DecaMetodoModificacion"},"ejecutado_por":{"type":"string","maxLength":200,"minLength":1,"title":"Ejecutado Por"},"envio_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Envio Ref","description":"ref del envío a corregir (campos por-envío)"},"envio_nuevo":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Envio Nuevo","description":"Envío nuevo a añadir — fraccionar carga (solo in_place)"},"envio_eliminar_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Envio Eliminar Ref","description":"ref del envío a eliminar (solo in_place, solo si el documento es multienvío)"},"informado_por":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Informado Por"},"informado_canal":{"anyOf":[{"$ref":"#/components/schemas/DecaCanal"},{"type":"null"}]},"informado_en":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Informado En"}},"type":"object","required":["campos","motivo","metodo","ejecutado_por"],"title":"ModificacionRequest"},"Parte":{"properties":{"nombre":{"type":"string","maxLength":200,"minLength":1,"title":"Nombre"},"nif":{"type":"string","maxLength":15,"minLength":9,"title":"Nif"},"direccion":{"allOf":[{"$ref":"#/components/schemas/Direccion"}],"description":"Domicilio de la parte"}},"type":"object","required":["nombre","nif","direccion"],"title":"Parte","description":"Identificación de una empresa o persona (cargador, transportista)."},"YoResponse":{"properties":{"cliente":{"type":"string","title":"Cliente"},"administracion":{"type":"boolean","title":"Administracion"},"cuenta":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cuenta"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"modo":{"type":"string","enum":["real","pruebas"],"title":"Modo"},"expira":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expira"}},"type":"object","required":["cliente","administracion","scopes","modo"],"title":"YoResponse","description":"`GET /yo` — 200. Confirma que la clave funciona y qué puede hacer, sin\nfiltrar de más (no expone `id`/`prefijo`/`clave_hash`).","example":{"administracion":false,"cliente":"Transportes Ejemplo SL","cuenta":"gestion@ejemplo.es","modo":"pruebas","scopes":["leer","crear","modificar","finalizar"]}}}},"servers":[{"url":"/api/v1"}]}