API de Frete: Como Calcular Frete e Prazo dos Correios

Desenvolvedora integra uma api de frete ao sistema da loja, com caixas de encomenda e fita métrica sobre a mesa

Uma API de frete recebe os dados da encomenda e devolve quanto custa enviar e em quantos dias ela chega. Parece simples até o carrinho travar numa sexta à noite porque os Correios pararam de responder. Abaixo estão os campos do cálculo, o acesso atual à API oficial dos Correios, as alternativas e um jeito de manter o checkout de pé quando a cotação falha.

O frete decide muita compra. Se o valor aparece alto demais, o cliente abandona o carrinho. Se aparece baixo demais, a loja paga a diferença do próprio bolso. Por isso, a integração precisa receber dados de entrada corretos. E, como mostra o exemplo da sexta à noite, também precisa aguentar falhas na hora da consulta.

Escolher uma API de frete é só metade do serviço. A outra metade é mandar os dados certos e tratar a falha, e é disso que os exemplos em Python e JavaScript ao longo do texto cuidam.

O que entra no cálculo de uma API de frete

Toda cotação parte das mesmas informações; muda só o nome do campo entre fornecedores. Os Correios, por exemplo, pedem o peso em gramas e as medidas em centímetros. Errar a unidade é o bug mais comum de quem está começando.

CEP de origem e CEP de destino

O par de CEPs define a rota e, com ela, a faixa de preço e o prazo. O CEP de origem costuma ser fixo (o endereço do seu centro de distribuição). Já o de destino vem do cliente, digitado no carrinho. Antes de cotar, limpe e valide o formato: tire o hífen e os espaços que o cliente digitou e confira se sobraram oito dígitos. Se você também precisa preencher rua e bairro a partir do CEP, o guia de API de consulta de CEP mostra essa etapa, que é outra chamada e outro problema.

Peso real e peso cúbico

O peso real é o que a balança marca, com embalagem. O peso cúbico, também chamado de peso cubado, representa o espaço que o volume ocupa no transporte. Uma caixa grande com um travesseiro dentro pesa pouco, mas ocupa o lugar de uma carga pesada. Em regra, a transportadora cobra pelo maior dos dois.

A fórmula usada pelos Correios para encomendas nacionais é:

peso cúbico (kg) = comprimento (cm) × largura (cm) × altura (cm) ÷ 6.000

O 6.000 é o fator de cubagem, o mesmo padrão adotado no transporte aéreo. Uma caixa de 40 × 30 × 30 cm tem 36.000 cm³. Dividido por 6.000, esse volume dá 6 kg de peso cúbico, mesmo que o conteúdo pese 1,5 kg.

Tem um porém. Nas regras comerciais dos Correios, o peso cúbico só passa a valer quando ele próprio passa de um piso. Num termo de condições dos Correios para SEDEX e PAC, esse piso é de 5 kg; confira o valor vigente no seu contrato. Abaixo dele, cobra-se o peso real. Como a regra pode mudar, deixe o piso numa constante configurável. Quando você manda o tipo de objeto e as três medidas para a API de preço, ela aplica a regra vigente e devolve o peso efetivamente cobrado.

import math

FATOR_CUBAGEM = 6000  # cm³ por kg, padrão dos Correios em encomendas nacionais
PISO_CUBICO_KG = 5  # confira o valor vigente no seu contrato

def peso_cubico_kg(comprimento_cm, largura_cm, altura_cm):
    return (comprimento_cm * largura_cm * altura_cm) / FATOR_CUBAGEM

def peso_para_cotacao_g(peso_real_kg, comprimento_cm, largura_cm, altura_cm):
    """Estimativa local: o peso cúbico só conta acima do piso.
    O valor oficial cobrado vem da própria API de preço."""
    cubico = peso_cubico_kg(comprimento_cm, largura_cm, altura_cm)
    maior = max(peso_real_kg, cubico) if cubico > PISO_CUBICO_KG else peso_real_kg
    return math.ceil(maior * 1000)

print(peso_cubico_kg(40, 30, 30))            # 6.0
print(peso_para_cotacao_g(1.5, 40, 30, 30))  # 6000
print(peso_para_cotacao_g(1.5, 30, 30, 30))  # 1500 (cúbico de 4,5 kg, abaixo do piso)

Use essa conta para estimar custo, escolher embalagem e montar a tabela de reserva (o fallback, que aparece mais adiante). A cotação que vai para o cliente, porém, deve vir da API.

Operador mede caixa de papelão sobre balança para informar peso e dimensões à api de frete

Formato, dimensões e serviço

O formato do objeto muda quais medidas são obrigatórias. Envelope, pacote e rolo têm regras próprias. No envelope vão comprimento e largura; no pacote, comprimento, largura e altura; no rolo, comprimento e diâmetro. No PAC, o envelope é sempre medido como pacote. Os Correios também impõem limites: para pacotes, nenhum lado pode passar de 100 cm, e a soma das três dimensões fica limitada a 200 cm. PAC e SEDEX aceitam até 30 kg no balcão; com contrato, o limite pode chegar a 50 kg, sob consulta, conforme a página oficial de encomendas nacionais.

O serviço escolhido (PAC, SEDEX, SEDEX 10, SEDEX 12) define preço e prazo. Em geral, o PAC sai mais barato e demora mais. O SEDEX custa mais e chega antes. Na loja, o comum é mostrar os dois lado a lado.

Valor declarado, aviso de recebimento e mão própria

Esses serviços adicionais entram no preço final:

  • Valor declarado (VD): funciona como seguro. Em caso de extravio, a indenização considera o valor informado.
  • Aviso de recebimento (AR): o remetente recebe comprovante de quem assinou a entrega.
  • Mão própria (MP): a encomenda só é entregue ao destinatário indicado.

Cada adicional custa dinheiro, então ofereça só o que faz sentido. Eletrônico caro pede valor declarado. Documento contratual pede AR.

A tabela usa os nomes de campo da API Preço dos Correios, que a próxima seção apresenta.

Campo de entrada Na API de preço dos Correios Unidade ou formato Obrigatório?
CEP de origem cepOrigem 8 dígitos Sim
CEP de destino cepDestino 8 dígitos Sim
Serviço coProduto código do serviço no contrato Sim
Peso psObjeto gramas Sim
Formato tpObjeto 1 envelope, 2 pacote, 3 rolo Sim (define quais medidas são exigidas)
Comprimento, largura, altura comprimento, largura, altura centímetros Sim, para pacote
Diâmetro diametro centímetros Sim, para rolo
Valor declarado vlDeclarado reais Só com o adicional VD
Adicionais (AR, MP, VD) servicosAdicionais lista de códigos Não

Na prática: cadastre peso e medidas da embalagem pronta, não do produto solto. É a caixa que viaja, e é ela que a transportadora mede no centro de triagem.

API dos Correios: como calcular preço e prazo hoje

Durante anos, quem queria calcular frete dos Correios por API usava o webservice CalcPrecoPrazo, aberto e sem autenticação. Esse modelo acabou. Os Correios migraram para um conjunto de APIs REST publicadas no portal Correios Web Services (CWS), e as consultas abertas de preço e prazo deixaram de ser o caminho oficial. Hoje, só quem tem contrato ativo consegue usar a API dos Correios para cotação.

O que você precisa ter antes da primeira chamada

O caminho oficial exige quatro coisas:

  1. Contrato com os Correios na modalidade a faturar, em que a loja posta durante o mês e paga tudo depois, numa fatura.
  2. Cartão de postagem vinculado a esse contrato. É o número que identifica a sua empresa em cada envio.
  3. Serviços 38202 (API Preços) e 38210 (API Prazos) vinculados ao contrato e ao cartão de postagem. Esses números liberam o acesso às APIs e não são os códigos de PAC ou SEDEX que vão na cotação.
  4. Senha de API cadastrada no portal CWS, usada para gerar o token.

Com isso em mãos, o sistema chama a API Token, recebe um token com prazo de validade e o envia no cabeçalho Authorization: Bearer nas chamadas de preço e prazo. Guarde o token no cache da aplicação, com a hora em que expira, e gere outro só perto do vencimento. Um token novo a cada cotação é desperdício e aumenta a latência.

Diagrama do fluxo de acesso à API oficial dos Correios: contrato, cartão de postagem, senha no CWS, token, API Preço e API Prazo

A API Preço

Segundo o manual da API Preço, há uma rota para consultar um serviço por vez e outra para consulta em lote, que manda até 100 cotações numa única requisição. A resposta traz, entre outros campos, o preço final (pcFinal), o peso cobrado (psCobrado) e o indicador inPesoCubico, que diz se o peso cúbico entrou na conta.

Os códigos de serviço dependem do contrato. O manual usa 03298 para PAC e 03220 para SEDEX, mas confira os seus no CWS antes de fixar qualquer código.

// Node 18+ (fetch nativo). Consulta individual de preço na API dos Correios.
// Confira rota e parâmetros no manual oficial antes de usar em produção.
// Informe nuContrato e nuDR para receber o preço do seu contrato.
const BASE = "https://api.correios.com.br/preco/v1";

async function cotarPreco({ token, coProduto, cepOrigem, cepDestino, pesoGramas, c, l, a }) {
  const params = new URLSearchParams({
    cepOrigem,
    cepDestino,
    psObjeto: String(pesoGramas),
    tpObjeto: "2", // pacote
    comprimento: String(c),
    largura: String(l),
    altura: String(a),
  });

  const resp = await fetch(`${BASE}/nacional/${coProduto}?${params}`, {
    headers: { Authorization: `Bearer ${token}` },
    signal: AbortSignal.timeout(3000),
  });

  if (!resp.ok) {
    const erro = new Error(`Correios respondeu ${resp.status}`);
    erro.status = resp.status;
    throw erro;
  }
  const dados = await resp.json();
  return {
    // pcFinal vem como texto com vírgula decimal, ex.: "11,64"
    preco: Number(String(dados.pcFinal).replace(".", "").replace(",", ".")),
    pesoCobrado: Number(dados.psCobrado),
  };
}

Atenção: a consulta em lote (POST) das APIs Preço e Prazo pode responder 206, que significa resposta parcial: parte dos serviços consultados voltou e parte não. Trate esse status como sucesso incompleto e não como erro total, senão você descarta cotações válidas.

A API Prazo

O prazo sai de outra API, com outro serviço no contrato. O manual da API Prazo descreve a consulta por serviço, com CEPs de origem e destino. A resposta devolve o prazo em dias (prazoEntrega) e a data máxima de entrega (dataMaxima). Ela também indica se há entrega domiciliar e entrega aos sábados. Para montar a frase “chega até o dia 18”, use a data máxima em vez de somar dias no calendário por conta própria: ela já vem calculada pelos Correios, com fins de semana e feriados na conta.

As duas APIs têm limite de 150 requisições por segundo por usuário e IP, conforme os manuais. Para a maioria das lojas, é folga de sobra, mas uma rotina que recalcula o frete de milhares de produtos de uma vez pode bater no teto. Nesse caso, a rota de lote da API Preço, com até 100 itens por chamada, reduz o número de requisições.

Alternativas à API dos Correios para o cálculo de frete

Nem toda loja tem contrato com os Correios ou quer depender de uma só transportadora. Há pelo menos três caminhos além da integração direta.

Agregadores de frete

Os agregadores reúnem várias transportadoras numa única integração: você manda os dados uma vez e recebe cotações dos Correios e de transportadoras privadas. Muitos também geram etiqueta. O custo é depender de mais um intermediário, com regras e disponibilidade próprias.

API de frete do Hub do Desenvolvedor

A API de frete do Hub do Desenvolvedor recebe os dados do endereço e da encomenda (peso e dimensões) e devolve o valor do frete dos Correios em JSON ou XML. Confira na documentação do painel quais campos de prazo a resposta traz. A vantagem para quem desenvolve é juntar essa consulta a outras que o sistema já faz, como CEP, CNPJ e CPF, na mesma conta e no mesmo plano. Para quem precisa de endereço completo pelo CEP, a página de rastreio e dados dos Correios cobre essa parte.

A chamada abaixo é ilustrativa. Rota, nomes de parâmetros e formato de resposta estão na documentação do painel do Hub, que é a referência oficial.

import requests

# Exemplo ilustrativo: substitua URL_DA_API e SEU_TOKEN pelos dados do painel do Hub.
URL_DA_API = "URL_DA_API"
SEU_TOKEN = "SEU_TOKEN"

def cotar_frete(cep_origem, cep_destino, peso_kg, comprimento, largura, altura):
    params = {
        "token": SEU_TOKEN,
        "cep_origem": cep_origem,
        "cep_destino": cep_destino,
        "peso": peso_kg,  # confira na documentação do Hub se o peso vai em kg ou em gramas
        "comprimento": comprimento,
        "largura": largura,
        "altura": altura,
    }
    resp = requests.get(URL_DA_API, params=params, timeout=3)
    resp.raise_for_status()
    return resp.json()

Se você quer ver essa cotação funcionando no seu projeto, crie uma conta no Hub do Desenvolvedor e teste a API de cálculo de frete durante o período gratuito, com os CEPs e as caixas reais da sua operação.

Tabela própria

Algumas lojas calculam o frete com uma tabela interna, por faixa de CEP e de peso. Funciona para frete fixo por região ou frete grátis acima de um valor. O problema é a manutenção: quando a tarifa muda, a tabela fica defasada e a margem some sem que ninguém perceba. Por isso, ela serve melhor como fallback.

Opção Precisa de contrato com os Correios? Transportadoras Esforço de integração Melhor uso
API oficial dos Correios (CWS) Sim, com cartão de postagem Só Correios Alto: token, dois serviços, códigos por contrato Operação com volume e contrato próprio
Agregador de frete Não, em geral Correios e privadas Médio Lojas que querem comparar transportadoras
API do Hub do Desenvolvedor Consulte as condições no painel do Hub Correios Baixo: mesmo plano das consultas de CEP, CNPJ e CPF Sistemas que já usam CEP, CNPJ ou CPF do Hub
Tabela própria Não Qualquer uma, por estimativa Baixo para criar, alto para manter Fallback e regras promocionais

Na prática, muitas equipes combinam as opções: uma API de frete é a fonte principal, e a tabela entra só quando ela falha. O artigo sobre APIs para e-commerce mostra como o frete convive com pagamento, estoque e antifraude na mesma loja.

API de frete no checkout: cache, timeout, fallback e carrinho

A cotação de frete fica no meio do caminho entre o carrinho e o pagamento: sem ela, a venda não fecha. Se ela demora oito segundos, o cliente desiste. Se ela quebra, a página de pagamento quebra junto. Uma API de frete bem integrada precisa de três proteções: cache, timeout curto e plano B.

Cliente vê opções de entrega no celular durante o checkout, calculadas por uma api de frete

Cache de cotação

O cliente digita o CEP no produto, no carrinho e no checkout: sem cache, três chamadas iguais; com cache, uma.

A chave do cache precisa conter tudo que muda o preço: CEP de origem, CEP de destino, serviço, peso, as três medidas e os adicionais. Se faltar um campo, você devolve o frete de um carrinho para um carrinho diferente. Validade de algumas horas costuma bastar, porque tarifa não muda de minuto em minuto. O post sobre o que é cache explica TTL (time to live, o tempo de vida de cada item guardado) e invalidação com mais calma.

Uma otimização comum é guardar na chave só os cinco primeiros dígitos do CEP de destino, para reaproveitar a cotação entre vizinhos. Evite isso no frete. Dois CEPs do mesmo prefixo podem cair em faixas diferentes de preço e prazo, sobretudo perto da divisa entre municípios.

Timeout e circuit breaker

Toda chamada externa precisa de timeout; no checkout, de 2 a 4 segundos. Passou disso, é melhor mostrar uma estimativa do que um spinner.

O timeout resolve a chamada individual. O circuit breaker resolve a queda prolongada. Ele funciona como o disjuntor de casa: depois de algumas falhas seguidas, “abre o circuito” e para de chamar o fornecedor por um tempo. Na versão completa, passado o intervalo, ele deixa uma chamada de teste passar e, se ela funcionar, volta ao normal. O guia de circuit breaker detalha os estados fechado, aberto e meio-aberto.

Fallback de tabela

Quando o circuito abre ou o timeout estoura, entra a tabela interna. Ela devolve um frete estimado por faixa de CEP e de peso, com margem de segurança. O cliente fecha a compra. Erro de dado do cliente, como CEP inexistente, não deve abrir o circuito: devolva a mensagem de erro em vez do frete estimado.

Fluxograma da cotação no checkout com cache, circuit breaker, timeout e tabela de fallback

// Cache em memória + timeout + circuit breaker simples (sem estado meio-aberto) + fallback de tabela.
const cache = new Map();
const TTL_MS = 3 * 60 * 60 * 1000; // 3 horas
const circuito = { falhas: 0, abertoAte: 0 };
const LIMITE_FALHAS = 5;
const JANELA_ABERTO_MS = 60 * 1000;

function chaveCotacao(p) {
  return [p.cepOrigem, p.cepDestino, p.servico, p.pesoGramas, p.c, p.l, p.a,
    (p.adicionais || []).join(","), p.vlDeclarado || ""].join("|");
}

function freteTabela(p) {
  // Exemplo só por faixa de peso; em produção, combine faixa de CEP e de peso com base no seu histórico real.
  const kg = p.pesoGramas / 1000;
  const base = kg <= 1 ? 25 : kg <= 5 ? 40 : 70;
  return { preco: base, estimado: true };
}

async function obterFrete(p, cotar) {
  const chave = chaveCotacao(p);
  const guardado = cache.get(chave);
  if (guardado && guardado.expira > Date.now()) return guardado.valor;

  if (Date.now() < circuito.abertoAte) return freteTabela(p);

  try {
    const valor = await cotar(p); // a função de cotação já aplica timeout
    circuito.falhas = 0;
    cache.set(chave, { valor, expira: Date.now() + TTL_MS });
    return valor;
  } catch (erro) {
    // Erro de dado do cliente (CEP inexistente, por exemplo) não é falha do fornecedor.
    if (erro.status >= 400 && erro.status < 500) throw erro;
    circuito.falhas += 1;
    if (circuito.falhas >= LIMITE_FALHAS) {
      circuito.abertoAte = Date.now() + JANELA_ABERTO_MS;
      circuito.falhas = 0;
    }
    return freteTabela(p);
  }
}

O exemplo simplifica o estado meio-aberto: depois da janela, todas as chamadas voltam a passar. Em produção, use uma biblioteca que libere uma única chamada de teste. Troque também o Map, que vive num só processo, por Redis ou outro cache compartilhado entre os servidores. E registre em log cada entrada do fallback: é esse log que mostra a queda do fornecedor antes que o cliente reclame.

Dica de operação: marque no pedido quando o frete veio da tabela. Quando a equipe cruzar o frete cobrado do cliente com o que os Correios faturaram, esses pedidos são os primeiros a conferir, porque podem ter saído com valor abaixo do custo real.

Frete no carrinho do e-commerce

Mostre o campo de CEP já na página do produto, porque muita gente decide a compra pelo frete. Faça a cotação no servidor, nunca no navegador, para não expor o token nem permitir que alguém manipule o valor. E recalcule quando o carrinho mudar: um item a mais pode trocar a caixa e alterar o peso cúbico e o preço.

Com mais de um centro de distribuição, a origem também vira variável, e a regra de qual estoque atende cada pedido pesa tanto quanto a cotação. O texto sobre API inteligente para logística trata desse roteamento.

Se a sua equipe quer tirar essa camada do próprio código, ligue a consulta de frete do Hub ao seu servidor, com o cache e o fallback acima, e teste com uma conta antes de decidir.

Perguntas frequentes sobre API de frete

O CalcPrecoPrazo dos Correios ainda funciona?

Não. O antigo webservice aberto de preço e prazo deixou de ser o caminho oficial e não responde de forma confiável. As consultas passaram para as APIs REST do portal CWS, que exigem contrato, cartão de postagem e token. Sistemas que ainda chamam o endereço antigo precisam migrar.

Preciso de contrato para usar a API oficial dos Correios?

Sim. A API Preço e a API Prazo pedem contrato ativo, cartão de postagem e os serviços 38202 e 38210 vinculados. Sem contrato próprio, a saída é usar um agregador ou uma API de frete de terceiros, conferindo as condições de cada fornecedor.

Como calcular o peso cúbico para os Correios?

Multiplique comprimento, largura e altura em centímetros e divida por 6.000. O resultado sai em quilos. A cobrança usa o maior valor entre peso real e peso cúbico, respeitando o piso a partir do qual o peso cúbico passa a contar.

Qual a diferença entre PAC e SEDEX na cotação?

O PAC costuma ser mais barato e mais lento. O SEDEX custa mais e entrega antes. Na API, cada um tem seu código de serviço, e a loja consulta os dois para mostrar as opções ao cliente.

Posso guardar em cache o valor do frete?

Pode e deve, desde que a chave inclua todos os campos que afetam o preço: CEPs, serviço, peso, dimensões e adicionais. Uma validade de algumas horas equilibra economia de chamadas e fidelidade à tarifa vigente.

O que fazer quando a API de frete sai do ar no checkout?

Use timeout curto, circuit breaker e uma tabela de fallback por faixa de CEP e peso. Assim, o cliente recebe um frete estimado e conclui a compra, e a equipe revisa depois os pedidos marcados como estimados.

Resumo para levar ao código

Integrar bem o frete dá mais trabalho do que parece: dados de entrada certos, contrato e token no acesso oficial e um checkout que sobrevive às quedas do fornecedor. Uma API de frete confiável, com cache e fallback em volta, resolve a maior parte disso. Se você quer frete no mesmo plano das suas consultas de CEP e CNPJ, teste a API de frete do Hub do Desenvolvedor e compare as cotações com o que a sua operação paga hoje.


Compartilhe nas mídias: