Saltar al contenido
DecaLegal

API de DecaLegal · v1.0.0

La misma API que usa el portal, para integrar tu ERP: crear envíos, preparar y emitir documentos, consultar versiones y descargar PDF, QR y evidencias. El servidor valida cada cuerpo contra el contrato OpenAPI publicado aquí.

URL base
https://deca.legal/api/v1
Formato
JSON en UTF-8; ficheros en multipart/form-data
Autenticación
Bearer token de integración, con permisos por ámbito
Límite de peticiones
Por cliente de integración; cabeceras Retry-After en 429

Autenticación y permisos

Cada empresa crea sus clientes de integración en el portal (Integraciones) y emite tokens con los ámbitos que necesita. El token identifica al cliente y al espacio de trabajo: no existe ningún parámetro para elegir otro. Los tokens se muestran una sola vez y se pueden revocar en cualquier momento.

curl https://deca.legal/api/v1/me \
  -H "Authorization: Bearer $DECAPLUS_TOKEN" \
  -H "Accept: application/json"

Ámbitos disponibles:

  • shipments:readConsultar envíos
  • shipments:writeCrear y editar envíos
  • documents:readConsultar documentos
  • documents:issueEmitir documentos
  • documents:amendModificar documentos emitidos
  • transports:completeRegistrar el fin real del servicio
  • imports:writeSubir archivos para importar
  • evidence:readDescargar expedientes de evidencias

Convenciones

Idempotencia
Las operaciones que crean o emiten aceptan la cabecera Idempotency-Key, única por espacio de trabajo, cliente, método y ruta. Repetir la misma clave con el mismo cuerpo devuelve la misma respuesta; con otro cuerpo, 409.
Emisión asíncrona
Emitir devuelve 202 con una operación. Consulta su estado o espera el webhook: el documento sólo pasa a publicado cuando el PDF está custodiado y la descarga de inspección responde.
Concurrencia
Las ediciones de borradores exigen la cabecera If-Match con el ETag del recurso. Sin ella la respuesta es 428; si otro proceso lo cambió antes, 409, y hay que releer.
Errores
Cuerpo JSON con código estable, mensaje en español y, en 422, la lista de campos con su problema. Nada de lo emitido se puede modificar ni borrar por API.

Platform

GET /me Credencial y workspace efectivo

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 429Límite temporal de uso
GET /operations/{id} Estado de operación asíncrona

Sólo la integración/workspace con permiso sobre el recurso original puede consultar. Hereda scopes del recurso; no es acceso global por conocer UUID.

Parámetros

  • id · path · obligatorio
    string (uuid)

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente

Shipments

GET /shipments Listar envíos del workspace

Ámbito requerido: shipments:read

Parámetros

  • cursor · query
    string
  • limit · query
    integer
  • status · query
    string
  • external_id · query
    string

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
POST /shipments Crear borrador de envío

Ámbito requerido: shipments:write

Parámetros

  • Idempotency-Key · header · obligatorio
    string — Clave por workspace/cliente/método/ruta. Mismo cuerpo devuelve misma operación; cuerpo distinto: 409. Ventana mínima de deduplicación: 7 días.

Cuerpo · application/json

  • source_system *
    string
  • external_id *
    string
  • contractual_loader *
    object
  • effective_carrier *
    object
  • origin *
    object
  • destination *
    object
  • goods *
    object[]
  • transport_date *
    string (date)
  • vehicle *
    object — En articulado son obligatorias las matrículas del tractor y del remolque/semirremolque. Validación de formato por país, sin asumir siempre matrícula española.
  • special_circulation_authorization_required *
    boolean
  • special_circulation_authorization *
    object | null
  • observations
    string | null
  • regulatory_profile *
    const "deca_basic"
  • cargo_scope_declaration *
    "ordinary_confirmed" | "special_or_unknown"
  • internal_reference
    string | null
  • run_id
    string (uuid) | null

Respuestas

  • 201Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 409Conflicto de estado, revisión o idempotencia
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
GET /shipments/{id} Consultar un envío

Ámbito requerido: shipments:read

Parámetros

  • id · path · obligatorio
    string (uuid)

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
PATCH /shipments/{id} Editar borrador con control de concurrencia

Ámbito requerido: shipments:write

Parámetros

  • id · path · obligatorio
    string (uuid)
  • If-Match · header · obligatorio
    string — ETag fuerte obtenido del recurso. Revisión obsoleta: 409; ausente: 428.

Cuerpo · application/json

  • contractual_loader
    object
  • effective_carrier
    object
  • origin
    object
  • destination
    object
  • goods
    object[]
  • transport_date
    string (date)
  • vehicle
    object — En articulado son obligatorias las matrículas del tractor y del remolque/semirremolque. Validación de formato por país, sin asumir siempre matrícula española.
  • special_circulation_authorization_required
    boolean
  • special_circulation_authorization
    object | null
  • observations
    string | null
  • regulatory_profile
    const "deca_basic"
  • cargo_scope_declaration
    "ordinary_confirmed" | "special_or_unknown"
  • internal_reference
    string | null
  • run_id
    string (uuid) | null

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 409Conflicto de estado, revisión o idempotencia
  • 422Validación de datos o de dominio
  • 428Precondición requerida
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
POST /shipments/{id}/complete Registrar final real del servicio

Ámbito requerido: transports:complete

Parámetros

  • id · path · obligatorio
    string (uuid)
  • Idempotency-Key · header · obligatorio
    string — Clave por workspace/cliente/método/ruta. Mismo cuerpo devuelve misma operación; cuerpo distinto: 409. Ventana mínima de deduplicación: 7 días.

Cuerpo · application/json

  • actual_finished_at *
    string (date-time)
  • reason
    string | null

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 409Conflicto de estado, revisión o idempotencia
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente

Documents

POST /documents Preparar DeCA desde envíos agrupables

Ámbito requerido: documents:issue

Parámetros

  • Idempotency-Key · header · obligatorio
    string — Clave por workspace/cliente/método/ruta. Mismo cuerpo devuelve misma operación; cuerpo distinto: 409. Ventana mínima de deduplicación: 7 días.

Cuerpo · application/json

  • shipment_ids *
    string (uuid)[]
  • regulatory_profile *
    const "deca_basic"

Respuestas

  • 201Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 409Conflicto de estado, revisión o idempotencia
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
GET /documents/{id} Documento lógico y borrador activo

Ámbito requerido: documents:read

Parámetros

  • id · path · obligatorio
    string (uuid)

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
POST /documents/{id}/issue Emitir y publicar de forma asíncrona

No devuelve éxito final antes de verificar archivo WORM y publicación. operation.result contiene URL/QR/hash al finalizar. Un nuevo borrador de enmienda usa esta misma operación.

Ámbito requerido: documents:issue

Parámetros

  • id · path · obligatorio
    string (uuid)
  • Idempotency-Key · header · obligatorio
    string — Clave por workspace/cliente/método/ruta. Mismo cuerpo devuelve misma operación; cuerpo distinto: 409. Ventana mínima de deduplicación: 7 días.

Cuerpo · application/json

  • draft_id *
    string (uuid)
  • draft_revision *
    integer

Respuestas

  • 202Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 409Conflicto de estado, revisión o idempotencia
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
GET /documents/{id}/versions Versiones de ese documento

Ámbito requerido: documents:read

Parámetros

  • id · path · obligatorio
    string (uuid)
  • cursor · query
    string
  • limit · query
    integer

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
POST /documents/{id}/amendments Crear borrador Vn+1 desde versión vigente

Ámbito requerido: documents:amend

Parámetros

  • id · path · obligatorio
    string (uuid)
  • Idempotency-Key · header · obligatorio
    string — Clave por workspace/cliente/método/ruta. Mismo cuerpo devuelve misma operación; cuerpo distinto: 409. Ventana mínima de deduplicación: 7 días.
  • If-Match · header · obligatorio
    string — ETag fuerte obtenido del recurso. Revisión obsoleta: 409; ausente: 428.

Cuerpo · application/json

  • base_version_id *
    string (uuid)
  • reason *
    string
  • shipments *
    object[]

Respuestas

  • 201Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 409Conflicto de estado, revisión o idempotencia
  • 422Validación de datos o de dominio
  • 428Precondición requerida
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
GET /document-versions/{id}/pdf Descargar pdf de versión autorizada

Descarga privada autenticada; no usar esta ruta como URL del QR.

Ámbito requerido: documents:read

Parámetros

  • id · path · obligatorio
    string (uuid)

Respuestas

  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
  • 200Bytes del archivo de esa versión
GET /document-versions/{id}/qr Descargar qr de versión autorizada

Descarga privada autenticada; no usar esta ruta como URL del QR.

Ámbito requerido: documents:read

Parámetros

  • id · path · obligatorio
    string (uuid)
  • format · query
    "png" | "svg"

Respuestas

  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
  • 200Bytes del archivo de esa versión
GET /document-versions/{id}/evidence Descargar evidence de versión autorizada

Descarga privada autenticada; no usar esta ruta como URL del QR.

Ámbito requerido: evidence:read

Parámetros

  • id · path · obligatorio
    string (uuid)

Respuestas

  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
  • 200Bytes del archivo de esa versión

Imports

POST /imports Subir archivo para extracción o mapeo

La idempotencia de multipart incluye hash del archivo y metadatos normalizados, no el boundary MIME. No aceptar URLs remotas arbitrarias. Documento con IA siempre termina en revisión humana antes de emisión.

Ámbito requerido: imports:write

Parámetros

  • Idempotency-Key · header · obligatorio
    string — Clave por workspace/cliente/método/ruta. Mismo cuerpo devuelve misma operación; cuerpo distinto: 409. Ventana mínima de deduplicación: 7 días.

Cuerpo · multipart/form-data

  • file *
    string (binary)
  • kind *
    "spreadsheet" | "document"
  • mapping_id
    string (uuid) | null

Respuestas

  • 202Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 409Conflicto de estado, revisión o idempotencia
  • 413Archivo demasiado grande
  • 415Tipo no admitido
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente
GET /imports/{id} Consultar importación y sus errores

Ámbito requerido: imports:write

Parámetros

  • id · path · obligatorio
    string (uuid)
  • cursor · query
    string
  • limit · query
    integer

Respuestas

  • 200Respuesta correcta
  • 401Credencial ausente o inválida
  • 403Permiso insuficiente
  • 404Recurso inexistente o no accesible
  • 422Validación de datos o de dominio
  • 429Límite temporal de uso
  • 503Dependencia no disponible temporalmente

Inspection

GET /d/{public_token}.pdf Inspección directa independiente de Laravel

Token sin login/captcha/botón intermedio. Lookup de su hash en Azure, expiración por reloj, lectura del blob/version exactos. No redirigir QR antiguo a la versión vigente. 404 neutro para token inexistente o acceso caducado. Sincronización de control en Azure: no consulta DB/Redis de Forge.

Se sirve desde la capa de descarga, fuera de la URL base: https://documents.example.invalid

Parámetros

  • public_token · path · obligatorio
    string — Capacidad secreta de 256 bits; no es UUID de tabla ni dato para analítica.

Respuestas

  • 200PDF exacto, inmutable y vigente para descarga de esta versión
  • 404No disponible; respuesta neutra sin metadatos empresariales
  • 429Protección antiabuso proporcionada, no bloqueo habitual de inspecciones
  • 503Fallo temporal de origen o integridad. Nunca PDF distinto como sustitución.
HEAD /d/{public_token}.pdf Inspección directa independiente de Laravel

Token sin login/captcha/botón intermedio. Lookup de su hash en Azure, expiración por reloj, lectura del blob/version exactos. No redirigir QR antiguo a la versión vigente. 404 neutro para token inexistente o acceso caducado. Sincronización de control en Azure: no consulta DB/Redis de Forge.

Se sirve desde la capa de descarga, fuera de la URL base: https://documents.example.invalid

Parámetros

  • public_token · path · obligatorio
    string — Capacidad secreta de 256 bits; no es UUID de tabla ni dato para analítica.

Respuestas

  • 200PDF exacto, inmutable y vigente para descarga de esta versión
  • 404No disponible; respuesta neutra sin metadatos empresariales
  • 429Protección antiabuso proporcionada, no bloqueo habitual de inspecciones
  • 503Fallo temporal de origen o integridad. Nunca PDF distinto como sustitución.

Esta página se genera del contrato OpenAPI del repositorio; el detalle completo de esquemas, enumeraciones y ejemplos está en el fichero descargable.