> For the complete documentation index, see [llms.txt](https://docs.zapiet.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zapiet.com/zapiet-rates-by-zip-code/get-rates.md).

# Get rates

Quote shipping rates for a destination and cart.

## Get shipping rates

> Returns the rates Zapiet would show at checkout for the given destination and cart.\
> \
> \*\*Send \`Accept: application/json\` on every request.\*\* Without it, validation errors come back as a redirect and rate-limit errors as an HTML page instead of JSON.\
> \
> If no zone or rate matches and the shop has a fallback rate turned on, the fallback rate is returned. \`rates\` is only empty when there is no fallback rate or the shop is not eligible to calculate rates.\
> \
> Limited to 60 requests per minute per API key and per IP address. Quotes are included in your plan.<br>

```json
{"openapi":"3.0.3","info":{"title":"Zapiet - Rates by Zip Code API","version":"1.0.0"},"tags":[{"name":"Rates","description":"Shipping rate quotes"}],"servers":[{"url":"https://deliveryratesbyzipcode.com/api/v1"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your API key, sent as `Authorization: Bearer dbz_...`"},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-Api-Key","description":"Alternative to the bearer header: `X-Api-Key: dbz_...`"}},"schemas":{"RatesRequest":{"type":"object","required":["destination"],"properties":{"destination":{"$ref":"#/components/schemas/Destination"},"items":{"type":"array","description":"Cart lines, used for weight-based and subtotal-based rates. Omit or send an empty array if your rates do not depend on the cart.","items":{"$ref":"#/components/schemas/Item"}},"locale":{"type":"string","default":"en","description":"Language code for translated rate names and descriptions, for example `en` or `fr`."},"shop":{"type":"string","description":"Your Shopify domain. If sent, it must match the shop the API key belongs to."}}},"Destination":{"type":"object","required":["postal_code"],"description":"The delivery address. The more complete it is, the closer the quote matches checkout.","properties":{"postal_code":{"type":"string","description":"Zip or postal code used to match a zone."},"address1":{"type":"string","nullable":true},"address2":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"province":{"type":"string","nullable":true,"description":"Province, state or region."},"country":{"type":"string","nullable":true,"description":"Country code, for example `GB` or `US`."},"name":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true}}},"Item":{"type":"object","required":["quantity"],"properties":{"quantity":{"type":"integer","minimum":1},"grams":{"type":"integer","description":"Weight of one unit in grams. Zapiet multiplies it by `quantity`."},"price":{"type":"integer","description":"Price of one unit in the shop's smallest currency unit (cents or pence). Zapiet multiplies it by `quantity`."}}},"RatesResponse":{"type":"object","properties":{"rates":{"type":"array","items":{"$ref":"#/components/schemas/Rate"}}}},"Rate":{"type":"object","properties":{"zone_name":{"type":"string","description":"The Zapiet zone that matched. Empty for a fallback rate."},"service_name":{"type":"string","description":"Customer-facing rate name, translated when `locale` has a translation."},"service_code":{"type":"string","description":"Stable identifier for this rate. Safe to store. For a fallback rate, it is the rate name in lowercase with dashes, for example `standard-shipping`."},"total_price":{"type":"string","description":"Price in the shop's smallest currency unit, as a string. `\"495\"` in GBP is 4.95 GBP."},"description":{"type":"string","nullable":true,"description":"Customer-facing description. `null` for a fallback rate."},"currency":{"type":"string","description":"ISO currency code of the shop."},"phone_required":{"type":"boolean","description":"Whether checkout requires a phone number for this rate."}}},"Error":{"type":"object","properties":{"message":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}}},"paths":{"/rates":{"post":{"tags":["Rates"],"operationId":"getRates","summary":"Get shipping rates","description":"Returns the rates Zapiet would show at checkout for the given destination and cart.\n\n**Send `Accept: application/json` on every request.** Without it, validation errors come back as a redirect and rate-limit errors as an HTML page instead of JSON.\n\nIf no zone or rate matches and the shop has a fallback rate turned on, the fallback rate is returned. `rates` is only empty when there is no fallback rate or the shop is not eligible to calculate rates.\n\nLimited to 60 requests per minute per API key and per IP address. Quotes are included in your plan.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatesRequest"}}}},"responses":{"200":{"description":"Quote calculated. `rates` may contain a fallback rate, or be empty if nothing is available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatesResponse"}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request body failed validation, for example a missing postal code or a `shop` that does not match the API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"429":{"description":"Rate limit exceeded (60 requests per minute). Wait for the number of seconds in `Retry-After`, then retry.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Requests allowed per minute.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Prices, weights and quantity

Send `price` and `grams` **per unit**. Zapiet multiplies them by `quantity`. Two items at 50.00 GBP and 1 kg each are one line:

```json
{ "quantity": 2, "price": 5000, "grams": 1000 }
```

Prices go in and come out in the shop's smallest currency unit (cents, pence), the same unit Shopify uses at checkout. In the response, `total_price` is a string: `"495"` with `"currency": "GBP"` is 4.95 GBP.

## Fallback rates

If the shop has a fallback rate turned on, you get it back when:

* the postal code does not match any zone, or
* the postal code matches a zone but no rate matches the cart's weight or subtotal.

A fallback rate has an empty `zone_name` and a `null` `description`. Handle both in your UI.

## Empty rates

An empty `rates` array is a successful quote, not an error. It is the same result checkout would show. You get it when:

* nothing matches and the shop has no fallback rate turned on, or
* the shop cannot calculate rates, for example because its Zapiet subscription is not active.

Do not treat an empty array as an authentication failure.

## The address

Only `postal_code` is required, because Zapiet matches rates by zip code. Send as much of the address as you have. The more complete it is, the closer the quote matches checkout.
