Pular para o conteúdo
Veltra Ajuda
Manual da APIPlaybookEntrar

Referência da API

API por rota: guia explicado para o TMS

Abrir o Swagger

API por rota: guia explicado para o TMS

Esta página explica, rota por rota, a API que o sistema da transportadora (o TMS) usa para falar com o Veltra. Ela é escrita para duas pessoas: o desenvolvedor que vai fazer a integração e o operador que precisa entender o que a integração faz. Os exemplos são completos: você copia, troca SUA_CHAVE_AQUI pela sua chave e roda.

Todos os valores dos exemplos são fictícios. As chaves de acesso de documentos fiscais (44 posições) aparecem cortadas nas respostas só para caber na tela; na vida real elas vêm inteiras.

Swagger e esta página: qual usar#

O Veltra publica um Swagger (uma tela interativa gerada a partir do código). Ele e esta página se complementam:

  • Swagger = o mapa interativo. Mostra as rotas, os campos e deixa você testar uma chamada na hora. Endereços:
    • Tela: https://api.veltrasolution.com/swagger-ui.html
    • Arquivo OpenAPI (JSON) das rotas de manifestos e filiais: https://api.veltrasolution.com/v3/api-docs/integracao
  • Esta página = o guia explicado. Diz quando chamar cada rota, o que acontece ao repetir, quais erros esperar e o que fazer com cada um.

O Swagger e o arquivo /v3/api-docs/integracao são públicos (não pedem chave), porque mostram só o formato das rotas, nunca dados de ninguém. Dois cuidados:

  • O Swagger público cobre só as rotas /integracao/** (filiais e manifestos). As rotas de leitura /v1/saida/** têm um OpenAPI próprio, que exige a sua chave: GET /v1/saida/openapi/INTEGRACAO_TMS (veja a rota na seção de leitura).
  • O contrato de referência, escrito à mão, fica em contracts/openapi/veltra-integracao.yaml. Se o Swagger e o contrato divergirem em algum detalhe, vale o que o sistema faz, que é o que esta página descreve.

O que é a API#

A API do Veltra é um conjunto de endereços web (rotas) que falam JSON. O TMS usa em dois sentidos:

  1. Entrada. O TMS envia filiais e manifestos (a viagem: motorista, veículo e a lista de CT-e e NF) ao Veltra.
  2. Saída. O TMS lê o que aconteceu (baixas, ocorrências, comprovantes) e pode baixar o PDF, o pacote de evidências e o XML do evento do CT-e. Para ser avisado sem precisar perguntar, use também os webhooks.

Endereço base#

OndeEndereço base
Produção e teste (mesmo endereço)https://api.veltrasolution.com
Ambiente local de desenvolvimento do Veltrahttp://localhost:8080

A API tem um endereço único para todos os clientes (ADR 0031). O endereço do portal da sua transportadora é outro (um subdomínio com o nome do cliente), e trocar o subdomínio do portal não muda a API. Nos exemplos usamos a variável BASE:

Shell
BASE="https://api.veltrasolution.com"

Como autenticar#

A autenticação do TMS é sempre por chave de API, no cabeçalho X-Veltra-Api-Key:

curl
curl "$BASE/v1/api-keys/atual" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Regras que o sistema aplica:

  • O único cabeçalho aceito para a chave é X-Veltra-Api-Key. Não existe chave de API em Authorization: Bearer.
  • o cabeçalho Authorization com a sessão do portal serve para o portal (sessão de um usuário). Não mande os dois cabeçalhos na mesma chamada: o Veltra recusa com 401 (uma credencial por chamada).
  • Cabeçalho vazio, chave desconhecida, revogada ou expirada devolve 401. Chave de uma transportadora desativada também devolve 401.
  • Quem emite a chave é o administrador da transportadora, na tela Chaves de API do portal. O valor completo aparece uma única vez. Depois só o prefixo fica visível (por exemplo vlt_test_a1b2c3d4). Guarde em um cofre de segredos; nunca em código versionado, em log ou em e-mail.

Tipos de chave (finalidade)#

Cada chave tem uma finalidade, que define o que ela alcança. A chave que você usa para integrar o TMS é a de finalidade INTEGRACAO_TMS.

FinalidadePara quemO que alcança
INTEGRACAO_TMSO TMS da própria transportadoraTudo desta página que é rota de TMS
ENTRADA_TRANSPORTADORATransportadora parceira de um embarcador (ADR 0029)Só as 4 rotas de manifesto (POST, GET, PUT e cancelar). Manifesto de outra parceira responde 404. Todo o resto responde 403
CONSULTA_EMBARCADOR e CONSULTA_DESTINATARIOEmbarcador ou destinatário que só consultaSó leitura de eventos, documentos/{id} e openapi/{finalidade}, limitada às raízes de CNPJ cadastradas na chave. O resto responde 403

Chaves de consulta e de entrada em produção dependem de um módulo contratado. Sem ele, a resposta é 403 com o código CHAVE_SUSPENSA; a chave não é apagada e volta a funcionar quando o módulo for contratado. O custo do módulo está na página de preços e no módulo 7 da trilha, não nesta página.

Ambientes: teste e produção#

Cada chave pertence a um ambiente: TESTE ou PRODUCAO. Eles usam o mesmo endereço base; quem decide o ambiente é a chave.

Chave de...O que acontece
TesteManifestos são gravados como sandbox: nunca vão para o app de motoristas reais, nunca disparam webhook de produção, não criam motorista nem veículo no cadastro real e são apagados depois de cerca de 30 dias (junto com o registro de idempotência). Idempotência, numeroExterno e vínculo de documentos são separados por ambiente
ProduçãoManifesto real. Só é emitida para transportadora ativa (em homologação, a emissão devolve 409)

Exceções que pegam desenvolvedores de surpresa:

  • Filiais: a chave de teste só lê filiais. Criar ou alterar filial com ela devolve 403. Use a de produção.
  • Configuração de prazo: é uma só por transportadora, não separa teste de produção. Gravar com a chave de teste altera a configuração real.

Formato das chamadas e das respostas#

  • JSON em UTF-8. Envie Content-Type: application/json quando houver corpo.
  • Datas: AAAA-MM-DD para data (prazoEntrega) e ISO 8601 com fuso para data e hora (2026-10-01T09:15:00-03:00).
  • Campos desconhecidos são ignorados. Cuidado com o inverso: um campo obrigatório com o nome errado conta como ausente. Os nomes diferenciam maiúsculas de minúsculas (cnpjEmbarcador, nunca cnpj_embarcador).
  • Erros seguem o padrão RFC 9457 (application/problem+json). Veja a seção de erros.
  • Arquivos (PDF, ZIP, XML) voltam como o arquivo, não como JSON.
  • Tamanho do corpo: o servidor na frente da API aceita até 25 MB por chamada. Um manifesto aceita no máximo 1000 documentos.

Versionamento#

  • A versão da API está no caminho: /integracao/v1/... e /v1/....
  • As mudanças dentro de uma versão são só aditivas: campo novo opcional, rota nova, valor novo de uma lista. Nada que já funciona deixa de funcionar. Por isso o seu código deve ignorar campos que não conhece e tratar com cuidado valores novos de listas (por exemplo, um tipo de evento novo).
  • O arquivo de contrato em contracts/openapi/veltra-integracao.yaml traz o histórico por versão.

Idempotency-Key: repetir sem duplicar#

Rede cai, resposta se perde, o TMS não sabe se o envio funcionou. Para isso existe o cabeçalho Idempotency-Key.

  • É obrigatório em POST /integracao/v1/manifestos e em PUT /integracao/v1/manifestos/{numeroExterno}. Sem ele: 400.
  • Gere um valor por tentativa lógica de envio (recomendado: um UUID) e repita o mesmo valor se precisar reenviar a mesma coisa. Tamanho: 1 a 255 caracteres.
  • Mesma chave e mesmo corpo: o Veltra devolve a resposta original (200 no POST), sem gravar nada de novo. A ordem dos campos no JSON não importa; a ordem da lista documentos importa.
  • Mesma chave com corpo diferente: 409.
  • A chave é separada por transportadora e por ambiente e fica guardada por no mínimo 72 horas.
  • As demais rotas de escrita (cancelar, filiais, configuração de prazo) não usam Idempotency-Key: elas são seguras para repetir por natureza (veja a observação de cada rota).

Paginação#

Só as listas de leitura (/v1/saida/eventos e /v1/saida/manifestos) são paginadas, por cursor e não por número de página:

  • limite: de 1 a 200 (padrão 50).
  • alteradoDesde: o cursor. Na primeira leitura, omita. Nas seguintes, mande o proximoCursor da resposta anterior.
  • O cursor é opaco: guarde e devolva como veio; não monte nem edite.
  • O Veltra só devolve itens alterados há pelo menos 5 segundos (janela de segurança). O mesmo item pode aparecer em duas respostas seguidas: trate pelo id.

As listas de filiais não são paginadas: voltam inteiras.

Limites de taxa (rate limit)#

  • Cada chave pode ter um limite de chamadas por minuto. Passou do limite: 429 com o cabeçalho Retry-After (em segundos). Espere esse tempo e tente de novo.
  • As chaves de consulta nascem com um limite por minuto definido na emissão (de 1 a 600). A chave do TMS emitida pelo portal não vem com limite configurado. Mesmo assim, programe o seu código para respeitar 429 e Retry-After, e não faça laço sem pausa.
  • Para saber de novidades sem consultar toda hora, prefira os webhooks; para ler, use o cursor com uma pausa entre as rodadas (por exemplo, de 10 a 30 segundos).

Códigos de status comuns#

StatusQuandoO que fazer
200Deu certo (leitura, alteração, cancelamento, ou reenvio idempotente)Seguir
201Criado (manifesto novo, filial nova, chave nova)Guardar o id devolvido
204Deu certo, sem corpo (revogar chave)Seguir
400Corpo ou parâmetro inválidoLer o campo detail, corrigir e reenviar
401Chave ausente, errada, revogada, expirada, ou Authorization junto com a chaveConferir a chave e o cabeçalho
403A chave não pode usar esta rota, chave de teste tentando gravar filial, ou CHAVE_SUSPENSAConferir o tipo de chave e o ambiente
404Não existe neste ambiente (ou é de outra transportadora ou fora do escopo da chave)Conferir o id, o numeroExterno e o ambiente da chave
409Conflito: Idempotency-Key com outro corpo, numeroExterno ou sigla repetidos, TESTE_ENCERRADOVeja a rota
429Limite de chamadas por minutoEsperar o Retry-After
5xxFalha do VeltraTentar de novo com pausa crescente (e a mesma Idempotency-Key)

O Veltra nunca usa 401 nem 402 por causa de cobrança.

Como é um erro#

Erros de manifestos e filiais vêm em application/problem+json:

JSON
{
  "type": "https://veltra.com.br/problemas/validacao",
  "title": "Requisição inválida",
  "status": 400,
  "detail": "motorista.cpf inválido"
}
  • status: o código HTTP.
  • detail: a explicação em português. Use para mostrar ao operador e para log. Não use o texto de detail para decidir o que o seu código faz: use o status e, quando existir, o campo codigo.
  • codigo: aparece nos erros que têm código estável (TESTE_ENCERRADO, CHAVE_SUSPENSA).
  • erros: lista de documentos recusados (manifestos).

Um aviso de franqueza: as rotas de leitura /v1/saida/** sempre respondem com o código HTTP certo, mas o formato do corpo de erro nelas pode ser o padrão do servidor em vez do problem+json. Por isso, decida sempre pelo código HTTP.

Preciso de... use a rota#

Preciso de...Use
Conferir se a minha chave funciona e qual ambiente ela éGET /v1/api-keys/atual
Cadastrar as filiais do TMS no VeltraPOST /integracao/v1/filiais
Listar as filiais cadastradasGET /integracao/v1/filiais
Ver uma filialGET /integracao/v1/filiais/{id}
Corrigir nome, endereço ou raio de uma filialPUT /integracao/v1/filiais/{id}
Enviar um manifesto novo (entrega, coleta, rota ou transferência)POST /integracao/v1/manifestos
Saber a situação de um manifesto e de cada documentoGET /integracao/v1/manifestos/{numeroExterno}
Trocar motorista, veículo ou documentos de um manifesto já enviadoPUT /integracao/v1/manifestos/{numeroExterno}
Cancelar o que falta de um manifestoPOST /integracao/v1/manifestos/{numeroExterno}/cancelar
Saber o que aconteceu desde a última vez (baixas, ocorrências, comprovantes)GET /v1/saida/eventos
Listar os manifestos que o Veltra temGET /v1/saida/manifestos
Ver um manifesto pelo id do VeltraGET /v1/saida/manifestos/{id}
Ver a situação de um documento pelo id do VeltraGET /v1/saida/documentos/{id}
Baixar o PDF do comprovanteGET /v1/saida/comprovantes/{id}/pdf
Baixar o pacote ZIP de evidênciasGET /v1/saida/comprovantes/{id}/pacote
Baixar o XML do evento do CT-e (110180)GET /v1/saida/eventos-cte/{id}/xml
Gerar um cliente de código só com as rotas de leituraGET /v1/saida/openapi/{finalidade}
Ler a regra de prazo de entregaGET /v1/saida/configuracao-prazo
Mandar para o Veltra as cidades, prazos e feriadosPUT /v1/saida/configuracao-prazo
Emitir, listar ou revogar chaves de APITela Chaves de API do portal (rotas /v1/api-keys, de administrador)
Ser avisado de cada novidade sem consultar toda horaWebhooks (veja a referência de webhooks)

Rotas que o TMS não usa#

Para você não se perder no Swagger e nos contratos: estas áreas existem, mas não são do TMS.

ÁreaQuem usaObservação
/superadmin/**Equipe do VeltraHomologação de transportadoras, cobrança e alertas da plataforma
/v1/webhooks/asaasO serviço de cobrançaNão é chamado pelo TMS
/v1/integracoes/webhooks/**Administrador no portalCadastro e reenvio de webhooks (veja os webhooks)
Demais rotas /v1/**Portal web e app do motoristaUsam o login de usuário, não a chave de API

A página de leitura e a de entrada são tabelas geradas direto do contrato. Esta página é a versão explicada delas.


Verificação da chave

GET /v1/api-keys/atual#

Para que serve: responde "quem sou eu": mostra a transportadora e o ambiente da chave que você está usando.

Quando chamar: na primeira conexão, para confirmar que a chave é a certa e que o ambiente é o esperado (teste ou produção); e em qualquer monitoramento simples do seu lado.

Cabeçalhos

CabeçalhoObrigatórioValor
X-Veltra-Api-KeysimA chave do TMS (INTEGRACAO_TMS)

Parâmetros: nenhum.

Exemplo

curl
curl "$BASE/v1/api-keys/atual" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200

JSON
{
  "transportadoraId": "0192f3a4-5b6c-7d8e-9f01-000000000100",
  "apiKeyId": "0192f3a4-5b6c-7d8e-9f01-000000000101",
  "apiKeyPrefixo": "vlt_test_a1b2c3d4",
  "ambiente": "TESTE"
}
CampoTipoDescrição
transportadoraIdtexto (uuid)A transportadora dona da chave
apiKeyIdtexto (uuid)O id da chave
apiKeyPrefixotextoO prefixo, a parte que aparece na tela de chaves do portal
ambienteTESTE ou PRODUCAOO ambiente da chave

Erros

StatusQuandoO que fazer
401Chave ausente, errada, revogada ou expirada; ou Authorization juntoConferir a chave e remover o Authorization
403A chave não é do tipo TMS (por exemplo, chave de consulta)Usar a chave de finalidade INTEGRACAO_TMS
429Limite de chamadas por minutoEsperar o Retry-After

Observações: a rota só aceita chave de API. Um usuário do portal (com Authorization) não a usa.


Chaves de API (administração)

As três rotas abaixo são de administrador da transportadora, no portal, com o login de usuário (Authorization: Bearer). O TMS não as chama com a chave de API; quem emite, lista e revoga é uma pessoa, na tela Chaves de API. Elas estão aqui para o desenvolvedor entender o ciclo de vida da chave. Nos exemplos, TOKEN_DO_PORTAL é a sessão do administrador.

POST /v1/api-keys#

Para que serve: emite uma chave de API nova para a transportadora do administrador logado.

Quando chamar: ao começar a integração (uma chave de teste), ao ir para produção (uma chave de produção) e ao trocar uma chave que vazou.

Cabeçalhos: o cabeçalho Authorization com a sessão do portal (perfil de administrador) e Content-Type: application/json.

Corpo da requisição

CampoTipoObrigatórioDescrição
nometexto (até 120)simNome para você reconhecer a chave, por exemplo "TMS produção"
ambienteTESTE ou PRODUCAOsimO ambiente da chave. PRODUCAO só para transportadora ativa
curl
curl -X POST "$BASE/v1/api-keys" \
  -H "Authorization: Bearer $TOKEN_DO_PORTAL" \
  -H "Content-Type: application/json" \
  -d '{ "nome": "TMS teste", "ambiente": "TESTE" }'

Resposta de sucesso: 201

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000101",
  "nome": "TMS teste",
  "ambiente": "TESTE",
  "apiKeyValorEmClaro": "SUA_CHAVE_AQUI",
  "apiKeyPrefixo": "vlt_test_a1b2c3d4",
  "criadaEm": "2026-11-05T12:00:00Z"
}

apiKeyValorEmClaro é o valor completo da chave e aparece só nesta resposta. Depois dela, só o hash fica guardado e ninguém consegue recuperar o valor.

Erros

StatusQuandoO que fazer
400Falta nome ou ambiente, ou nome acima de 120 caracteresCorrigir o corpo
401Sessão do portal ausente ou vencidaEntrar de novo
403O usuário não é administradorPedir a um administrador
409Chave de PRODUCAO para transportadora que ainda não está ativa (em homologação ou inativa)Pedir ao Veltra para concluir a homologação

Observações: emitir várias chaves é permitido. Revogue as que não usa mais.

GET /v1/api-keys#

Para que serve: lista as chaves da transportadora, inclusive as revogadas. Nunca mostra o valor, só o prefixo.

Quando chamar: para auditar quais chaves existem e quais já foram revogadas.

Cabeçalhos: o cabeçalho Authorization com a sessão do portal (administrador).

Parâmetros: nenhum.

curl
curl "$BASE/v1/api-keys" \
  -H "Authorization: Bearer $TOKEN_DO_PORTAL"

Resposta de sucesso: 200

JSON
[
  {
    "id": "0192f3a4-5b6c-7d8e-9f01-000000000101",
    "nome": "TMS teste",
    "ambiente": "TESTE",
    "apiKeyPrefixo": "vlt_test_a1b2c3d4",
    "criadaEm": "2026-11-05T12:00:00Z"
  }
]

Em cada item, revogadaEm (data e hora) só aparece quando a chave já foi revogada. As chaves que o administrador de um embarcador emitiu para as transportadoras parceiras dele não entram nesta lista.

Erros: 401 (sem sessão) e 403 (não é administrador).

DELETE /v1/api-keys/{id}#

Para que serve: revoga uma chave. A partir desse instante, qualquer chamada com ela recebe 401.

Quando chamar: quando a chave vazou, quando alguém que a conhecia saiu da equipe, ou quando a integração antiga foi desligada.

Cabeçalhos: o cabeçalho Authorization com a sessão do portal (administrador).

Parâmetros de caminho

NomeTipoObrigatórioDescrição
idtexto (uuid)simO id da chave (o campo id da lista, não o prefixo)
curl
curl -X DELETE "$BASE/v1/api-keys/0192f3a4-5b6c-7d8e-9f01-000000000101" \
  -H "Authorization: Bearer $TOKEN_DO_PORTAL"

Resposta de sucesso: 204 (sem corpo).

Erros

StatusQuandoO que fazer
401Sessão ausente ou vencidaEntrar de novo
403Não é administradorPedir a um administrador
404O id não existe nesta transportadoraConferir o id na lista

Observações: revogar é definitivo e seguro de repetir (revogar de novo uma chave já revogada responde 204). Para trocar de chave sem parar a integração, emita a nova, troque no TMS, confirme que funciona e só então revogue a antiga.


Filiais

A filial é o ponto da transportadora (matriz, base, terminal). O manifesto de transferência cita as filiais pela sigla externa (siglaExterna), por isso elas precisam existir antes. As quatro rotas abaixo usam a mesma regra do cadastro de filiais do portal.

GET /integracao/v1/filiais#

Para que serve: lista todas as filiais da transportadora.

Quando chamar: para conferir o que já está cadastrado antes de enviar manifestos de transferência, ou para sincronizar o cadastro do TMS.

Cabeçalhos: X-Veltra-Api-Key (chave de teste ou de produção).

Parâmetros: nenhum. A lista vem completa, ordenada por nome.

curl
curl "$BASE/integracao/v1/filiais" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200

JSON
[
  {
    "id": "0192f3a4-5b6c-7d8e-9f01-000000000201",
    "nome": "Filial Campinas",
    "siglaExterna": "CPS",
    "endereco": "Rodovia Exemplo km 10, Campinas - SP",
    "latitude": null,
    "longitude": null,
    "raioGeofenceM": 200,
    "ativa": true
  }
]
CampoTipoDescrição
idtexto (uuid)O id da filial no Veltra
nometextoNome da filial
siglaExternatextoA sigla que o seu TMS usa, sempre em maiúsculas
enderecotexto ou nuloEndereço em uma linha
latitude, longitudenúmero ou nuloO pino da filial no mapa. Nulo quando a filial foi criada pela API sem coordenadas
raioGeofenceMinteiroRaio, em metros, ao redor do pino para considerar que o motorista "chegou"
ativaverdadeiro ou falsoSe a filial está em uso

Erros: 401, 403 (chave que não é de TMS), 429.

Observações: a chave de teste lê as filiais reais (só não grava).

POST /integracao/v1/filiais#

Para que serve: cadastra uma filial.

Quando chamar: uma vez por filial, antes do primeiro manifesto de transferência. Para poucas filiais, é mais simples cadastrar no portal.

Cabeçalhos: X-Veltra-Api-Key (chave de produção) e Content-Type: application/json.

Corpo da requisição

CampoTipoObrigatórioDescrição
nometexto (até 200)simNome da filial
siglaExternatexto (até 60)simIdentificador da filial no seu TMS. Único por transportadora. É guardado em maiúsculas, sem espaços nas pontas
enderecotexto (até 500)nãoEndereço em uma linha
latitude, longitudenúmeronãoPino no mapa. Mande os dois juntos
raioGeofenceMinteiro, de 10 a 50000nãoRaio em metros. Padrão: 200
ativaverdadeiro ou falsonãoPadrão: a filial nasce ativa
curl
curl -X POST "$BASE/integracao/v1/filiais" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "nome": "Filial Campinas",
    "siglaExterna": "CPS",
    "endereco": "Rodovia Exemplo km 10, Campinas - SP",
    "latitude": -22.9099,
    "longitude": -47.0626,
    "raioGeofenceM": 300
  }'

Resposta de sucesso: 201, com a filial criada (mesmos campos da lista).

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000201",
  "nome": "Filial Campinas",
  "siglaExterna": "CPS",
  "endereco": "Rodovia Exemplo km 10, Campinas - SP",
  "latitude": -22.9099,
  "longitude": -47.0626,
  "raioGeofenceM": 300,
  "ativa": true
}

Erros

StatusQuandoO que fazer
400nome ou siglaExterna em branco ou longos demais, ou raio fora de 10 a 50000Corrigir o campo indicado em detail
401Chave inválidaConferir a chave
403Chave de teste (ela só lê cadastros) ou chave que não é de TMSUsar a chave de produção
409Já existe filial com essa siglaExterna (detail: "já existe filial com a sigla externa CPS")Usar o PUT para alterar

Observações

  • Sem Idempotency-Key. Repetir o POST com a mesma sigla devolve 409, o que protege contra duplicata.
  • A API não localiza o endereço no mapa. Sem latitude e longitude, a filial fica sem pino até alguém ajustar no portal. Se você já tem as coordenadas, mande.

GET /integracao/v1/filiais/{id}#

Para que serve: mostra uma filial pelo id do Veltra.

Quando chamar: quando você guardou o id devolvido no cadastro e quer reler os dados.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
idtexto (uuid)simO id da filial (o campo id da lista, não a sigla)
curl
curl "$BASE/integracao/v1/filiais/0192f3a4-5b6c-7d8e-9f01-000000000201" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200, com a filial (mesmos campos da lista).

Erros: 401, 403, 404 (a filial não existe: detail "filial não encontrada"), 429.

Observações: para achar uma filial pela sigla, leia a lista e filtre do seu lado.

PUT /integracao/v1/filiais/{id}#

Para que serve: altera os dados de uma filial.

Quando chamar: quando o nome, o endereço, o pino ou o raio mudam no TMS, ou para desativar uma filial ("ativa": false).

Cabeçalhos: X-Veltra-Api-Key (chave de produção) e Content-Type: application/json.

Parâmetros de caminho: id (uuid da filial), como na rota anterior.

Corpo da requisição: os mesmos campos do POST. nome e siglaExterna continuam obrigatórios.

curl
curl -X PUT "$BASE/integracao/v1/filiais/0192f3a4-5b6c-7d8e-9f01-000000000201" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "nome": "Filial Campinas Norte",
    "siglaExterna": "CPS",
    "raioGeofenceM": 250
  }'

Resposta de sucesso: 200, com a filial atualizada.

Erros

StatusQuandoO que fazer
400Campo inválido (como no POST)Corrigir
401Chave inválidaConferir a chave
403Chave de teste ou que não é de TMSUsar a chave de produção
404A filial não existeConferir o id
409A siglaExterna nova já é de outra filialEscolher outra sigla

Observações

  • O PUT pode ser repetido sem problema (mesmo corpo, mesmo resultado).
  • Se você não mandar latitude e longitude, o pino atual é mantido (ele nunca é apagado por omissão, e a API não localiza endereço novo no mapa). Se não mandar raioGeofenceM, o raio atual é mantido. Se não mandar ativa, o estado atual é mantido.
  • Atenção: o texto do endereco é substituído pelo que você mandar. Omitido, o endereço da filial fica em branco. Mande sempre o endereço junto, mesmo que não tenha mudado.
  • Trocar a sigla de uma filial muda como os próximos manifestos de transferência devem citá-la.

Manifestos

Um manifesto é uma viagem: motorista, veículo e a lista de documentos (CT-e e NF) que o motorista entrega, coleta ou transfere. O Veltra não recebe XML: recebe as chaves e os dados essenciais de cada documento. A trilha de ajuda tem o passo a passo no módulo 4; aqui está o detalhe de cada rota.

POST /integracao/v1/manifestos#

Para que serve: envia um manifesto novo, em uma chamada, com todos os documentos.

Quando chamar: quando o TMS fechar a viagem e o motorista estiver para sair. O Veltra monta as paradas sozinho, agrupando os documentos por destinatário (CNPJ ou CPF) mais endereço, na ordem em que aparecem em documentos.

Cabeçalhos

CabeçalhoObrigatórioValor
X-Veltra-Api-KeysimA chave do TMS (teste ou produção)
Idempotency-KeysimUm UUID por tentativa lógica (veja a seção de idempotência)
Content-Typesimapplication/json

Parâmetros de caminho e de consulta: nenhum.

Corpo da requisição: o manifesto

CampoTipoObrigatórioDescrição
tipotextosimROTA (entregas e coletas juntas), TRANSFERENCIA (entre filiais), ENTREGA ou COLETA. ENTREGA e COLETA continuam aceitos e valem como ROTA. Não muda depois de criado
numeroExternotexto (1 a 60)simO número do manifesto no seu TMS. É a chave natural: único por transportadora e ambiente
motoristaobjetosimcpf (11 dígitos, com ou sem máscara, com dígitos verificadores corretos) e nome (até 200)
veiculoobjetosimplaca de tração, padrão antigo ou Mercosul, com ou sem hífen
ajudanteslistanãoAté 2, cada um com cpf e nome. São dados do manifesto, não usuários do app
filialOrigemSiglatextosó em TRANSFERENCIAsiglaExterna da filial de origem. Sigla desconhecida recusa o manifesto
filialDestinoSiglatextosó em TRANSFERENCIAsiglaExterna da filial de destino
chaveMdfetexto (44)nãoChave do MDF-e do manifesto, para rastreabilidade. Não substitui o numeroExterno
quantidadePaletesinteiro, 0 ou maisnãoPaletes do manifesto
documentoslistasimDe 1 a 1000 documentos. A ordem é a ordem sugerida das paradas

Cada item de documentos

CampoTipoObrigatórioDescrição
modelonúmerosim55 (NF-e), 57 (CT-e) ou 58 (MDF-e). Mande como número, não como texto
numerotexto (até 20)simNúmero do documento
serietexto (até 10)nãoSérie do documento
chavetexto (44)sim para CT-eChave de acesso de 44 posições. O Veltra confere o dígito verificador e o modelo. Para NF-e é opcional: sem ela, o documento é identificado por numero, serie e cnpjEmbarcador
cnpjTransportadoratextonãoCNPJ de quem emitiu o CT-e (só modelo 57). Ausente, o Veltra usa o CNPJ que está na chave
cnpjEmbarcadortextosim se modelo não for 57CNPJ do dono da NF
tomadorCnpjtextonãoCNPJ de quem paga o frete (só CT-e). Sem ele, nenhum terceiro recebe o PDF nem o canhoto
tarefatextonãoENTREGA ou COLETA. Omitido: coleta em manifesto COLETA e entrega nos demais tipos
embarcadorobjetonãocnpjCpf e nome de quem embarca a mercadoria. É aceito, mas ainda não é gravado
destinatarioobjetosimVeja a tabela abaixo
nfVinculadaslistanão (informe em CT-e)As NF que o CT-e transporta (veja a tabela abaixo). O Veltra aceita o CT-e sem elas, mas sem as NF o vínculo não é feito
volumesinteiro, 0 ou maisnãoQuantidade de volumes
pesonúmero, 0 ou maisnãoPeso em kg
valornúmero, 0 ou maisnãoValor do documento, só para exibição na torre. Não entra em cálculo
prazoEntregadatanãoAAAA-MM-DD
cteEmitidoEmdata e horanãoEmissão do CT-e. Serve de data-base do prazo se a transportadora escolheu essa regra
latitude, longitudenúmeronãoCoordenadas da parada. Mande as duas juntas. Sem elas, o endereço é localizado no mapa em segundo plano
protocoloAutorizacaotexto, 15 dígitosnãoProtocolo de autorização do CT-e. Alimenta o evento 110180
tipoServicotextonãoNORMAL, SUBCONTRATACAO, REDESPACHO, REDESPACHO_INTERMEDIARIO ou SERVICO_VINCULADO_MULTIMODAL
globalizadoverdadeiro ou falsonãoCT-e globalizado. Omitido: não

protocoloAutorizacao, tipoServico e globalizado só valem para CT-e. Em outro modelo, são ignorados e a resposta traz um aviso em erros.

destinatario (junto com o endereço, define a parada)

CampoTipoObrigatórioDescrição
cnpjCpftextosimCNPJ ou CPF, com ou sem máscara. Agrupa as paradas e identifica o link do destinatário
nometexto (até 200)simNome do destinatário
emailtextonãoPara o aviso da entrega ao destinatário. É dado pessoal
enderecoobjetosimlogradouro, municipio e uf são obrigatórios; numero, complemento, bairro e cep são opcionais

Cada item de nfVinculadas

CampoTipoObrigatórioDescrição
numerotexto (até 20)simNúmero da NF
cnpjEmbarcadortextosimCNPJ de quem emitiu a NF
serietexto (até 10)nãoSérie da NF
chavetexto (44)nãoChave da NF-e. Se vier depois, o Veltra vincula
valornúmeronãoValor da NF, só para exibição
nfeEmitidoEmdata e horanãoEmissão da NF-e (data-base do prazo, se escolhida)

Exemplo completo (curl)

curl
BASE="https://api.veltrasolution.com"
CHAVE_CTE="3526091122233300018157""0010000123451482135762"

curl -X POST "$BASE/integracao/v1/manifestos" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -H "Idempotency-Key: 0192f3a4-5b6c-7d8e-9f01-23456789abcd" \
  -H "Content-Type: application/json" \
  -d @- <<JSON
{
  "tipo": "ENTREGA",
  "numeroExterno": "REL-2026-000123",
  "motorista": { "cpf": "529.982.247-25", "nome": "Motorista Exemplo da Silva" },
  "veiculo": { "placa": "ABC1D23" },
  "ajudantes": [ { "cpf": "111.444.777-35", "nome": "Ajudante Exemplo" } ],
  "quantidadePaletes": 4,
  "documentos": [
    {
      "modelo": 57,
      "chave": "$CHAVE_CTE",
      "numero": "12345",
      "serie": "1",
      "cnpjTransportadora": "11222333000181",
      "destinatario": {
        "cnpjCpf": "11444777000161",
        "nome": "Mercado Exemplo Ltda",
        "email": "entrega@mercado.exemplo",
        "endereco": {
          "logradouro": "Rua das Flores",
          "numero": "120",
          "bairro": "Centro",
          "municipio": "Campinas",
          "uf": "SP",
          "cep": "13010-000"
        }
      },
      "nfVinculadas": [
        { "numero": "45678", "serie": "1", "cnpjEmbarcador": "12345678000195" }
      ],
      "volumes": 12,
      "peso": 350.5,
      "prazoEntrega": "2026-10-02"
    }
  ]
}
JSON

A chave do CT-e foi dividida em duas partes dentro de uma variável do shell só para caber na tela; o resultado é a chave inteira de 44 posições.

Resposta de sucesso: 201 (manifesto novo, versão 1)

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000001",
  "numeroExterno": "REL-2026-000123",
  "tipo": "ENTREGA",
  "ambiente": "TESTE",
  "versaoAtual": 1,
  "quantidadeParadas": 1,
  "quantidadeDocumentos": 1,
  "documentos": [
    {
      "id": "0192f3a4-5b6c-7d8e-9f01-000000000010",
      "modelo": 57,
      "chave": "3526091122233300018157...",
      "numero": "12345",
      "serie": "1",
      "status": "PENDENTE",
      "nfVinculadas": [
        {
          "id": "0192f3a4-5b6c-7d8e-9f01-000000000011",
          "chave": null,
          "numero": "45678",
          "serie": "1",
          "status": "PENDENTE"
        }
      ]
    }
  ],
  "erros": []
}
Campo da respostaDescrição
idO id do manifesto no Veltra. É o que a rota /v1/saida/manifestos/{id} usa
numeroExterno, tipoO que você enviou
ambienteO ambiente da sua chave
versaoAtual1 na criação; sobe de 1 em 1 a cada alteração (PUT)
quantidadeParadasQuantas paradas o Veltra montou
quantidadeDocumentosQuantos documentos foram aceitos
documentos[].idO id do documento no Veltra. É o que /v1/saida/documentos/{id} usa. Guarde
documentos[].statusPENDENTE, EM_TRANSPORTE, ENTREGUE, ENTREGUE_PARCIAL, DEVOLVIDO ou CANCELADO. O status é por documento (e por NF), não do manifesto inteiro
errosDocumentos recusados e avisos desta chamada. Vazio quando tudo foi aceito

Resposta com recusa parcial: 201. Quando alguns documentos têm problema e outros não, o Veltra grava os bons e devolve os recusados em erros. O campo documentoIndex conta a partir de 0 e aponta a posição do documento na sua lista documentos:

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000001",
  "numeroExterno": "REL-2026-000123",
  "tipo": "ENTREGA",
  "ambiente": "TESTE",
  "versaoAtual": 1,
  "quantidadeParadas": 1,
  "quantidadeDocumentos": 1,
  "documentos": [],
  "erros": [
    {
      "documentoIndex": 1,
      "codigo": "CHAVE_INVALIDA",
      "motivo": "chave de acesso: dígito verificador inválido",
      "chave": "3526091122233300018157...",
      "numero": "12346"
    }
  ]
}

(O campo documentos foi resumido neste exemplo; na resposta real ele traz o documento aceito.) Sempre leia erros depois de um 201: o manifesto foi criado, mas um documento pode ter ficado de fora.

Códigos de recusa de um documento (erros[].codigo)

CódigoQuando aconteceO que fazer
CHAVE_INVALIDAChave com tamanho ou dígito verificador errado, ou documento que não pôde ser gravadoCorrigir a chave e reenviar com PUT
CHAVE_CTE_OBRIGATORIACT-e (modelo 57) sem chaveInformar a chave do CT-e
MODELO_INCOMPATIVELA chave é de um modelo diferente do modelo informadoConferir o modelo
CNPJ_INVALIDOcnpjTransportadora, cnpjEmbarcador ou tomadorCnpj inválidoCorrigir o CNPJ
DESTINATARIO_INVALIDOdestinatario.cnpjCpf ausente ou inválido, e-mail inválido, nome acima de 200, ou endereço sem logradouro, município e UFCorrigir o destinatário
DOCUMENTO_JA_BAIXADOSó no PUT: você tirou do manifesto um documento que já tem baixaO documento fica (veja o PUT)
OUTROOutras regras: modelo fora de 55, 57 e 58; numero em branco ou longo; tarefa inválida; só latitude sem longitude; valores negativos; protocoloAutorizacao sem 15 dígitos; tipoServico inválido; documento repetido no manifestoLer o motivo

Erros da chamada inteira

StatusQuandoO que fazer
400Falta o cabeçalho Idempotency-Key (detail: "cabeçalho Idempotency-Key é obrigatório")Enviar o cabeçalho
400Idempotency-Key com mais de 255 caracteresUsar um UUID
400JSON ilegível (detail: "Corpo da requisição ilegível.")Validar o JSON
400Erro de cabeçalho do manifesto: tipo ausente ou fora da lista; numeroExterno ausente; motorista ou veiculo ausentes; motorista.cpf inválido; veiculo.placa inválida; mais de 2 ajudantes; chaveMdfe inválida; documentos vazio ou acima de 1000Corrigir o campo que o detail indica
400Transferência sem filialOrigemSigla ou filialDestinoSigla, ou sigla que não existeCadastrar a filial antes (rota de filiais)
400Todos os documentos foram recusados. type termina em documentos-invalidos e erros lista o motivo de cada um. Nada foi gravadoCorrigir os documentos e reenviar
401Chave inválidaConferir a chave
403Chave sem permissão para manifesto (por exemplo, chave de consulta), ou módulo de entrada suspenso (CHAVE_SUSPENSA)Usar a chave certa
409Idempotency-Key já usada com outro corpoGerar uma chave nova, se for outro envio
409numeroExterno já existe neste ambiente (type termina em manifesto-ja-existe)Use PUT para alterar
409codigo = TESTE_ENCERRADO: o teste grátis da transportadora acabou e a chave de produção não grava manifesto novoA transportadora contrata no portal. A chave de teste não é afetada
409Conflito de gravação simultânea (type termina em conflito)Tentar de novo com a mesma Idempotency-Key
429Limite de chamadasEsperar o Retry-After

Observações

  • Idempotência. Reenvio com a mesma Idempotency-Key e o mesmo corpo devolve 200 com a resposta original e não grava nada de novo. Isso vale também depois que o teste grátis acabou: um manifesto já gravado continua devolvendo a resposta gravada.
  • Deduplicação por numeroExterno. Mandar o mesmo número com outra Idempotency-Key é 409: o Veltra entende que é um manifesto repetido e não cria outro. Para mudar um manifesto existente, use o PUT.
  • Coleta sem CT-e. O documento é a NF (modelo 55) com numero, serie e cnpjEmbarcador. O destinatario é o local onde o motorista busca. Quando o CT-e for emitido depois, ele chega em outro manifesto com as mesmas NF e o Veltra vincula sozinho.
  • Mesma parada. Documentos para o mesmo destinatário e o mesmo endereço ficam na mesma parada, cada um com a sua tarefa.
  • Teste. O manifesto de teste não chega ao app de motoristas reais nem dispara webhook de produção.
  • Limites. Até 1000 documentos, até 2 ajudantes, numeroExterno com até 60 caracteres.
  • Eventos. O Veltra não dispara webhook de manifesto; para acompanhar o andamento, assine os eventos de baixa, ocorrência e parada (veja os webhooks).

GET /integracao/v1/manifestos/{numeroExterno}#

Para que serve: consulta a situação atual de um manifesto que o seu TMS enviou, com o status de cada documento e de cada NF.

Quando chamar: para conferir o que o Veltra tem depois de um envio ou de uma alteração, e para ver o andamento (PENDENTE, EM_TRANSPORTE, ENTREGUE e assim por diante).

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
numeroExternotexto (1 a 60)simO número do manifesto no seu TMS, o mesmo do envio

Parâmetros de consulta: nenhum.

curl
curl "$BASE/integracao/v1/manifestos/REL-2026-000123" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200 (mesma estrutura da resposta do envio, com documentos preenchido)

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000001",
  "numeroExterno": "REL-2026-000123",
  "tipo": "ENTREGA",
  "ambiente": "PRODUCAO",
  "versaoAtual": 2,
  "quantidadeParadas": 1,
  "quantidadeDocumentos": 1,
  "documentos": [
    {
      "id": "0192f3a4-5b6c-7d8e-9f01-000000000010",
      "modelo": 57,
      "chave": "3526091122233300018157...",
      "numero": "12345",
      "serie": "1",
      "status": "EM_TRANSPORTE",
      "nfVinculadas": [
        {
          "id": "0192f3a4-5b6c-7d8e-9f01-000000000011",
          "chave": null,
          "numero": "45678",
          "serie": "1",
          "status": "EM_TRANSPORTE"
        }
      ]
    }
  ],
  "erros": []
}

Erros

StatusQuandoO que fazer
401Chave inválidaConferir a chave
403Chave sem permissãoUsar a chave de TMS
404Não existe neste ambiente da chave (ou é de outra transportadora). O Veltra nunca revela se existe em outro ambienteConferir o numeroExterno e se a chave é a de teste ou a de produção

Observações: a consulta é somente leitura e pode ser repetida à vontade. Uma chave de teste só enxerga manifestos de teste, e a de produção, só os de produção. Documentos removidos numa alteração não aparecem aqui. Para ser avisado da mudança de status sem consultar, use os webhooks.

PUT /integracao/v1/manifestos/{numeroExterno}#

Para que serve: altera um manifesto já enviado. Alterar é reenviar o manifesto inteiro: o Veltra compara com a versão atual, calcula o que entrou, saiu ou mudou e grava uma nova versão (versaoAtual + 1), guardando o histórico.

Quando chamar: para trocar motorista, veículo ou ajudantes no meio da rota, adicionar ou tirar documentos, ou corrigir um documento que foi recusado no envio. O que já foi feito continua registrado em nome de quem fez.

Cabeçalhos: os mesmos do POST: X-Veltra-Api-Key, Idempotency-Key (obrigatório) e Content-Type: application/json.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
numeroExternotexto (1 a 60)simO número do manifesto no seu TMS

Corpo da requisição: o manifesto completo, com os mesmos campos do POST. O numeroExterno do corpo precisa ser igual ao do caminho, e o tipo precisa ser o mesmo do manifesto original.

curl
CHAVE_CTE="3526091122233300018157""0010000123451482135762"

curl -X PUT "$BASE/integracao/v1/manifestos/REL-2026-000123" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -H "Idempotency-Key: 0192f3a4-5b6c-7d8e-9f01-23456789abce" \
  -H "Content-Type: application/json" \
  -d @- <<JSON
{
  "tipo": "ENTREGA",
  "numeroExterno": "REL-2026-000123",
  "motorista": { "cpf": "111.444.777-35", "nome": "Outro Motorista Exemplo" },
  "veiculo": { "placa": "XYZ9A87" },
  "documentos": [
    {
      "modelo": 57,
      "chave": "$CHAVE_CTE",
      "numero": "12345",
      "serie": "1",
      "cnpjTransportadora": "11222333000181",
      "destinatario": {
        "cnpjCpf": "11444777000161",
        "nome": "Mercado Exemplo Ltda",
        "endereco": { "logradouro": "Rua das Flores", "numero": "120", "municipio": "Campinas", "uf": "SP" }
      },
      "nfVinculadas": [
        { "numero": "45678", "serie": "1", "cnpjEmbarcador": "12345678000195" }
      ]
    }
  ]
}
JSON

Resposta de sucesso: 200, com a estrutura de ManifestoResponse (como no GET): versaoAtual sobe e documentos mostra a situação atual. Se algo foi recusado, vem em erros:

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000001",
  "numeroExterno": "REL-2026-000123",
  "tipo": "ENTREGA",
  "ambiente": "PRODUCAO",
  "versaoAtual": 2,
  "quantidadeParadas": 1,
  "quantidadeDocumentos": 2,
  "documentos": [],
  "erros": [
    {
      "documentoIndex": null,
      "codigo": "DOCUMENTO_JA_BAIXADO",
      "motivo": "O documento já tem baixa e não pode ser removido do manifesto",
      "chave": "3526091122233300018157...",
      "numero": "12346"
    }
  ]
}

(O campo documentos foi resumido neste exemplo.) documentoIndex fica null quando o documento recusado não está na sua lista, que é o caso da remoção recusada.

Erros

StatusQuandoO que fazer
400numeroExterno do corpo diferente do caminho (detail: "numeroExterno do corpo difere do informado no caminho")Igualar os dois
400Tentou mudar o tipo (detail: "o tipo do manifesto não pode mudar (atual: ...)")Manter o tipo; para outro tipo, cancele e crie outro manifesto
400Qualquer erro de cabeçalho do manifesto ou de Idempotency-Key (as mesmas regras do POST)Corrigir
400Todos os documentos recusadosCorrigir os documentos
401Chave inválidaConferir a chave
403Chave sem permissãoUsar a chave de TMS
404O manifesto não existe neste ambienteConferir o numeroExterno e o ambiente da chave
409Idempotency-Key já usada com outro corpoGerar uma chave nova

Observações

  • Documento que sumiu mas já tem baixa ou ocorrência não é removido. O restante da alteração é aplicado e a resposta traz DOCUMENTO_JA_BAIXADO em erros. Um comprovante nunca some.
  • Reenviar exatamente o conteúdo atual (mesmo com outra Idempotency-Key) não cria versão nova: a resposta traz a mesma versaoAtual.
  • Idempotência igual à do POST: mesma chave e mesmo corpo devolve a mesma resposta.
  • Ambiente. O manifesto é localizado pelo ambiente da chave e a alteração nunca muda o ambiente dele.
  • Um documento cancelado ou devolvido que volta no manifesto é tratado como nova tentativa e volta a PENDENTE. Entregue continua entregue.
  • Uma alteração não gera webhook; a nova versão fica na linha do tempo do manifesto.

POST /integracao/v1/manifestos/{numeroExterno}/cancelar#

Para que serve: cancela o que ainda falta de um manifesto (cancelamento parcial).

Quando chamar: quando a viagem foi desfeita (veículo quebrou, carga redistribuída). Os documentos cancelados saem do app do motorista.

Cabeçalhos: X-Veltra-Api-Key. O corpo é opcional; se mandar, use Content-Type: application/json. Não precisa de Idempotency-Key.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
numeroExternotextosimO número do manifesto no seu TMS

Corpo da requisição (opcional)

CampoTipoObrigatórioDescrição
motivotexto (até 500)nãoMotivo, registrado na linha do tempo de cada documento cancelado
curl
curl -X POST "$BASE/integracao/v1/manifestos/REL-2026-000123/cancelar" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{ "motivo": "Veículo quebrado; carga redistribuída em outro manifesto" }'

Resposta de sucesso: 200, com a situação do manifesto depois do cancelamento. O que já foi entregue permanece:

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000001",
  "numeroExterno": "REL-2026-000123",
  "tipo": "ENTREGA",
  "ambiente": "PRODUCAO",
  "versaoAtual": 2,
  "quantidadeParadas": 1,
  "quantidadeDocumentos": 2,
  "documentos": [
    {
      "id": "0192f3a4-5b6c-7d8e-9f01-000000000010",
      "modelo": 57,
      "chave": "3526091122233300018157...",
      "numero": "12345",
      "serie": "1",
      "status": "CANCELADO",
      "nfVinculadas": []
    },
    {
      "id": "0192f3a4-5b6c-7d8e-9f01-000000000012",
      "modelo": 57,
      "chave": "3526091122233300018157...",
      "numero": "12346",
      "serie": "1",
      "status": "ENTREGUE",
      "nfVinculadas": []
    }
  ],
  "erros": []
}

Erros

StatusQuandoO que fazer
400motivo com mais de 500 caracteresEncurtar
401Chave inválidaConferir a chave
403Chave sem permissãoUsar a chave de TMS
404O manifesto não existe neste ambienteConferir o numeroExterno e o ambiente

Observações

  • Cancelar de novo é seguro: responde 200 com a mesma situação, sem mudar nada.
  • O cancelamento é por documento: só o que ainda não foi entregue nem coletado é cancelado.
  • Cancelar não gera webhook de manifesto.

Leitura de saída (/v1/saida)

Estas rotas servem para ler o que o Veltra registrou. Elas valem para o ambiente da sua chave. Para saber as regras de cada finalidade de chave, veja a tabela de finalidades no começo da página.

GET /v1/saida/eventos#

Para que serve: lista os eventos que mudaram desde a última leitura: baixa, ocorrência, comprovante, chegada e saída de parada, posição do veículo, estado do evento do CT-e, e as mudanças de manifesto.

Quando chamar: em repetição, de tempos em tempos, para manter o TMS em dia. É o jeito de "puxar" as novidades. Se preferir ser avisado, use os webhooks (os eventos têm o mesmo formato).

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de consulta

NomeTipoObrigatórioDescrição
alteradoDesdetextonãoO proximoCursor da resposta anterior. Omitido: começa do início
limiteinteiro, de 1 a 200nãoQuantos itens por resposta. Padrão: 50

Primeira leitura

curl
curl "$BASE/v1/saida/eventos?limite=100" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Próximas leituras (com o cursor guardado)

curl
curl "$BASE/v1/saida/eventos?limite=100&alteradoDesde=CURSOR_GUARDADO_AQUI" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200

JSON
{
  "itens": [
    {
      "id": "018f6a2e-7c31-7a3e-8c2a-000000000006",
      "tipo": "baixa.registrada",
      "versao": 1,
      "ocorridoEm": "2026-10-22T12:00:00-03:00",
      "ambiente": "PRODUCAO",
      "dados": {
        "paradaId": "22222222-2222-4222-8222-222222222222",
        "baixaId": "44444444-4444-4444-8444-444444444444",
        "documentoId": "33333333-3333-4333-8333-333333333333"
      }
    },
    {
      "id": "018f6a2e-7c31-7a3e-8c2a-000000000008",
      "tipo": "comprovante.emitido",
      "versao": 1,
      "ocorridoEm": "2026-10-22T12:00:00-03:00",
      "ambiente": "PRODUCAO",
      "dados": {
        "documentoId": "33333333-3333-4333-8333-333333333333",
        "comprovanteId": "66666666-6666-4666-8666-666666666666"
      }
    }
  ],
  "proximoCursor": "CURSOR_GUARDADO_AQUI"
}
CampoDescrição
itensLista de eventos no mesmo envelope dos webhooks: id, tipo, versao, ocorridoEm, ambiente, dados. O conteúdo de dados depende do tipo
itens[].idIdentifica o evento. Use para não processar duas vezes
itens[].tipoUm destes: parada.chegada, parada.saida, baixa.registrada, ocorrencia.registrada, comprovante.emitido, evento_cte.estado_alterado, posicao.lote
proximoCursorGuarde e mande em alteradoDesde na próxima leitura. É null quando não há nada a devolver e você ainda não tinha cursor

O formato exato de dados de cada tipo está nos esquemas de contracts/webhooks/ e na referência de webhooks.

Erros

StatusQuandoO que fazer
400limite fora de 1 a 200 (detail: "limite deve estar entre 1 e 200")Corrigir
400Cursor inventado ou alterado (detail: "cursor alteradoDesde inválido")Use só o valor devolvido em proximoCursor
401Chave inválidaConferir a chave
403Chave sem permissão, ou CHAVE_SUSPENSA (chave de consulta sem o módulo)Usar a chave certa
429Limite de chamadasEsperar o Retry-After

Observações

  • Janela de 5 segundos. Um evento recém-criado pode demorar alguns segundos para aparecer. Não é falha; consulte de novo.
  • Repetição é normal. O mesmo evento pode vir em duas respostas seguidas (por exemplo, se o seu processo caiu antes de guardar o cursor). Processar duas vezes tem de dar o mesmo resultado: trate pelo id.
  • Fluxo recomendado: leia, processe os itens, só depois grave o proximoCursor.
  • Posição do veículo (posicao.lote) vai só para a chave do TMS. Chaves de embarcador e destinatário não recebem esse tipo.
  • Chaves de consulta só veem eventos de documentos das raízes de CNPJ cadastradas nelas.
  • Leitura pura: pode ser repetida sem efeito colateral.

GET /v1/saida/manifestos#

Para que serve: lista os manifestos do ambiente da chave, com cursor.

Quando chamar: para conferir ou reconstruir a lista de manifestos que o Veltra tem (por exemplo, numa conciliação). Só a chave do TMS usa esta rota.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de consulta: alteradoDesde e limite, como em /v1/saida/eventos.

curl
curl "$BASE/v1/saida/manifestos?limite=50" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200

JSON
{
  "itens": [
    {
      "id": "0192f3a4-5b6c-7d8e-9f01-000000000001",
      "numero": "REL-2026-000123",
      "tipoManifesto": "ENTREGA",
      "atualizadoEm": "2026-10-22T15:00:00Z",
      "kmSaida": 120000,
      "kmChegada": 120450,
      "kmRodados": 450
    }
  ],
  "proximoCursor": "CURSOR_GUARDADO_AQUI"
}
CampoDescrição
itens[].idO id do manifesto no Veltra
itens[].numeroO numeroExterno do seu TMS
itens[].tipoManifestoO tipo gravado do manifesto
itens[].atualizadoEmÚltima atualização
itens[].kmSaidaKm do hodômetro informado pelo motorista na saída do veículo da base. null quando não foi informado
itens[].kmChegadaKm informado na chegada. null enquanto não chegou ou não informou
itens[].kmRodadoskmChegada - kmSaida. null quando falta um dos dois ou quando a chegada é menor que a saída (a torre recebe um alerta de km)
proximoCursorCursor para a próxima leitura

Erros: 400 (limite ou cursor inválidos), 401, 403 (chave que não é de TMS), 429.

Observações: os três campos de km vêm da viagem (saída da base) mais recente que levou o manifesto e são null para manifesto sem saída de veículo (por exemplo, uma entrega comum sem transferência). Mudar o km não muda atualizadoEm: para saber na hora que o km foi informado, assine o evento veiculo.km_registrado. É só uma lista resumida, sem os documentos. Para a situação de cada documento, use GET /integracao/v1/manifestos/{numeroExterno}. O cursor funciona como o de eventos, com a mesma janela de 5 segundos.

GET /v1/saida/manifestos/{id}#

Para que serve: mostra um manifesto pelo id do Veltra.

Quando chamar: quando você tem o id (da resposta do envio) e quer o resumo. Só a chave do TMS usa.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
idtexto (uuid)simO id do manifesto, devolvido no envio
curl
curl "$BASE/v1/saida/manifestos/0192f3a4-5b6c-7d8e-9f01-000000000001" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200

JSON
{
  "id": "0192f3a4-5b6c-7d8e-9f01-000000000001",
  "numero": "REL-2026-000123",
  "tipoManifesto": "ENTREGA",
  "atualizadoEm": "2026-10-22T15:00:00Z",
  "kmSaida": 120000,
  "kmChegada": null,
  "kmRodados": null
}

Os campos kmSaida, kmChegada e kmRodados são os mesmos da lista (acima) e são null quando o motorista ainda não informou o km.

Erros: 401, 403, 404 (não existe neste ambiente ou é de outra transportadora), 400 (id que não é um UUID), 429.

Observações: não traz trilha nem posição do veículo.

GET /v1/saida/documentos/{id}#

Para que serve: mostra a situação de um documento fiscal (CT-e ou NF) pelo id do Veltra.

Quando chamar: quando um evento citou o documentoId e você quer saber o estado atual desse documento.

Cabeçalhos: X-Veltra-Api-Key. Aceita a chave do TMS e as chaves de consulta.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
idtexto (uuid)simO id do documento (documentos[].id da resposta do manifesto, ou documentoId dos eventos)
curl
curl "$BASE/v1/saida/documentos/33333333-3333-4333-8333-333333333333" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200

JSON
{
  "id": "33333333-3333-4333-8333-333333333333",
  "numero": "12345",
  "status": "ENTREGUE",
  "podeVerPdfECanhoto": true,
  "atualizadoEm": "2026-10-22T15:05:00Z"
}
CampoDescrição
statusEstado atual do documento, por exemplo PENDENTE, EM_TRANSPORTE, ENTREGUE, CANCELADO
podeVerPdfECanhotoPara o TMS da transportadora, sempre true. Para chave de consulta, só é true quando o terceiro é o tomador do frete

Erros: 401, 403, 404 (não existe neste ambiente, ou, para chave de consulta, está fora das raízes de CNPJ da chave: é a mesma resposta de "não existe"), 400 (id inválido), 429.

Observações: não traz posição, placa ou trilha do veículo.

GET /v1/saida/comprovantes/{id}/pdf#

Para que serve: baixa o PDF do comprovante de um documento. É o mesmo arquivo que o portal mostra.

Quando chamar: depois de receber o evento comprovante.emitido; o comprovanteId está em dados. Só a chave do TMS usa. Chave de consulta recebe 403.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
idtexto (uuid)simO comprovanteId do evento comprovante.emitido
curl
curl "$BASE/v1/saida/comprovantes/66666666-6666-4666-8666-666666666666/pdf" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -o comprovante.pdf

Resposta de sucesso: 200 com Content-Type: application/pdf e o cabeçalho Content-Disposition com o nome comprovante-<id>.pdf. O corpo é o arquivo.

Erros

StatusQuandoO que fazer
401Chave inválidaConferir a chave
403Chave que não é de TMSUsar a chave de TMS
404COMPROVANTE_NAO_ENCONTRADO: o comprovante não existe neste ambiente (ou é de outra transportadora). Vem em application/problem+json, com o código no campo codigoConferir o id (é o comprovanteId do evento comprovante.emitido) e o ambiente da chave
409COMPROVANTE_AINDA_NAO_PUBLICADO: o comprovante existe, mas o PDF ainda não foi publicado. Vem em application/problem+json, com o código no campo codigoEsperar um pouco e tentar de novo; o certo é baixar depois do evento comprovante.emitido
429Limite de chamadasEsperar o Retry-After

Observações: o arquivo é entregue como está guardado; baixe e confira o SHA-256 se quiser provar que não mudou. O PDF só vem assinado quando a transportadora ligou a validação opcional (veja o módulo 6 da trilha). Cada download é registrado para fins de medição, e o download pode ser repetido.

GET /v1/saida/comprovantes/{id}/pacote#

Para que serve: baixa o pacote de evidências (arquivo ZIP) do comprovante: o PDF, o manifesto da evidência e os arquivos de apoio (as fotos, e os arquivos de validação quando existem).

Quando chamar: quando você precisa guardar a prova completa de uma entrega, por exemplo para auditoria ou para anexar numa disputa. Só a chave do TMS usa.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de caminho: id (uuid), o comprovanteId, como na rota do PDF.

curl
curl "$BASE/v1/saida/comprovantes/66666666-6666-4666-8666-666666666666/pacote" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -o comprovante.zip

Resposta de sucesso: 200 com Content-Type: application/zip e Content-Disposition com o nome comprovante-<id>.zip. O corpo é o arquivo.

Erros: os mesmos do PDF: 401, 403, 429, 404 (COMPROVANTE_NAO_ENCONTRADO) para comprovante inexistente e 409 (COMPROVANTE_AINDA_NAO_PUBLICADO) para comprovante ainda não publicado, ambos em application/problem+json.

Observações: o ZIP traz um arquivo LEIA-ME.txt que explica o conteúdo. Se uma foto ainda não estiver disponível, o pacote não é entregue e a resposta é um erro: tente depois.

GET /v1/saida/eventos-cte/{id}/xml#

Para que serve: baixa o XML assinado do evento 110180 (Comprovante de Entrega do CT-e), com o protocolo da SEFAZ.

Quando chamar: quando o estado do evento do CT-e chegou a REGISTRADO (evento evento_cte.estado_alterado) e o TMS quer guardar o XML. Só a chave do TMS usa.

Importante: o Veltra não transmite o evento 110190 (insucesso). Esse evento deve ser emitido pelo TMS por conta própria.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
idtexto (uuid)simO id do evento do CT-e no Veltra: o mesmo id que a tela de eventos do CT-e do portal usa
curl
curl "$BASE/v1/saida/eventos-cte/0192f3a4-5b6c-7d8e-9f01-000000000300/xml" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -o evento-110180.xml

Resposta de sucesso: 200 com Content-Type: application/xml e o XML no corpo.

Erros

StatusQuandoO que fazer
401Chave inválidaConferir a chave
403Chave que não é de TMSUsar a chave de TMS
404Não existe neste ambiente, ou o perfil da transportadora não gerou o evento 110180 para esse documentoConfirmar o perfil com a transportadora
429Limite de chamadasEsperar o Retry-After

Observações: o XML só existe para documentos cujo perfil da transportadora gera esse evento. O download é registrado para medição e pode ser repetido.

GET /v1/saida/openapi/{finalidade}#

Para que serve: devolve o OpenAPI filtrado (em YAML) com só as rotas que a finalidade pode chamar. Use para gerar um cliente de código sem as rotas que a sua chave não alcança.

Quando chamar: uma vez, ao começar a integração de leitura, e quando quiser regenerar o cliente.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
finalidadetextosimINTEGRACAO_TMS, CONSULTA_EMBARCADOR ou CONSULTA_DESTINATARIO
curl
curl "$BASE/v1/saida/openapi/INTEGRACAO_TMS" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -o veltra-saida-tms.yaml

Resposta de sucesso: 200 com Content-Type: application/yaml.

Erros

StatusQuandoO que fazer
400Finalidade desconhecida (detail: "Finalidade desconhecida.")Usar um dos três valores
401Chave inválidaConferir a chave
403A chave não recebe esse OpenAPI: chave de consulta pedindo a finalidade de outro tipo, ou pedido de ENTRADA_TRANSPORTADORAPedir a finalidade da própria chave
429Limite de chamadasEsperar o Retry-After

Observações: a chave do TMS pode pedir qualquer uma das três finalidades. Chave de consulta só obtém a própria finalidade. Este arquivo é separado do Swagger público: ele cobre as rotas /v1/saida/**.

GET /v1/saida/configuracao-prazo#

Para que serve: lê a regra de prazo de entrega da transportadora: o prazo padrão, a data-base, as horas por cidade e os feriados locais.

Quando chamar: antes de gravar uma configuração nova (para não apagar o que já existe), ou para conferir o que o Veltra está usando.

Cabeçalhos: X-Veltra-Api-Key.

Parâmetros: nenhum.

curl
curl "$BASE/v1/saida/configuracao-prazo" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI"

Resposta de sucesso: 200

JSON
{
  "prazoPadraoHoras": 72,
  "dataBase": "NFE",
  "origemPrazo": "TMS_QUANDO_VIER",
  "cidades": [
    { "municipio": "Campinas", "uf": "SP", "horas": 48 }
  ],
  "feriadosLocais": [
    { "data": "2026-07-14", "nome": "Feriado municipal" }
  ]
}
CampoTipoDescrição
prazoPadraoHorasinteiro, de 1 a 720Prazo padrão, em horas úteis (segunda a sexta, no fuso de São Paulo)
dataBasetextoDe onde o prazo começa a contar: CTE (emissão do CT-e), NFE (emissão da NF-e) ou CHEGADA_MANIFESTO. Se a data escolhida não existir, vale a chegada do manifesto
origemPrazotextoTMS_QUANDO_VIER: se o TMS mandar prazoEntrega, ele prevalece. SEMPRE_CONFIGURADO: vale sempre o prazo calculado pela configuração
cidadeslistaHoras específicas por município e UF (cada uma de 1 a 720)
feriadosLocaislistaDatas que não consomem horas, além dos feriados nacionais

Sem configuração gravada, a resposta traz o padrão: 72 horas, NFE, TMS_QUANDO_VIER, sem cidades e sem feriados.

Erros: 401, 403 (chave que não é de TMS), 429.

Observações: é a mesma configuração que o portal mostra. O portal também responde em GET /v1/configuracao-prazo; para o TMS, use a rota /v1/saida/.

PUT /v1/saida/configuracao-prazo#

Para que serve: grava a relação de cidades, prazos e feriados. Substitui toda a configuração.

Quando chamar: na implantação, e sempre que o prazo por cidade ou os feriados mudarem no TMS. A mudança vale para as cargas que chegarem depois.

Cabeçalhos: X-Veltra-Api-Key e Content-Type: application/json.

Corpo da requisição

CampoTipoObrigatórioDescrição
prazoPadraoHorasinteiro, de 1 a 720simPrazo padrão em horas úteis
dataBasetextosimCTE, NFE ou CHEGADA_MANIFESTO
origemPrazotextosimTMS_QUANDO_VIER ou SEMPRE_CONFIGURADO
cidadeslistasimPode ser vazia. Cada item: municipio (até 120), uf (2 letras), horas (de 1 a 720). Não repita município e UF
feriadosLocaislistasimPode ser vazia. Cada item: data (AAAA-MM-DD) e nome (até 120). Não repita data
curl
curl -X PUT "$BASE/v1/saida/configuracao-prazo" \
  -H "X-Veltra-Api-Key: SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "prazoPadraoHoras": 72,
    "dataBase": "CTE",
    "origemPrazo": "SEMPRE_CONFIGURADO",
    "cidades": [
      { "municipio": "Campinas", "uf": "SP", "horas": 48 },
      { "municipio": "Sumaré", "uf": "SP", "horas": 48 }
    ],
    "feriadosLocais": [
      { "data": "2026-07-14", "nome": "Feriado municipal" }
    ]
  }'

Resposta de sucesso: 200, com a configuração gravada (mesmo formato do GET; as UFs são devolvidas em maiúsculas e os nomes sem espaços sobrando).

Erros

StatusQuandoO que fazer
400prazoPadraoHoras fora de 1 a 720; cidades ou feriadosLocais ausentes; cidade, UF ou horas inválidas; cidade repetida; feriado inválido; data de feriado repetidaCorrigir o corpo
401Chave inválidaConferir a chave
403Chave que não é de TMSUsar a chave de TMS
429Limite de chamadasEsperar o Retry-After

Observações

  • É uma substituição completa. As cidades e os feriados que você não mandar são apagados. Leia com o GET, altere e devolva tudo.
  • É seguro repetir: o mesmo corpo dá o mesmo resultado.
  • Configurar o prazo não substitui a conversa com a transportadora sobre calendário local e regra de prazo; combine antes de ligar em produção.
  • A configuração é única da transportadora e não separa teste de produção.

Boas práticas de integração

  1. Guarde a chave em um cofre, nunca em código, log ou e-mail. Use uma chave por sistema, para revogar só a que vazou.
  2. Comece pela chave de teste e só vá para produção depois da homologação (checklist abaixo).
  3. Use Idempotency-Key sempre, com um UUID gerado antes da primeira tentativa e guardado junto do registro que você está enviando. Na repetição, mande o mesmo valor.
  4. Repita com pausa crescente em 429 e em 5xx: espere o Retry-After quando existir; senão, 1 s, 2 s, 4 s, e assim por diante, com um teto.
  5. Não repita sem pensar em 400. Erro 400 não se resolve repetindo: corrija o dado.
  6. Leia sempre erros depois de um 201 ou 200 de manifesto. O manifesto pode ter sido criado com documentos recusados.
  7. Guarde os ids do Veltra (id do manifesto, documentos[].id) junto do numeroExterno do seu TMS.
  8. Leia eventos com cursor, em ordem, e grave o cursor só depois de processar. Trate cada evento pelo id.
  9. Prefira webhooks para ser avisado e use o GET /v1/saida/eventos como rede de segurança (por exemplo, uma leitura a cada poucos minutos) para recuperar o que se perdeu.
  10. Ignore campos que você não conhece e não quebre com valores novos de listas.
  11. Use o status HTTP e o codigo para decidir o que fazer, nunca o texto de detail.
  12. Registre em log o Idempotency-Key, o numeroExterno e o status de cada chamada (sem a chave de API).

Erros comuns e como resolver

SintomaCausa provávelComo resolver
401 em tudoChave com espaço, cortada, revogada, ou transportadora desativadaCopiar de novo; conferir com GET /v1/api-keys/atual; ver a tela Chaves de API
401 mesmo com a chave certaMandou também AuthorizationEnviar só X-Veltra-Api-Key
403 ao criar filialEstá usando a chave de testeUsar a chave de produção
403 com CHAVE_SUSPENSAChave de consulta ou de entrada sem o módulo contratadoContratar o módulo no portal; a chave volta sozinha
404 ao consultar um manifesto que você acabou de enviarChave de ambiente diferente (enviou com teste, consulta com produção, ou o contrário)Usar a mesma chave nas duas chamadas
400 "cabeçalho Idempotency-Key é obrigatório"Faltou o cabeçalho no POST ou no PUTIncluir Idempotency-Key
400 "motorista.cpf inválido"CPF com dígito verificador erradoCorrigir o CPF
400 "filialOrigemSigla: filial com sigla externa ... não encontrada"A filial não está cadastradaCadastrar a filial antes
400 com documentos-invalidosTodos os documentos foram recusadosLer erros, corrigir e reenviar
201 mas falta um documentoEle foi recusado e está em errosCorrigir e reenviar com PUT
409 ao reenviar o mesmo manifestonumeroExterno já existeUse PUT para alterar
409 "Idempotency-Key já usada com outro corpo"Reusou a chave de idempotência com um manifesto diferenteGerar uma chave nova para cada envio diferente
409 TESTE_ENCERRADOO teste grátis da transportadora acabouA transportadora contrata no portal
O evento não aparece em /v1/saida/eventosJanela de 5 segundos, ou o cursor está à frenteEsperar e consultar de novo; guardar o cursor só depois de processar
400 "cursor alteradoDesde inválido"Montou ou editou o cursorUsar só o proximoCursor devolvido
Erro (404, 409 ou 500) no PDF ou no pacoteO comprovante não existe neste ambiente ou ainda não foi publicadoConferir o id e o ambiente; tentar de novo depois, com pausa
404 no XML do evento do CT-eO perfil da transportadora não gerou o evento 110180Confirmar o perfil com a transportadora
429Passou do limite por minutoEsperar o Retry-After e reduzir o ritmo

Checklist de homologação do TMS

Marque cada item com a chave de teste antes de pedir a chave de produção.

  • A chave de teste funciona em GET /v1/api-keys/atual e mostra "ambiente": "TESTE".
  • O TMS não manda Authorization junto com X-Veltra-Api-Key.
  • A chave não está em código, em log nem em repositório.
  • As filiais foram cadastradas (no portal, ou pela API com chave de produção) e a lista GET /integracao/v1/filiais confere com o TMS.
  • Um manifesto de entrega foi enviado com sucesso (201) e consultado com GET.
  • Um manifesto de coleta sem CT-e foi enviado.
  • Um manifesto de transferência foi enviado com as siglas das duas filiais.
  • O TMS lê erros na resposta e mostra o motivo ao operador.
  • O reenvio com a mesma Idempotency-Key e o mesmo corpo devolveu 200 e não duplicou nada.
  • Reenviar o mesmo numeroExterno com outra Idempotency-Key devolveu 409, e o TMS tratou como "já enviado".
  • A alteração com PUT (troca de motorista ou de documento) subiu a versaoAtual.
  • O cancelamento foi testado, inclusive repetido.
  • O TMS trata 400, 401, 403, 404, 409, 429 e 5xx como descrito nesta página.
  • A leitura GET /v1/saida/eventos guarda o cursor, trata o id do evento e tolera repetição.
  • O PDF e o pacote de um comprovante de teste foram baixados e abertos.
  • Se o TMS usa o evento do CT-e: o XML do 110180 foi baixado (ou o 404 foi tratado).
  • A configuração de prazo foi lida e gravada com a lista completa (sabendo que ela é única por transportadora).
  • Os webhooks, se usados, verificam a assinatura (veja o módulo 5).
  • A transportadora emitiu a chave de produção (tela Chaves de API) e a chave de teste continua separada.