{
  "openapi": "3.1.1",
  "info": {
    "title": "API DeCA",
    "version": "1.0.0",
    "description": "API para emitir, retificar, consultar e descarregar documentos espanhóis de controlo administrativo do transporte de mercadorias. Para obter um token, contacte o suporte da SERTEC PESAGE. Os tokens sk_test_ utilizam desenvolvimento e os sk_live_ produção, com dados separados. A restrição por IP é opcional.\n\nCada credencial permite consultar e descarregar os seus documentos durante as 24 horas seguintes à criação. A descarga por QR tem uma validade independente. As retificações conservam o documento original.\n\nA eliminação lógica só é permitida nas primeiras 2 horas para corrigir erros de geração. A integração deve confirmar que o documento não foi entregue ao transportador nem utilizado no transporte. O ficheiro e a rastreabilidade são conservados, mas o acesso é bloqueado.\n\nPodes pedir um token `sk_demo_` sem uma conta nem o registo de uma organização. Dura **24 horas a partir da emissão** e funciona apenas a partir do **IP público que o pediu**. Mudar de rede ou de IP exige outro token. Utiliza apenas **dados fictícios**. Todas as páginas do PDF apresentam **SEM VALIDADE** junto do logótipo e uma marca diagonal **DEMO**. Estes documentos não são válidos para transportar mercadorias nem para uso administrativo. A demo acrescenta demo: true, expires_at, qr_url (alias de url) e pdf_url (alias de pdf_download_url). document_locale é o idioma escolhido ao solicitar o token (es por predefinição). Os dados e PDF temporários estão separados do arquivo real e não são encriptados como os documentos reais. A demo aceita corpos até 32 KiB e dez documentos por sessão. A emissão de tokens permite três por minuto e dez por hora a partir do mesmo IP; a criação de documentos permite cinco por minuto e vinte por hora a partir do mesmo IP. Os limites partilhados por rede, região e carga global podem aplicar-se mais cedo. Estes valores correspondem à configuração predefinida."
  },
  "servers": [
    {
      "url": "https://deca.sertecpesage.com",
      "description": "Produção"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Documentos",
      "description": "Emissão, retificação e acesso aos documentos próprios recentes."
    },
    {
      "name": "Descarga por QR",
      "description": "Descarga direta do PDF através do segredo de um documento."
    },
    {
      "name": "Demonstração da API",
      "description": "Obtém um token público temporário e gera documentos de demonstração com dados fictícios."
    }
  ],
  "paths": {
    "/api/v1/documents": {
      "post": {
        "operationId": "createDocument",
        "tags": [
          "Documentos"
        ],
        "summary": "Criar documento",
        "description": "Envie todos os dados do transporte. A resposta é entregue depois de gerar e armazenar o PDF cifrado.\n\nUma referência não nula é única por organização e ambiente. Repetir a referência com os mesmos dados normalizados e metadata devolve o resultado original no prazo de 24 horas (200), sem emitir outro PDF. Uma nova criação devolve 201. Dados diferentes ou uma referência de outra credencial produzem 409 sem divulgar documentos. Sem referência não se garante a deduplicação.\n\nUma referência cujo resultado expirou devolve 409 DOCUMENT_WINDOW_EXPIRED. Se o documento estiver eliminado, o conteúdo não é devolvido e a referência não é reutilizada; a nova tentativa devolve 404. Para retificar, utilize os endpoints PUT.\n\nPodes pedir um token `sk_demo_` sem uma conta nem o registo de uma organização. Dura **24 horas a partir da emissão** e funciona apenas a partir do **IP público que o pediu**. Mudar de rede ou de IP exige outro token. A demo acrescenta demo: true, expires_at, qr_url (alias de url) e pdf_url (alias de pdf_download_url). document_locale é o idioma escolhido ao solicitar o token (es por predefinição). Os dados e PDF temporários estão separados do arquivo real e não são encriptados como os documentos reais.",
        "requestBody": {
          "required": true,
          "description": "Dados completos do documento a criar.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDocumentRequest"
              },
              "examples": {
                "create": {
                  "summary": "Emissão com peso e reboque",
                  "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": "Grandeza alternativa quando é 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": "Nova tentativa idempotente; devolve o resultado original sem gerar 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": "Novo documento gerado e armazenado.",
            "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": "Referência em conflito ou resultado da nova tentativa expirado.",
            "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, sem PDF, segredo QR nem metadata. O servidor aplica sempre a janela de 24 horas e o isolamento da credencial. Ordenação decrescente por data de criação e UUID para desempate, paginação por página e filtros inclusivos de data de transporte. A janela é avaliada em cada pedido; não constitui uma imagem estável entre páginas. Não permite consultar o histórico.\n\nOs documentos eliminados não aparecem na lista.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Página pedida, a partir de 1.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Documentos por página, entre 1 e 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Data mínima de transporte, inclusive. Não alarga a janela de leitura.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "examples": {
              "default": {
                "value": "2026-10-05"
              }
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Data máxima de transporte, inclusive; igual ou posterior a from.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "examples": {
              "default": {
                "value": "2026-10-05"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de documentos recentes. Uma página sem resultados tem data vazio.",
            "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": "Retificar documento",
        "x-deca-order": 20,
        "description": "Identifique o documento anterior pelo UUID e envie todos os dados corrigidos, sem alterações parciais. Só pode ser retificada a última versão da mesma credencial. É permitido retificar um documento com mais de 24 horas sem devolver o conteúdo anterior. Um documento eliminado devolve 404 e não pode ser retificado.\n\nÉ gerado um documento retificativo com novos UUID, PDF e QR; o original e o seu QR são conservados. Entregue o novo PDF ao condutor. O campo reference do corpo corresponde à nova versão, não ao documento da URL.\n\nRepetir o mesmo PUT com os mesmos dados normalizados e metadata devolve a retificação já emitida durante as 24 horas seguintes à sua criação, sem gerar outra versão. Esta verificação ocorre antes de rejeitar um documento já retificado e também funciona se a nova tentativa identificar o mesmo documento por referência. Alterar dados de um documento já retificado devolve 409. Um resultado de nova tentativa expirado devolve 409 DOCUMENT_WINDOW_EXPIRED. Se a retificação devolvida estiver eliminada, a nova tentativa devolve 404. Para outra retificação, utilize o UUID ou a referência da última versão.",
        "requestBody": {
          "required": true,
          "description": "Dados completos corrigidos do transporte.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RectifyDocumentRequest"
              },
              "examples": {
                "rectify": {
                  "summary": "Retificação completa com nova referência",
                  "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 retificativo emitido, ou resultado de uma nova tentativa idêntica sem criar outra versão.",
            "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 já retificado, nova referência em conflito ou resultado da nova tentativa expirado.",
            "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": "Eliminação lógica para corrigir erros detetados ao gerar um documento, exclusivamente **antes de o entregar ao transportador ou ao condutor e antes de o utilizar num transporte**. A integração deve confirmar ambas as condições; estar dentro do prazo não basta. Se o documento já foi entregue ou utilizado, deve ser retificado através de PUT.\n\nSó é permitida enquanto a hora do servidor for anterior a created_at + **2 horas**; às 2 horas exatas já não é permitida. Nem uma consulta nem uma nova tentativa reiniciam o prazo. Cada versão usa a sua própria data de criação. Só pode ser eliminada a última versão da credencial autenticada.\n\nO PDF, os dados e a rastreabilidade são conservados, mas o documento deixa de aparecer na lista. As consultas por UUID ou referência, a descarga autenticada, o QR e as novas tentativas que devolveriam o conteúdo respondem 404. A consulta de estado responde apenas com status: deleted durante a janela de consulta de 24 horas. A referência continua reservada. Não existe endpoint de reativação; a eliminação conserva o ficheiro para permitir uma recuperação futura.\n\nRepetir DELETE nas mesmas 2 horas devolve 204 sem alterar a data de eliminação. Após esse prazo devolve 409.\n\nO primeiro acesso correto à ligação QR também bloqueia a eliminação com 409 DOCUMENT_ALREADY_ACCESSED. Este acesso não prova, por si só, que o transporte se realizou.",
        "requestBody": {
          "required": true,
          "description": "Motivo e confirmação de que o documento ainda não foi entregue nem utilizado.",
          "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. Sem 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 expirado, documento entregue ou utilizado, ou versão já retificada. O primeiro acesso correto à ligação QR também bloqueia a eliminação com 409 DOCUMENT_ALREADY_ACCESSED. Este acesso não prova, por si só, que o transporte se realizou.",
            "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 original no prazo de 24 horas, apenas para a credencial que emitiu o documento. Inclui todos os campos aceites e normalizados e a metadata sem alteração semântica.\n\nUm UUID ou uma referência inexistente, de outra credencial ou fora da janela devolve a mesma resposta `404`, sem confirmar a existência nem o proprietário. Cada referência identifica a sua própria versão e não redireciona para uma retificação posterior.\n\nUm documento eliminado devolve 404. Para saber se está eliminado, utilize a consulta de estado.",
        "responses": {
          "200": {
            "description": "Resultado original 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 apenas o estado de um documento da credencial autenticada, durante as 24 horas seguintes à criação. Um documento eliminado responde 200 com {\"status\":\"deleted\"}; não devolve dados do transporte, PDF, ligação QR nem metadata. Um documento ativo responde com {\"status\":\"active\"}.\n\nUm UUID inexistente, de outra credencial ou fora das 24 horas devolve o mesmo 404. A eliminação não alarga esta janela.",
        "responses": {
          "200": {
            "description": "Estado do documento sem dados do conteúdo.",
            "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 ativo",
                    "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. Em alternativa, utilize `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": "Descarregar PDF",
        "description": "Devolve exatamente os bytes do PDF armazenado, sem o regenerar. Exige a credencial proprietária e uma antiguidade inferior a 24 horas. Esta limitação não altera a conservação legal nem a validade do QR.\n\nUm documento eliminado devolve 404 sem 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": "Descarregar PDF por QR",
        "description": "Ligação incluída no QR. O segredo k autoriza apenas este documento. Não requer Bearer, sessão, CAPTCHA nem página intermédia. Quem conhece a ligação pode descarregá-lo. Não registe a URL completa em logs, análise nem rastos.\n\nA descarga não expira às 24 horas nem é revogada automaticamente ao rodar ou revogar o Bearer. O QR anterior conserva o seu PDF após uma retificação; não redireciona para a nova versão.\n\nO PDF é entregue com `Content-Disposition: inline` para abrir no visualizador do navegador.\n\nUm documento eliminado devolve 404, mesmo com o segredo correto.",
        "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": [
          "Demonstração da API"
        ],
        "summary": "Pedir um token demo",
        "description": "Envia um objeto JSON vazio para este endpoint público. Não é necessário um cabeçalho Bearer. A resposta `201` contém `token` e `expires_at`; a data de expiração é expressa em UTC.\n\nPodes pedir um token `sk_demo_` sem uma conta nem o registo de uma organização. Dura **24 horas a partir da emissão** e funciona apenas a partir do **IP público que o pediu**. Mudar de rede ou de IP exige outro token.\n\nUtiliza apenas **dados fictícios**. Todas as páginas do PDF apresentam **SEM VALIDADE** junto do logótipo e uma marca diagonal **DEMO**. Estes documentos não são válidos para transportar mercadorias nem para uso administrativo.\n\nA demo aceita corpos até 32 KiB e dez documentos por sessão. A emissão de tokens permite três por minuto e dez por hora a partir do mesmo IP; a criação de documentos permite cinco por minuto e vinte por hora a partir do mesmo IP. Os limites partilhados por rede, região e carga global podem aplicar-se mais cedo. Estes valores correspondem à configuração predefinida. Envia document_locale para escolher o idioma de todos os PDF do token: es, ca, gl, ca-valencia, eu, en, pt-pt ou fr. Se for omitido, utiliza-se es. A resposta também inclui document_locale; para alterá-lo é necessário um novo token.",
        "security": [],
        "requestBody": {
          "required": true,
          "description": "Envia um objeto JSON vazio para este endpoint público. Não é necessário um cabeçalho Bearer. A resposta `201` contém `token` e `expires_at`; a data de expiração é expressa em UTC. Envia document_locale para escolher o idioma de todos os PDF do token: es, ca, gl, ca-valencia, eu, en, pt-pt ou fr. Se for omitido, utiliza-se es. A resposta também inclui document_locale; para alterá-lo é necessário um 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. Espanhol por predefinição."
                  }
                }
              },
              "examples": {
                "default": {
                  "value": {}
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Token demo emitido; válido durante 24 horas e associado ao IP do pedido.",
            "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": [
          "Demonstração da API"
        ],
        "summary": "Abrir o PDF demo por QR",
        "description": "O QR abre o PDF diretamente no navegador através de `/demo/d/{uuid}?k=...`, sem Bearer. O documento e as suas ligações expiram com a sessão demo; criar ou retificar um documento não prolonga a duração do token.\n\nUtiliza apenas **dados fictícios**. Todas as páginas do PDF apresentam **SEM VALIDADE** junto do logótipo e uma marca diagonal **DEMO**. Estes documentos não são válidos para transportar mercadorias nem para uso administrativo.",
        "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 integração fornecido pelo suporte da SERTEC PESAGE. Envie em Authorization: Bearer, exclusivamente por HTTPS. sk_test_ seleciona desenvolvimento e sk_live_ produção. Se o token tiver uma lista de IP autorizados, o pedido deve provir de um deles; uma lista vazia permite qualquer IP. Não envie o token na URL nem o exponha em aplicações cliente.\n\nPodes pedir um token `sk_demo_` sem uma conta nem o registo de uma organização. Dura **24 horas a partir da emissão** e funciona apenas a partir do **IP público que o pediu**. Mudar de rede ou de IP exige outro token. Utiliza apenas **dados fictícios**. Todas as páginas do PDF apresentam **SEM VALIDADE** junto do logótipo e uma marca diagonal **DEMO**. Estes documentos não são válidos para transportar mercadorias nem para uso administrativo."
      },
      "qrSecret": {
        "type": "apiKey",
        "in": "query",
        "name": "k",
        "description": "Segredo opaco da ligação QR; copie exatamente o valor devolvido em url."
      }
    },
    "parameters": {
      "DocumentUuid": {
        "name": "uuid",
        "in": "path",
        "required": true,
        "description": "UUID público do documento; conhecê-lo não concede acesso.",
        "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. Em alternativa, utilize `/api/v1/documents/ref/{reference}` com o 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. Em alternativa, utilize `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ém informação sensível e não deve ser armazenada em cache.",
        "schema": {
          "type": "string",
          "examples": [
            "no-store, private"
          ]
        }
      }
    },
    "schemas": {
      "CountryCode": {
        "type": "string",
        "pattern": "^[A-Z]{2}$",
        "description": "Código do país com duas letras; normalizado para maiúsculas. O formato não verifica a pertença 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, com ponto, sem vírgula nem notação científica. Até 15 algarismos inteiros e 6 decimais. A resposta elimina os zeros decimais finais.",
        "examples": [
          "1850.000"
        ]
      },
      "WeightKilograms": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/PositiveDecimal"
          },
          {
            "type": "number",
            "exclusiveMinimum": 0,
            "exclusiveMaximum": 1000000000000000,
            "multipleOf": 0.000001
          }
        ],
        "description": "Peso positivo em kg, como número JSON ou texto decimal. Até 15 algarismos inteiros e 6 decimais. A resposta normaliza para texto e conserva a precisão; o PDF apresenta até 3 decimais, com vírgula decimal e pontos para os milhares. Utilize texto decimal para evitar perda de precisão em valores elevados.",
        "examples": [
          1850.5
        ]
      },
      "Address": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "street",
          "postal_code",
          "city",
          "country"
        ],
        "properties": {
          "street": {
            "type": "string",
            "minLength": 1,
            "description": "Rua e número da morada.",
            "maxLength": 255
          },
          "postal_code": {
            "type": "string",
            "minLength": 1,
            "description": "Código postal como texto para preservar zeros iniciais.",
            "maxLength": 255
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "description": "Localidade da morada.",
            "maxLength": 255
          },
          "country": {
            "$ref": "#/components/schemas/CountryCode"
          }
        }
      },
      "Shipper": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "tax_country",
          "tax_id",
          "address"
        ],
        "description": "Carregador contratual; pode diferir do armazém de origem e do cliente da DeCA.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Nome ou denominação social.",
            "maxLength": 255
          },
          "tax_country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "tax_id": {
            "type": "string",
            "minLength": 1,
            "description": "Identificador fiscal normalizado para maiúsculas sem espaços nem hífenes; o comprimento é verificado após normalização. Em Espanha validam-se formato e caráter de controlo de DNI, NIE e NIF de entidades (CIF). Os NIF especiais K, L e M são verificados apenas pelo formato: prefixo, sete carateres alfanuméricos e letra final. Para outros países exige-se formato alfanumérico sem verificação do controlo fiscal. A validação não comprova existência nem registo fiscal.",
            "maxLength": 32
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          }
        }
      },
      "Carrier": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "tax_country",
          "tax_id"
        ],
        "description": "Transportador que efetua realmente o transporte, incluindo o subcontratado.",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Nome ou denominação social.",
            "maxLength": 255
          },
          "tax_country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "tax_id": {
            "type": "string",
            "minLength": 1,
            "description": "Identificador fiscal normalizado para maiúsculas sem espaços nem hífenes; o comprimento é verificado após normalização. Em Espanha validam-se formato e caráter de controlo de DNI, NIE e NIF de entidades (CIF). Os NIF especiais K, L e M são verificados apenas pelo formato: prefixo, sete carateres alfanuméricos e letra final. Para outros países exige-se formato alfanumérico sem verificação do controlo fiscal. A validação não comprova existência nem registo fiscal.",
            "maxLength": 32
          },
          "address": {
            "description": "Morada opcional do transportador. Se fornecida, exige todos os campos de Address; o artigo 6 não a exige como dado mínimo.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "street",
              "postal_code",
              "city",
              "country"
            ],
            "properties": {
              "street": {
                "type": "string",
                "minLength": 1,
                "description": "Rua e número da morada.",
                "maxLength": 255
              },
              "postal_code": {
                "type": "string",
                "minLength": 1,
                "description": "Código postal como texto para preservar zeros iniciais.",
                "maxLength": 255
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "description": "Localidade da morada.",
                "maxLength": 255
              },
              "country": {
                "$ref": "#/components/schemas/CountryCode"
              }
            }
          }
        }
      },
      "TransportLocation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "place",
          "city",
          "country"
        ],
        "properties": {
          "place": {
            "type": "string",
            "minLength": 1,
            "description": "Local real de carga ou descarga, identificável pelo nome da instalação ou morada. Com city e country deve permitir identificá-lo claramente; street e postal_code são opcionais. A identidade da empresa destinatária não é um dado mínimo obrigatório.",
            "maxLength": 255
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "description": "Localidade.",
            "maxLength": 255
          },
          "country": {
            "type": "string",
            "enum": [
              "ES"
            ],
            "description": "O âmbito inicial abrange transportes internos em Espanha; não substitui o CMR internacional."
          },
          "street": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Rua e número opcionais do local de carga ou descarga para precisar a localização."
          },
          "postal_code": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Código postal opcional do local de carga ou descarga, como texto para preservar zeros iniciais."
          }
        }
      },
      "AlternativeMeasure": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "value",
          "unit"
        ],
        "description": "Outra grandeza quando for difícil determinar o peso. Envie esta grandeza ou o peso, nunca ambos.",
        "properties": {
          "value": {
            "$ref": "#/components/schemas/PositiveDecimal"
          },
          "unit": {
            "type": "string",
            "minLength": 1,
            "description": "Unidade explícita da grandeza, até 255 carateres.",
            "maxLength": 255,
            "examples": [
              "palés"
            ]
          }
        }
      },
      "Goods": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "description"
        ],
        "description": "Natureza e peso da mercadoria, ou grandeza alternativa quando aplicável. Envie exatamente uma medida.",
        "properties": {
          "description": {
            "type": "string",
            "minLength": 1,
            "description": "Descrição da natureza da mercadoria.",
            "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": "Veículo efetivo; se houver reboque ou semirreboque, preencha os dois campos em conjunto.",
        "properties": {
          "country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "registration": {
            "type": "string",
            "minLength": 1,
            "description": "Matrícula normalizada para maiúsculas sem espaços nem hífenes. Em Espanha são admitidas a matrícula ordinária vigente, as provinciais anteriores e a série especial E. Para outros países, entre 3 e 20 carateres alfanuméricos.",
            "maxLength": 20,
            "examples": [
              "4827 MNL"
            ]
          },
          "trailer_country": {
            "$ref": "#/components/schemas/CountryCode"
          },
          "trailer_registration": {
            "type": "string",
            "minLength": 1,
            "description": "Matrícula do reboque ou semirreboque, normalizada como a do trator. Em Espanha exige-se a série R. Para outros países, entre 3 e 20 carateres 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": "Autorização especial de circulação quando necessária. Omita ou envie null se não se aplicar.",
        "properties": {
          "number": {
            "type": "string",
            "minLength": 1,
            "description": "Número ou referência da autorização.",
            "maxLength": 255
          },
          "issuer": {
            "type": "string",
            "minLength": 1,
            "description": "Organismo emissor, se indicado.",
            "maxLength": 255
          }
        }
      },
      "CreateDocumentRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "transport_date",
          "shipper",
          "carrier",
          "origin",
          "destination",
          "goods",
          "vehicle"
        ],
        "properties": {
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "description": "Referência própria opcional, única por organização e ambiente e impressa no PDF. Identifica novas tentativas e permite consultar por referência. Não é libertada ao eliminar o documento.",
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])",
            "maxLength": 120
          },
          "transport_date": {
            "type": "string",
            "format": "date",
            "description": "Data real do transporte em formato YYYY-MM-DD; não é o instante de criação 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": "Observações cuja inclusão no documento seja pedida pelos intervenientes.",
            "maxLength": 4000
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Objeto JSON opcional, conservado e devolvido sem alteração semântica. Não é impresso no PDF. Máximo de 16 KiB ao serializar e 8 níveis 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": "Referência do cliente ou null.",
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Instante original de criação, em UTC."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL HTTPS completa de descarga por QR, incluindo o segredo. Não registe nem publique."
          },
          "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 imagem PNG em Base64, sem prefixo data URI.",
                "contentEncoding": "base64"
              }
            }
          },
          "pdf_download_url": {
            "type": "string",
            "format": "uri",
            "description": "URL de descarga autenticada; requer Bearer da credencial proprietária no prazo de 24 horas."
          },
          "rectifies_uuid": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "UUID retificado ou null numa emissão inicial."
          },
          "normalized_data": {
            "$ref": "#/components/schemas/CreateDocumentRequest"
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "A mesma metadata do pedido; null se não foi fornecida."
          },
          "document_locale": {
            "type": "string",
            "enum": [
              "es",
              "ca",
              "gl",
              "ca-valencia",
              "eu",
              "en",
              "pt-pt",
              "fr"
            ],
            "description": "Idioma do PDF escolhido na emissão segundo a organização. Conservado no resultado; alterar o idioma da organização não modifica documentos existentes. Não altera campos JSON nem mensagens 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 detetados; sem dados do pedido, segredos nem rastos.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "field",
                "code",
                "message"
              ],
              "properties": {
                "field": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Caminho do campo separado por pontos; null para um erro geral."
                },
                "code": {
                  "type": "string",
                  "pattern": "^[A-Z][A-Z0-9_]*$",
                  "description": "Código estável para a lógica de integração."
                },
                "message": {
                  "type": "string",
                  "description": "Mensagem breve em inglês. Não a utilize 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": "Nova referência do documento retificativo, opcional e única por organização e ambiente. Não reutilize a referência 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 em formato YYYY-MM-DD; não é o instante de criação 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": "Observações cuja inclusão no documento seja pedida pelos intervenientes.",
            "maxLength": 4000
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Objeto JSON opcional, conservado e devolvido sem alteração semântica. Não é impresso no PDF. Máximo de 16 KiB ao serializar e 8 níveis de profundidade."
          }
        },
        "description": "Todos os dados corrigidos do transporte. O documento anterior é identificado na URL. Se reference for incluído, deve ser uma nova referência para o documento retificativo."
      },
      "DeleteDocumentRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "reason",
          "confirm_not_delivered",
          "confirm_not_used"
        ],
        "properties": {
          "reason": {
            "type": "string",
            "minLength": 1,
            "description": "Motivo do erro detetado ao gerar o documento.",
            "maxLength": 2000
          },
          "confirm_not_delivered": {
            "type": "boolean",
            "description": "Deve ser true para eliminar: confirma que não foi entregue ao transportador nem ao condutor. false devolve 409 DOCUMENT_ALREADY_DELIVERED."
          },
          "confirm_not_used": {
            "type": "boolean",
            "description": "Deve ser true para eliminar: confirma que não foi utilizado num 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. Não inclui informação do transporte, PDF, QR, metadata nem 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 pedir um token `sk_demo_` sem uma conta nem o registo de uma organização. Dura **24 horas a partir da emissão** e funciona apenas a partir do **IP público que o pediu**. Mudar de rede ou de IP exige outro token."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Data de expiração do token em UTC. Todos os seus documentos e ligações expiram neste instante."
          },
          "document_locale": {
            "type": "string",
            "enum": [
              "es",
              "ca",
              "gl",
              "ca-valencia",
              "eu",
              "en",
              "pt-pt",
              "fr"
            ],
            "description": "Idioma dos PDF deste token. Espanhol por predefinição."
          }
        }
      },
      "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": "Referência do cliente ou null.",
            "pattern": "^[A-Za-z0-9-]+(?![\\s\\S])"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Instante original de criação, em UTC."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL HTTPS completa de descarga por QR, incluindo o segredo. Não registe nem publique."
          },
          "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 imagem PNG em Base64, sem prefixo data URI.",
                "contentEncoding": "base64"
              }
            }
          },
          "pdf_download_url": {
            "type": "string",
            "format": "uri",
            "description": "Podes pedir um token `sk_demo_` sem uma conta nem o registo de uma organização. Dura **24 horas a partir da emissão** e funciona apenas a partir do **IP público que o pediu**. Mudar de rede ou de IP exige outro token."
          },
          "rectifies_uuid": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "UUID retificado ou null numa emissão inicial."
          },
          "normalized_data": {
            "$ref": "#/components/schemas/CreateDocumentRequest"
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "A mesma metadata do pedido; null se não foi fornecida."
          },
          "document_locale": {
            "type": "string",
            "enum": [
              "es",
              "ca",
              "gl",
              "ca-valencia",
              "eu",
              "en",
              "pt-pt",
              "fr"
            ],
            "description": "Idioma dos PDF deste token. Espanhol por predefinição."
          },
          "demo": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Apenas na demo; sempre true. Não aparece nos resultados de desenvolvimento ou produção."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Data de expiração do token em UTC. Todos os seus documentos e ligações expiram neste instante."
          },
          "qr_url": {
            "type": "string",
            "format": "uri",
            "description": "Apenas na demo; alias de url."
          },
          "pdf_url": {
            "type": "string",
            "format": "uri",
            "description": "Apenas na demo; alias de pdf_download_url. Exige o token demo e o seu IP."
          }
        },
        "description": "A demo acrescenta demo: true, expires_at, qr_url (alias de url) e pdf_url (alias de pdf_download_url). document_locale é o idioma escolhido ao solicitar o token (es por predefinição). Os dados e PDF temporários estão separados do arquivo real e não são encriptados como os documentos reais."
      }
    },
    "examples": {
      "DocumentResult": {
        "summary": "Resultado completo com dados fictícios 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 retificativo com novos UUID, PDF e QR",
        "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 original nativo, até 5 MB. Descarga direta sem regeneração.",
        "headers": {
          "Content-Disposition": {
            "description": "Nome seguro que não incorpora dados 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 propagação da URL secreta."
          },
          "X-Content-Type-Options": {
            "schema": {
              "type": "string",
              "enum": [
                "nosniff"
              ]
            },
            "description": "Impedir a interpretação do conteúdo como outro tipo."
          }
        },
        "content": {
          "application/pdf": {
            "schema": {
              "type": "string",
              "contentMediaType": "application/octet-stream"
            }
          }
        }
      },
      "PdfPreview": {
        "description": "PDF original nativo, até 5 MB. Visualização no navegador sem regeneração.",
        "headers": {
          "Content-Disposition": {
            "description": "Nome seguro que não incorpora dados 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 propagação da URL secreta."
          },
          "X-Content-Type-Options": {
            "schema": {
              "type": "string",
              "enum": [
                "nosniff"
              ]
            },
            "description": "Impedir a interpretação do conteúdo como outro tipo."
          }
        },
        "content": {
          "application/pdf": {
            "schema": {
              "type": "string",
              "contentMediaType": "application/octet-stream"
            }
          }
        }
      },
      "BadRequest": {
        "description": "JSON malformado; o pedido não é processado.",
        "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\nUm token demo expirado ou enviado de outro IP devolve `401`. Um QR demo expirado devolve `404`. Se a demo estiver desativada, devolve `503 DEMO_UNAVAILABLE`. O primeiro acesso ao QR ou uma retificação impedem a eliminação do documento; mantêm-se as confirmações de eliminação do contrato habitual.",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "examples": [
                "Bearer"
              ]
            },
            "description": "Esquema de autenticação obrigatório."
          }
        },
        "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 não autorizado ou ação não 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 indisponível para este acesso; não revela existência, proprietário nem 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": "Os pedidos POST, PUT e DELETE com corpo exigem 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 detetados. Os oito idiomas traduzem os títulos e etiquetas do PDF, não os nomes, moradas, observações nem outros dados enviados pela integração. Os textos impressos admitem carateres latinos, gregos e cirílicos compatíveis com as fontes; emoji, CJK e escritas da direita para a esquerda devolvem 422 UNSUPPORTED_CHARACTERS no campo afetado. metadata conserva Unicode arbitrário e não é impressa.",
        "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": "Limite atingido: 60 pedidos por minuto e token para /api/v1, ou 30 pedidos por minuto para o mesmo IP e documento na descarga por QR.\n\nFoi atingido um limite contra abusos ou de capacidade temporária da demonstração; respeita Retry-After. A demo aceita corpos até 32 KiB e dez documentos por sessão. A emissão de tokens permite três por minuto e dez por hora a partir do mesmo IP; a criação de documentos permite cinco por minuto e vinte por hora a partir do mesmo IP. Os limites partilhados por rede, região e carga global podem aplicar-se mais cedo. Estes valores correspondem à configuração predefinida.",
        "headers": {
          "Retry-After": {
            "description": "Segundos a aguardar antes da próxima tentativa.",
            "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 sem detalhes sensíveis. Uma emissão falhada não deixa um 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 excede o limite de 128 KiB.\n\nA demo aceita corpos até 32 KiB e dez documentos por sessão. A emissão de tokens permite três por minuto e dez por hora a partir do mesmo IP; a criação de documentos permite cinco por minuto e vinte por hora a partir do mesmo IP. Os limites partilhados por rede, região e carga global podem aplicar-se mais cedo. Estes valores correspondem à configuração predefinida.",
        "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": "Serviço indisponível devido a uma configuração incorreta da URL pública HTTPS. Uma emissão falhada não persiste um documento parcial.\n\nA demonstração está desativada ou indisponível. 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 demonstração está desativada ou indisponível.",
        "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": "Foi atingido um limite contra abusos ou de capacidade temporária da demonstração; respeita Retry-After.",
        "headers": {
          "Retry-After": {
            "description": "Segundos a aguardar antes da próxima tentativa.",
            "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."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
}
