API: CIOT Agregado

Contratos de 30 dias com extrato de viagens (créditos) e despesas (débitos).

Visão geral

O CIOT Agregado é um modelo alternativo ao CIOT por viagem: em vez de uma operação para cada frete, abre-se um único contrato de até 30 dias para uma composição veicular específica (cavalo + reboques), e cada viagem executada gera um crédito no extrato. Despesas (adiantamento, peças, combustível etc.) entram como débitos. O saldo é sempre total_creditos − total_debitos.

Quando usar Agregado em vez de Por viagem

  • Composição veicular roda repetidamente para a mesma empresa contratante.
  • Operação contínua em base mensal — evita emitir 1 CIOT por frete.
  • Modalidades suportadas hoje: Frota própria operando agregados e ETC contratado / ETC equiparado a TAC. ANTT é o órgão regulador.

Autenticação e ambiente

Use os headers X-FreteFlow-Key (prefix.secret) e X-FreteFlow-Signature (HMAC-SHA256 do body cru). Veja Autenticação.

O ambiente (homolog/producao) é uma propriedade imutável do agregado, herdada da configuração da empresa na abertura. Todos os eventos pós-emissão (registro de viagem, débito, cancelamento, encerramento) usam o ambiente do próprio agregado.

Escopos necessários

read para GET; write para POST.

Ciclo de vida

aberto ──► em_encerramento ──► encerrado
   │
   └──► cancelado            (manualmente, sem encerramento)

Triggers de encerramento:
  • Manual via POST /operations/{id}/encerrar
  • Automático após 30 dias (cron diário)

Endpoints

POST/api/public/v1/ciot-agregado/operationsAuth: API key

Abre um novo contrato de CIOT Agregado para a composição informada.

bash
curl -X POST 'https://freteflow.log.br/api/public/v1/ciot-agregado/operations' \
  -H 'X-FreteFlow-Key: prefix.secret' \
  -H 'X-FreteFlow-Signature: <hmac-sha256>' \
  -H 'Content-Type: application/json' \
  -d '{
    "partner_id": "<uuid do transportador>",
    "placa_cavalo": "ABC1D23",
    "placas_reboques": ["XYZ4E56"],
    "valor_contratado": 12000.00,
    "origem_uf": "SP",
    "origem_municipio_nome": "São Paulo",
    "destino_uf": "RJ",
    "destino_municipio_nome": "Rio de Janeiro",
    "pagamento": { "tipo_pagamento": "pix", "chave_pix": "...", "cpf_cnpj_owner": "..." }
  }'

Reuso de agregado vigente

Se já existir um agregado aberto para a mesma composição (transportador + placas), a chamada retorna o existente com reason: "existing_agregado" em vez de criar duplicidade.
GET/api/public/v1/ciot-agregado/operationsAuth: API key

Lista os agregados da empresa (limite 200). Aceita filtros via query string:

status=aberto|em_encerramento|encerrado|cancelado
partner_id=<uuid>
q=<código, codigo_ciot ou placa>
GET/api/public/v1/ciot-agregado/operations/{id}Auth: API key

Retorna o agregado completo, o extrato de viagens, o extrato de débitos e o saldo consolidado.

json
{
  "agregado": { "id": "...", "code": "AGR-0001", "status": "aberto", "codigo_ciot": "...", "data_prevista_encerramento": "..." },
  "viagens":  [ { "numero_viagem": 1, "valor": 2500.00, "status": "ativa", "origem_municipio_nome": "...", "destino_municipio_nome": "..." } ],
  "debitos":  [ { "numero_debito": 1, "valor": 800.00, "tipo": "adiantamento", "status": "ativo" } ],
  "saldo":    { "total_creditos": 2500.00, "total_debitos": 800.00, "saldo": 1700.00 }
}
POST/api/public/v1/ciot-agregado/operations/{id}/viagensAuth: API key

Registra uma viagem executada (crédito). Não chama o órgão regulador — apenas alimenta o extrato do agregado. Retorna numero_viagem sequencial dentro do agregado.

bash
curl -X POST '.../operations/<id>/viagens' \
  -H 'X-FreteFlow-Key: ...' -H 'X-FreteFlow-Signature: ...' \
  -H 'Content-Type: application/json' \
  -d '{
    "data_viagem": "2026-05-28T08:00:00Z",
    "expedidor_cpf_cnpj": "12345678000190", "expedidor_nome": "Embarcador",
    "recebedor_cpf_cnpj": "98765432000110", "recebedor_nome": "Destinatário",
    "origem_uf": "SP", "origem_municipio_nome": "São Paulo",
    "destino_uf": "RJ", "destino_municipio_nome": "Rio de Janeiro",
    "valor": 2500.00
  }'
POST/api/public/v1/ciot-agregado/operations/{id}/debitosAuth: API key

Registra uma despesa (débito) deduzida do saldo. Use para adiantamentos, peças, combustível, etc. Requer motivo.

json
{
  "tipo": "adiantamento",
  "valor": 800.00,
  "motivo": "Adiantamento de viagem 2"
}
POST/api/public/v1/ciot-agregado/operations/{id}/viagens/{viagemId}/cancelAuth: API key
POST/api/public/v1/ciot-agregado/operations/{id}/debitos/{debitoId}/cancelAuth: API key

Cancelam, respectivamente, uma viagem ou um débito específicos. Ambos exigem motivo e são auditados. O cancelamento estorna o crédito/débito do saldo.

POST/api/public/v1/ciot-agregado/operations/{id}/cancelAuth: API key

Cancela o contrato inteiro. Só é permitido quando todas as viagens e débitos vinculados já foram previamente cancelados.

POST/api/public/v1/ciot-agregado/operations/{id}/encerrarAuth: API key

Encerra o agregado, consolida automaticamente as rotas a partir das viagens ativas (agrupando por par origem→destino) e comunica o encerramento ao órgão regulador. Aceita peso_carga_final e motivo.

Encerramento automático em 30 dias

Um job diário encerra automaticamente todo agregado aberto com data_prevista_encerramento ≤ now(), com motivo expiracao_automatica_30_dias. Você não precisa chamar este endpoint para cumprir o prazo.
GET/api/public/v1/ciot-agregado/operations/{id}/pdfAuth: API key

Retorna o PDF do contrato com capa, identificação, extrato de viagens, extrato de débitos e — quando encerrado — as rotas consolidadas. Disponível quando o status é emitido, encerrado ou cancelado. Em ambiente homolog o PDF traz marca d'água "HOMOLOGAÇÃO".

Erros comuns

409 existing_agregado     Já existe agregado aberto para essa composição.
422 invalid_modalidade     Transportador não está configurado como "agregado".
422 status_invalido        Operação requer status diferente do atual.
422 saldo_pendente         Cancelamento do agregado bloqueado por movimentos ativos.
422 not_supported          Recurso indisponível para esse agregado.

Webhooks

Eventos dedicados de CIOT Agregado serão publicados em fase futura. Hoje, monitore via polling no GET /operations/{id}.

Próximos passos

  • Configure o transportador como Agregado em Parceiros → CIOT — modalidade.
  • Abra o primeiro contrato via painel em /ciot/agregados/novo ou via API.
  • Veja o ciclo de vida e dicas operacionais em Emitir CIOT (passo a passo).