Integração com TMS Externo

Esta documentação orienta fornecedores de software TMS (Transportation Management System) sobre como integrar seus sistemas ao Vendelo, permitindo cotação automática de frete e gestão completa do processo de despacho por meio de APIs REST padronizadas.

Introdução à Integração TMS

A integração entre o Vendelo e sistemas TMS externos permite que transportadoras e fornecedores de software logístico ofereçam cotações automáticas de frete e gerenciem todo o ciclo de despacho diretamente na plataforma Vendelo. O processo começa quando um operador solicita opções de frete para um pedido e pode evoluir até a geração de etiquetas e rastreamento.

Público-alvo: este guia é destinado especificamente a integradores e fornecedores de software TMS que desejam conectar seus sistemas ao Vendelo para ofertar serviços de frete integrados.

A integração opera em dois níveis:

  • Nível 1: cotação de frete.
  • Nível 2: cotação + despacho completo (registro, geração de etiqueta, acompanhamento e cancelamento).

Exemplo – Mock de Referência

Para facilitar o desenvolvimento e os testes, disponibilizamos um projeto de referência que simula um fornecedor TMS externo. Este exemplo implementa os endpoints necessários e demonstra boas práticas de integração.

Repositório GitHub: https://github.com/alcgithub/Vendelo.FakeShippingProvider

O projeto de referência (C#/.NET 6) inclui:

  • Endpoints: cotação, cart, geração de etiqueta, cancelamento e consulta.
  • Autenticação flexível: token estático e OAuth 2.0.
  • Validação de payload: CEPs, produtos e campos obrigatórios.
  • Rotas de debug: apoio para testes locais.
  • Collection Postman: cenários completos com scripts de validação.
Tela de configuração de variáveis de ambiente no Postman mostrando baseUrl, token, clientId e outros parâmetros
Configuração das variáveis de ambiente no Postman para facilitar os testes com o mock de referência.

Serviços fake simulados

O mock retorna quatro serviços de frete no endpoint de cotação:

ID Nome do Serviço Transportadora Características
1 SEDEX (Correios) Correios Serviço expresso com prazo reduzido
2 PAC (Correios) Correios Serviço econômico com prazo estendido
3 Jadlog Package Jadlog Serviço de transportadora privada
4 ChinaLog ChinaLog Serviço internacional simulado

Mecânica de Seleção do Vendelo

O Vendelo utiliza regras de frete para determinar quando e como chamar fornecedores TMS externos.

Processo de seleção automática

  1. Identifica a filial do pedido e busca regras ativas do tipo PER_WEIGHT_FROM_EXTERNAL_SHIPPING_PROVIDER.
  2. Aplica filtros de CEP, peso e valor conforme configurado na regra.
  3. Resolve a conta de integração (filial específica tem prioridade sobre filial padrão).
  4. Monta o request com dados de origem, destino, transportadora e produtos.
  5. Executa a chamada para POST /api/v1/shipment/calculate.
  6. Processa as opções retornadas e apresenta para seleção.
Tela de configuração de regra de despesa adicional mostrando tipo PER_WEIGHT_FROM_EXTERNAL_SHIPPING_PROVIDER
Configuração de regra para despesa adicional de frete com integração TMS externa.

Seleção automática vs manual

  • Seleção automática: aplica a melhor opção conforme configuração da regra.
  • Seleção manual: operador escolhe entre as opções disponíveis.
Interface mostrando opções de frete com seleção automática habilitada
Tela de seleção de despesas de frete no documento.

Aplicação da despesa selecionada

Após a seleção, o Vendelo registra a opção escolhida como despesa adicional do documento e distribui o valor entre os itens conforme as regras internas.

Despesa de frete já selecionada com ícone de lápis para reconfiguração
Despesa de frete já aplicada ao documento, com possibilidade de reseleção.

Configuração da Conta de Integração

Para habilitar a integração com seu TMS, configure uma conta de integração no Vendelo com as credenciais e parâmetros de conexão.

Campo Obrigatório Descrição
Host Sim URL base da API, sem barra final. Ex: https://api.seutms.com.br
Token Condicional Token Bearer fixo (quando não usar OAuth).
UserName Condicional client_id para OAuth 2.0.
Password Condicional client_secret para OAuth 2.0.
Tipo Sim Selecionar EXTERNAL_SHIPPING_PROVIDER.
Integration Tag Opcional Identificador para múltiplas contas do mesmo tipo.
Formulário de configuração de conta de integração TMS externo
Tela de configuração da conta de integração TMS externo.

Resolução de conta por filial

  • Filial específica: prioridade máxima.
  • Filial padrão: fallback para filiais sem conta própria.
  • Integration Tag: separa integrações distintas.

Ordem de resolução: filial do pedido → filial padrão. Se nenhuma conta válida for encontrada, a integração TMS não é executada.

Fluxo Operacional Completo

Cotação de frete (Nível 1 e 2)

  1. Operador abre as opções de frete do documento.
  2. Vendelo encontra regras ativas e conta de integração.
  3. Sistema monta request com origem, destino e itens.
  4. Executa POST /api/v1/shipment/calculate.
  5. Exibe opções de serviço para seleção.
  6. Aplica a opção escolhida como despesa no documento.

Registro do envio (Nível 2)

Botão de gerar etiqueta pendente na interface do usuário
Fluxo de despacho com indicação de etiqueta pendente.
  1. Usuário acessa a tela de volumes.
  2. Vendelo envia POST /api/v1/cart.
  3. TMS retorna o ID do pedido externo.
  4. Vendelo salva o ID e marca o volume como registrado.
Aviso na interface sobre etiquetas pendentes de geração
Aviso de etiquetas pendentes para acompanhamento operacional.

Geração de etiqueta

Botão salvar para gerar etiquetas
Ação de geração de etiquetas após registro no TMS.
  1. Usuário confirma os volumes.
  2. Vendelo envia POST /api/v1/shipment/generate.
  3. TMS gera etiqueta e rastreio.
  4. Vendelo exibe links de etiqueta e rastreamento no documento.
Opção de frete escolhida exibida como selecionada por padrão ao gerar etiqueta
Opção de frete previamente escolhida reaproveitada no momento da geração.

Acompanhamento e rastreamento

Detalhes do volume registrado com etiqueta de envio gerada
Detalhes do volume com dados de envio e rastreamento.
Status do envio mostrando etiqueta gerada com código de rastreamento
Status atualizado do envio após geração da etiqueta.

Endpoints

Todos os endpoints devem seguir padrão REST com JSON.

Nível 1 – Cotação apenas

Endpoint Método Obrigatório Descrição
/api/v1/shipment/calculate POST Sim Retorna opções de frete (preço e prazo).

Nível 2 – Cotação + despacho completo

Endpoint Método Obrigatório Descrição
/api/v1/shipment/calculatePOSTSimCotação
/api/v1/cartPOSTSimRegistro do envio
/api/v1/shipment/generatePOSTSimGeração de etiqueta
/api/v1/cart/cancelPOSTSimCancelamento
/api/v1/orders/{id}GETSimStatus e rastreamento

Regra de consistência: se implementar /api/v1/cart, implemente também os demais endpoints do Nível 2.

Autenticação OAuth 2.0

Para credenciais com expiração, recomendamos OAuth 2.0 com refresh token.

Endpoint de renovação

EndpointMétodoQuando usado
/oauth/tokenPOSTRenovação automática antes do vencimento.

Request de renovação

{
  "grant_type": "refresh_token",
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2...",
  "client_id": "vendelo-client",
  "client_secret": "vendelo-secret"
}

Response esperado

{
  "token_type": "Bearer",
  "access_token": "eyJhbGciOiJSUzI1NiJ9...",
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2...",
  "expires_in": 2592000
}

Renovação automática: o Vendelo renova tokens próximos do vencimento antes das operações.

Estrutura de Dados

Tabela de Incoterms (PT-BR)

O campo incoterms deve ser enviado conforme os valores esperados pela integração. Abaixo estão os itens e a descrição em português:

Valor em incoterms Descrição (PT-BR) Responsabilidade principal pelo frete
BY_SENDER Por conta do remetente Remetente
BY_RECIPIENT Por conta do destinatário Destinatário
THIRD_PARTY Por conta de terceiros Terceiro pagador
NO_FREIGHT Sem frete / retirada Não se aplica

Importante: valide o valor recebido em incoterms como enum/string controlada. Quando o valor não for reconhecido, retorne erro de validação em JSON (HTTP 422).

Cotação de Frete – Request

Exemplo JSON válido de request enviado pelo Vendelo:

{
  "from": {
    "postal_code": "01310100",
    "erp_id": "F001",
    "company_document": "12345678000199",
    "state_register": "123456789"
  },
  "to": {
    "postal_code": "30130010",
    "erp_id": "C00042",
    "document": "98765432100",
    "company_document": "98765432000188",
    "state_register": "987654321"
  },
  "incoterms": "BY_SENDER",
  "carrier": {
    "id": "vendelo-carrier-id",
    "erp_id": "TMS_CAR_001"
  },
  "products": [
    {
      "id": "item-uuid-vendelo",
      "erp_id": "A00001",
      "name": "Produto Exemplo",
      "width": 15,
      "height": 10,
      "length": 20,
      "weight": 0.5,
      "quantity": 2,
      "unit_price": 149.9,
      "discount_total": 15.0,
      "insurance_value": 284.8,
      "available_stock": 25,
      "user_fields": [
        { "name": "U_VDO_CODIGO_EXTRA", "value": "7101" },
        { "name": "U_VDO_ORIGEM", "value": "Importado" }
      ]
    }
  ],
  "user_fields": [
    { "name": "U_XXX_REDESPACHO", "value": "Y" },
    { "name": "U_XXX_FONTE", "value": "Indicacao" }
  ]
}

Cotação de Frete – Response

[
  {
    "id": "1",
    "name": "Expresso",
    "custom_price": 28.9,
    "custom_delivery_time": 2,
    "carrier": {
      "erp_id": "V10000"
    },
    "company": {
      "id": "1",
      "name": "Nome da Transportadora",
      "picture": "https://cdn.seusite.com.br/logo.png"
    },
    "user_fields": [
      { "name": "U_XXX_REDESPACHO", "value": "N" },
      { "name": "U_XXX_FONTE", "value": "TMS" }
    ],
    "packages": [
      {
        "format": "box",
        "weight": 1.0,
        "price": 28.9,
        "insurance_value": 284.8,
        "dimensions": {
          "width": 15,
          "height": 10,
          "length": 20
        },
        "products": [
          {
            "id": "item-uuid-vendelo",
            "quantity": 2,
            "user_fields": [
              { "name": "U_VDO_CODIGO_EXTRA", "value": "7202" },
              { "name": "U_VDO_ORIGEM", "value": "Nacional" }
            ]
          }
        ]
      }
    ],
    "error": null
  }
]

Campos opcionais de substituição no response

O response de cotação aceita dois campos opcionais que, quando presentes, instruem o Vendelo a realizar substituições no documento assim que o operador confirmar a opção de frete.

carrier — Substituição de transportadora

Retorne o bloco carrier quando quiser trocar a transportadora do documento pela transportadora identificada pelo erp_id informado. Se não quiser alterar a transportadora, omita o bloco inteiramente.

Situação no response Comportamento no Vendelo
carrier.erp_id presente O Vendelo localiza a transportadora pelo erp_id e substitui a transportadora atual do documento no momento da seleção.
Bloco carrier ausente A transportadora do documento permanece inalterada.

Nunca retorne "carrier": null nem "erp_id": null. Não envie carrier.id no response — o ID interno é resolvido pelo Vendelo a partir do erp_id.

user_fields — Substituição de campos de usuário

Retorne user_fields quando quiser atualizar campos de usuário no documento ou nos itens. Os campos podem ser informados em dois níveis:

Nível Campo no response Comportamento no Vendelo ao selecionar a opção
Documento user_fields na raiz da opção de frete Para cada campo retornado, localiza o campo de mesmo name no documento e sobrescreve o valor. Se ainda não existir, cria o campo com o valor informado.
Item packages[].products[].user_fields Aplica a mesma lógica de substituição ou criação no item identificado pelo id retornado.

Omita user_fields quando não houver valor a atualizar — não envie arrays vazios. Campos de usuário no nível do volume/pacote são ignorados.

Cada campo deve conter:

Campo Descrição
name Nome técnico do campo de usuário cadastrado no Vendelo/ERP, por exemplo U_XXX_FONTE.
value Novo valor a ser aplicado. Sobrescreve o valor atual se o campo já existir.

Tratamento de Erros

Implemente tratamento consistente de erros com códigos HTTP apropriados:

Código HTTP Significado Comportamento do Vendelo
200SucessoProcessa resposta normalmente
400Payload inválidoExibe mensagem ao operador
401Não autorizadoTenta renovar token e repetir
422Falha de validaçãoExibe erros por campo
429Rate limitRetenta com backoff
5xxErro internoRegistra log e exibe mensagem genérica

Estrutura de erro padrão

{
  "error": "CEP de destino invalido.",
  "errors": {
    "to.postal_code": ["O CEP informado nao foi encontrado."]
  }
}

Importante: não retorne HTML em erros. O Vendelo espera JSON em todos os cenários.

Perguntas Frequentes

Posso implementar apenas cotação sem despacho?

Sim. No Nível 1, apenas /api/v1/shipment/calculate é obrigatório.

Como funciona a resolução de conta por filial?

O Vendelo busca primeiro a conta da filial do documento. Se não existir, usa a conta da filial padrão.

Os campos carrier são enviados na cotação?

No request, o Vendelo envia carrier.id e carrier.erp_id para identificar a transportadora atual do documento. No response, o TMS deve retornar apenas carrier.erp_id — e somente quando quiser substituir a transportadora do documento por outra. Se o bloco carrier for omitido, a transportadora do documento permanece inalterada.

O TMS pode devolver campos de usuário na cotação?

Sim. O response de /api/v1/shipment/calculate pode retornar user_fields no nível da opção de frete (para atualizar campos do documento) e em packages[].products[] (para atualizar campos de itens). Esses campos funcionam como uma instrução de substituição: ao selecionar a opção, o Vendelo aplica os valores retornados. O campo é opcional e deve ser omitido quando não houver nenhum valor a atualizar.

O retorno de user_fields altera campos já preenchidos?

Sim. Ao selecionar a opção de frete, o Vendelo aplica os campos retornados pelo TMS. Para cada campo, o Vendelo localiza no documento ou no item o campo de usuário com o mesmo name e sobrescreve o valor atual. Se o campo ainda não existir, ele é criado com o valor informado. A operação é sempre uma substituição completa — não há mesclagem parcial de valores.

Como faço para substituir a transportadora do documento via response?

Retorne o bloco carrier com o campo erp_id preenchido com o código da nova transportadora. O Vendelo localizará a transportadora correspondente e substituirá a transportadora atual do documento no momento em que o operador selecionar a opção de frete. Se não quiser alterar a transportadora, omita o bloco carrier por completo — nunca retorne "carrier": null nem "erp_id": null.

O que é available_stock no produto?

É o estoque disponível por item no momento da cotação, carregado do ERP e enviado em products[].available_stock.

Como funciona a renovação automática de OAuth?

O Vendelo renova o token via refresh token quando necessário, sem intervenção manual.

Posso usar credenciais diferentes por filial?

Sim. Configure contas separadas por filial e, se necessário, diferencie por Integration Tag.

Como testar durante o desenvolvimento?

Use o mock de referência e a collection Postman para validar cotação e despacho de ponta a ponta.