{
  "openapi": "3.0.3",
  "info": {
    "title": "DECA ERP API",
    "version": "1.8.0",
    "description": "REST API for integrating DECA ERP with invoicing, dispatch and fleet management systems. Create incomplete trips, immediately obtain a private completion link, check their status, download the current PDF, synchronize master data, batch-import customers and manage multi-shipment trips.\n\nAlways send authentication in the `X-Api-Key` header. Test requests operate on the company linked to that key.",
    "contact": {
      "name": "DECA ERP support",
      "email": "nts@netsistemas.com",
      "url": "https://deca.netsistemas.com/integracion-erp.html"
    },
    "license": {
      "name": "Use subject to the terms of service",
      "url": "https://deca.netsistemas.com/legal.php"
    }
  },
  "externalDocs": {
    "description": "ERP integration guide, examples and demo project",
    "url": "https://deca.netsistemas.com/integracion-erp.html"
  },
  "servers": [
    {
      "url": "https://deca.netsistemas.com",
      "description": "DECA ERP server"
    }
  ],
  "tags": [
    {
      "name": "Write operations",
      "description": "Create and update DeCA documents. The JSON `accion` field selects the operation."
    },
    {
      "name": "Read operations",
      "description": "Individual retrieval, ERP reference searches and filtered lists."
    },
    {
      "name": "History",
      "description": "Immutable PDF versions and change auditing for each document."
    },
    {
      "name": "Downloads",
      "description": "Asynchronous ZIP batch preparation and status tracking."
    },
    {
      "name": "Carrier completion",
      "description": "Private links for the carrier to complete and submit the permitted details."
    },
    {
      "name": "Multi-stop trips",
      "description": "Multi-shipment documents. Each shipment identifies its origin, destination, reference and goods lines."
    },
    {
      "name": "ERP master data",
      "description": "Idempotent synchronization of customers, carriers, vehicles and drivers using `origenRegistro` and `idExterno`."
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    },
    {
      "UserApiKeyAuth": []
    }
  ],
  "paths": {
    "/api.php": {
      "post": {
        "tags": [
          "Write operations"
        ],
        "operationId": "escribirDeca",
        "summary": "Create or update a DeCA",
        "description": "Use `accion=crear` to create and `accion=actualizar` with `id` to update a document. Updates behave like PATCH: omitted fields are preserved. Including `lineas` replaces all existing goods lines.\n\nCreation without `fechaTransporte` leaves the trip unscheduled with no PDF yet, but the response already includes `urlEdicion`. The `modoEdicionTransportista` permission is stored on the server: `operativo` allows date and registrations; `carga` also allows goods description, quantity, unit and weight. The carrier can save drafts and submit completion; the ERP checks `estadoCumplimentacion`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/DecaCreateRequest"
                  },
                  {
                    "$ref": "#/components/schemas/DecaUpdateRequest"
                  }
                ],
                "discriminator": {
                  "propertyName": "accion",
                  "mapping": {
                    "crear": "#/components/schemas/DecaCreateRequest",
                    "actualizar": "#/components/schemas/DecaUpdateRequest"
                  }
                }
              },
              "examples": {
                "crearPlanificado": {
                  "summary": "Create a trip with a date and goods",
                  "value": {
                    "accion": "crear",
                    "cargadorNombre": "Harinas Leonesas SL",
                    "cargadorNif": "B24010101",
                    "cargadorDomicilio": "Pol. Ind. León Oeste 12, León",
                    "transportistaNombre": "Transportes del Norte SL",
                    "transportistaNif": "B00000001",
                    "origen": "León",
                    "destino": "Valladolid",
                    "fechaTransporte": "2026-08-20",
                    "matriculaTractora": "1234 KLM",
                    "matriculaRemolque": "R 1234 ABC",
                    "numAlbaran": "ALB-2026-001",
                    "origenRegistro": "ERP_CLIENTE",
                    "idExterno": "EXP-12345",
                    "lineas": [
                      {
                        "descripcion": "Harina de trigo",
                        "cantidad": 40,
                        "unidad": "sacos",
                        "pesoKg": 1000
                      },
                      {
                        "descripcion": "Sémola de trigo",
                        "cantidad": 10,
                        "unidad": "sacos",
                        "pesoKg": 250
                      }
                    ]
                  }
                },
                "crearNoPlanificado": {
                  "summary": "Create an unscheduled trip",
                  "value": {
                    "accion": "crear",
                    "cargadorNombre": "Cerámicas Levante SA",
                    "cargadorNif": "A46020202",
                    "origen": "Valencia",
                    "destino": "Burgos",
                    "origenRegistro": "ERP_CLIENTE",
                    "idExterno": "PRE-2026-0042",
                    "modoEdicionTransportista": "carga",
                    "diasValidezEnlace": 30,
                    "observaciones": "Pendiente de planificación"
                  }
                },
                "asignarFecha": {
                  "summary": "Assign a date to an unscheduled trip",
                  "value": {
                    "accion": "actualizar",
                    "id": 125,
                    "fechaTransporte": "2026-08-21",
                    "cargadorDomicilio": "Av. Mediterráneo 18, Valencia",
                    "matriculaTractora": "7350 LPD",
                    "lineas": [
                      {
                        "descripcion": "Azulejo cerámico paletizado",
                        "cantidad": 18,
                        "unidad": "palets",
                        "pesoKg": 12600
                      }
                    ]
                  }
                },
                "actualizarVehiculo": {
                  "summary": "Change vehicle without altering other details",
                  "value": {
                    "accion": "actualizar",
                    "id": 125,
                    "matriculaTractora": "7350 LPD",
                    "matriculaRemolque": "R 8841 LHG",
                    "observaciones": "Cambio de tractora comunicado desde el ERP"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document created or updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecaWriteResponse"
                },
                "examples": {
                  "conPdf": {
                    "summary": "Dated trip",
                    "value": {
                      "ok": true,
                      "idDeca": 125,
                      "token": "7f4ef35861d34c748be6d12058741b96",
                      "url": "https://deca.netsistemas.com/deca.php?t=7f4ef35861d34c748be6d12058741b96",
                      "numVersion": 1,
                      "pdf": true
                    }
                  },
                  "sinPdf": {
                    "summary": "Unscheduled trip",
                    "value": {
                      "ok": true,
                      "idDeca": 126,
                      "token": "98d49c58694f4ccf8dd6585726127454",
                      "url": "https://deca.netsistemas.com/deca.php?t=98d49c58694f4ccf8dd6585726127454",
                      "urlDocumento": null,
                      "urlDescargaPdf": null,
                      "urlEdicion": "https://deca.netsistemas.com/completar_matriculas.php?t=ejemplo_privado",
                      "modoEdicionTransportista": "carga",
                      "camposEditables": [
                        "fechaTransporte",
                        "matriculaTractora",
                        "matriculaRemolque",
                        "mercancias"
                      ],
                      "estadoCumplimentacion": "no_iniciado",
                      "enlaceActivo": true,
                      "numVersion": null,
                      "pdf": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "tags": [
          "Read operations"
        ],
        "operationId": "consultarDeca",
        "summary": "Retrieve, find or list DeCAs",
        "description": "The `accion` parameter selects the query:\n\n- `consultar`: retrieves a document by `id`, including completion status.\n- `enlace_edicion`: returns the same active private link or creates one if none exists.\n- `buscar`: finds the ERP-linked document using `origen` and `idExterno`.\n- `listar`: returns a page of results and accepts optional dates.\n\nTo list unscheduled trips, use `noPlanificados=1`. Do not filter by transport date in this case, as those trips have no transport date.",
        "parameters": [
          {
            "name": "accion",
            "in": "query",
            "required": true,
            "description": "Type of query to execute.",
            "schema": {
              "type": "string",
              "enum": [
                "consultar",
                "enlace_edicion",
                "buscar",
                "listar"
              ]
            },
            "example": "listar"
          },
          {
            "name": "id",
            "in": "query",
            "description": "DeCA identifier. Required for `accion=consultar` or `accion=enlace_edicion`.",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "example": 125
          },
          {
            "name": "modoEdicionTransportista",
            "in": "query",
            "description": "Link permission. Only for `accion=enlace_edicion`; does not reopen completed links.",
            "schema": {
              "type": "string",
              "enum": [
                "operativo",
                "carga"
              ],
              "default": "operativo"
            }
          },
          {
            "name": "diasValidezEnlace",
            "in": "query",
            "description": "Validity of a new link. Only for `accion=enlace_edicion`.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 90,
              "default": 30
            }
          },
          {
            "name": "origen",
            "in": "query",
            "description": "Stable source-system code. Required for `accion=buscar`.",
            "schema": {
              "type": "string"
            },
            "example": "ERP_CLIENTE"
          },
          {
            "name": "idExterno",
            "in": "query",
            "description": "ERP shipment, dispatch or delivery-note identifier. Required for `accion=buscar`.",
            "schema": {
              "type": "string",
              "maxLength": 512
            },
            "example": "EXP-12345"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of records. Only for `accion=listar`.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "First record of the page. Only for `accion=listar`.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "fechaCampo",
            "in": "query",
            "description": "Date field used by `fechaDesde` and `fechaHasta`. Only for `accion=listar`.",
            "schema": {
              "type": "string",
              "enum": [
                "creacion",
                "modificacion",
                "registro",
                "transporte"
              ],
              "default": "creacion"
            }
          },
          {
            "name": "fechaDesde",
            "in": "query",
            "description": "Inclusive start date. Optional and usable without an end date.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-08-01"
          },
          {
            "name": "fechaHasta",
            "in": "query",
            "description": "Inclusive end date. Optional and usable without a start date.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-08-31"
          },
          {
            "name": "noPlanificados",
            "in": "query",
            "description": "Use `1` to return only trips without `fechaTransporte`. Only for `accion=listar`.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful query. The structure depends on `accion`.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DecaConsultaResponse"
                    },
                    {
                      "$ref": "#/components/schemas/DecaBusquedaResponse"
                    },
                    {
                      "$ref": "#/components/schemas/DecaListadoResponse"
                    },
                    {
                      "$ref": "#/components/schemas/EnlaceEdicionResponse"
                    }
                  ]
                },
                "examples": {
                  "consulta": {
                    "summary": "Query result by ID",
                    "value": {
                      "ok": true,
                      "idDeca": 125,
                      "url": "https://deca.netsistemas.com/deca.php?t=7f4ef35861d34c748be6d12058741b96",
                      "numVersion": 2,
                      "fechaTransporte": "2026-08-21",
                      "matriculaTractora": "1234 KLM",
                      "matriculaRemolque": null,
                      "estado": {
                        "anulado": false,
                        "terminado": false,
                        "albaranado": true,
                        "numAlbaran": "ALB-2026-001"
                      },
                      "origenRegistro": "ERP_CLIENTE",
                      "idExterno": "EXP-12345",
                      "lineas": [
                        {
                          "descripcion": "Harina de trigo",
                          "cantidad": 40,
                          "unidad": "sacos",
                          "pesoKg": 1000
                        }
                      ]
                    }
                  },
                  "busquedaNoEncontrada": {
                    "summary": "ERP reference not found",
                    "value": {
                      "ok": true,
                      "encontrado": false
                    }
                  },
                  "listado": {
                    "summary": "Results page",
                    "value": {
                      "ok": true,
                      "total": 1,
                      "limit": 100,
                      "offset": 0,
                      "fechaCampo": "creacion",
                      "items": [
                        {
                          "idDeca": 125,
                          "fechaTransporte": "2026-08-21",
                          "cargadorNombre": "Harinas Leonesas SL",
                          "origen": "León",
                          "destino": "Valladolid",
                          "mercancia": "Harina de trigo",
                          "numVersion": 2,
                          "url": "https://deca.netsistemas.com/deca.php?t=7f4ef35861d34c748be6d12058741b96",
                          "fechaCreacion": "2026-08-20 09:30",
                          "fechaModificacion": "2026-08-20 10:15",
                          "fechaRegistro": "2026-08-20",
                          "origenRegistro": "ERP_CLIENTE",
                          "idExterno": "EXP-12345",
                          "estado": {
                            "anulado": false,
                            "terminado": false,
                            "albaranado": true,
                            "numAlbaran": "ALB-2026-001"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api_versiones.php": {
      "get": {
        "tags": [
          "History"
        ],
        "operationId": "consultarVersionesDeca",
        "summary": "Get history or download a PDF version",
        "description": "Without `version`, returns PDF versions and the change log. With `version`, downloads that historical PDF. With `actual=1`, downloads the current PDF directly. All requests require the `X-Api-Key` header. Use `incluirDetalle=1` to include before-and-after snapshots for each change.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "DeCA identifier.",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "example": 125
          },
          {
            "name": "version",
            "in": "query",
            "required": false,
            "description": "Version number to download as PDF.",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "example": 2
          },
          {
            "name": "actual",
            "in": "query",
            "required": false,
            "description": "Use `1` to download the current PDF version directly.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "incluirDetalle",
            "in": "query",
            "required": false,
            "description": "Includes previous and new data for each change.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON history or PDF content, depending on the parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": true
                    },
                    "idDeca": {
                      "type": "integer",
                      "example": 125
                    },
                    "numVersionActual": {
                      "type": "integer",
                      "nullable": true,
                      "example": 3
                    },
                    "versiones": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "numVersion": {
                            "type": "integer"
                          },
                          "actual": {
                            "type": "boolean"
                          },
                          "fechaCreacion": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "tamanoBytes": {
                            "type": "integer"
                          },
                          "urlDescarga": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    },
                    "cambios": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "idAuditoria": {
                            "type": "integer"
                          },
                          "accion": {
                            "type": "string",
                            "enum": [
                              "ALTA",
                              "MODIFICACION",
                              "FINALIZACION"
                            ]
                          },
                          "origen": {
                            "type": "string",
                            "enum": [
                              "WEB",
                              "API",
                              "ENLACE"
                            ]
                          },
                          "actor": {
                            "type": "string",
                            "nullable": true
                          },
                          "campos": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "numVersion": {
                            "type": "integer",
                            "nullable": true
                          },
                          "fecha": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "numeroEmpresa": {
                      "type": "integer",
                      "format": "int64",
                      "minimum": 1,
                      "readOnly": true,
                      "description": "Sequential and immutable DeCA number within a company. Read-only. It does not replace the global ID used in requests and URLs."
                    }
                  }
                }
              },
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api_repartos.php": {
      "post": {
        "tags": [
          "Multi-stop trips"
        ],
        "operationId": "guardarReparto",
        "summary": "Create or update a multi-shipment DeCA",
        "description": "Use `accion=crear` to create and `accion=actualizar` with `id` for a partial update. Including `envios` replaces the entire previous collection. Without `fechaTransporte`, the document remains pending and no PDF is generated.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "accion"
                ],
                "properties": {
                  "accion": {
                    "type": "string",
                    "enum": [
                      "crear",
                      "actualizar"
                    ]
                  },
                  "id": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Required when updating."
                  },
                  "idCliente": {
                    "type": "integer",
                    "nullable": true
                  },
                  "idTransportista": {
                    "type": "integer",
                    "nullable": true
                  },
                  "cargadorNombre": {
                    "type": "string",
                    "maxLength": 150
                  },
                  "cargadorNif": {
                    "type": "string",
                    "maxLength": 20
                  },
                  "cargadorDomicilio": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "transportistaNombre": {
                    "type": "string",
                    "maxLength": 150
                  },
                  "transportistaNif": {
                    "type": "string",
                    "maxLength": 20
                  },
                  "fechaTransporte": {
                    "type": "string",
                    "format": "date",
                    "nullable": true
                  },
                  "matriculaTractora": {
                    "type": "string",
                    "maxLength": 15,
                    "nullable": true
                  },
                  "matriculaRemolque": {
                    "type": "string",
                    "maxLength": 15,
                    "nullable": true
                  },
                  "observaciones": {
                    "type": "string",
                    "nullable": true
                  },
                  "origenRegistro": {
                    "type": "string",
                    "maxLength": 50,
                    "nullable": true
                  },
                  "idExterno": {
                    "type": "string",
                    "maxLength": 512,
                    "nullable": true,
                    "description": "Stable email, order or shipment identifier. Up to 512 UTF-16 units; never truncated. Unique per company together with origenRegistro."
                  },
                  "modoEdicionTransportista": {
                    "type": "string",
                    "enum": [
                      "operativo",
                      "carga"
                    ],
                    "default": "operativo",
                    "description": "`carga` also allows the carrier to edit each line description, quantity, unit and weight."
                  },
                  "diasValidezEnlace": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 90,
                    "default": 30
                  },
                  "envios": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "$ref": "#/components/schemas/EnvioReparto"
                    }
                  }
                }
              },
              "examples": {
                "crearReparto": {
                  "summary": "Route with two deliveries",
                  "value": {
                    "accion": "crear",
                    "cargadorNombre": "Distribuciones Centro SL",
                    "cargadorNif": "B28030303",
                    "cargadorDomicilio": "Calle Comercio 15, Madrid",
                    "transportistaNombre": "Transportes del Norte SL",
                    "transportistaNif": "B00000001",
                    "fechaTransporte": "2026-08-24",
                    "matriculaTractora": "1234 KLM",
                    "origenRegistro": "ERP_CLIENTE",
                    "idExterno": "RUTA-2026-0087",
                    "envios": [
                      {
                        "referencia": "PED-4501",
                        "origen": "Madrid",
                        "destino": "Toledo",
                        "lineas": [
                          {
                            "descripcion": "Conservas en cajas",
                            "cantidad": 40,
                            "unidad": "cajas",
                            "pesoKg": 520
                          }
                        ]
                      },
                      {
                        "referencia": "PED-4502",
                        "origen": "Toledo",
                        "destino": "Ciudad Real",
                        "lineas": [
                          {
                            "descripcion": "Bebidas paletizadas",
                            "cantidad": 8,
                            "unidad": "palets",
                            "pesoKg": 4300
                          }
                        ]
                      }
                    ]
                  }
                },
                "actualizarMatricula": {
                  "summary": "Update shared details only",
                  "value": {
                    "accion": "actualizar",
                    "id": 125,
                    "matriculaTractora": "7350 LPD"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Multi-stop trip updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RepartoResponse"
                }
              }
            }
          },
          "201": {
            "description": "Multi-stop trip created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RepartoResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "tags": [
          "Multi-stop trips"
        ],
        "operationId": "consultarRepartos",
        "summary": "Retrieve, find or list multi-stop trips",
        "parameters": [
          {
            "name": "accion",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "consultar",
                "buscar",
                "listar"
              ]
            }
          },
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "origen",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "idExterno",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "soloRepartos",
            "in": "query",
            "description": "Use 1 to exclude single-shipment documents.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful query",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api_clientes.php": {
      "get": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "consultarEntidades",
        "summary": "Retrieve or list customers and carriers",
        "description": "Without identification parameters, returns a paginated list. Retrieve a specific record using `id` or the `origen` + `idExterno` pair.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "Internal entity identifier.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "origen",
            "in": "query",
            "description": "System that assigned the external reference. Send together with idExterno.",
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          },
          {
            "name": "idExterno",
            "in": "query",
            "description": "Stable ERP record identifier. Send together with origen.",
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "activo",
            "in": "query",
            "description": "Filter by status. The default returns active and inactive records.",
            "schema": {
              "type": "string",
              "enum": [
                "todos",
                "1",
                "0"
              ],
              "default": "todos"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Free-text search in the main fields and external reference.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of items per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "First item of the page.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "rol",
            "in": "query",
            "description": "Filter entities by their role in DeCA.",
            "schema": {
              "type": "string",
              "enum": [
                "todos",
                "cliente",
                "transportista",
                "ambos"
              ],
              "default": "todos"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful query.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ClienteItemResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ClienteListResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "guardarEntidad",
        "summary": "Create, update, activate or deactivate an entity",
        "description": "Use `accion=guardar` for idempotent synchronization. If `origenRegistro` + `idExterno` already exists, the record is updated; otherwise it is created. `actualizar`, `activar` and `desactivar` accept `id` or an external reference. No physical deletion is performed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClienteWriteRequest"
              },
              "examples": {
                "sincronizar": {
                  "summary": "Create or update an entity from the ERP",
                  "value": {
                    "accion": "guardar",
                    "nombre": "Harinas Leonesas SL",
                    "nif": "B24010101",
                    "domicilio": "Pol. Ind. Leon Oeste 12, Leon",
                    "esCliente": true,
                    "esTransportista": false,
                    "activo": true,
                    "origenRegistro": "ERP_EMPRESA",
                    "idExterno": "CLI-00428"
                  }
                },
                "desactivar": {
                  "summary": "Deactivate by ERP reference",
                  "value": {
                    "accion": "desactivar",
                    "origenRegistro": "ERP_EMPRESA",
                    "idExterno": "CLI-00428"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClienteWriteResponse"
                }
              }
            }
          },
          "201": {
            "description": "Record created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClienteWriteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api_clientes_importar.php": {
      "post": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "importarEntidades",
        "summary": "Validate or batch-import customers and carriers",
        "description": "Processes 1 to 1,000 records in isolation for the company linked to `X-Api-Key`. Use `accion=validar` first; `accion=importar` processes the entire batch in a transaction and saves no rows if any error exists. Duplicates are identified by ERP reference, tax ID or name within the same company.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClienteImportacionRequest"
              },
              "examples": {
                "validar": {
                  "summary": "Preview before importing",
                  "value": {
                    "accion": "validar",
                    "modoDuplicados": "actualizar",
                    "registros": [
                      {
                        "origenRegistro": "ERP_EMPRESA",
                        "idExterno": "CLI-00428",
                        "nombre": "Harinas Leonesas SL",
                        "nif": "B24010101",
                        "domicilio": "León",
                        "esCliente": true,
                        "esTransportista": false,
                        "activo": true
                      },
                      {
                        "origenRegistro": "ERP_EMPRESA",
                        "idExterno": "TRA-00017",
                        "nombre": "Transportes El Rápido SL",
                        "nif": "B87654321",
                        "esCliente": false,
                        "esTransportista": true,
                        "activo": true
                      }
                    ]
                  }
                },
                "importar": {
                  "summary": "Confirm a validated batch",
                  "value": {
                    "accion": "importar",
                    "modoDuplicados": "actualizar",
                    "registros": [
                      {
                        "origenRegistro": "ERP_EMPRESA",
                        "idExterno": "CLI-00428",
                        "nombre": "Harinas Leonesas SL",
                        "nif": "B24010101",
                        "esCliente": true
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch validated or imported successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClienteImportacionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Subscription expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "description": "The batch contains validation errors.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClienteImportacionResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api_vehiculos.php": {
      "get": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "consultarVehiculos",
        "summary": "Get or list vehicles",
        "description": "Without identification parameters, returns a paginated list. Retrieve a specific record using `id` or the `origen` + `idExterno` pair.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "Internal vehicle identifier.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "origen",
            "in": "query",
            "description": "System that assigned the external reference. Send together with idExterno.",
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          },
          {
            "name": "idExterno",
            "in": "query",
            "description": "Stable ERP record identifier. Send together with origen.",
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "activo",
            "in": "query",
            "description": "Filter by status. The default returns active and inactive records.",
            "schema": {
              "type": "string",
              "enum": [
                "todos",
                "1",
                "0"
              ],
              "default": "todos"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Free-text search in the main fields and external reference.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of items per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "First item of the page.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful query.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/VehiculoItemResponse"
                    },
                    {
                      "$ref": "#/components/schemas/VehiculoListResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "guardarVehiculo",
        "summary": "Create, update, activate or deactivate a vehicle",
        "description": "Use `accion=guardar` for idempotent synchronization. If `origenRegistro` + `idExterno` already exists, the record is updated; otherwise it is created. `actualizar`, `activar` and `desactivar` accept `id` or an external reference. No physical deletion is performed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VehiculoWriteRequest"
              },
              "examples": {
                "sincronizar": {
                  "summary": "Create or update a vehicle from the ERP",
                  "value": {
                    "accion": "guardar",
                    "matricula": "1234 KLM",
                    "tipo": "tractora",
                    "marca": "Volvo",
                    "modelo": "FH 460",
                    "activo": true,
                    "origenRegistro": "ERP_EMPRESA",
                    "idExterno": "VEH-00117"
                  }
                },
                "desactivar": {
                  "summary": "Deactivate by ERP reference",
                  "value": {
                    "accion": "desactivar",
                    "origenRegistro": "ERP_EMPRESA",
                    "idExterno": "VEH-00117"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VehiculoWriteResponse"
                }
              }
            }
          },
          "201": {
            "description": "Record created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VehiculoWriteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api_conductores.php": {
      "get": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "consultarConductores",
        "summary": "Get or list drivers",
        "description": "Without identification parameters, returns a paginated list. Retrieve a specific record using `id` or the `origen` + `idExterno` pair.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "Internal driver identifier.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "origen",
            "in": "query",
            "description": "System that assigned the external reference. Send together with idExterno.",
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          },
          {
            "name": "idExterno",
            "in": "query",
            "description": "Stable ERP record identifier. Send together with origen.",
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "activo",
            "in": "query",
            "description": "Filter by status. The default returns active and inactive records.",
            "schema": {
              "type": "string",
              "enum": [
                "todos",
                "1",
                "0"
              ],
              "default": "todos"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Free-text search in the main fields and external reference.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of items per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "First item of the page.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful query.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ConductorItemResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ConductorListResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "guardarConductor",
        "summary": "Create, update, activate or deactivate a driver",
        "description": "Use `accion=guardar` for idempotent synchronization. If `origenRegistro` + `idExterno` already exists, the record is updated; otherwise it is created. `actualizar`, `activar` and `desactivar` accept `id` or an external reference. No physical deletion is performed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConductorWriteRequest"
              },
              "examples": {
                "sincronizar": {
                  "summary": "Create or update a driver from the ERP",
                  "value": {
                    "accion": "guardar",
                    "nombre": "Carlos Martin Gomez",
                    "telefono": "34600111222",
                    "email": "carlos@transportes.test; trafico@transportes.test",
                    "notificarEmail": true,
                    "activo": true,
                    "origenRegistro": "ERP_EMPRESA",
                    "idExterno": "CON-00032"
                  }
                },
                "desactivar": {
                  "summary": "Deactivate by ERP reference",
                  "value": {
                    "accion": "desactivar",
                    "origenRegistro": "ERP_EMPRESA",
                    "idExterno": "CON-00032"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConductorWriteResponse"
                }
              }
            }
          },
          "201": {
            "description": "Record created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConductorWriteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api_lugares.php": {
      "get": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "consultarLugares",
        "summary": "Retrieve or list saved places",
        "description": "Optional master data for farms, warehouses and recurring locations. The API key always limits results to its company.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "origen",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 50
            },
            "description": "System that assigned the external reference; use together with idExterno."
          },
          {
            "name": "idExterno",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 80
            },
            "description": "Stable ERP reference; use together with origen."
          },
          {
            "name": "activo",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "todos",
                "1",
                "0"
              ],
              "default": "todos"
            }
          },
          {
            "name": "uso",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "todos",
                "origen",
                "destino",
                "ambos"
              ],
              "default": "todos"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful query.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/LugarItemResponse"
                    },
                    {
                      "$ref": "#/components/schemas/LugarListResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "guardarLugar",
        "summary": "Create, update, activate or deactivate a saved place",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LugarWriteRequest"
              },
              "examples": {
                "synchronise": {
                  "summary": "Create or update an ERP farm",
                  "value": {
                    "accion": "guardar",
                    "codigo": "FR-018",
                    "nombre": "Los Prados Farm",
                    "domicilio": "Rural Road 4, Segovia",
                    "esOrigen": true,
                    "esDestino": false,
                    "activo": true,
                    "origenRegistro": "CUSTOMER_ERP",
                    "idExterno": "FARM-018"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LugarWriteResponse"
                }
              }
            }
          },
          "201": {
            "description": "Record created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LugarWriteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api_descargas.php": {
      "post": {
        "tags": [
          "Downloads"
        ],
        "operationId": "createDownloadBatch",
        "summary": "Prepare a ZIP batch of PDFs",
        "description": "Takes a snapshot of the current versions. It immediately returns HTTP 202 and an idLote; the ERP then checks the status without keeping the request open.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fechaCampo": {
                    "type": "string",
                    "enum": [
                      "transporte",
                      "registro",
                      "creacion",
                      "modificacion"
                    ],
                    "default": "transporte"
                  },
                  "fechaDesde": {
                    "type": "string",
                    "format": "date"
                  },
                  "fechaHasta": {
                    "type": "string",
                    "format": "date"
                  },
                  "ids": {
                    "type": "array",
                    "maxItems": 10000,
                    "items": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "soloPendientes": {
                    "type": "boolean",
                    "default": true,
                    "description": "Excludes versions that have already been downloaded."
                  }
                },
                "description": "Provide a date range or a list of ids. Maximum 10,000 documents and 512 MB."
              },
              "example": {
                "fechaCampo": "transporte",
                "fechaDesde": "2026-09-01",
                "fechaHasta": "2026-09-30",
                "soloPendientes": true
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Batch accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadBatch"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "tags": [
          "Downloads"
        ],
        "operationId": "getOrDownloadBatch",
        "summary": "Check or download a batch",
        "description": "accion=estado advances preparation in blocks and returns progress. Repeat until estado=disponible. accion=descargar returns the ZIP and records each downloaded version. The ZIP expires 24 hours after becoming available.",
        "parameters": [
          {
            "name": "accion",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "estado",
                "descargar"
              ]
            }
          },
          {
            "name": "idLote",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON status or ZIP file, depending on accion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadBatch"
                }
              },
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "410": {
            "description": "The temporary ZIP has expired."
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api_usuarios.php": {
      "get": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "listApiUsers",
        "summary": "List users and personal-key status",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Users without full key values."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "ERP master data"
        ],
        "operationId": "manageApiUsers",
        "summary": "Import users or regenerate/revoke a personal key",
        "description": "Requires X-Api-Key. Complete keys are returned only when generated.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "accion": "importar",
                "usuarios": [
                  {
                    "usuario": "operator1",
                    "clave": "SecureWebPassword",
                    "activo": true,
                    "accesoTodosDeca": true,
                    "soloPropiosDeca": true,
                    "generarApiKey": true
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Operation completed."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "32-character key assigned to the company. Treat it as a password and never include it in URLs or diagnostic logs."
      },
      "UserApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-User-Api-Key",
        "description": "Personal key identifying both company and user. Do not send it together with X-Api-Key."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request or incomplete data",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "ok": false,
              "error": "fechaTransporte debe ser YYYY-MM-DD."
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "ok": false,
              "error": "Clave API no válida."
            }
          }
        }
      },
      "Forbidden": {
        "description": "API unavailable for the company or subscription expired",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "ok": false,
              "error": "Suscripción caducada."
            }
          }
        }
      },
      "NotFound": {
        "description": "Record not found for the authenticated company.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "ok": false,
              "error": "DeCA no encontrado."
            }
          }
        }
      },
      "Conflict": {
        "description": "A record with the same details or external reference already exists.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "ok": false,
              "error": "Ya existe un DeCA para origen 'ERP_CLIENTE' / idExterno 'EXP-12345'. Use 'actualizar'."
            }
          }
        }
      },
      "ServerError": {
        "description": "The operation could not be completed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "ok": false,
              "error": "No se pudo completar la operación."
            }
          }
        }
      }
    },
    "schemas": {
      "DownloadBatch": {
        "type": "object",
        "required": [
          "ok",
          "idLote",
          "estado",
          "totalDocumentos",
          "procesados",
          "porcentaje"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "example": true
          },
          "idLote": {
            "type": "string",
            "format": "uuid"
          },
          "estado": {
            "type": "string",
            "enum": [
              "preparando",
              "disponible",
              "error",
              "caducado"
            ]
          },
          "totalDocumentos": {
            "type": "integer",
            "example": 326
          },
          "procesados": {
            "type": "integer",
            "example": 180
          },
          "porcentaje": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "tamanoBytes": {
            "type": "integer",
            "format": "int64"
          },
          "fechaSolicitud": {
            "type": "string",
            "format": "date-time"
          },
          "fechaDisponible": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "caduca": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "urlEstado": {
            "type": "string",
            "format": "uri"
          },
          "urlDescarga": {
            "type": "string",
            "format": "uri",
            "description": "Only returned when estado is disponible. It requires the same X-Api-Key."
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "LineaMercancia": {
        "type": "object",
        "description": "Line of transported goods.",
        "properties": {
          "descripcion": {
            "type": "string",
            "maxLength": 200,
            "description": "Description of the goods."
          },
          "cantidad": {
            "type": "number",
            "minimum": 0,
            "nullable": true,
            "description": "Quantity in the specified unit."
          },
          "unidad": {
            "type": "string",
            "maxLength": 30,
            "nullable": true,
            "description": "Unit of measure: pallets, packages, sacks, m3, etc."
          },
          "pesoKg": {
            "type": "number",
            "minimum": 0,
            "nullable": true,
            "description": "Line weight in kilograms."
          }
        }
      },
      "DecaInputFields": {
        "type": "object",
        "properties": {
          "idCliente": {
            "type": "integer",
            "minimum": 0,
            "nullable": true,
            "description": "Entity with the customer role. Send 0 or null in an update to remove the link."
          },
          "idTransportista": {
            "type": "integer",
            "minimum": 0,
            "nullable": true,
            "description": "Entity with the carrier role. Send 0 or null in an update to remove the link."
          },
          "cargadorNombre": {
            "type": "string",
            "description": "Contractual consignor name or company name. Required when a transport date is set."
          },
          "cargadorNif": {
            "type": "string",
            "description": "Contractual consignor tax ID. Required when a transport date is set."
          },
          "cargadorDomicilio": {
            "type": "string",
            "description": "Contractual consignor address. Required when a transport date is set."
          },
          "transportistaNombre": {
            "type": "string",
            "description": "If omitted, uses the configured company name."
          },
          "transportistaNif": {
            "type": "string",
            "description": "If omitted, uses the configured company tax ID."
          },
          "origen": {
            "type": "string",
            "maxLength": 512,
            "description": "Place of origin. Required when a transport date is set."
          },
          "destino": {
            "type": "string",
            "maxLength": 512,
            "description": "Destination. Required when a transport date is set."
          },
          "fechaTransporte": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Trip date in YYYY-MM-DD format. Omit it or send an empty string to leave the trip unscheduled."
          },
          "matriculaTractora": {
            "type": "string",
            "nullable": true,
            "description": "Main vehicle registration, if known. Send an empty string or null in an update to clear it."
          },
          "matriculaRemolque": {
            "type": "string",
            "nullable": true,
            "description": "Trailer registration, if applicable. Send an empty string in an update to clear it."
          },
          "observaciones": {
            "type": "string",
            "nullable": true
          },
          "numAlbaran": {
            "type": "string",
            "nullable": true,
            "description": "Delivery-note number. If supplied during creation, the document is marked as having a delivery note."
          },
          "anulado": {
            "type": "boolean",
            "description": "Optional status, mainly used in updates."
          },
          "terminado": {
            "type": "boolean",
            "description": "Optional status, mainly used in updates."
          },
          "albaranado": {
            "type": "boolean",
            "description": "Optional status, mainly used in updates."
          },
          "origenRegistro": {
            "type": "string",
            "nullable": true,
            "description": "Stable source-system code, for example `ERP_CLIENTE`."
          },
          "idExterno": {
            "type": "string",
            "nullable": true,
            "description": "Stable email, order or shipment identifier. Up to 512 UTF-16 units; never truncated. Unique per company together with origenRegistro.",
            "maxLength": 512
          },
          "modoEdicionTransportista": {
            "type": "string",
            "enum": [
              "operativo",
              "carga"
            ],
            "default": "operativo",
            "description": "Private-link permissions. `operativo`: date and registrations. `carga`: also goods description, quantity, unit and weight. Does not allow changes to companies, tax IDs, routes or administrative statuses."
          },
          "diasValidezEnlace": {
            "type": "integer",
            "minimum": 1,
            "maximum": 90,
            "default": 30,
            "description": "Validity in days when a new link is needed. Retrieving an active link does not change its token or expiry."
          },
          "lineas": {
            "type": "array",
            "description": "Trip goods. With a date set, at least one line must have a description and at least one must specify `pesoKg` or `cantidad` + `unidad`. Sending this property in an update replaces all previous lines.",
            "items": {
              "$ref": "#/components/schemas/LineaMercancia"
            }
          },
          "mercancia": {
            "type": "string",
            "deprecated": true,
            "description": "Compatibility field for creating a single line. Use `lineas` in new integrations."
          },
          "pesoKg": {
            "type": "number",
            "minimum": 0,
            "deprecated": true,
            "description": "Compatibility field associated with `mercancia`."
          },
          "otraMagnitud": {
            "type": "string",
            "deprecated": true,
            "description": "Compatibility field associated with `mercancia`."
          },
          "idConductor": {
            "type": "integer",
            "minimum": 0,
            "nullable": true,
            "description": "Short form for assigning one driver. Use conductores to assign two."
          },
          "notaConductorDeca": {
            "type": "string",
            "maxLength": 300,
            "nullable": true,
            "description": "Trip-specific note for the driver assigned in short form."
          },
          "mostrarNotaConductorDeca": {
            "type": "boolean",
            "description": "Shows the short-form driver note in the PDF."
          },
          "conductores": {
            "type": "array",
            "minItems": 0,
            "maxItems": 2,
            "items": {
              "$ref": "#/components/schemas/ConductorDeca"
            },
            "description": "Optional. Replaces all assignments. Omit on update to keep current drivers; [] clears them. Supports idConductor (legacy) or name/contact data for a one-off driver. Does not modify master records."
          },
          "incluirConductorPdf": {
            "type": "boolean",
            "description": "Includes driver names and authorised notes in the PDF. On creation it is inherited from the customer when omitted. It never includes an ID number, telephone or email."
          },
          "idLugarOrigen": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "Saved origin place belonging to the same company. When supplied, the API copies its name and address to the trip."
          },
          "idLugarDestino": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "Saved destination place belonging to the same company. When supplied, the API copies its name and address to the trip."
          }
        }
      },
      "DecaCreateRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/DecaInputFields"
          },
          {
            "type": "object",
            "required": [
              "accion"
            ],
            "properties": {
              "accion": {
                "type": "string",
                "enum": [
                  "crear"
                ]
              }
            }
          }
        ]
      },
      "DecaUpdateRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/DecaInputFields"
          },
          {
            "type": "object",
            "required": [
              "accion",
              "id"
            ],
            "properties": {
              "accion": {
                "type": "string",
                "enum": [
                  "actualizar"
                ]
              },
              "id": {
                "type": "integer",
                "minimum": 1,
                "description": "`idDeca` identifier to update."
              }
            }
          }
        ]
      },
      "EstadoDeca": {
        "type": "object",
        "properties": {
          "anulado": {
            "type": "boolean"
          },
          "terminado": {
            "type": "boolean"
          },
          "albaranado": {
            "type": "boolean"
          },
          "numAlbaran": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "EnvioReparto": {
        "type": "object",
        "required": [
          "lineas"
        ],
        "properties": {
          "referencia": {
            "type": "string",
            "maxLength": 80,
            "nullable": true,
            "description": "ERP order, dispatch or delivery."
          },
          "origen": {
            "type": "string",
            "maxLength": 512
          },
          "destino": {
            "type": "string",
            "maxLength": 512
          },
          "observaciones": {
            "type": "string",
            "maxLength": 300,
            "nullable": true
          },
          "lineas": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/LineaMercancia"
            }
          },
          "idLugarOrigen": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "Saved origin place belonging to the same company. When supplied, the API copies its name and address to the trip."
          },
          "idLugarDestino": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "Saved destination place belonging to the same company. When supplied, the API copies its name and address to the trip."
          }
        },
        "description": "Origin and destination may be entered manually or resolved with idLugarOrigen and idLugarDestino. When a transport date is set, every shipment must have valid text or identifiers for both."
      },
      "RepartoResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/DecaWriteResponse"
          },
          {
            "type": "object",
            "required": [
              "reparto",
              "numeroEnvios",
              "envios"
            ],
            "properties": {
              "reparto": {
                "type": "boolean"
              },
              "numeroEnvios": {
                "type": "integer",
                "minimum": 1
              },
              "envios": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EnvioReparto"
                }
              }
            }
          }
        ]
      },
      "Cumplimentacion": {
        "type": "object",
        "properties": {
          "urlEdicion": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "modoEdicionTransportista": {
            "type": "string",
            "enum": [
              "operativo",
              "carga"
            ],
            "nullable": true
          },
          "camposEditables": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "estadoCumplimentacion": {
            "type": "string",
            "enum": [
              "no_iniciado",
              "pendiente",
              "completado",
              "cerrado"
            ]
          },
          "fechaUltimoGuardado": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fechaFinalizacion": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fechaCaducidadEnlace": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "enlaceActivo": {
            "type": "boolean"
          }
        }
      },
      "EnlaceEdicionResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Cumplimentacion"
          },
          {
            "type": "object",
            "required": [
              "ok",
              "idDeca",
              "estadoCumplimentacion",
              "enlaceActivo"
            ],
            "properties": {
              "ok": {
                "type": "boolean"
              },
              "idDeca": {
                "type": "integer"
              },
              "idCliente": {
                "type": "integer",
                "nullable": true
              },
              "idTransportista": {
                "type": "integer",
                "nullable": true
              },
              "numVersion": {
                "type": "integer",
                "nullable": true
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "urlDocumento": {
                "type": "string",
                "format": "uri",
                "nullable": true
              },
              "urlDescargaPdf": {
                "type": "string",
                "format": "uri",
                "nullable": true
              },
              "pdfDisponible": {
                "type": "boolean"
              },
              "numeroEmpresa": {
                "type": "integer",
                "format": "int64",
                "minimum": 1,
                "readOnly": true,
                "description": "Sequential and immutable DeCA number within a company. Read-only. It does not replace the global ID used in requests and URLs."
              }
            }
          }
        ]
      },
      "DecaWriteResponse": {
        "type": "object",
        "required": [
          "ok",
          "idDeca",
          "token",
          "url",
          "pdf"
        ],
        "properties": {
          "idCliente": {
            "type": "integer",
            "nullable": true
          },
          "idTransportista": {
            "type": "integer",
            "nullable": true
          },
          "ok": {
            "type": "boolean"
          },
          "idDeca": {
            "type": "integer"
          },
          "token": {
            "type": "string",
            "description": "Technical document-URL token. The integration should retain `idDeca`, `urlEdicion` and its external reference."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Legacy field: stable document URL. May be unavailable until a PDF exists. Use `urlDocumento` and `urlEdicion` in new integrations."
          },
          "urlDocumento": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Public view of the current DeCA. Null until a PDF version exists."
          },
          "urlDescargaPdf": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Authenticated endpoint for downloading the current PDF with `X-Api-Key`."
          },
          "pdfDisponible": {
            "type": "boolean"
          },
          "urlEdicion": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Private link to include in the order sent to the carrier. Does not require an API key."
          },
          "modoEdicionTransportista": {
            "type": "string",
            "enum": [
              "operativo",
              "carga"
            ],
            "nullable": true
          },
          "camposEditables": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "estadoCumplimentacion": {
            "type": "string",
            "enum": [
              "no_iniciado",
              "pendiente",
              "completado",
              "cerrado"
            ]
          },
          "fechaUltimoGuardado": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fechaFinalizacion": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fechaCaducidadEnlace": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "enlaceActivo": {
            "type": "boolean"
          },
          "numVersion": {
            "type": "integer",
            "nullable": true,
            "description": "Null while the trip has no date or PDF."
          },
          "pdf": {
            "type": "boolean",
            "description": "Indicates whether this operation generated a PDF version."
          },
          "numeroEmpresa": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "readOnly": true,
            "description": "Sequential and immutable DeCA number within a company. Read-only. It does not replace the global ID used in requests and URLs."
          },
          "incluirConductorPdf": {
            "type": "boolean"
          },
          "conductores": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConductorDecaRespuesta"
            }
          },
          "firmaExpedidorPdf": {
            "type": "boolean",
            "description": "Indicates whether the PDF includes the consignor signature area."
          },
          "firmaDestinatarioPdf": {
            "type": "boolean",
            "description": "Indicates whether the PDF includes the consignee signature area."
          },
          "firmaTransportistaPdf": {
            "type": "boolean",
            "description": "Indicates whether the PDF includes the carrier or driver signature area."
          }
        }
      },
      "DecaConsultaResponse": {
        "type": "object",
        "required": [
          "ok",
          "idDeca",
          "url",
          "estado",
          "lineas"
        ],
        "properties": {
          "idCliente": {
            "type": "integer",
            "nullable": true
          },
          "idTransportista": {
            "type": "integer",
            "nullable": true
          },
          "ok": {
            "type": "boolean"
          },
          "idDeca": {
            "type": "integer"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "urlDocumento": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "urlDescargaPdf": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "pdfDisponible": {
            "type": "boolean"
          },
          "urlEdicion": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "modoEdicionTransportista": {
            "type": "string",
            "enum": [
              "operativo",
              "carga"
            ],
            "nullable": true
          },
          "camposEditables": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "estadoCumplimentacion": {
            "type": "string",
            "enum": [
              "no_iniciado",
              "pendiente",
              "completado",
              "cerrado"
            ]
          },
          "fechaUltimoGuardado": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fechaFinalizacion": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fechaCaducidadEnlace": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "enlaceActivo": {
            "type": "boolean"
          },
          "numVersion": {
            "type": "integer",
            "nullable": true
          },
          "fechaTransporte": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "matriculaTractora": {
            "type": "string",
            "maxLength": 15,
            "nullable": true,
            "description": "Current tractor registration. Null until assigned."
          },
          "matriculaRemolque": {
            "type": "string",
            "maxLength": 15,
            "nullable": true,
            "description": "Current trailer registration. Null if not applicable or not yet assigned."
          },
          "estado": {
            "$ref": "#/components/schemas/EstadoDeca"
          },
          "origenRegistro": {
            "type": "string",
            "nullable": true
          },
          "idExterno": {
            "type": "string",
            "nullable": true,
            "maxLength": 512,
            "description": "Stable email, order or shipment identifier. Up to 512 UTF-16 units; never truncated. Unique per company together with origenRegistro."
          },
          "lineas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LineaMercancia"
            }
          },
          "numeroEmpresa": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "readOnly": true,
            "description": "Sequential and immutable DeCA number within a company. Read-only. It does not replace the global ID used in requests and URLs."
          },
          "incluirConductorPdf": {
            "type": "boolean"
          },
          "conductores": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConductorDecaRespuesta"
            }
          },
          "envios": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnvioReparto"
            },
            "description": "Structured routes and goods. Includes saved-place identifiers when they were used."
          },
          "firmaExpedidorPdf": {
            "type": "boolean",
            "description": "Indicates whether the PDF includes the consignor signature area."
          },
          "firmaDestinatarioPdf": {
            "type": "boolean",
            "description": "Indicates whether the PDF includes the consignee signature area."
          },
          "firmaTransportistaPdf": {
            "type": "boolean",
            "description": "Indicates whether the PDF includes the carrier or driver signature area."
          }
        }
      },
      "DecaBusquedaResponse": {
        "type": "object",
        "required": [
          "ok",
          "encontrado"
        ],
        "properties": {
          "idCliente": {
            "type": "integer",
            "nullable": true
          },
          "idTransportista": {
            "type": "integer",
            "nullable": true
          },
          "ok": {
            "type": "boolean"
          },
          "encontrado": {
            "type": "boolean"
          },
          "idDeca": {
            "type": "integer",
            "nullable": true
          },
          "url": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "numVersion": {
            "type": "integer",
            "nullable": true
          },
          "fechaTransporte": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "numeroEmpresa": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "readOnly": true,
            "description": "Sequential and immutable DeCA number within a company. Read-only. It does not replace the global ID used in requests and URLs."
          }
        }
      },
      "DecaListadoItem": {
        "type": "object",
        "properties": {
          "idCliente": {
            "type": "integer",
            "nullable": true
          },
          "idTransportista": {
            "type": "integer",
            "nullable": true
          },
          "idDeca": {
            "type": "integer"
          },
          "fechaTransporte": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "cargadorNombre": {
            "type": "string",
            "nullable": true
          },
          "origen": {
            "type": "string",
            "nullable": true
          },
          "destino": {
            "type": "string",
            "nullable": true
          },
          "mercancia": {
            "type": "string",
            "nullable": true
          },
          "numVersion": {
            "type": "integer",
            "nullable": true
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "urlDocumento": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "urlDescargaPdf": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "pdfDisponible": {
            "type": "boolean"
          },
          "cumplimentacion": {
            "$ref": "#/components/schemas/Cumplimentacion"
          },
          "fechaCreacion": {
            "type": "string",
            "nullable": true,
            "example": "2026-08-20 09:30"
          },
          "fechaModificacion": {
            "type": "string",
            "nullable": true,
            "example": "2026-08-20 10:15"
          },
          "fechaRegistro": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "origenRegistro": {
            "type": "string",
            "nullable": true
          },
          "idExterno": {
            "type": "string",
            "nullable": true,
            "maxLength": 512,
            "description": "Stable email, order or shipment identifier. Up to 512 UTF-16 units; never truncated. Unique per company together with origenRegistro."
          },
          "estado": {
            "$ref": "#/components/schemas/EstadoDeca"
          },
          "numeroEmpresa": {
            "type": "integer",
            "format": "int64",
            "minimum": 1,
            "readOnly": true,
            "description": "Sequential and immutable DeCA number within a company. Read-only. It does not replace the global ID used in requests and URLs."
          }
        }
      },
      "DecaListadoResponse": {
        "type": "object",
        "required": [
          "ok",
          "total",
          "limit",
          "offset",
          "fechaCampo",
          "items"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "total": {
            "type": "integer",
            "description": "Total records matching the filter."
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "fechaCampo": {
            "type": "string",
            "enum": [
              "creacion",
              "modificacion",
              "registro",
              "transporte"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DecaListadoItem"
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "string",
            "description": "Readable message describing the error cause."
          }
        }
      },
      "ClienteImportacionRegistro": {
        "type": "object",
        "required": [
          "nombre",
          "nif"
        ],
        "properties": {
          "nombre": {
            "type": "string",
            "maxLength": 150
          },
          "nif": {
            "type": "string",
            "maxLength": 20
          },
          "domicilio": {
            "type": "string",
            "maxLength": 200,
            "nullable": true
          },
          "esCliente": {
            "type": "boolean",
            "default": true
          },
          "esTransportista": {
            "type": "boolean",
            "default": false
          },
          "activo": {
            "type": "boolean",
            "default": true
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true
          },
          "incluirConductorPdf": {
            "type": "boolean",
            "default": false,
            "description": "Preference copied to each new DeCA for the customer."
          },
          "firmaExpedidorPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a consignor signature area to the footer of new DeCAs."
          },
          "firmaDestinatarioPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a consignee signature area to the footer of new DeCAs."
          },
          "firmaTransportistaPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a carrier or driver signature area to the footer of new DeCAs."
          }
        }
      },
      "ClienteImportacionRequest": {
        "type": "object",
        "required": [
          "accion",
          "registros"
        ],
        "properties": {
          "accion": {
            "type": "string",
            "enum": [
              "validar",
              "importar"
            ],
            "default": "validar"
          },
          "modoDuplicados": {
            "type": "string",
            "enum": [
              "actualizar",
              "omitir"
            ],
            "default": "actualizar"
          },
          "registros": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
              "$ref": "#/components/schemas/ClienteImportacionRegistro"
            }
          }
        }
      },
      "ClienteImportacionResumen": {
        "type": "object",
        "required": [
          "total",
          "crear",
          "actualizar",
          "omitir",
          "errores"
        ],
        "properties": {
          "total": {
            "type": "integer"
          },
          "crear": {
            "type": "integer"
          },
          "actualizar": {
            "type": "integer"
          },
          "omitir": {
            "type": "integer"
          },
          "errores": {
            "type": "integer"
          }
        }
      },
      "ClienteImportacionFila": {
        "type": "object",
        "required": [
          "fila",
          "accion"
        ],
        "properties": {
          "fila": {
            "type": "integer"
          },
          "accion": {
            "type": "string",
            "enum": [
              "crear",
              "actualizar",
              "omitir",
              "error"
            ]
          },
          "idCliente": {
            "type": "integer",
            "nullable": true
          },
          "nombre": {
            "type": "string",
            "nullable": true
          },
          "nif": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ClienteImportacionResponse": {
        "type": "object",
        "required": [
          "ok",
          "importado",
          "valido",
          "resumen",
          "filas"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "importado": {
            "type": "boolean"
          },
          "valido": {
            "type": "boolean"
          },
          "resumen": {
            "$ref": "#/components/schemas/ClienteImportacionResumen"
          },
          "filas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClienteImportacionFila"
            }
          }
        }
      },
      "ClienteWriteRequest": {
        "type": "object",
        "required": [
          "accion"
        ],
        "properties": {
          "accion": {
            "type": "string",
            "enum": [
              "crear",
              "actualizar",
              "guardar",
              "activar",
              "desactivar"
            ],
            "default": "guardar",
            "description": "`guardar` is recommended for ERP synchronization because it creates or updates by external reference."
          },
          "id": {
            "type": "integer",
            "minimum": 1,
            "description": "Internal ID, required if no external reference is used."
          },
          "nombre": {
            "type": "string",
            "maxLength": 150
          },
          "nif": {
            "type": "string",
            "maxLength": 20
          },
          "domicilio": {
            "type": "string",
            "maxLength": 200,
            "nullable": true
          },
          "esCliente": {
            "type": "boolean",
            "default": true,
            "description": "Allows selecting the entity as the contractual consignor."
          },
          "esTransportista": {
            "type": "boolean",
            "default": false,
            "description": "Allows selecting the entity as the actual carrier."
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true,
            "description": "Stable source-system code. Send together with idExterno."
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true,
            "description": "Stable ERP identifier. Send together with origenRegistro."
          },
          "incluirConductorPdf": {
            "type": "boolean",
            "default": false,
            "description": "Preference copied to each new DeCA for the customer."
          },
          "firmaExpedidorPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a consignor signature area to the footer of new DeCAs."
          },
          "firmaDestinatarioPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a consignee signature area to the footer of new DeCAs."
          },
          "firmaTransportistaPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a carrier or driver signature area to the footer of new DeCAs."
          }
        }
      },
      "VehiculoWriteRequest": {
        "type": "object",
        "required": [
          "accion"
        ],
        "properties": {
          "accion": {
            "type": "string",
            "enum": [
              "crear",
              "actualizar",
              "guardar",
              "activar",
              "desactivar"
            ],
            "default": "guardar",
            "description": "`guardar` is recommended for ERP synchronization because it creates or updates by external reference."
          },
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "matricula": {
            "type": "string",
            "maxLength": 15
          },
          "tipo": {
            "type": "string",
            "enum": [
              "tractora",
              "remolque",
              "rigido",
              "otro"
            ],
            "default": "tractora"
          },
          "marca": {
            "type": "string",
            "maxLength": 60,
            "nullable": true
          },
          "modelo": {
            "type": "string",
            "maxLength": 80,
            "nullable": true
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true,
            "description": "Stable source-system code. Send together with idExterno."
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true,
            "description": "Stable ERP identifier. Send together with origenRegistro."
          }
        }
      },
      "ConductorWriteRequest": {
        "type": "object",
        "required": [
          "accion"
        ],
        "properties": {
          "accion": {
            "type": "string",
            "enum": [
              "crear",
              "actualizar",
              "guardar",
              "activar",
              "desactivar"
            ],
            "default": "guardar",
            "description": "`guardar` is recommended for ERP synchronization because it creates or updates by external reference."
          },
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "nombre": {
            "type": "string",
            "maxLength": 150
          },
          "telefono": {
            "type": "string",
            "description": "The supplied text is preserved exactly, without adding a country code or removing spaces, signs or hyphens. Maximum 20 characters.",
            "maxLength": 20
          },
          "email": {
            "type": "string",
            "maxLength": 500,
            "nullable": true,
            "description": "One or more valid email addresses separated by semicolons. Up to 10 are allowed."
          },
          "notificarEmail": {
            "type": "boolean",
            "description": "If true, sends automatic notifications when the pending DeCA is created and when it becomes complete. Requires an email address."
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true,
            "description": "Stable source-system code. Send together with idExterno."
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true,
            "description": "Stable ERP identifier. Send together with origenRegistro."
          },
          "notaDeca": {
            "type": "string",
            "maxLength": 300,
            "nullable": true,
            "description": "Operational note proposed for the driver's new DeCA documents."
          },
          "mostrarNotaDeca": {
            "type": "boolean",
            "default": false,
            "description": "Proposes showing notaDeca next to the name in new DeCA documents."
          }
        }
      },
      "ClienteItem": {
        "type": "object",
        "properties": {
          "idCliente": {
            "type": "integer"
          },
          "nombre": {
            "type": "string"
          },
          "nif": {
            "type": "string"
          },
          "domicilio": {
            "type": "string",
            "nullable": true
          },
          "esCliente": {
            "type": "boolean"
          },
          "esTransportista": {
            "type": "boolean"
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true,
            "description": "Stable source-system code. Send together with idExterno."
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true,
            "description": "Stable ERP identifier. Send together with origenRegistro."
          },
          "fechaAlta": {
            "type": "string",
            "format": "date-time"
          },
          "fechaModificacion": {
            "type": "string",
            "format": "date-time"
          },
          "incluirConductorPdf": {
            "type": "boolean",
            "default": false,
            "description": "Preference copied to each new DeCA for the customer."
          },
          "firmaExpedidorPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a consignor signature area to the footer of new DeCAs."
          },
          "firmaDestinatarioPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a consignee signature area to the footer of new DeCAs."
          },
          "firmaTransportistaPdf": {
            "type": "boolean",
            "default": false,
            "description": "Adds a carrier or driver signature area to the footer of new DeCAs."
          }
        }
      },
      "VehiculoItem": {
        "type": "object",
        "properties": {
          "idVehiculo": {
            "type": "integer"
          },
          "matricula": {
            "type": "string"
          },
          "tipo": {
            "type": "string",
            "enum": [
              "tractora",
              "remolque",
              "rigido",
              "otro"
            ]
          },
          "marca": {
            "type": "string",
            "nullable": true
          },
          "modelo": {
            "type": "string",
            "nullable": true
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true,
            "description": "Stable source-system code. Send together with idExterno."
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true,
            "description": "Stable ERP identifier. Send together with origenRegistro."
          },
          "fechaAlta": {
            "type": "string",
            "format": "date-time"
          },
          "fechaModificacion": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConductorItem": {
        "type": "object",
        "properties": {
          "idConductor": {
            "type": "integer"
          },
          "nombre": {
            "type": "string"
          },
          "telefono": {
            "type": "string",
            "description": "The supplied text is preserved exactly, without adding a country code or removing spaces, signs or hyphens. Maximum 20 characters.",
            "maxLength": 20
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": "Email addresses separated by semicolons."
          },
          "notificarEmail": {
            "type": "boolean"
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true,
            "description": "Stable source-system code. Send together with idExterno."
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true,
            "description": "Stable ERP identifier. Send together with origenRegistro."
          },
          "fechaAlta": {
            "type": "string",
            "format": "date-time"
          },
          "fechaModificacion": {
            "type": "string",
            "format": "date-time"
          },
          "notaDeca": {
            "type": "string",
            "maxLength": 300,
            "nullable": true,
            "description": "Operational note proposed for the driver's new DeCA documents."
          },
          "mostrarNotaDeca": {
            "type": "boolean",
            "default": false,
            "description": "Proposes showing notaDeca next to the name in new DeCA documents."
          }
        }
      },
      "ClienteItemResponse": {
        "type": "object",
        "required": [
          "ok",
          "item"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "item": {
            "$ref": "#/components/schemas/ClienteItem"
          }
        }
      },
      "ClienteWriteResponse": {
        "type": "object",
        "required": [
          "ok",
          "creado",
          "item"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "creado": {
            "type": "boolean",
            "description": "true if created; false if updated."
          },
          "item": {
            "$ref": "#/components/schemas/ClienteItem"
          }
        }
      },
      "ClienteListResponse": {
        "type": "object",
        "required": [
          "ok",
          "total",
          "limit",
          "offset",
          "items"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClienteItem"
            }
          }
        }
      },
      "VehiculoItemResponse": {
        "type": "object",
        "required": [
          "ok",
          "item"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "item": {
            "$ref": "#/components/schemas/VehiculoItem"
          }
        }
      },
      "VehiculoWriteResponse": {
        "type": "object",
        "required": [
          "ok",
          "creado",
          "item"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "creado": {
            "type": "boolean",
            "description": "true if created; false if updated."
          },
          "item": {
            "$ref": "#/components/schemas/VehiculoItem"
          }
        }
      },
      "VehiculoListResponse": {
        "type": "object",
        "required": [
          "ok",
          "total",
          "limit",
          "offset",
          "items"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VehiculoItem"
            }
          }
        }
      },
      "ConductorItemResponse": {
        "type": "object",
        "required": [
          "ok",
          "item"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "item": {
            "$ref": "#/components/schemas/ConductorItem"
          }
        }
      },
      "ConductorWriteResponse": {
        "type": "object",
        "required": [
          "ok",
          "creado",
          "item"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "creado": {
            "type": "boolean",
            "description": "true if created; false if updated."
          },
          "item": {
            "$ref": "#/components/schemas/ConductorItem"
          }
        }
      },
      "ConductorListResponse": {
        "type": "object",
        "required": [
          "ok",
          "total",
          "limit",
          "offset",
          "items"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConductorItem"
            }
          }
        }
      },
      "ConductorDeca": {
        "type": "object",
        "properties": {
          "idConductor": {
            "type": "integer",
            "minimum": 0,
            "nullable": true
          },
          "notaDeca": {
            "type": "string",
            "maxLength": 300,
            "nullable": true,
            "description": "Trip-specific operational note. Do not include an ID number, telephone, email or unnecessary private data."
          },
          "mostrarNotaDeca": {
            "type": "boolean",
            "description": "Shows notaDeca next to the driver name when incluirConductorPdf is true."
          },
          "nombre": {
            "type": "string",
            "maxLength": 100,
            "description": "Required for a one-off driver without idConductor."
          },
          "telefono": {
            "type": "string",
            "nullable": true,
            "maxLength": 20,
            "description": "The supplied text is preserved exactly, without adding a country code or removing spaces, signs or hyphens. Maximum 20 characters."
          },
          "email": {
            "type": "string",
            "nullable": true,
            "maxLength": 500
          },
          "notificarEmail": {
            "type": "boolean",
            "description": "For this document. A valid email is required when true."
          }
        },
        "description": "Up to two drivers per document. Send idConductor to copy an existing profile, or nombre for a one-off driver. Contact overrides belong only to this DeCA; profile records are not modified."
      },
      "LugarWriteRequest": {
        "type": "object",
        "required": [
          "accion"
        ],
        "properties": {
          "accion": {
            "type": "string",
            "enum": [
              "crear",
              "actualizar",
              "guardar",
              "activar",
              "desactivar"
            ],
            "default": "guardar"
          },
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "codigo": {
            "type": "string",
            "maxLength": 80,
            "nullable": true
          },
          "nombre": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150
          },
          "domicilio": {
            "type": "string",
            "maxLength": 200,
            "nullable": true
          },
          "esOrigen": {
            "type": "boolean",
            "default": true
          },
          "esDestino": {
            "type": "boolean",
            "default": false
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true
          }
        },
        "description": "The place must be enabled for at least origin or destination. Use guardar with origenRegistro and idExterno for idempotent synchronisation."
      },
      "LugarItem": {
        "type": "object",
        "properties": {
          "idLugar": {
            "type": "integer"
          },
          "codigo": {
            "type": "string",
            "maxLength": 80,
            "nullable": true
          },
          "nombre": {
            "type": "string"
          },
          "domicilio": {
            "type": "string",
            "maxLength": 200,
            "nullable": true
          },
          "esOrigen": {
            "type": "boolean"
          },
          "esDestino": {
            "type": "boolean"
          },
          "activo": {
            "type": "boolean"
          },
          "origenRegistro": {
            "type": "string",
            "maxLength": 50,
            "nullable": true
          },
          "idExterno": {
            "type": "string",
            "maxLength": 80,
            "nullable": true
          },
          "fechaAlta": {
            "type": "string",
            "format": "date-time"
          },
          "fechaModificacion": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LugarItemResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "item": {
            "$ref": "#/components/schemas/LugarItem"
          }
        }
      },
      "LugarWriteResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "creado": {
            "type": "boolean"
          },
          "item": {
            "$ref": "#/components/schemas/LugarItem"
          }
        }
      },
      "LugarListResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LugarItem"
            }
          }
        }
      },
      "ConductorDecaRespuesta": {
        "type": "object",
        "properties": {
          "idConductor": {
            "type": "integer",
            "minimum": 0,
            "nullable": true
          },
          "notaDeca": {
            "type": "string",
            "maxLength": 300,
            "nullable": true,
            "description": "Trip-specific operational note. Do not include an ID number, telephone, email or unnecessary private data."
          },
          "mostrarNotaDeca": {
            "type": "boolean",
            "description": "Shows notaDeca next to the driver name when incluirConductorPdf is true."
          },
          "nombre": {
            "type": "string",
            "maxLength": 100,
            "description": "Required for a one-off driver without idConductor."
          },
          "telefono": {
            "type": "string",
            "nullable": true,
            "maxLength": 20,
            "description": "The supplied text is preserved exactly, without adding a country code or removing spaces, signs or hyphens. Maximum 20 characters."
          },
          "email": {
            "type": "string",
            "nullable": true,
            "maxLength": 500
          },
          "notificarEmail": {
            "type": "boolean",
            "description": "For this document. A valid email is required when true."
          },
          "orden": {
            "type": "integer",
            "minimum": 1,
            "maximum": 2
          }
        },
        "description": "Driver snapshot saved in the document. idConductor is null for one-off drivers."
      }
    }
  }
}
