Technical descriptions are translated from the versioned contract. Original identifiers and JSON are preserved; data examples are omitted.
Registers a Transport Operation with ANTT from the trip, without depending on a CT-e issued by FleetPay.
It is the companion to POST /fiscal/cte/{cte_uuid}/ciot/emissao: the party contracting freight and declaring the CIOT is not always the party issuing its tax document. On this route, the entire trip is supplied in the body — contracted carrier, route, cargo, vehicle, driver, documents and amounts — and the CIOT is the only output.
Both routes coexist. If you issue the CT-e through FleetPay and want its CIOT linked to it, continue using the anchored route: nothing has changed there.
The response code tells you the outcome
Treating a 202 as success sends a truck onto the road with a CIOT that may not exist. After a 202, query the operation by id until its status changes from sent.
The operation exists even when the declaration fails
The record is created before contacting the provider. A 422 returns the operation's id in error.details.ciot.id; it remains readable through GET /fiscal/ciot/{id}, with the reason recorded. Save this ID: it is how a rejection is investigated.
Idempotency
referencia_externa is optional and unique per company. With it, a network retry receives 400 validacao rather than generating another CIOT for the same freight operation — which would be a regulatory problem, not merely an inconvenience. Without it, you bear that risk.
Scope of this version
Full or partial loads, declared on your own behalf (contratado.documento must be the authenticated company's CNPJ), with one to ten vehicles and one to one hundred tax documents containing sender and recipient.
For partial loads, provide carga.contratantes. rota.trechos can detail up to one hundred pickup/delivery pairs; rota.origem and rota.destino still represent the trip's endpoints. TAC agregado, freight installments and toll vouchers with toll plazas are not yet accepted by this route.
Simulated sandbox mode
This operation has no contracted CIOT provider behind it: in the sandbox environment, FleetPay generates a deterministic response with no regulatory effect — nothing is registered with ANTT, and no CIOT handled here has legal validity.
Test sentinels
In simulated mode, these referencia_externa values force an outcome — use them to exercise paths beyond the happy path:
The external reference acts as the sentinel because it is the only body field that belongs to you, is optional and is not sent to ANTT — requesting an outcome through it does not contaminate any operation data.
Availability depends on the environment, enabled scopes and provider. This reference does not execute requests or collect credentials.
Complete Operation Definition
{
"tags": [
"CIOT"
],
"summary": "Declarar CIOT sem CT-e",
"operationId": "declararCiot",
"description": "Registra uma Operação de Transporte na ANTT a partir da **viagem**, sem depender de um\nCT-e emitido pela FleetPay.\n\nÉ o irmão de `POST /fiscal/cte/{cte_uuid}/ciot/emissao`, e existe porque quem contrata\nfrete e precisa declarar o CIOT nem sempre é quem emite o documento fiscal dele. Nesta\nrota a viagem inteira chega no corpo — contratado, rota, carga, veículo, motorista,\ndocumentos e valores — e o CIOT é a única coisa que se produz.\n\n**As duas rotas convivem.** Se você emite o CT-e pela FleetPay e quer o CIOT amarrado a\nele, continue na rota ancorada: nada mudou lá.\n\n## O código de resposta conta o desfecho\n\n| Código | Significa | Pode seguir viagem? |\n|---|---|---|\n| `201` | A ANTT devolveu o CIOT: número e código verificador na resposta. | **Sim** |\n| `202` | A declaração foi entregue e o veredito vem depois. | **Não** — consulte antes |\n| `422` | A declaração não saiu daqui, ou foi recusada. | Não |\n\nTratar um `202` como sucesso põe caminhão na estrada com um CIOT que talvez não exista.\nEm `202`, releia a operação pelo `id` até o status sair de `sent`.\n\n## A operação existe mesmo quando a declaração falha\n\nA linha é criada **antes** da chamada ao provedor. Um `422` devolve o `id` da operação\nem `error.details.ciot.id`, e ela continua legível por `GET /fiscal/ciot/{id}` com o\nmotivo gravado. Guarde esse id: é por ele que se investiga uma recusa.\n\n## Idempotência\n\n`referencia_externa` é opcional e **única por empresa**. Com ela, um retry de rede\nesbarra em `400 validacao` em vez de gerar um segundo CIOT para o mesmo frete — o que\nseria problema regulatório, não inconveniência. Sem ela, o risco é seu.\n\n## Escopo desta versão\n\nCarga **lotação ou fracionada**, declarada **em nome próprio** (o\n`contratado.documento` tem de ser o CNPJ da empresa autenticada), de um a dez veículos\ne de um a cem documentos fiscais com remetente e destinatário.\n\nNo fracionado, informe `carga.contratantes`. `rota.trechos` pode detalhar até cem\npares de coleta e entrega; `rota.origem` e `rota.destino` continuam representando os\nextremos da viagem. TAC agregado, parcelas do frete e Vale-Pedágio com praças ainda\nnão são aceitos por esta rota.\n\n## Modo simulado em homologação\n\nEsta operação **não tem provedor de CIOT contratado** por trás: em homologação a\nresposta é gerada pela FleetPay, é determinística e **não tem efeito regulatório** —\nnada é registrado na ANTT e nenhum CIOT tratado aqui tem valor legal.\n\n### Sentinelas de teste\n\nEm modo simulado, estes valores de `referencia_externa` forçam um desfecho — use-os\npara exercitar os caminhos que não são o feliz:\n\n| `referencia_externa` | Resposta |\n|---|---|\n| `CIOT-PENDENTE` | `202` — declaração entregue, sem veredito |\n| `CIOT-RECUSAR` | `422 declaracao_recusada` — o provedor recusou |\n| qualquer outro valor | `201` — CIOT registrado |\n\nA referência externa serve de sentinela porque é o único campo do corpo que é seu, é\nopcional e **não vai para a ANTT** — pedir um desfecho por ela não contamina nenhum\ndado da operação.\n",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeclaracaoCiot"
}
}
}
},
"responses": {
"201": {
"description": "CIOT registrado na ANTT.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RespostaCiot"
}
}
}
},
"202": {
"description": "Declaração entregue e ainda sem desfecho. **Não siga viagem**: releia a operação\npelo `id` até o status sair de `sent`.\n",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RespostaCiot"
}
}
}
},
"400": {
"description": "`validacao` — falta campo obrigatório da viagem, ou a `referencia_externa` já foi\nusada por outra operação desta empresa.\n",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Erro"
}
}
}
},
"401": {
"$ref": "#/components/responses/Erro401"
},
"403": {
"$ref": "#/components/responses/Erro403"
},
"422": {
"description": "`declaracao_bloqueada` — a declaração não chegou a ser transmitida (o contratado\nnão é a empresa autenticada, o perfil dele não é coberto, ou não há provedor).\n`declaracao_recusada` — o provedor respondeu recusando.\n\nNos dois casos `error.details.ciot.id` traz o endereço da operação, que permanece\nlegível por `GET /fiscal/ciot/{id}`.\n",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Erro"
}
}
}
}
},
"method": "POST",
"path": "/fiscal/ciot",
"parameters": []
}