Calcular preços de entrega
Este guia é para um integrador — ou um agente de IA operando via o servidor MCP — que precisa
saber a taxa de entrega de um endereço antes de criar um pedido DELIVERY.
O fluxo em resumo
Por quê
POST /v1/orders armazena delivery_price literalmente: qualquer valor que você envie em um pedido
DELIVERY é o valor cobrado, sem recálculo no lado do servidor. O merchant
configura como a entrega é precificada a partir do painel OlaClick, em Settings → Delivery →
"Configure delivery prices and coverage". A API expõe essa configuração e um endpoint de
cotação para que você resolva o número correto — nada na API cria ou edita a
configuração de preços em si.
As seis opções do painel e o que elas significam para você
| Opção no painel | mode da API | O que você envia |
|---|---|---|
| Entrega gratuita | FIXED com fixed_price: 0 | Nada — use o fixed_price da configuração de preços diretamente |
| Preço fixo | FIXED | Nada — use o fixed_price da configuração de preços diretamente, sem necessidade de cotação |
| Distrito de destino | BY_DISTRICT | Um district_id escolhido de districts[] — o preço já está nessa lista, sem necessidade de cotação |
| Distância percorrida | BY_DRIVE_DISTANCE | latitude e longitude |
| Áreas personalizadas | BY_AREA | latitude e longitude (o merchant precisa ter a validação de endereço do Google Maps habilitada) |
| Faixas personalizadas | BY_RANGE | latitude e longitude |
Um fluxo por modo de precificação
Cada diagrama começa depois que GET /v1/delivery/pricing já informou o mode.
Entrega gratuita
Preço fixo
Nenhuma chamada de cotação é necessária; o endpoint de cotação retornaria o mesmo número.
Distrito de destino
Uma cotação com um district_id desconhecido ou desabilitado retorna price: 0 com area_id: null — isso é um
pedido para corrigir, não uma entrega gratuita.
Distância percorrida
Áreas personalizadas
Faixas personalizadas
Passo 1 — ler a configuração
GET /v1/delivery/pricing
Scope necessário: orders:read
curl https://public-api.olaclick.app/v1/delivery/pricing \
-H "Authorization: Bearer olk_live_..."
O formato da resposta depende de mode. Os campos não relevantes para o modo atual voltam
como null ou vazios.
FIXED
{
"data": {
"active": true,
"mode": "FIXED",
"fixed_price": 5,
"distance": null,
"ranges": [],
"districts": [],
"accepts_out_of_coverage": false
}
}
BY_DISTRICT
{
"data": {
"active": true,
"mode": "BY_DISTRICT",
"fixed_price": null,
"distance": null,
"ranges": [],
"districts": [
{ "id": "6b2f1a04-1c7e-4a2b-9f11-2d8e0b3c4d55", "name": "Miraflores", "price": 6 },
{ "id": "9c4f4203-9e2c-403d-88cc-7c0ce9e0f572", "name": "San Isidro", "price": 8 }
],
"accepts_out_of_coverage": false
}
}
BY_DRIVE_DISTANCE
{
"data": {
"active": true,
"mode": "BY_DRIVE_DISTANCE",
"fixed_price": null,
"distance": { "starting_price": 3, "price_per_km": 1.5, "max_distance_km": 12 },
"ranges": [],
"districts": [],
"accepts_out_of_coverage": true
}
}
BY_RANGE
{
"data": {
"active": true,
"mode": "BY_RANGE",
"fixed_price": null,
"distance": null,
"ranges": [
{ "min": 0, "max": 3000, "price": 4 },
{ "min": 3000, "max": 10000, "price": 7 }
],
"districts": [],
"accepts_out_of_coverage": false
}
}
Campos de resposta:
| Campo | Descrição |
|---|---|
active | Se a entrega está habilitada para esta empresa |
mode | FIXED, BY_DISTRICT, BY_DRIVE_DISTANCE, BY_AREA ou BY_RANGE |
fixed_price | Preço fixo de entrega. Preenchido apenas quando mode é FIXED |
distance | { starting_price, price_per_km, max_distance_km }. Preenchido apenas quando mode é BY_DRIVE_DISTANCE |
ranges | Faixas de distância a partir da loja, min/max em metros, ordenadas por max ascendente. Preenchido apenas quando mode é BY_RANGE |
districts | Distritos atendidos com seu preço fixo. Preenchido apenas quando mode é BY_DISTRICT |
accepts_out_of_coverage | Quando true, um endereço fora da cobertura configurada ainda recebe um preço de 0 na cotação em vez de um 422 |
Passo 2 — obter uma cotação
BY_AREA, BY_DRIVE_DISTANCE e BY_RANGE não trazem um preço em GET /v1/delivery/pricing
— chame o endpoint de cotação com as coordenadas do endereço:
GET /v1/delivery/quote
Scope necessário: orders:read
| Parâmetro de consulta | Descrição |
|---|---|
latitude, longitude | Graus decimais. Envie ambos ou nenhum |
district_id | Um district_id de districts[]. Apenas para BY_DISTRICT; coordenadas enviadas junto são ignoradas nesse modo. Omiti-lo (ou enviar um distrito desconhecido ou desabilitado) retorna price: 0 com area_id: null |
curl "https://public-api.olaclick.app/v1/delivery/quote?latitude=-34.5955&longitude=-58.3930" \
-H "Authorization: Bearer olk_live_..."
{
"data": {
"price": 6.5,
"area_id": "6b2f1a04-1c7e-4a2b-9f11-2d8e0b3c4d55",
"area_name": "Palermo"
}
}
area_id e area_name identificam a área (BY_AREA), faixa (BY_RANGE) ou
distrito (BY_DISTRICT) correspondente; para BY_DRIVE_DISTANCE e FIXED eles são null.
Quando a cotação é 0
Um price: 0 é uma resposta legítima em dois casos e um sinal de requisição incorreta em um terceiro, então
verifique a configuração de preços antes de passá-lo para POST /v1/orders:
| Situação | Como identificar |
|---|---|
| Entrega gratuita | mode é FIXED e fixed_price é 0 |
| Fora de cobertura, mas o merchant aceita | mode é BY_AREA, BY_RANGE ou BY_DISTRICT, accepts_out_of_coverage é true e area_id é null |
Cotação BY_DISTRICT sem um district_id válido | mode é BY_DISTRICT e area_id é null: o distrito foi omitido, é desconhecido ou está desabilitado. Escolha um district_id de districts[] e cote novamente — ou pule a cotação e use o price daquele distrito diretamente |
Nunca crie um pedido DELIVERY com delivery_price: 0 a menos que uma das duas primeiras linhas
se aplique.
Erros
| Status | Causa | Detalhe |
|---|---|---|
| 422 | Nenhuma coordenada enviada, mas o modo de precificação as exige | "This company's delivery pricing mode requires latitude and longitude." |
| 422 | Apenas uma das coordenadas latitude/longitude enviada | Erro de validação local — devem ser enviadas juntas |
| 422 | Uma coordenada fora do intervalo (latitude fora de ±90, longitude fora de ±180) | Erro de validação local nomeando o campo |
| 422 | Endereço fora da cobertura configurada e o merchant não aceita entregas fora de cobertura (accepts_out_of_coverage: false) | location_out_of_business_range. Quando accepts_out_of_coverage é true não há erro: a cotação retorna 200 com price: 0 e area_id: null |
| 422 | Precificação não totalmente configurada para esta empresa | "Delivery pricing is not fully configured for this company." — ex.: BY_AREA sem a validação de endereço do Google Maps habilitada, nenhum distrito/área configurado, ou o merchant não tem coordenadas próprias |
| 422 | As coordenadas não podem ser roteadas | A mensagem do próprio provedor de rotas, ex.: "Coordinates specified are too far apart" — isso normalmente significa que latitude e longitude foram invertidas |
| 404 | A empresa não tem configurações de e-commerce | Nada para cotar |
De onde vêm as coordenadas
latitude/longitude precisam vir de algum lugar fora da API — ela não geocodifica um
endereço em texto. Fontes típicas:
- O dispositivo do cliente final (geolocalização do navegador/app)
- Um autocomplete de endereço ou seletor de mapa do próprio lado do integrador
- Um endereço já salvo na OlaClick:
GET /v1/addresses?client_id=...retornalatitude/longitudepara cada endereço salvo, ePOST /v1/addressespermite salvar novos endereços com coordenadas
Passo 3 — criar o pedido
Depois de obter o preço, crie o pedido DELIVERY com ele:
POST /v1/orders
{
"service_type": "DELIVERY",
"client_id": "9c8e720f-31b1-485a-85fa-0aaf552faaa9",
"address_id": "6b2f1a04-1c7e-4a2b-9f11-2d8e0b3c4d55",
"delivery_price": 6.5
}
Envie um header Idempotency-Key para que uma requisição repetida não crie um pedido duplicado. Veja a
Referência da API REST para o formato completo de requisição e resposta, e a
página do Servidor MCP para as ferramentas de cliente e endereço.
Fazendo isso pelo servidor MCP
O mesmo fluxo é exposto como ferramentas MCP:
| Ferramenta | O que faz |
|---|---|
get_delivery_pricing | Lê a configuração de preços de entrega da empresa |
get_delivery_quote | Obtém uma cotação de preço de entrega para um endereço |
list_addresses | Lista os endereços de entrega salvos de um cliente |
create_address | Salva um novo endereço de entrega (com coordenadas) para um cliente |
create_order | Cria o pedido DELIVERY com o delivery_price cotado |
Fluxo do agente: preços → endereço com coordenadas → cotação → pedido. Chame get_delivery_pricing
primeiro para saber o modo, resolva ou salve um endereço com coordenadas (list_addresses /
create_address), chame get_delivery_quote, depois create_order com o preço retornado.
Aplique as mesmas verificações de 0 descritas acima antes de criar o pedido, e passe um idempotency_key
para create_order para que uma nova tentativa após um timeout reproduza o mesmo pedido em vez de criar
um segundo.
Scopes necessários: orders:read (precificação e cotação), addresses:read / addresses:write
(ler ou salvar endereços), orders:write (criar o pedido).
Exemplos de prompt:
"Como meu restaurante cobra pela entrega?"
"Quanto custaria a entrega para a latitude -34.5955, longitude -58.3930?"
"Crie um pedido de entrega para o cliente 9c8e720f-31b1-485a-85fa-0aaf552faaa9 para o endereço padrão dele e inclua a taxa de entrega"
Veja a página do Servidor MCP para todos os parâmetros de cada ferramenta.
Exemplo prático
Um merchant com precificação BY_DRIVE_DISTANCE (starting_price: 3, price_per_km: 1.5,
max_distance_km: 12), usando coordenadas de Buenos Aires:
| Endereço | Coordenadas | Resultado |
|---|---|---|
| Próximo à loja | -34.5955, -58.3930 | Um preço baixo — próximo do starting_price |
| Mais distante | -34.5810, -58.4210 | Um preço mais alto, escalado pela distância |
| Fora do alcance | -34.9214, -57.9545 | 422 location_out_of_business_range, ou price: 0 com area_id: null se o merchant aceita entregas fora de cobertura |