Skip to main content

Calculate delivery prices

This guide is for an integrator — or an AI agent working through the MCP server — who needs to know the delivery fee for an address before creating a DELIVERY order.

The flow at a glance​

Why​

POST /v1/orders stores delivery_price verbatim: whatever value you send on a DELIVERY order is the value that gets charged, with no server-side recalculation. The merchant configures how delivery is priced from the OlaClick panel, under Settings → Delivery → "Configure delivery prices and coverage". The API exposes that configuration and a quote endpoint so you can resolve the right number — nothing in the API creates or edits the pricing configuration itself.

The six panel options and what they mean for you​

Panel optionAPI modeWhat you send
Free deliveryFIXED with fixed_price: 0Nothing — use fixed_price from the pricing configuration directly
Fixed priceFIXEDNothing — use fixed_price from the pricing configuration directly, no quote call needed
Destination districtBY_DISTRICTA district_id picked from districts[] — the price is already in that list, no quote call needed
Travelled distanceBY_DRIVE_DISTANCElatitude and longitude
Custom areasBY_AREAlatitude and longitude (the merchant must have Google Maps address validation enabled)
Custom rangesBY_RANGElatitude and longitude

One flow per pricing mode​

Each diagram starts after GET /v1/delivery/pricing has told you the mode.

Free delivery​

Fixed price​

No quote call is needed; the quote endpoint would return the same number.

Destination district​

A quote with an unknown or disabled district_id answers price: 0 with area_id: null — that is a request to fix, not a free delivery.

Travelled distance​

Custom areas​

Custom ranges​

Step 1 — read the configuration​

GET /v1/delivery/pricing

Required scope: orders:read

curl https://public-api.olaclick.app/v1/delivery/pricing \
-H "Authorization: Bearer olk_live_..."

The response shape depends on mode. The fields not relevant to the current mode come back null or empty.

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
}
}

Response fields:

FieldDescription
activeWhether delivery is enabled for this company
modeFIXED, BY_DISTRICT, BY_DRIVE_DISTANCE, BY_AREA, or BY_RANGE
fixed_priceFlat delivery price. Populated only when mode is FIXED
distance{ starting_price, price_per_km, max_distance_km }. Populated only when mode is BY_DRIVE_DISTANCE
rangesDistance tiers from the store, min/max in meters, ordered by max ascending. Populated only when mode is BY_RANGE
districtsDeliverable districts with their fixed price. Populated only when mode is BY_DISTRICT
accepts_out_of_coverageWhen true, an address outside the configured coverage still gets a price of 0 from the quote instead of a 422

Step 2 — get a quote​

BY_AREA, BY_DRIVE_DISTANCE, and BY_RANGE don't carry a price on GET /v1/delivery/pricing — call the quote endpoint with the address's coordinates:

GET /v1/delivery/quote

Required scope: orders:read

Query parameterDescription
latitude, longitudeDecimal degrees. Send both or neither
district_idA district_id from districts[]. Only for BY_DISTRICT; coordinates sent alongside it are ignored in that mode. Omitting it (or sending an unknown or disabled district) returns price: 0 with 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 and area_name identify the matching area (BY_AREA), range (BY_RANGE) or district (BY_DISTRICT); for BY_DRIVE_DISTANCE and FIXED they are null.

When the quote is 0​

A price: 0 is a legitimate answer in two cases and a sign of a bad request in a third, so check the pricing configuration before passing it to POST /v1/orders:

SituationHow to tell
Free deliverymode is FIXED and fixed_price is 0
Outside coverage, but the merchant accepts itmode is BY_AREA, BY_RANGE or BY_DISTRICT, accepts_out_of_coverage is true and area_id is null
BY_DISTRICT quote without a valid district_idmode is BY_DISTRICT and area_id is null: the district was omitted, unknown or disabled. Pick a district_id from districts[] and quote again — or skip the quote and use that district's price directly

Never create a DELIVERY order with delivery_price: 0 unless one of the first two rows applies.

Errors​

StatusCauseDetail
422Neither coordinate sent, but the pricing mode requires them"This company's delivery pricing mode requires latitude and longitude."
422Only one of latitude/longitude sentLocal validation error — they must be provided together
422A coordinate out of range (latitude outside ±90, longitude outside ±180)Local validation error naming the field
422Address outside the configured coverage and the merchant does not accept out-of-coverage deliveries (accepts_out_of_coverage: false)location_out_of_business_range. When accepts_out_of_coverage is true there is no error: the quote returns 200 with price: 0 and area_id: null
422Pricing not fully configured for this company"Delivery pricing is not fully configured for this company." — e.g. BY_AREA without Google Maps address validation enabled, no districts/areas configured, or the merchant has no coordinates of its own
422Coordinates can't be routedThe routing provider's own message, e.g. "Coordinates specified are too far apart" — this typically means latitude and longitude were swapped
404The company has no e-commerce settingsNothing to quote against

Where the coordinates come from​

latitude/longitude have to come from somewhere other than the API — it does not geocode a text address. Typical sources:

  • The end customer's device (browser/app geolocation)
  • An address autocomplete or map picker on the integrator's own side
  • An address already saved in OlaClick: GET /v1/addresses?client_id=... returns latitude/longitude for each saved address, and POST /v1/addresses lets you save new ones with coordinates

Step 3 — create the order​

Once you have the price, create the DELIVERY order with it:

POST /v1/orders
{
"service_type": "DELIVERY",
"client_id": "9c8e720f-31b1-485a-85fa-0aaf552faaa9",
"address_id": "6b2f1a04-1c7e-4a2b-9f11-2d8e0b3c4d55",
"delivery_price": 6.5
}

Send an Idempotency-Key header so a retried request can't create a duplicate order. See the REST API Reference for the full request and response shape, and the MCP Server page for the client and address tools.

Doing it through the MCP server​

The same flow is exposed as MCP tools:

ToolWhat it does
get_delivery_pricingRead the company's delivery pricing configuration
get_delivery_quoteGet a delivery price quote for one address
list_addressesList a client's saved delivery addresses
create_addressSave a new delivery address (with coordinates) for a client
create_orderCreate the DELIVERY order with the quoted delivery_price

Agent flow: pricing → address with coordinates → quote → order. Call get_delivery_pricing first to learn the mode, resolve or save an address with coordinates (list_addresses / create_address), call get_delivery_quote, then create_order with the returned price. Apply the same 0 checks as above before creating the order, and pass an idempotency_key to create_order so a retry after a timeout replays the same order instead of creating a second one.

Needed scopes: orders:read (pricing and quote), addresses:read / addresses:write (reading or saving addresses), orders:write (creating the order).

Example prompts:

"How does my restaurant charge for delivery?"

"How much would delivery cost to latitude -34.5955, longitude -58.3930?"

"Create a delivery order for client 9c8e720f-31b1-485a-85fa-0aaf552faaa9 to their default address and include the delivery fee"

See the MCP Server page for every tool's full parameters.

Worked example​

A merchant priced BY_DRIVE_DISTANCE (starting_price: 3, price_per_km: 1.5, max_distance_km: 12), using Buenos Aires coordinates:

AddressCoordinatesResult
Near the store-34.5955, -58.3930A low price — close to starting_price
Farther away-34.5810, -58.4210A higher price, scaled by distance
Out of range-34.9214, -57.9545422 location_out_of_business_range, or price: 0 with area_id: null if the merchant accepts out-of-coverage deliveries