API REST · OAuth2 · Webhooks

API de Parceiros — Encaminhei

Integre cotação, emissão de etiquetas, rastreamento e webhooks de status diretamente no seu sistema. API REST com autenticação OAuth2.

1. Visão geral

Todas as chamadas usam HTTPS e trafegam JSON. A URL base da API é:

https://parceiros.encaminhei.com
Este é o endereço de produção. Para testar sem emitir etiqueta de verdade e sem cobrança, use o ambiente de testes: veja a seção 10. Sandbox.

O fluxo típico de uma integração é:

  1. Autenticar com client_id + client_secret e obter um access token.
  2. Cotar o frete para um trecho/pacote e escolher uma oferta.
  3. Emitir o envio a partir da oferta escolhida e receber a URL da etiqueta.
  4. Acompanhar o status por webhook (recomendado) ou consultando o rastreio.

Autorização nas chamadas

Exceto o endpoint de token, toda chamada exige o header:

Authorization: Bearer <access_token>

2. Autenticação (OAuth2)

A API usa o fluxo OAuth2 client_credentials. Troque suas credenciais por um access token JWT de curta duração (1 hora). Reemita o token quando expirar.

POST /api/v2/oauth/token

Corpo application/x-www-form-urlencoded:

grant_type=client_credentials
client_id=SEU_CLIENT_ID
client_secret=SEU_CLIENT_SECRET
scope=cotacao:read envio:write envio:read rastreio:read   (opcional)

Exemplo:

curl -X POST https://parceiros.encaminhei.com/api/v2/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=SEU_CLIENT_ID" \
  -d "client_secret=SEU_CLIENT_SECRET"

Resposta 200:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "cotacao:read envio:write envio:read rastreio:read"
}

Scopes

O token só pode acessar os recursos cobertos pelos scopes do seu cliente. Se você omitir scope, recebe todos os do cliente; se pedir, deve ser um subconjunto.

ScopePermite
cotacao:readCotar frete
envio:writeEmitir e cancelar envios
envio:readConsultar e listar envios
rastreio:readConsultar o rastreio
webhook:manageGerenciar as inscrições de webhook
Erros de autenticação seguem o formato OAuth2: { "error": "...", "error_description": "..." }.

3. Cotação cotacao:read

Retorna as ofertas de frete disponíveis para o trecho e pacote informados. Cada oferta traz um ofertaId (um GUID): a oferta fica gravada no nosso lado, com preço, prazo, pacote e CEPs, e você a usa na emissão para garantir o preço cotado.

POST /api/v2/cotacoes
{
  "remetente": "01310100",
  "destino": "20040002",
  "peso": 1.5,
  "altura": 10,
  "largura": 15,
  "comprimento": 20,
  "valorSegurado": 80
}

Resposta 200 — lista de ofertas:

[
  {
    "ofertaId": "0b6f1c1e6d0e4f5e9d3b2f7a8c9e1a42",
    "expiraEm": "2026-10-30T18:00:00+00:00",
    "transportadoraId": "3f2a1c8e-....",
    "transportadora": "Correios",
    "servicoCodigo": 1,
    "servico": "SEDEX",
    "preco": 45.88,
    "precoReferencia": 58.90,
    "prazoMinimo": 1,
    "prazoMaximo": 1,
    "aviso": "Acima de R$ 1.500,00, só com nota fiscal",
    "seguroAte": null
  },
  {
    "ofertaId": "7c2d4e9a1b3f4c5d8e6a0f1b2c3d4e5f",
    "expiraEm": "2026-10-30T18:00:00+00:00",
    "transportadoraId": "3f2a1c8e-....",
    "transportadora": "Correios",
    "servicoCodigo": 2,
    "servico": "PAC",
    "preco": 29.53,
    "precoReferencia": 38.40,
    "prazoMinimo": 5,
    "prazoMaximo": 5,
    "aviso": null,
    "seguroAte": null
  }
]
CampoTipoDescrição
ofertaIdstringIdentificador da oferta gravada (price-lock): 32 caracteres hexadecimais, sem hífens. Trate-o como texto opaco e envie-o na emissão exatamente como recebeu. Cada oferta vale para uma única emissão.
expiraEmdata ISO 8601Até quando o ofertaId vale, com o fuso (+00:00, UTC).
transportadoraIduuidIdentificador da transportadora — estável, ao contrário do nome.
transportadorastringNome de exibição (ex.: Correios).
servicoCodigointCódigo da modalidade. Use-o para casar serviços entre cotações, não o nome.
servicostringNome de exibição do serviço (ex.: SEDEX).
precodecimalO que você paga. É este valor que a emissão cobra.
precoReferenciadecimalValor de referência sugerido, baseado na tabela Platinum dos Correios. Depende de acordo comercial — ver a nota abaixo.
prazoMinimointDias úteis, mínimo.
prazoMaximointDias úteis, máximo.
avisostring ou nullAviso sobre a oferta, quando há. Ex.: "Acima de R$ 1.500,00, só com nota fiscal" — com esse valor declarado, este serviço só emite com NF-e (com declaração de conteúdo a emissão é recusada).
seguroAtedecimal ou nullTeto do seguro quando o serviço o limita: com nota fiscal acima do máximo do serviço, o envio sai com seguro até este valor (não pelo valor total). Nulo quando não limita. Quando vier preenchido, a emissão exige "aceiteSeguroLimitado": true.
Sobre o precoReferencia. É um valor de referência sugerido, calculado a partir da tabela Platinum dos Correios — não é uma cobrança, nem um preço que definimos para o seu cliente. O que você cobra de quem compra de você é decisão sua; este campo existe para lhe dar um parâmetro de mercado ao lado do preco, que é o que você paga.

Ele depende de acordo comercial e não está habilitado para todas as contas. Sem esse acordo, precoReferencia vem igual ao preco. O campo está sempre presente na resposta — ele não some quando não há referência ativa, para não quebrar quem já integrou.

Não existe ofertaId do preço de referência, e isso é deliberado: a emissão é sempre pela tabela base, no valor de preco, que vem da oferta gravada. O valor de referência é só informativo e não pode ser usado para emitir.
O ofertaId vale por 60 minutos a partir da cotação, e expiraEm traz o instante exato. Depois disso, a emissão devolve 400 oferta_invalida: basta cotar de novo. Dentro do prazo, o preço cobrado é exatamente o da oferta: a emissão não recota e não aplica tolerância de preço.

4. Emissão de envio envio:write

Emite a etiqueta em uma única chamada, a partir do ofertaId. Toda transportadora ativa para a sua conta pode ser emitida pela API v2, e não só JadLog e Correios. É obrigatório enviar o header Idempotency-Key (um UUID seu por tentativa) — assim, um retry da mesma requisição não duplica a etiqueta nem o débito.

POST /api/v2/envios

Headers:

Authorization: Bearer <access_token>
Content-Type: application/json
Idempotency-Key: 870fb130-3211-42fe-abc4-fb380361918b

O pacote, o preço e o prazo vêm da oferta. Os campos peso, altura, largura, comprimento e valorSegurado não são mais obrigatórios: omita-os. Se você enviar algum, ele precisa ser igual ao cotado (peso com 3 casas decimais, os demais com 2); senão a emissão é recusada com 400 pacote_divergente_da_oferta. O CEP do remetente e do destinatário também precisa ser o cotado (400 cep_divergente_da_oferta).

Corpo:

{
  "ofertaId": "0b6f1c1e6d0e4f5e9d3b2f7a8c9e1a42",
  "clienteReferencia": "PEDIDO-1234",
  "remetente": {
    "nome": "Minha Loja", "cpfCnpj": "11222333000181",
    "telefone": "11999999999", "email": "[email protected]",
    "logradouro": "Av Paulista", "numero": "1000", "complemento": "cj 1",
    "bairro": "Bela Vista", "cidade": "Sao Paulo", "uf": "SP",
    "cep": "01310100", "inscricaoEstadual": "ISENTO"
  },
  "destinatario": {
    "nome": "Cliente", "cpfCnpj": "11144477735",
    "telefone": "21988887777", "email": "[email protected]",
    "logradouro": "Rua do Mercado", "numero": "50", "complemento": "",
    "bairro": "Centro", "cidade": "Rio de Janeiro", "uf": "RJ", "cep": "20040002"
  },
  "declaracaoConteudo": [
    { "item": "Produto X", "quantidade": 1, "valor": 80 }
  ]
}

Resposta 200:

{
  "envioId": 221910605028,
  "status": "emitido",
  "preco": 45.88,
  "etiquetaUrl": "https://www.encaminhei.com/ParceiroImprimirEtiqueta/eyJuIjoyMjE5MTA2MDUwMjgsInQiOiJldHEiLCJlIjoxNzkxMDAwMDAwfQ.f3Xc2_Kq9m1sYd0aVb7NQe8Lp5RtZ6HgWjKcU4nMxYs",
  "rastreioUrl": "https://www.encaminhei.com/ParceiroRastreio/eyJuIjoyMjE5MTA2MDUwMjgsInQiOiJyc3QiLCJlIjoxNzkxMDAwMDAwfQ.Lm4Kd8_Vp2wRt6yUi9OaSf1BnZx3CqEjHgTvMlYkNbA"
}

Status da emissão (síncrono x assíncrono)

O campo status da resposta indica se a etiqueta já está pronta:

statusSignifica
emitidoEtiqueta pronta para impressão imediata (transportadoras síncronas, ex.: Correios, JadLog). A etiquetaUrl já funciona.
emissao_em_andamentoEnvio aceito; a etiqueta está sendo produzida de forma assíncrona (ex.: Loggi). Aguarde alguns instantes e consulte GET /api/v2/envios/{id}, ou acompanhe pelos webhooks de status.
O webhook envio.emitido sinaliza que o envio foi aceito e registrado (dispara em ambos os casos). Para transportadoras assíncronas, use a evolução do status (consulta/webhooks envio.postado, etc.) para saber quando a etiqueta/objeto avançou.

Documento fiscal: Nota Fiscal ou Declaração de Conteúdo

Cada envio leva um documento fiscal — você escolhe qual informar no corpo da emissão:

Para enviar com…Informe
Nota FiscalnotaFiscal (número) e, opcionalmente, chaveAcessoNF (44 dígitos). Não envie declaracaoConteudo.
Declaração de ConteúdodeclaracaoConteudo — lista de itens (item, quantidade, valor). Não envie notaFiscal.

A regra é simples: se houver itens em declaracaoConteudo, o envio é tratado como Declaração de Conteúdo; caso contrário, como Nota Fiscal. Exemplo com NF:

{
  "ofertaId": "...",
  "clienteReferencia": "PEDIDO-1234",
  "notaFiscal": 12345,
  "chaveAcessoNF": "35260612345678000190550010000123451000123456",
  "remetente": { "...": "..." },
  "destinatario": { "...": "..." }
}
Remetente contribuinte de ICMS só envia com Nota Fiscal. A SEFAZ não autoriza a DCe quando o remetente é contribuinte de ICMS. Por isso, a emissão com declaracaoConteudo é recusada com 400 dce_indisponivel_contribuinte quando a inscricaoEstadual do remetente está preenchida e não é ISENTO, ou quando o CNPJ do remetente já foi identificado como contribuinte em uma emissão anterior. Nesse caso, envie o pedido com a NF-e (notaFiscal / chaveAcessoNF). A regra vale igual no sandbox.
DCe (Declaração de Conteúdo Eletrônica): quando o envio usa declaração de conteúdo e a transportadora não é Correios, a resposta inclui um daceUrl — link para baixar o DACE. O documento é gerado sob demanda no primeiro acesso ao link (ou na 1ª impressão da etiqueta). Para Correios, a DCe é tratada via pré-postagem (sem daceUrl próprio); para Nota Fiscal, não há DCe.

Seguro limitado

Se a oferta veio com seguroAte preenchido, envie "aceiteSeguroLimitado": true no corpo da emissão: é a sua ciência (e a do seu cliente) de que o seguro vai até esse valor. Sem o aceite, a emissão é recusada com 400 aceite_seguro_limitado_obrigatorio, sem débito.

Idempotência

Reenviar a mesma Idempotency-Key com o mesmo corpo retorna a resposta original (mesmo envioId), sem emitir de novo. Reusar a chave com um corpo diferente retorna 409.

Erros também ficam gravados sob a chave. Uma recusa como 400 aceite_seguro_limitado_obrigatorio é a resposta daquela Idempotency-Key: reenviar com a mesma chave devolve o mesmo erro, e com o corpo corrigido devolve 409 idempotency_key_conflito. Para reenviar com o aceite, use uma nova Idempotency-Key.

Uso único da oferta

Cada ofertaId serve para um envio. Uma falha na emissão não consome a oferta: você pode tentar de novo com ela, mas com uma nova Idempotency-Key — o erro fica gravado sob a chave usada e seria devolvido de novo (ver Idempotência). Já uma segunda emissão com a mesma oferta (e outra Idempotency-Key) é recusada com 409 oferta_ja_utilizada; cote de novo. Repetir a mesma Idempotency-Key de uma emissão que deu certo continua devolvendo a resposta original.

Se a conexão cair antes da resposta, repita com a mesma chave. Se ela continuar respondendo 409 requisicao_em_andamento, tente com uma nova chave e a mesma oferta: como a oferta é de uso único, isso nunca gera um segundo envio — se a primeira tentativa chegou a emitir, a resposta é 409 oferta_ja_utilizada e o envio aparece em GET /api/v2/envios. Se a oferta já tiver vencido (expiraEm), a resposta é 400 oferta_invalida — mesmo que a primeira tentativa tenha emitido: antes de cotar e emitir de novo, confira em GET /api/v2/envios se o envio (pelo seu clienteReferencia) já existe.

Erros comuns

HTTPcodigoSignificado
402credito_insuficienteSem limite/saldo para o débito
400dce_indisponivel_contribuinteO remetente é contribuinte de ICMS e não pode usar a declaração de conteúdo. Reenvie com a nota fiscal (NF-e) e uma nova Idempotency-Key
400documento_fiscal_obrigatorioFaltou a chave/número da nota fiscal ou a declaração de conteúdo (ou vieram os dois, nos Correios). Informe um deles e reenvie com uma nova Idempotency-Key
409oferta_ja_utilizadaA oferta já virou um envio (uso único). Cote de novo
400pacote_divergente_da_ofertaPeso, dimensões ou valor segurado enviados diferem do cotado. Omita esses campos ou cote de novo
400cep_divergente_da_ofertaO CEP de origem ou de destino difere do cotado. Cote de novo
400exigencia_da_transportadoraO envio não atende uma exigência da transportadora (telefone, e-mail, NF-e ou valor declarado). A mensagem diz qual
409idempotency_key_conflitoIdempotency-Key reusada com corpo diferente
400oferta_invalidaofertaId inexistente, expirado, de outro ambiente ou que não pode ser usado nesta emissão. Cote de novo
400aceite_seguro_limitado_obrigatorioA oferta limita o seguro (seguroAte) e o corpo veio sem "aceiteSeguroLimitado": true. Reenvie com o aceite e uma nova Idempotency-Key

5. Consulta e listagem envio:read

Detalhe de um envio

GET /api/v2/envios/{id}
{
  "envioId": 221910605028,
  "status": "EtiquetaLiberada",
  "codigoRastreio": "AD611719409BR",
  "transportadoraId": "....",
  "servicoCodigo": 1,
  "servico": "SEDEX",
  "valor": 45.88,
  "clienteReferencia": "PEDIDO-1234",
  "dataCriacao": "2026-06-28T22:10:00",
  "etiquetaUrl": "https://www.encaminhei.com/ParceiroImprimirEtiqueta/eyJuIjoyMjE5MTA2MDUwMjgsInQiOiJldHEiLCJlIjoxNzkxMDAwMDAwfQ.f3Xc2_Kq9m1sYd0aVb7NQe8Lp5RtZ6HgWjKcU4nMxYs",
  "rastreioUrl": "https://www.encaminhei.com/ParceiroRastreio/eyJuIjoyMjE5MTA2MDUwMjgsInQiOiJyc3QiLCJlIjoxNzkxMDAwMDAwfQ.Lm4Kd8_Vp2wRt6yUi9OaSf1BnZx3CqEjHgTvMlYkNbA",
  "dceStatus": "Autorizada",
  "daceUrl": "https://www.encaminhei.com/ParceiroDace/eyJuIjoyMjE5MTA2MDUwMjgsInQiOiJkY2UiLCJlIjoxNzkxMDAwMDAwfQ.Qw7Ye1_Rt4uIo2pAs5DfGh8JkLz3XcVbNm6TyUiOpQr"
}

Os campos dceStatus e daceUrl aparecem apenas para envios com declaração de conteúdo em transportadora não-Correios (DCe SEFAZ-direta). dceStatus pode ser Pendente, Autorizada, Rejeitada, ContingenciaOffline etc. — fica Pendente/ausente até a DCe ser emitida (no 1º acesso ao DACE ou à etiqueta).

Listagem paginada

GET /api/v2/envios?limit=20&cursor=<proximoCursor>

Paginação por cursor (mais recentes primeiro). Use o proximoCursor retornado para buscar a próxima página; quando vier null, não há mais.

{
  "itens": [ { "envioId": 221910605028, "status": "...", ... } ],
  "proximoCursor": 221910605008
}
limit aceita de 1 a 100 (padrão 20). Um envio de outro parceiro retorna 404 — você só enxerga os seus.

6. Rastreio rastreio:read

GET /api/v2/envios/{id}/rastreio

Lista os eventos de rastreio do envio (vazio enquanto não houver movimentação da transportadora).

[
  { "codigo": 3, "status": "Postado", "descricao": "Objeto postado",
    "local": "Sao Paulo/SP", "data": "2026-06-28T09:00:00" },
  { "codigo": 4, "status": "Entregue", "descricao": "Objeto entregue ao destinatario",
    "local": "Rio de Janeiro/RJ", "data": "2026-06-29T14:20:00" }
]

7. Cancelamento envio:write

POST /api/v2/envios/{id}/cancelamento

Cancela um envio ainda não postado. Resposta 200:

{ "status": "cancelado" }

Se o envio já foi postado/entregue ou já está cancelado, retorna 400 com codigo = cancelamento_invalido e a mensagem do motivo.

8. Webhooks (notificações de status) webhook:manage

Em vez de ficar consultando o rastreio, registre uma URL e a Encaminhei envia um POST assinado a cada mudança de status do envio.

Registrar / atualizar a inscrição

POST /api/v2/webhooks
{
  "url": "https://seu-sistema.com/webhooks/encaminhei",
  "eventos": ["envio.emitido", "envio.postado", "envio.entregue", "envio.cancelado"]
}

Resposta 201 — o secret é mostrado uma única vez; guarde-o para verificar a assinatura:

{
  "id": "2c41c649-c53c-433d-b0a7-f6790290abbb",
  "url": "https://seu-sistema.com/webhooks/encaminhei",
  "eventos": ["envio.emitido","envio.postado","envio.entregue","envio.cancelado"],
  "secret": "whsec_0c9900fd820e76309ebc39dbb80b78565e4c7a5968b8af5f83e4a753fd965ef1",
  "ativo": true
}
Há uma inscrição por parceiro. Chamar POST de novo substitui a inscrição atual (nova URL/eventos e um novo secret) — não cria uma segunda.

Consultar a inscrição

GET /api/v2/webhooks

Retorna a inscrição atual (sem o segredo). 404 se não houver inscrição ativa.

{
  "id": "2c41c649-c53c-433d-b0a7-f6790290abbb",
  "url": "https://seu-sistema.com/webhooks/encaminhei",
  "eventos": ["envio.emitido","envio.postado","envio.entregue","envio.cancelado"],
  "ativo": true,
  "criadoEm": "2026-06-28T20:00:00",
  "atualizadoEm": null
}

Desativar a inscrição

DELETE /api/v2/webhooks

Desativa a inscrição (para de receber eventos). Responde 204; 404 se não houver inscrição ativa. Para voltar a receber, faça um novo POST.

A URL deve ser HTTPS pública. URLs locais/privadas (localhost, IPs internos) são rejeitadas.

Eventos disponíveis

EventoQuandoQuem emite em produção
envio.emitidoEtiqueta emitidaEmissão pela API v2
envio.saiu_para_coletaColetador a caminho do remetenteAinda não emitido em produção (depende da coleta pela API, prevista para o futuro)
envio.coletadoColetado pela transportadoraTransição de status para Coletado
envio.postadoObjeto postadoTransição de status para Postado
envio.em_transitoObjeto em trânsitoAinda não emitido em produção
envio.tentativa_entregaTentativa de entrega sem sucesso (pode se repetir; veja data.detalhe)Ainda não emitido em produção
envio.entregueEntregue ao destinatárioTransição de status para Entregue
envio.devolvidoDevolvido ao remetenteTransição de status para Devolvido
envio.canceladoEnvio canceladoCancelamento do envio
envio.sinistroExtravio / avaria / rouboTransição de status para Sinistro
Você já pode assinar os 10 eventos. Os marcados como "ainda não emitido em produção" fazem parte do contrato, mas só chegam quando a transportadora ou a coleta passarem a fornecer essa informação; no ambiente de testes (sandbox) o simulador os emite.

Corpo entregue

{
  "event": "envio.entregue",
  "event_id": "96f49e90-4965-4b1c-9989-9a5fccb68a1b",
  "webhook_version": 1,
  "occurred_at": "2026-06-29T14:20:05.123Z",
  "data": {
    "envio_id": 221910605028,
    "status": "Entregue",
    "codigo_rastreio": "AD611719409BR",
    "transportadora_id": "....",
    "cliente_referencia": "PEDIDO-1234",
    "valor": 45.88,
    "detalhe": null
  }
}

data.detalhe é um texto livre opcional (ex.: "destinatário ausente" em envio.tentativa_entrega); vem null quando não há detalhe. É um campo aditivo: webhook_version continua 1.

Headers de cada entrega

HeaderDescrição
X-Encaminhei-Signaturesha256=<hmac hex> — assinatura do corpo
X-Encaminhei-Event-IdUUID estável do evento (use para deduplicar)
X-Encaminhei-EventNome do evento
X-Encaminhei-Webhook-VersionVersão do contrato
X-Encaminhei-Ambientesandbox ou producao — ambiente de origem do evento

Verificação da assinatura

Calcule HMAC-SHA256 do corpo bruto usando o seu secret e compare (em tempo constante) com o valor após sha256= no header. Rejeite a requisição se não bater.

Node.js

const crypto = require("crypto");

function verificar(rawBody, header, secret) {
  const esperado = "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
  return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(esperado));
}

C#

using System.Security.Cryptography;

bool Verificar(string corpoBruto, string header, string secret)
{
    using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
    var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(corpoBruto));
    var esperado = "sha256=" + Convert.ToHexString(hash).ToLowerInvariant();
    return CryptographicOperations.FixedTimeEquals(
        Encoding.UTF8.GetBytes(esperado), Encoding.UTF8.GetBytes(header));
}

Confirmação, retry e idempotência

  • Responda 2xx rapidamente (timeout de 10s) para confirmar o recebimento.
  • Em falha (não-2xx ou timeout), reenviamos com backoff: 1m, 5m, 15m, 1h, 6h, 24h. Após esgotar, a entrega é marcada como falha.
  • Erros permanentes (ex.: 404/410) não são retentados.
  • O mesmo evento pode ser reentregue — deduplique pelo X-Encaminhei-Event-Id.

9. Tratamento de erros

Fora o endpoint de token (formato OAuth2), todos os erros usam um envelope consistente:

{
  "codigo": "url_invalida",
  "mensagem": "A URL do webhook deve usar HTTPS.",
  "detalhes": []
}
HTTPSignificado
400Requisição inválida (ver codigo/mensagem)
401Token ausente, inválido ou expirado
402Crédito insuficiente
403Token sem o scope necessário
404Recurso não encontrado (ou não pertence a você)
409Conflito (idempotência / oferta já utilizada)
500Erro interno

API v1 (obsoleta)

A API v1 está obsoleta e congelada: não recebe novidades nem correções de contrato. Use a v2 descrita nesta página, que emite por qualquer transportadora ativa a partir da oferta gravada.

10. Sandbox (ambiente de testes)

O sandbox é uma cópia do contrato da API para você integrar e testar sem emitir etiqueta real e sem ser cobrado. Tudo nele é fictício: nenhuma transportadora é acionada e nada vai para a sua fatura.

https://sandbox.encaminhei.com

As rotas são as mesmas de produção (/v2/..., por exemplo /api/v2/cotacoes), com o mesmo formato de resposta, os mesmos códigos de erro e o mesmo webhook. Para ir a produção, troque só o host e a credencial.

Como obter a credencial

Qualquer conta de pessoa jurídica pode gerar a credencial de sandbox, mesmo pré-paga ou sem verificação. Para usar a API em produção, a conta precisa estar verificada e ser pós-paga; fale com o atendimento da Encaminhei. Para gerar a credencial de sandbox: no painel, abra Integração via API, aba Sandbox, e crie a credencial. O client_secret aparece uma única vez. A credencial de sandbox só funciona no host de sandbox, e a de produção só funciona no de produção; usar uma no host da outra retorna 401. Autentique-se em https://sandbox.encaminhei.com/api/v2/oauth/token, como na seção 2.

O que é fictício

  • Preços e prazos não são reais. As transportadoras são simuladas, com valores fixos e redondos. Não use o sandbox para calibrar a sua margem.
  • Saldo fictício. A sua conta de sandbox começa com R$ 10.000,00. Cada emissão debita desse saldo e o cancelamento estorna. Quando o saldo acaba, a emissão retorna 402 com credito_insuficiente, igual a produção. Na aba Sandbox do painel, Restaurar saldo devolve o valor inicial.
  • Etiqueta e DACE de exemplo. Os PDFs de etiqueta e DACE são gerados na hora e levam a marca SANDBOX — SEM VALOR em todas as páginas. Não servem para postar nada.
  • Números de envio a partir de 900000000000000, e códigos de rastreio no formato SBX seguido de 11 dígitos. Assim um envio de teste nunca se confunde com um real.

Provocando falhas

Para testar como o seu sistema reage a erros, use estes valores no CEP de destino da cotação (com ou sem hífen). Eles só valem no sandbox; em produção o mesmo CEP é tratado normalmente.

ValorResultado
CEP de destino 00000001Nenhuma transportadora atende o trecho: a cotação retorna a lista de ofertas vazia.
CEP de destino 00000002A cotação é normal, mas o ofertaId já nasce expirado; a emissão com ele retorna 400 oferta_invalida (ofertaId inválido ou expirado).
Saldo fictício esgotadoA emissão retorna 402 credito_insuficiente. Depois de gastar o saldo com emissões de teste, restaure-o no painel.

Simulador de eventos

Em produção o status do envio muda quando a transportadora informa. No sandbox ninguém informa nada, então quem avança o envio é você, no simulador da aba Sandbox do painel:

  • Avança o status, um evento por vez, seguindo a ordem permitida para o envio (por exemplo, não é possível entregar um envio cancelado). Há também a opção de rodar até o fim.
  • Cada evento dispara um webhook assinado exatamente como o de produção (mesmo corpo, mesmos headers, mesma verificação de assinatura da seção 8) para a URL do webhook de sandbox que você cadastrou. O webhook de sandbox é separado do de produção, com URL e secret próprios.
  • Mostra o log das entregas de webhook de cada envio, com o resultado de cada tentativa, e permite reenviar uma entrega.
  • Copia o curl do webhook, já com a assinatura calculada, para você repetir a chamada contra o seu sistema, e o curl da consulta do envio.
  • Voltar para aqui: rebobina o mesmo envio até um evento anterior da linha do tempo, para você repetir um cenário sem emitir outro. Voltar não dispara webhook; ao avançar de novo, os eventos novos disparam.

O cancelamento pelo simulador segue a mesma regra de status e o mesmo estorno do cancelamento pela API.

Diferenças do rastreio

O GET /api/v2/envios/{id}/rastreio do sandbox tem o mesmo formato de produção, com duas diferenças:

  • Logo após a emissão, a lista já traz um item envio.emitido. Em produção ela fica vazia até a transportadora informar a primeira movimentação.
  • O campo status traz o nome do evento do simulador (por exemplo, envio.postado). Em produção ele traz o status informado pela transportadora. Para decidir o estado do envio, use o codigo, que segue a mesma regra nos dois ambientes.

Eventos de webhook novos

Três eventos do catálogo da seção 8 só chegam hoje pelo simulador do sandbox, porque produção ainda não os emite: envio.saiu_para_coleta, envio.em_transito e envio.tentativa_entrega. Assine-os no webhook de sandbox para já deixar o seu sistema pronto para eles.

Retenção

Os envios, eventos e entregas de webhook de sandbox são apagados 90 dias depois de criados. A credencial e o saldo fictício não são apagados.

Dúvidas de integração? Fale com o time da Encaminhei.