{
  "openapi": "3.1.1",
  "info": {
    "title": "API DeCA",
    "version": "1.0.0",
    "description": "API para emitir, rectificar, consultar e descargar documentos españois de control administrativo do transporte de mercadorías. Para obter un token, contacta co soporte de SERTEC PESAGE. Os tokens sk_test_ usan desenvolvemento e os sk_live_ produción, con datos separados. A restrición por IP é opcional.\n\nCada credencial permite consultar e descargar os seus documentos durante as 24 horas seguintes á creación. A descarga por QR ten unha vixencia independente. As rectificacións conservan o documento orixinal.\n\nO borrado lóxico só se permite durante as primeiras 2 horas para corrixir erros de xeración. A integración debe confirmar que o documento non se entregou ao transportista nin se utilizou no transporte. Consérvanse o ficheiro e a rastrexabilidade, pero bloquéase o acceso.\n\nPodes solicitar un token `sk_demo_` sen conta nin alta dunha organización. Dura **24 horas desde a súa emisión** e só funciona desde a **IP pública que o solicitou**. Cambiar de rede ou de IP require solicitar outro token. Utiliza unicamente **datos ficticios**. Cada páxina do PDF mostra **SEN VALIDEZ** xunto ao logo e unha marca diagonal **DEMO**. Estes documentos non serven para transportar mercadorías nin como documentos administrativos válidos. A demo engade demo: true, expires_at, qr_url (alias de url) e pdf_url (alias de pdf_download_url). document_locale é o idioma escollido ao solicitar o token (es por defecto). Os datos e PDF temporais están separados do arquivo real e non se cifran como os documentos reais. A demo admite corpos de ata 32 KiB e dez documentos por sesión. A emisión de tokens admite tres por minuto e dez por hora desde unha mesma IP; a creación, cinco por minuto e vinte por hora desde unha mesma IP. Os límites compartidos por rede, rexión e carga global poden aplicarse antes. Estas cifras corresponden á configuración predeterminada."
  },
  "servers": [
    {
      "url": "https://deca.sertecpesage.com",
      "description": "Produción"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Documentos",
      "description": "Emisión, rectificación e acceso aos documentos propios recentes."
    },
    {
      "name": "Descarga por QR",
      "description": "Descarga directa do PDF mediante o segredo dun documento."
    },
    {
      "name": "Demostración da API",
      "description": "Obtén un token público temporal e xera documentos de demostración con datos ficticios."
    }
  ],
  "paths": {
    "/api/v1/documents": {
      "post": {
        "operationId": "createDocument",
        "tags": [
          "Documentos"
        ],
        "summary": "Crear documento",
        "description": "Envía todos os datos do transporte. A resposta entrégase despois de xerar e almacenar o PDF cifrado.\n\nUnha referencia non nula é única por organización e contorno. Repetir a referencia cos mesmos datos normalizados e metadata devolve o resultado orixinal dentro de 24 horas (200), sen emitir outro PDF. Unha creación nova devolve 201. Datos diferentes ou unha referencia doutra credencial producen 409 sen divulgar documentos. Sen referencia non se garante a deduplicación.\n\nUnha referencia co resultado caducado devolve 409 DOCUMENT_WINDOW_EXPIRED. Se o documento está eliminado, non se devolve o contido nin se reutiliza a referencia; o reintento devolve 404. Para rectificar, usa os endpoints PUT.\n\nPodes solicitar un token `sk_demo_` sen conta nin alta dunha organización. Dura **24 horas desde a súa emisión** e só funciona desde a **IP pública que o solicitou**. Cambiar de rede ou de IP require solicitar outro token. A demo engade demo: true, expires_at, qr_url (alias de url) e pdf_url (alias de pdf_download_url). document_locale é o idioma escollido ao solicitar o token (es por defecto). Os datos e PDF temporais están separados do arquivo real e non se cifran como os documentos reais.",
        "requestBody": {
          "required": true,
          "description": "Datos completos do documento que se quere crear.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDocumentRequest"
              },
              "examples": {
                "create": {
                  "summary": "Emisión con peso e remolque",
                  "value": {
                    "reference": "EXP-2026-004587",
                    "transport_date": "2026-10-05",
                    "shipper": {
                      "name": "Distribuciones Demo, S. L.",
                      "tax_country": "ES",
                      "tax_id": "B12345674",
                      "address": {
                        "street": "Carrer de la Logística, 18",
                        "postal_code": "08040",
                        "city": "Barcelona",
                        "country": "ES"
                      }
                    },
                    "carrier": {
                      "name": "Transportes Demo, S. L.",
                      "tax_country": "ES",
                      "tax_id": "B87654323"
                    },
                    "origin": {
                      "place": "Almacén Barcelona",
                      "city": "Barcelona",
                      "country": "ES"
                    },
                    "destination": {
                      "place": "Almacén Zaragoza",
                      "city": "Zaragoza",
                      "country": "ES"
                    },
                    "goods": {
                      "description": "Vino embotellado",
                      "weight_kg": "1850.000"
                    },
                    "vehicle": {
                      "country": "ES",
                      "registration": "4827 MNL",
                      "trailer_country": "ES",
                      "trailer_registration": "R 5832 BCD"
                    },
                    "special_authorization": null,
                    "observations": null,
                    "metadata": {
                      "order_id": "4587",
                      "terminal": "POS-02"
                    }
                  }
                },
                "alternativeMeasure": {
                  "summary": "Magnitude alternativa cando é difícil determinar o peso",
                  "value": {
                    "transport_date": "2026-10-05",
                    "shipper": {
                      "name": "Distribuciones Demo, S. L.",
                      "tax_country": "ES",
                      "tax_id": "B12345674",
                      "address": {
                        "street": "Carrer de la Logística, 18",
                        "postal_code": "08040",
                        "city": "Barcelona",
                        "country": "ES"
                      }
                    },
                    "carrier": {
                      "name": "Transportes Demo, S. L.",
                      "tax_country": "ES",
                      "tax_id": "B87654323"
                    },
                    "origin": {
                      "place": "Almacén Barcelona",
                      "city": "Barcelona",
                      "country": "ES"
                    },
                    "destination": {
                      "place": "Almacén Zaragoza",
                      "city": "Zaragoza",
                      "country": "ES"
                    },
                    "goods": {
                      "description": "Carga cuyo peso es de difícil determinación.",
                      "alternative_measure": {
                        "value": "12",
                        "unit": "palés"
                      }
                    },
                    "vehicle": {
                      "country": "ES",
                      "registration": "4827 MNL"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reintento idempotente; devolve o resultado orixinal sen xerar outro PDF.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DocumentResult"
                    },
                    {
                      "$ref": "#/components/schemas/DemoDocumentResult"
                    }
                  ]
                },
                "examples": {
                  "original": {
                    "$ref": "#/components/examples/DocumentResult"
                  }
                }
              }
            }
          },
          "201": {
            "description": "Documento novo xerado e almacenado.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DocumentResult"
                    },
                    {
                      "$ref": "#/components/schemas/DemoDocumentResult"
                    }
                  ]
                },
                "examples": {
                  "created": {
                    "$ref": "#/components/examples/DocumentResult"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Referencia en conflito ou resultado do reintento caducado.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "referenceConflict": {
                    "value": {
                      "errors": [
                        {
                          "field": "reference",
                          "code": "REFERENCE_CONFLICT",
                          "message": "Reference conflicts with an existing request."
                        }
                      ]
                    }
                  },
                  "expiredReplay": {
                    "value": {
                      "errors": [
                        {
                          "field": "reference",
                          "code": "DOCUMENT_WINDOW_EXPIRED",
                          "message": "Original result is no longer available through the API."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/RequestTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "x-deca-order": 10
      },
      "get": {
        "operationId": "listDocuments",
        "tags": [
          "Documentos"
        ],
        "summary": "Listar documentos recentes",
        "description": "Devolve resumos, sen PDF, segredo QR nin metadata. O servidor aplica sempre a xanela de 24 horas e o illamento da credencial. Orde descendente por data de creación e UUID como desempate, paxinación por páxina e filtros inclusivos da data de transporte. A xanela avalíase en cada petición; non constitúe unha instantánea estable entre páxinas. Non permite consultar o histórico.\n\nOs documentos eliminados non aparecen na lista.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Páxina solicitada, a partir de 1.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Documentos por páxina, entre 1 e 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Data mínima de transporte, incluída. Non amplía a xanela de lectura.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "examples": {
              "default": {
                "value": "2026-10-05"
              }
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Data máxima de transporte, incluída; igual ou posterior a from.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "examples": {
              "default": {
                "value": "2026-10-05"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Páxina de documentos recentes. Unha páxina sen resultados ten data baleiro.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentList"
                },
                "examples": {
                  "default": {
                    "value": {
                      "data": [
                        {
                          "uuid": "75b10a04-1a2d-4f9e-9277-5f3c270f476e",
                          "reference": "EXP-2026-004587",
                          "created_at": "2026-10-05T14:43:00Z",
                          "transport_date": "2026-10-05",
                          "rectifies_uuid": null
                        }
                      ],
                      "meta": {
                        "current_page": 1,
                        "limit": 25,
                        "total": 1,
                        "last_page": 1
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-deca-order": 50
      }
    },
    "/api/v1/documents/{uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DocumentUuidWithReferenceAlternative"
        }
      ],
      "put": {
        "operationId": "rectifyDocument",
        "tags": [
          "Documentos"
        ],
        "summary": "Rectificar documento",
        "x-deca-order": 20,
        "description": "Identifica o documento anterior co UUID e envía todos os datos corrixidos, sen modificacións parciais. Só se pode rectificar a última versión da mesma credencial. Permítese rectificar un documento de máis de 24 horas sen devolver o contido anterior. Un documento eliminado devolve 404 e non se pode rectificar.\n\nXérase un documento rectificativo con UUID, PDF e QR novos; consérvanse o orixinal e o seu QR. Entrega o novo PDF ao condutor. O campo reference do corpo corresponde á nova versión, non ao documento da URL.\n\nRepetir o mesmo PUT cos mesmos datos normalizados e metadata devolve a rectificación xa emitida durante as 24 horas seguintes á súa creación, sen xerar outra versión. Esta comprobación realízase antes de rexeitar un documento xa rectificado e funciona tamén se o reintento identifica o mesmo documento por referencia. Cambiar datos dun documento xa rectificado devolve 409. Un resultado de reintento caducado devolve 409 DOCUMENT_WINDOW_EXPIRED. Se a rectificación devolta está eliminada, o reintento devolve 404. Para outra rectificación, usa o UUID ou a referencia da última versión.",
        "requestBody": {
          "required": true,
          "description": "Datos completos corrixidos do transporte.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RectifyDocumentRequest"
              },
              "examples": {
                "rectify": {
                  "summary": "Rectificación completa cunha referencia nova",
                  "value": {
                    "reference": "EXP-2026-004587-R1",
                    "transport_date": "2026-10-05",
                    "shipper": {
                      "name": "Distribuciones Demo, S. L.",
                      "tax_country": "ES",
                      "tax_id": "B12345674",
                      "address": {
                        "street": "Carrer de la Logística, 18",
                        "postal_code": "08040",
                        "city": "Barcelona",
                        "country": "ES"
                      }
                    },
                    "carrier": {
                      "name": "Transportes Demo, S. L.",
                      "tax_country": "ES",
                      "tax_id": "B87654323"
                    },
                    "origin": {
                      "place": "Almacén Barcelona",
                      "city": "Barcelona",
                      "country": "ES"
                    },
                    "destination": {
                      "place": "Almacén Zaragoza",
                      "city": "Zaragoza",
                      "country": "ES"
                    },
                    "goods": {
                      "description": "Vino embotellado",
                      "weight_kg": "1900.000"
                    },
                    "vehicle": {
                      "country": "ES",
                      "registration": "4827 MNL",
                      "trailer_country": "ES",
                      "trailer_registration": "R 5832 BCD"
                    },
                    "special_authorization": null,
                    "observations": "Corrección del peso de la mercancía.",
                    "metadata": {
                      "order_id": "4587",
                      "terminal": "POS-02"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Documento rectificativo emitido, ou resultado dun reintento idéntico sen crear outra versión.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DocumentResult"
                    },
                    {
                      "$ref": "#/components/schemas/DemoDocumentResult"
                    }
                  ]
                },
                "examples": {
                  "rectified": {
                    "$ref": "#/components/examples/RectifiedDocumentResult"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Documento xa rectificado, referencia nova en conflito ou resultado do reintento caducado.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "alreadyRectified": {
                    "value": {
                      "errors": [
                        {
                          "field": null,
                          "code": "DOCUMENT_ALREADY_RECTIFIED",
                          "message": "Document has already been rectified."
                        }
                      ]
                    }
                  },
                  "referenceConflict": {
                    "value": {
                      "errors": [
                        {
                          "field": "reference",
                          "code": "REFERENCE_CONFLICT",
                          "message": "Reference conflicts with an existing request."
                        }
                      ]
                    }
                  },
                  "expiredReplay": {
                    "value": {
                      "errors": [
                        {
                          "field": null,
                          "code": "DOCUMENT_WINDOW_EXPIRED",
                          "message": "Original result is no longer available through the API."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/RequestTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "x-deca-alternative-path": "/api/v1/documents/ref/{reference}"
      },
      "delete": {
        "operationId": "deleteDocument",
        "tags": [
          "Documentos"
        ],
        "summary": "Eliminar documento",
        "x-deca-order": 40,
        "description": "Borrado lóxico para corrixir erros detectados ao xerar un documento, exclusivamente **antes de entregalo ao transportista ou ao condutor e antes de utilizalo nun transporte**. A integración debe confirmar ambas as condicións; non abonda con estar dentro do prazo. Se o documento xa se entregou ou utilizou, debe rectificarse mediante PUT.\n\nSó se permite mentres a hora do servidor sexa anterior a created_at + **2 horas**; ás 2 horas exactas xa non se permite. Nin unha consulta nin un reintento reinician o prazo. Cada versión usa a súa propia data de creación. Só se pode eliminar a última versión da credencial autenticada.\n\nConsérvanse o PDF, os datos e a rastrexabilidade, pero o documento deixa de aparecer na lista. As consultas por UUID ou referencia, a descarga autenticada, o QR e os reintentos que devolverían o contido responden 404. A consulta de estado responde só con status: deleted durante a xanela de consulta de 24 horas. A referencia segue reservada. Non hai endpoint de reactivación; o borrado conserva o ficheiro para permitir unha recuperación futura.\n\nRepetir DELETE dentro das mesmas 2 horas devolve 204 sen cambiar a data de eliminación. Pasado o prazo devolve 409.\n\nO primeiro acceso correcto á ligazón QR tamén bloquea o borrado con 409 DOCUMENT_ALREADY_ACCESSED. Ese acceso non proba por si só que se realizase o transporte.",
        "requestBody": {
          "required": true,
          "description": "Motivo e confirmación de que o documento aínda non se entregou nin se utilizou.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteDocumentRequest"
              },
              "examples": {
                "generationError": {
                  "value": {
                    "reason": "Peso incorrecto detectado antes de enviar el documento al transportista.",
                    "confirm_not_delivered": true,
                    "confirm_not_used": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Documento marcado como eliminado. Sen corpo de resposta.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Prazo de 2 horas vencido, documento entregado ou utilizado, ou versión xa rectificada. O primeiro acceso correcto á ligazón QR tamén bloquea o borrado con 409 DOCUMENT_ALREADY_ACCESSED. Ese acceso non proba por si só que se realizase o transporte.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "expired": {
                    "value": {
                      "errors": [
                        {
                          "field": null,
                          "code": "DELETE_WINDOW_EXPIRED",
                          "message": "The two-hour deletion window has expired."
                        }
                      ]
                    }
                  },
                  "delivered": {
                    "value": {
                      "errors": [
                        {
                          "field": null,
                          "code": "DOCUMENT_ALREADY_DELIVERED",
                          "message": "A delivered document cannot be deleted."
                        }
                      ]
                    }
                  },
                  "used": {
                    "value": {
                      "errors": [
                        {
                          "field": null,
                          "code": "DOCUMENT_ALREADY_USED",
                          "message": "A document used in transport cannot be deleted."
                        }
                      ]
                    }
                  },
                  "rectified": {
                    "value": {
                      "errors": [
                        {
                          "field": null,
                          "code": "DOCUMENT_ALREADY_RECTIFIED",
                          "message": "Document has already been rectified."
                        }
                      ]
                    }
                  },
                  "accessed": {
                    "value": {
                      "errors": [
                        {
                          "field": null,
                          "code": "DOCUMENT_ALREADY_ACCESSED",
                          "message": "A document accessed through its QR link cannot be deleted."
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/RequestTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-deca-alternative-path": "/api/v1/documents/ref/{reference}"
      },
      "get": {
        "operationId": "getDocument",
        "tags": [
          "Documentos"
        ],
        "summary": "Consultar documento",
        "description": "Recupera o resultado orixinal dentro de 24 horas, só para a credencial que emitiu o documento. Inclúe todos os campos aceptados e normalizados e a metadata sen modificación semántica.\n\nUn UUID ou unha referencia inexistente, doutra credencial ou fóra da xanela devolve o mesmo `404`, sen confirmar a existencia nin o propietario. Cada referencia identifica a súa propia versión e non redirixe a unha rectificación posterior.\n\nUn documento eliminado devolve 404. Para saber se está eliminado, usa a consulta de estado.",
        "responses": {
          "200": {
            "description": "Resultado orixinal do documento.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DocumentResult"
                    },
                    {
                      "$ref": "#/components/schemas/DemoDocumentResult"
                    }
                  ]
                },
                "examples": {
                  "document": {
                    "$ref": "#/components/examples/DocumentResult"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "x-deca-order": 60,
        "x-deca-alternative-path": "/api/v1/documents/ref/{reference}"
      }
    },
    "/api/v1/documents/{uuid}/status": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DocumentStatusUuidWithReferenceAlternative"
        }
      ],
      "get": {
        "operationId": "getDocumentStatus",
        "tags": [
          "Documentos"
        ],
        "summary": "Consultar estado",
        "x-deca-order": 80,
        "description": "Devolve unicamente o estado dun documento da credencial autenticada, durante as 24 horas seguintes á creación. Un documento eliminado responde 200 con {\"status\":\"deleted\"}; non devolve datos do transporte, PDF, ligazón QR nin metadata. Un documento activo responde con {\"status\":\"active\"}.\n\nUn UUID inexistente, doutra credencial ou fóra das 24 horas devolve o mesmo 404. A eliminación non amplía esta xanela.",
        "responses": {
          "200": {
            "description": "Estado do documento sen datos do contido.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentStatus"
                },
                "examples": {
                  "deleted": {
                    "summary": "Documento eliminado",
                    "value": {
                      "status": "deleted"
                    }
                  },
                  "active": {
                    "summary": "Documento activo",
                    "value": {
                      "status": "active"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-deca-alternative-path": "/api/v1/documents/ref/{reference}/status"
      }
    },
    "/api/v1/documents/{uuid}/pdf": {
      "parameters": [
        {
          "name": "uuid",
          "in": "path",
          "required": true,
          "description": "UUID público do documento. Alternativamente, usa `GET /api/v1/documents/ref/{reference}/pdf`. Exemplo: `/api/v1/documents/ref/EXP-2026-004587/pdf`.",
          "schema": {
            "type": "string",
            "format": "uuid"
          },
          "examples": {
            "default": {
              "value": "75b10a04-1a2d-4f9e-9277-5f3c270f476e"
            }
          }
        }
      ],
      "get": {
        "operationId": "downloadDocumentPdf",
        "tags": [
          "Documentos"
        ],
        "summary": "Descargar PDF",
        "description": "Devolve exactamente os bytes do PDF almacenado, sen rexeneralo. Esixe a credencial propietaria e unha antigüidade inferior a 24 horas. Esta limitación non altera a conservación legal nin a vixencia do QR.\n\nUn documento eliminado devolve 404 sen entregar o PDF.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/PdfDownload"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-deca-order": 90,
        "x-deca-alternative-path": "/api/v1/documents/ref/{reference}/pdf"
      }
    },
    "/d/{uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DocumentUuid"
        }
      ],
      "get": {
        "operationId": "downloadDocumentByQr",
        "tags": [
          "Descarga por QR"
        ],
        "summary": "Descargar PDF por QR",
        "description": "Ligazón incluída no QR. O segredo k autoriza unicamente este documento. Non require Bearer, sesión, CAPTCHA nin páxina intermedia. Quen coñece a ligazón pode descargalo. Non rexistres a URL completa en logs, analítica nin trazas.\n\nA descarga non caduca ás 24 horas nin se revoga automaticamente ao rotar ou revogar o Bearer. O QR anterior conserva o seu PDF despois dunha rectificación; non redirixe á nova versión.\n\nO PDF entrégase con `Content-Disposition: inline` para abrilo no visor do navegador.\n\nUn documento eliminado devolve 404, aínda que o segredo sexa correcto.",
        "security": [
          {
            "qrSecret": []
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/PdfPreview"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-deca-order": 100
      }
    },
    "/api/v1/demo/tokens": {
      "post": {
        "operationId": "createDemoToken",
        "tags": [
          "Demostración da API"
        ],
        "summary": "Solicitar un token demo",
        "description": "Envía un obxecto JSON baleiro a este endpoint público. Non precisa unha cabeceira Bearer. A resposta `201` contén `token` e `expires_at`; a data de caducidade exprésase en UTC.\n\nPodes solicitar un token `sk_demo_` sen conta nin alta dunha organización. Dura **24 horas desde a súa emisión** e só funciona desde a **IP pública que o solicitou**. Cambiar de rede ou de IP require solicitar outro token.\n\nUtiliza unicamente **datos ficticios**. Cada páxina do PDF mostra **SEN VALIDEZ** xunto ao logo e unha marca diagonal **DEMO**. Estes documentos non serven para transportar mercadorías nin como documentos administrativos válidos.\n\nA demo admite corpos de ata 32 KiB e dez documentos por sesión. A emisión de tokens admite tres por minuto e dez por hora desde unha mesma IP; a creación, cinco por minuto e vinte por hora desde unha mesma IP. Os límites compartidos por rede, rexión e carga global poden aplicarse antes. Estas cifras corresponden á configuración predeterminada. Podes enviar document_locale para escoller o idioma de todos os PDF do token: es, ca, gl, ca-valencia, eu, en, pt-pt ou fr. Se se omite, utilízase es. A resposta tamén inclúe document_locale; cambialo require un novo token.",
        "security": [],
        "requestBody": {
          "required": true,
          "description": "Envía un obxecto JSON baleiro a este endpoint público. Non precisa unha cabeceira Bearer. A resposta `201` contén `token` e `expires_at`; a data de caducidade exprésase en UTC. Podes enviar document_locale para escoller o idioma de todos os PDF do token: es, ca, gl, ca-valencia, eu, en, pt-pt ou fr. Se se omite, utilízase es. A resposta tamén inclúe document_locale; cambialo require un novo token.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "document_locale": {
                    "type": "string",
                    "enum": [
                      "es",
                      "ca",
                      "gl",
                      "ca-valencia",
                      "eu",
                      "en",
                      "pt-pt",
                      "fr"
                    ],
                    "default": "es",
                    "description": "Idioma dos PDF deste token. Castelán por defecto."
                  }
                }
              },
              "examples": {
                "default": {
                  "value": {}
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Token demo emitido; válido durante 24 horas e vinculado á IP solicitante.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DemoTokenResult"
                },
                "examples": {
                  "default": {
                    "value": {
                      "token": "sk_demo_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
                      "expires_at": "2026-10-07T11:00:00Z",
                      "document_locale": "es"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "413": {
            "$ref": "#/components/responses/RequestTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/DemoRateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/DemoUnavailable"
          }
        },
        "x-deca-order": 5
      }
    },
    "/demo/d/{uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DocumentUuid"
        }
      ],
      "get": {
        "operationId": "downloadDemoDocumentByQr",
        "tags": [
          "Demostración da API"
        ],
        "summary": "Abrir o PDF demo por QR",
        "description": "O QR abre o PDF directamente no navegador mediante `/demo/d/{uuid}?k=...`, sen Bearer. Tanto o documento como as súas ligazóns caducan coa sesión demo; crear ou rectificar un documento non amplía a duración do token.\n\nUtiliza unicamente **datos ficticios**. Cada páxina do PDF mostra **SEN VALIDEZ** xunto ao logo e unha marca diagonal **DEMO**. Estes documentos non serven para transportar mercadorías nin como documentos administrativos válidos.",
        "security": [
          {
            "qrSecret": []
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/PdfPreview"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/DemoRateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/DemoUnavailable"
          }
        },
        "x-deca-order": 110
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Token de integración facilitado polo soporte de SERTEC PESAGE. Envíao en Authorization: Bearer, exclusivamente mediante HTTPS. sk_test_ selecciona desenvolvemento e sk_live_ produción. Se o token ten unha lista de IP autorizadas, a petición debe proceder dunha delas; unha lista baleira permite calquera IP. Non envíes o token na URL nin o expoñas en aplicacións cliente.\n\nPodes solicitar un token `sk_demo_` sen conta nin alta dunha organización. Dura **24 horas desde a súa emisión** e só funciona desde a **IP pública que o solicitou**. Cambiar de rede ou de IP require solicitar outro token. Utiliza unicamente **datos ficticios**. Cada páxina do PDF mostra **SEN VALIDEZ** xunto ao logo e unha marca diagonal **DEMO**. Estes documentos non serven para transportar mercadorías nin como documentos administrativos válidos."
      },
      "qrSecret": {
        "type": "apiKey",
        "in": "query",
        "name": "k",
        "description": "Segredo opaco da ligazón QR; copia exactamente o valor devolto en url."
      }
    },
    "parameters": {
      "DocumentUuid": {
        "name": "uuid",
        "in": "path",
        "required": true,
        "description": "UUID público do documento; coñecelo non concede acceso.",
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "examples": {
          "default": {
            "value": "75b10a04-1a2d-4f9e-9277-5f3c270f476e"
          }
        }
      },
      "DocumentUuidWithReferenceAlternative": {
        "name": "uuid",
        "in": "path",
        "required": true,
        "description": "UUID público do documento. Alternativamente, usa `/api/v1/documents/ref/{reference}` co mesmo método. Exemplo: `/api/v1/documents/ref/EXP-2026-004587`.",
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "examples": {
          "default": {
            "value": "75b10a04-1a2d-4f9e-9277-5f3c270f476e"
          }
        }
      },
      "DocumentStatusUuidWithReferenceAlternative": {
        "name": "uuid",
        "in": "path",
        "required": true,
        "description": "UUID público do documento. Alternativamente, usa `GET /api/v1/documents/ref/{reference}/status`. Exemplo: `/api/v1/documents/ref/EXP-2026-004587/status`.",
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "examples": {
          "default": {
            "value": "75b10a04-1a2d-4f9e-9277-5f3c270f476e"
          }
        }
      }
    },
    "headers": {
      "NoStore": {
        "description": "A resposta contén información sensible e non debe almacenarse na caché.",
        "schema": {
          "type": "string",
          "examples": [
            "no-store, private"
          ]
        }
      }
    },
    "schemas": {
      "CountryCode": {
        "type": "string",
        "pattern": "^[A-Z]{2}$",
        "description": "Código de país de dúas letras; normalízase a maiúsculas. O formato non comproba a pertenza ao catálogo ISO 3166-1.",
        "examples": [
          "ES"
        ]
      },
      "PositiveDecimal": {
        "type": "string",
        "pattern": "^(?!0+(?:\\.0+)?$)(?:0|[1-9][0-9]{0,14})(?:\\.[0-9]{1,6})?$",
        "description": "Decimal positivo como string, con punto, sen coma nin notación científica. Ata 15 cifras enteiras e 6 decimais. A resposta elimina os ceros decimais finais.",
        "examples": [
          "1850.000"
        ]
      },
      "WeightKilograms": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/PositiveDecimal"
          },
          {
            "type": "number",
            "exclusiveMinimum": 0,
            "exclusiveMaximum": 1000000000000000,
            "multipleOf": 0.000001
          }
        ],
        "description": "Peso positivo en kg, como número JSON ou texto decimal. Ata 15 cifras enteiras e 6 decimais. A resposta normaliza a texto e conserva a precisión; o PDF mostra ata 3 decimais, con coma decimal e puntos de milleiros. Usa texto decimal para evitar perda de precisión en valores grandes.",
        "examples": [
          1850.5
        ]
      },
      "Address": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "street",
          "postal_code",
          "city",
          "country"
        ],
        "properties": {
          "street": {
            "type": "string",
            "minLength": 1,
            "description": "Vía e número do domicilio.",
            "maxLength": 255
          },
          "postal_code": {
            "type": "string",
            "minLength": 1,
            "description": "Código postal como texto para conservar os ceros iniciais.",
            "maxLength": 255
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "description": "Localidade do domicilio.",
            "maxLength": 255
          },
          "country": {
            "$ref": "#/components/schemas/CountryCode"
          }
        }
      },
      "Shipper": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "tax_country",
          "tax_id",
          "address"
        ],
        "description": "Cargador contractual; pode ser diferente do almacén de orixe e do cliente de DeCA.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Nome ou razón social.",
            "maxLength": 255
          },
          "tax_country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "tax_id": {
            "type": "string",
            "minLength": 1,
            "description": "Identificador fiscal normalizado a maiúsculas sen espazos nin guións; a lonxitude compróbase tras normalizar. En España valídanse formato e carácter de control de DNI, NIE e NIF de entidades (CIF). Os NIF especiais K, L e M compróbanse só polo formato: prefixo, sete caracteres alfanuméricos e letra final. Para outros países esíxese formato alfanumérico sen verificar o control fiscal. Esta validación non acredita existencia nin alta censal.",
            "maxLength": 32
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          }
        }
      },
      "Carrier": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "tax_country",
          "tax_id"
        ],
        "description": "Transportista que realiza efectivamente o transporte, incluído o subcontratado.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Nome ou razón social.",
            "maxLength": 255
          },
          "tax_country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "tax_id": {
            "type": "string",
            "minLength": 1,
            "description": "Identificador fiscal normalizado a maiúsculas sen espazos nin guións; a lonxitude compróbase tras normalizar. En España valídanse formato e carácter de control de DNI, NIE e NIF de entidades (CIF). Os NIF especiais K, L e M compróbanse só polo formato: prefixo, sete caracteres alfanuméricos e letra final. Para outros países esíxese formato alfanumérico sen verificar o control fiscal. Esta validación non acredita existencia nin alta censal.",
            "maxLength": 32
          },
          "address": {
            "description": "Domicilio opcional do transportista. Se se envía, debe incluír todos os campos de Address; o artigo 6 non o esixe como dato mínimo.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "street",
              "postal_code",
              "city",
              "country"
            ],
            "properties": {
              "street": {
                "type": "string",
                "minLength": 1,
                "description": "Vía e número do domicilio.",
                "maxLength": 255
              },
              "postal_code": {
                "type": "string",
                "minLength": 1,
                "description": "Código postal como texto para conservar os ceros iniciais.",
                "maxLength": 255
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "description": "Localidade do domicilio.",
                "maxLength": 255
              },
              "country": {
                "$ref": "#/components/schemas/CountryCode"
              }
            }
          }
        }
      },
      "TransportLocation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "place",
          "city",
          "country"
        ],
        "properties": {
          "place": {
            "type": "string",
            "minLength": 1,
            "description": "Lugar real de carga ou descarga, identificable polo nome da instalación ou o enderezo. Con city e country debe permitir identificalo claramente; street e postal_code son opcionais. A identidade da empresa destinataria non é un dato mínimo obrigatorio.",
            "maxLength": 255
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "description": "Localidade.",
            "maxLength": 255
          },
          "country": {
            "type": "string",
            "enum": [
              "ES"
            ],
            "description": "O alcance inicial abrangue transportes interiores en España; non substitúe o CMR internacional."
          },
          "street": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Vía e número opcionais do lugar de carga ou descarga para precisar a súa localización."
          },
          "postal_code": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Código postal opcional do lugar de carga ou descarga, como texto para conservar ceros iniciais."
          }
        }
      },
      "AlternativeMeasure": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "value",
          "unit"
        ],
        "description": "Outra magnitude cando sexa difícil determinar o peso. Envía esta magnitude ou o peso, nunca ambas.",
        "properties": {
          "value": {
            "$ref": "#/components/schemas/PositiveDecimal"
          },
          "unit": {
            "type": "string",
            "minLength": 1,
            "description": "Unidade explícita da magnitude, ata 255 caracteres.",
            "maxLength": 255,
            "examples": [
              "palés"
            ]
          }
        }
      },
      "Goods": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "description"
        ],
        "description": "Natureza e peso da mercadoría, ou magnitude alternativa cando corresponda. Envía exactamente unha medida.",
        "properties": {
          "description": {
            "type": "string",
            "minLength": 1,
            "description": "Descrición da natureza da mercadoría.",
            "maxLength": 2000
          },
          "weight_kg": {
            "$ref": "#/components/schemas/WeightKilograms"
          },
          "alternative_measure": {
            "$ref": "#/components/schemas/AlternativeMeasure"
          }
        },
        "oneOf": [
          {
            "required": [
              "weight_kg"
            ]
          },
          {
            "required": [
              "alternative_measure"
            ]
          }
        ]
      },
      "Vehicle": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "country",
          "registration"
        ],
        "description": "Vehículo efectivo; se hai remolque ou semirremolque, informa os dous campos xuntos.",
        "properties": {
          "country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "registration": {
            "type": "string",
            "minLength": 1,
            "description": "Matrícula normalizada a maiúsculas e sen espazos nin guións. Para España admítense a matrícula ordinaria vixente, as provinciais anteriores e a serie especial E. Para outros países, entre 3 e 20 caracteres alfanuméricos.",
            "maxLength": 20,
            "examples": [
              "4827 MNL"
            ]
          },
          "trailer_country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "trailer_registration": {
            "type": "string",
            "minLength": 1,
            "description": "Matrícula do remolque ou semirremolque, normalizada como a do tractor. Para España esíxese a serie R. Para outros países, entre 3 e 20 caracteres alfanuméricos.",
            "maxLength": 20,
            "examples": [
              "R 5832 BCD"
            ]
          }
        },
        "oneOf": [
          {
            "required": [
              "trailer_country",
              "trailer_registration"
            ]
          },
          {
            "not": {
              "anyOf": [
                {
                  "properties": {
                    "trailer_country": {}
                  },
                  "required": [
                    "trailer_country"
                  ]
                },
                {
                  "properties": {
                    "trailer_registration": {}
                  },
                  "required": [
                    "trailer_registration"
                  ]
                }
              ]
            }
          }
        ]
      },
      "SpecialAuthorization": {
        "type": [
          "object",
          "null"
        ],
        "additionalProperties": false,
        "required": [
          "number"
        ],
        "description": "Autorización especial de circulación cando sexa necesaria. Omítea ou envía null se non procede.",
        "properties": {
          "number": {
            "type": "string",
            "minLength": 1,
            "description": "Número ou referencia da autorización.",
            "maxLength": 255
          },
          "issuer": {
            "type": "string",
            "minLength": 1,
            "description": "Organismo emisor, se se informa.",
            "maxLength": 255
          }
        }
      },
      "CreateDocumentRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "transport_date",
          "shipper",
          "carrier",
          "origin",
          "destination",
          "goods",
          "vehicle"
        ],
        "properties": {
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "description": "Referencia propia opcional, única por organización e contorno e impresa no PDF. Identifica os reintentos e permite consultar por referencia. Non se libera ao eliminar o documento.",
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])",
            "maxLength": 120
          },
          "transport_date": {
            "type": "string",
            "format": "date",
            "description": "Data real do transporte en formato YYYY-MM-DD; non é o instante de creación do PDF."
          },
          "shipper": {
            "$ref": "#/components/schemas/Shipper"
          },
          "carrier": {
            "$ref": "#/components/schemas/Carrier"
          },
          "origin": {
            "$ref": "#/components/schemas/TransportLocation"
          },
          "destination": {
            "$ref": "#/components/schemas/TransportLocation"
          },
          "goods": {
            "$ref": "#/components/schemas/Goods"
          },
          "vehicle": {
            "$ref": "#/components/schemas/Vehicle"
          },
          "special_authorization": {
            "$ref": "#/components/schemas/SpecialAuthorization"
          },
          "observations": {
            "type": [
              "string",
              "null"
            ],
            "description": "Observacións que os intervenientes soliciten facer constar no documento.",
            "maxLength": 4000
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Obxecto JSON opcional, conservado e devolto sen modificación semántica. Non se imprime no PDF. Máximo 16 KiB ao serializalo e 8 niveis de profundidade."
          }
        }
      },
      "DocumentResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "uuid",
          "reference",
          "created_at",
          "url",
          "qr",
          "pdf_download_url",
          "rectifies_uuid",
          "normalized_data",
          "metadata",
          "document_locale"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID do documento emitido."
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "description": "Referencia do cliente ou null.",
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Instante orixinal de creación, en UTC."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL HTTPS completa de descarga por QR, incluído o seu segredo. Non a rexistres nin publiques."
          },
          "qr": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "mime_type",
              "encoding",
              "data"
            ],
            "properties": {
              "mime_type": {
                "type": "string",
                "enum": [
                  "image/png"
                ]
              },
              "encoding": {
                "type": "string",
                "enum": [
                  "base64"
                ]
              },
              "data": {
                "type": "string",
                "description": "Bytes da imaxe PNG en Base64, sen prefixo data URI.",
                "contentEncoding": "base64"
              }
            }
          },
          "pdf_download_url": {
            "type": "string",
            "format": "uri",
            "description": "URL de descarga autenticada; require o Bearer da credencial propietaria dentro de 24 horas."
          },
          "rectifies_uuid": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "UUID rectificado ou null nunha emisión inicial."
          },
          "normalized_data": {
            "$ref": "#/components/schemas/CreateDocumentRequest"
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "A mesma metadata da petición; null se non se proporcionou."
          },
          "document_locale": {
            "type": "string",
            "enum": [
              "es",
              "ca",
              "gl",
              "ca-valencia",
              "eu",
              "en",
              "pt-pt",
              "fr"
            ],
            "description": "Idioma do PDF escollido ao emitilo segundo a organización. Consérvase no resultado; cambiar o idioma da organización non modifica documentos existentes. Non cambia campos JSON nin mensaxes de erro da API."
          }
        }
      },
      "DocumentSummary": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "uuid",
          "reference",
          "created_at",
          "transport_date",
          "rectifies_uuid"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid"
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "transport_date": {
            "type": "string",
            "format": "date"
          },
          "rectifies_uuid": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "DocumentList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentSummary"
            }
          },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "current_page",
              "limit",
              "total",
              "last_page"
            ],
            "properties": {
              "current_page": {
                "type": "integer",
                "minimum": 1
              },
              "limit": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "total": {
                "type": "integer",
                "minimum": 0
              },
              "last_page": {
                "type": "integer",
                "minimum": 1
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "type": "array",
            "minItems": 1,
            "description": "Todos os erros independentes detectados; sen datos de petición, segredos nin trazas.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "field",
                "code",
                "message"
              ],
              "properties": {
                "field": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Ruta do campo con puntos; null para un erro xeral."
                },
                "code": {
                  "type": "string",
                  "pattern": "^[A-Z][A-Z0-9_]*$",
                  "description": "Código estable para a lóxica de integración."
                },
                "message": {
                  "type": "string",
                  "description": "Mensaxe breve en inglés. Non a uses como identificador do erro."
                }
              }
            }
          }
        }
      },
      "RectifyDocumentRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "transport_date",
          "shipper",
          "carrier",
          "origin",
          "destination",
          "goods",
          "vehicle"
        ],
        "properties": {
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "description": "Referencia nova do documento rectificativo, opcional e única por organización e contorno. Non reutilices a referencia do documento identificado na URL.",
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])",
            "maxLength": 120
          },
          "transport_date": {
            "type": "string",
            "format": "date",
            "description": "Data real do transporte en formato YYYY-MM-DD; non é o instante de creación do PDF."
          },
          "shipper": {
            "$ref": "#/components/schemas/Shipper"
          },
          "carrier": {
            "$ref": "#/components/schemas/Carrier"
          },
          "origin": {
            "$ref": "#/components/schemas/TransportLocation"
          },
          "destination": {
            "$ref": "#/components/schemas/TransportLocation"
          },
          "goods": {
            "$ref": "#/components/schemas/Goods"
          },
          "vehicle": {
            "$ref": "#/components/schemas/Vehicle"
          },
          "special_authorization": {
            "$ref": "#/components/schemas/SpecialAuthorization"
          },
          "observations": {
            "type": [
              "string",
              "null"
            ],
            "description": "Observacións que os intervenientes soliciten facer constar no documento.",
            "maxLength": 4000
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Obxecto JSON opcional, conservado e devolto sen modificación semántica. Non se imprime no PDF. Máximo 16 KiB ao serializalo e 8 niveis de profundidade."
          }
        },
        "description": "Todos os datos corrixidos do transporte. O documento anterior identifícase na URL. Se se inclúe reference, debe ser unha referencia nova para o documento rectificativo."
      },
      "DeleteDocumentRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "reason",
          "confirm_not_delivered",
          "confirm_not_used"
        ],
        "properties": {
          "reason": {
            "type": "string",
            "minLength": 1,
            "description": "Motivo do erro detectado ao xerar o documento.",
            "maxLength": 2000
          },
          "confirm_not_delivered": {
            "type": "boolean",
            "description": "Debe ser true para eliminar: confirma que non se entregou ao transportista nin ao condutor. false devolve 409 DOCUMENT_ALREADY_DELIVERED."
          },
          "confirm_not_used": {
            "type": "boolean",
            "description": "Debe ser true para eliminar: confirma que non se utilizou nun transporte. false devolve 409 DOCUMENT_ALREADY_USED."
          }
        }
      },
      "DocumentStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "active",
              "deleted"
            ],
            "description": "Estado do documento. Non inclúe información do transporte, PDF, QR, metadata nin datas."
          }
        }
      },
      "DemoTokenResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "token",
          "expires_at",
          "document_locale"
        ],
        "properties": {
          "token": {
            "type": "string",
            "pattern": "^sk_demo_[0-9a-f]{64}(_(ca|gl|ca-valencia|eu|en|pt-pt|fr))?$",
            "description": "Podes solicitar un token `sk_demo_` sen conta nin alta dunha organización. Dura **24 horas desde a súa emisión** e só funciona desde a **IP pública que o solicitou**. Cambiar de rede ou de IP require solicitar outro token."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Caducidade do token en UTC. Todos os seus documentos e ligazóns vencen neste instante."
          },
          "document_locale": {
            "type": "string",
            "enum": [
              "es",
              "ca",
              "gl",
              "ca-valencia",
              "eu",
              "en",
              "pt-pt",
              "fr"
            ],
            "description": "Idioma dos PDF deste token. Castelán por defecto."
          }
        }
      },
      "DemoDocumentResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "uuid",
          "reference",
          "created_at",
          "url",
          "qr",
          "pdf_download_url",
          "rectifies_uuid",
          "normalized_data",
          "metadata",
          "document_locale",
          "demo",
          "expires_at",
          "qr_url",
          "pdf_url"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "UUID do documento emitido."
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "description": "Referencia do cliente ou null.",
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Instante orixinal de creación, en UTC."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL HTTPS completa de descarga por QR, incluído o seu segredo. Non a rexistres nin publiques."
          },
          "qr": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "mime_type",
              "encoding",
              "data"
            ],
            "properties": {
              "mime_type": {
                "type": "string",
                "enum": [
                  "image/png"
                ]
              },
              "encoding": {
                "type": "string",
                "enum": [
                  "base64"
                ]
              },
              "data": {
                "type": "string",
                "description": "Bytes da imaxe PNG en Base64, sen prefixo data URI.",
                "contentEncoding": "base64"
              }
            }
          },
          "pdf_download_url": {
            "type": "string",
            "format": "uri",
            "description": "Podes solicitar un token `sk_demo_` sen conta nin alta dunha organización. Dura **24 horas desde a súa emisión** e só funciona desde a **IP pública que o solicitou**. Cambiar de rede ou de IP require solicitar outro token."
          },
          "rectifies_uuid": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "UUID rectificado ou null nunha emisión inicial."
          },
          "normalized_data": {
            "$ref": "#/components/schemas/CreateDocumentRequest"
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "A mesma metadata da petición; null se non se proporcionou."
          },
          "document_locale": {
            "type": "string",
            "enum": [
              "es",
              "ca",
              "gl",
              "ca-valencia",
              "eu",
              "en",
              "pt-pt",
              "fr"
            ],
            "description": "Idioma dos PDF deste token. Castelán por defecto."
          },
          "demo": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Só na demo; sempre true. Non aparece en resultados de desenvolvemento ou produción."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Caducidade do token en UTC. Todos os seus documentos e ligazóns vencen neste instante."
          },
          "qr_url": {
            "type": "string",
            "format": "uri",
            "description": "Só na demo; alias de url."
          },
          "pdf_url": {
            "type": "string",
            "format": "uri",
            "description": "Só na demo; alias de pdf_download_url. Require o token demo e a súa IP."
          }
        },
        "description": "A demo engade demo: true, expires_at, qr_url (alias de url) e pdf_url (alias de pdf_download_url). document_locale é o idioma escollido ao solicitar o token (es por defecto). Os datos e PDF temporais están separados do arquivo real e non se cifran como os documentos reais."
      }
    },
    "examples": {
      "DocumentResult": {
        "summary": "Resultado completo con datos ficticios e QR ilustrativo",
        "value": {
          "uuid": "75b10a04-1a2d-4f9e-9277-5f3c270f476e",
          "reference": "EXP-2026-004587",
          "created_at": "2026-10-05T14:43:00Z",
          "url": "https://deca.sertecpesage.com/d/75b10a04-1a2d-4f9e-9277-5f3c270f476e?k=EXAMPLE_SECRET",
          "qr": {
            "mime_type": "image/png",
            "encoding": "base64",
            "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jRZkAAAAASUVORK5CYII="
          },
          "pdf_download_url": "https://deca.sertecpesage.com/api/v1/documents/75b10a04-1a2d-4f9e-9277-5f3c270f476e/pdf",
          "rectifies_uuid": null,
          "normalized_data": {
            "reference": "EXP-2026-004587",
            "transport_date": "2026-10-05",
            "shipper": {
              "name": "Distribuciones Demo, S. L.",
              "tax_country": "ES",
              "tax_id": "B12345674",
              "address": {
                "street": "Carrer de la Logística, 18",
                "postal_code": "08040",
                "city": "Barcelona",
                "country": "ES"
              }
            },
            "carrier": {
              "name": "Transportes Demo, S. L.",
              "tax_country": "ES",
              "tax_id": "B87654323"
            },
            "origin": {
              "place": "Almacén Barcelona",
              "city": "Barcelona",
              "country": "ES"
            },
            "destination": {
              "place": "Almacén Zaragoza",
              "city": "Zaragoza",
              "country": "ES"
            },
            "goods": {
              "description": "Vino embotellado",
              "weight_kg": "1850"
            },
            "vehicle": {
              "country": "ES",
              "registration": "4827MNL",
              "trailer_country": "ES",
              "trailer_registration": "R5832BCD"
            },
            "special_authorization": null,
            "observations": null,
            "metadata": {
              "order_id": "4587",
              "terminal": "POS-02"
            }
          },
          "metadata": {
            "order_id": "4587",
            "terminal": "POS-02"
          },
          "document_locale": "es"
        }
      },
      "RectifiedDocumentResult": {
        "summary": "Documento rectificativo con UUID, PDF e QR novos",
        "value": {
          "uuid": "dbf53b0c-e0ec-49a4-952d-ed59d9b1b0d1",
          "reference": "EXP-2026-004587-R1",
          "created_at": "2026-10-05T15:00:00Z",
          "url": "https://deca.sertecpesage.com/d/dbf53b0c-e0ec-49a4-952d-ed59d9b1b0d1?k=EXAMPLE_RECTIFICATION_SECRET",
          "qr": {
            "mime_type": "image/png",
            "encoding": "base64",
            "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jRZkAAAAASUVORK5CYII="
          },
          "pdf_download_url": "https://deca.sertecpesage.com/api/v1/documents/dbf53b0c-e0ec-49a4-952d-ed59d9b1b0d1/pdf",
          "rectifies_uuid": "75b10a04-1a2d-4f9e-9277-5f3c270f476e",
          "normalized_data": {
            "reference": "EXP-2026-004587-R1",
            "transport_date": "2026-10-05",
            "shipper": {
              "name": "Distribuciones Demo, S. L.",
              "tax_country": "ES",
              "tax_id": "B12345674",
              "address": {
                "street": "Carrer de la Logística, 18",
                "postal_code": "08040",
                "city": "Barcelona",
                "country": "ES"
              }
            },
            "carrier": {
              "name": "Transportes Demo, S. L.",
              "tax_country": "ES",
              "tax_id": "B87654323"
            },
            "origin": {
              "place": "Almacén Barcelona",
              "city": "Barcelona",
              "country": "ES"
            },
            "destination": {
              "place": "Almacén Zaragoza",
              "city": "Zaragoza",
              "country": "ES"
            },
            "goods": {
              "description": "Vino embotellado",
              "weight_kg": "1900"
            },
            "vehicle": {
              "country": "ES",
              "registration": "4827MNL",
              "trailer_country": "ES",
              "trailer_registration": "R5832BCD"
            },
            "special_authorization": null,
            "observations": "Corrección del peso de la mercancía.",
            "metadata": {
              "order_id": "4587",
              "terminal": "POS-02"
            }
          },
          "metadata": {
            "order_id": "4587",
            "terminal": "POS-02"
          },
          "document_locale": "es"
        }
      }
    },
    "responses": {
      "PdfDownload": {
        "description": "PDF orixinal nativo, de ata 5 MB. Descarga directa sen rexeneración.",
        "headers": {
          "Content-Disposition": {
            "description": "Nome seguro que non incorpora datos do cliente.",
            "schema": {
              "type": "string"
            },
            "examples": {
              "default": {
                "value": "attachment; filename=\"deca-75b10a04-1a2d-4f9e-9277-5f3c270f476e.pdf\""
              }
            }
          },
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          },
          "Referrer-Policy": {
            "schema": {
              "type": "string",
              "enum": [
                "no-referrer"
              ]
            },
            "description": "Evitar a propagación da URL secreta."
          },
          "X-Content-Type-Options": {
            "schema": {
              "type": "string",
              "enum": [
                "nosniff"
              ]
            },
            "description": "Impedir a interpretación do contido como outro tipo."
          }
        },
        "content": {
          "application/pdf": {
            "schema": {
              "type": "string",
              "contentMediaType": "application/octet-stream"
            }
          }
        }
      },
      "PdfPreview": {
        "description": "PDF orixinal nativo, de ata 5 MB. Visualización no navegador sen rexeneración.",
        "headers": {
          "Content-Disposition": {
            "description": "Nome seguro que non incorpora datos do cliente.",
            "schema": {
              "type": "string"
            },
            "examples": {
              "default": {
                "value": "inline; filename=\"deca-75b10a04-1a2d-4f9e-9277-5f3c270f476e.pdf\""
              }
            }
          },
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          },
          "Referrer-Policy": {
            "schema": {
              "type": "string",
              "enum": [
                "no-referrer"
              ]
            },
            "description": "Evitar a propagación da URL secreta."
          },
          "X-Content-Type-Options": {
            "schema": {
              "type": "string",
              "enum": [
                "nosniff"
              ]
            },
            "description": "Impedir a interpretación do contido como outro tipo."
          }
        },
        "content": {
          "application/pdf": {
            "schema": {
              "type": "string",
              "contentMediaType": "application/octet-stream"
            }
          }
        }
      },
      "BadRequest": {
        "description": "JSON mal formado; non se procesa a solicitude.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "INVALID_JSON",
                      "message": "Request body must contain valid JSON."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Bearer ausente, inválido ou revogado.\n\nUn token demo caducado ou enviado desde outra IP devolve `401`. Un QR demo caducado devolve `404`. Se a demo está desactivada, devolve `503 DEMO_UNAVAILABLE`. O primeiro acceso ao QR ou unha rectificación impiden eliminar o documento; mantéñense as confirmacións de borrado do contrato habitual.",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "examples": [
                "Bearer"
              ]
            },
            "description": "Esquema de autenticación requirido."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "UNAUTHORIZED",
                      "message": "Valid API credentials are required."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "IP non autorizada ou acción non permitida para a credencial.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "FORBIDDEN",
                      "message": "This request is not allowed."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Documento non dispoñible para este acceso; non revela existencia, propietario nin motivo.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "DOCUMENT_NOT_AVAILABLE",
                      "message": "Document is not available."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "As peticións POST, PUT e DELETE con corpo esixen Content-Type application/json.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "UNSUPPORTED_MEDIA_TYPE",
                      "message": "Content-Type must be application/json."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "ValidationError": {
        "description": "Campos inválidos; devolve todos os erros independentes detectados. Os oito idiomas traducen os títulos e etiquetas do PDF, non os nomes, enderezos, observacións nin outros datos enviados pola integración. Os textos impresos admiten caracteres latinos, gregos e cirílicos compatibles coas fontes; emoji, CJK e escrituras de dereita a esquerda devolven 422 UNSUPPORTED_CHARACTERS no campo afectado. metadata conserva Unicode arbitrario e non se imprime.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": "shipper.tax_id",
                      "code": "INVALID_CHECKSUM",
                      "message": "Invalid tax ID checksum."
                    },
                    {
                      "field": "vehicle.registration",
                      "code": "INVALID_REGISTRATION",
                      "message": "Invalid vehicle registration."
                    },
                    {
                      "field": "goods.weight_kg",
                      "code": "INVALID_WEIGHT",
                      "message": "Weight must be greater than zero."
                    },
                    {
                      "field": "goods.description",
                      "code": "UNSUPPORTED_CHARACTERS",
                      "message": "Printable text must use supported Latin, Greek or Cyrillic characters."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Límite acadado: 60 peticións por minuto e token para /api/v1, ou 30 peticións por minuto para a mesma IP e documento na descarga por QR.\n\nAlcanzouse un límite contra abusos ou de capacidade temporal da demostración; respecta Retry-After. A demo admite corpos de ata 32 KiB e dez documentos por sesión. A emisión de tokens admite tres por minuto e dez por hora desde unha mesma IP; a creación, cinco por minuto e vinte por hora desde unha mesma IP. Os límites compartidos por rede, rexión e carga global poden aplicarse antes. Estas cifras corresponden á configuración predeterminada.",
        "headers": {
          "Retry-After": {
            "description": "Segundos que deben transcorrer antes do seguinte intento.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "examples": [
                60
              ]
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "RATE_LIMIT_EXCEEDED",
                      "message": "Too many requests."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Erro interno sen detalles sensibles. Unha emisión fallida non deixa un documento parcial.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "INTERNAL_ERROR",
                      "message": "An internal error occurred."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "RequestTooLarge": {
        "description": "O corpo supera o límite de 128 KiB.\n\nA demo admite corpos de ata 32 KiB e dez documentos por sesión. A emisión de tokens admite tres por minuto e dez por hora desde unha mesma IP; a creación, cinco por minuto e vinte por hora desde unha mesma IP. Os límites compartidos por rede, rexión e carga global poden aplicarse antes. Estas cifras corresponden á configuración predeterminada.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "REQUEST_TOO_LARGE",
                      "message": "Request body exceeds the 128 KiB limit."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Servizo non dispoñible por unha configuración incorrecta da URL pública HTTPS. Unha emisión fallida non persiste un documento parcial.\n\nA demostración está desactivada ou non está dispoñible. DEMO_UNAVAILABLE.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "SERVICE_UNAVAILABLE",
                      "message": "The document service requires a configured HTTPS public URL."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "DemoUnavailable": {
        "description": "A demostración está desactivada ou non está dispoñible.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "default": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "DEMO_UNAVAILABLE",
                      "message": "The demo is temporarily unavailable."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "DemoRateLimited": {
        "description": "Alcanzouse un límite contra abusos ou de capacidade temporal da demostración; respecta Retry-After.",
        "headers": {
          "Retry-After": {
            "description": "Segundos que deben transcorrer antes do seguinte intento.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "examples": [
                60
              ]
            }
          },
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "rateLimit": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "RATE_LIMIT_EXCEEDED",
                      "message": "Too many demo requests. Try again later."
                    }
                  ]
                }
              },
              "capacity": {
                "value": {
                  "errors": [
                    {
                      "field": null,
                      "code": "DEMO_CAPACITY_REACHED",
                      "message": "The demo has reached its temporary capacity. Try again later."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
}
