Shipping Zone API
A shipping zone is a set of countries (optionally narrowed to provinces). Zones no longer own methods directly — they own provider attachments. Configuring shipping is three steps:
- Create a zone — the geography.
- Attach a provider to the zone (
core, or one supplied by an extension). - For the built-in
coreprovider, define methods and give each one a per-zone rate.
POST /api/shippingZones/{id}/methods, PATCH /api/shippingZones/{zone_id}/methods/{method_id} and DELETE /api/shippingZones/{zone_id}/methods/{method_id} no longer exist. Their replacements are the provider endpoints (/api/shippingZones/:zone_id/providers[...]) and the Core provider endpoints (/api/shippingProviders/core/methods and /api/shippingProviders/core/rates) documented below.
The calculation_type field is gone entirely — the shape of the cost is inferred from which cost field you set on a rate. condition_type accepts only "price", "weight" or null; the old "none" value is rejected.
Zones
Create a Shipping Zone
Creates a shipping zone. Only name is required by the payload schema, but the request is rejected with 400 At least one country is required unless the normalized country list is non-empty — so send countries (preferred) or the legacy country.
Creating a zone automatically attaches the built-in core provider to it.
| Field Name | Field Type | Required |
|---|---|---|
| name | string | Yes |
| countries | array of string | No |
| country | string | No |
| provinces | No |
- cURL
- JavaScript
curl
-H "Accept: application/json"
-H "Authorization: Bearer <admin JWT token>"
--data-raw '<JSON DATA>'
https://<your domain>/api/shippingZones
fetch('https://<your domain>/api/shippingZones', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer <admin JWT token>'
},
body: <JSON DATA>
})
.then(response => response.json())
.then(data => {
if(data.error) {
// Handle the error
} else {
// Handle the data
}
})
.catch(error => {
// Handle the error
});
{
"data": {
"shipping_zone_id": 3,
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "North America"
}
}
A multi-country zone with province restrictions:
{
"name": "North America",
"countries": ["US", "CA"],
"provinces": [
{ "country": "US", "province": "CA" },
{ "country": "US", "province": "OR" },
{ "country": "CA", "province": "BC" }
]
}
shipping_zone.country was droppedCountries live in the shipping_zone_country table and provinces in shipping_zone_province, both keyed by zone. The zone row itself carries only name, so the create response does not echo the geography back.
Update a Shipping Zone
Replaces the zone's name, countries and provinces. Country and province rows are replaced wholesale, not merged — send the complete lists every time. The same "at least one country" rule applies.
| Field Name | Field Type | Required |
|---|---|---|
| name | string | Yes |
| countries | array of string | No |
| country | string | No |
| provinces | No |
- cURL
- JavaScript
curl
-H "Accept: application/json"
-H "Authorization: Bearer <admin JWT token>"
--data-raw '<JSON DATA>'
https://<your domain>/api/shippingZones/{id}
fetch('https://<your domain>/api/shippingZones/{id}', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer <admin JWT token>'
},
body: <JSON DATA>
})
.then(response => response.json())
.then(data => {
if(data.error) {
// Handle the error
} else {
// Handle the data
}
})
.catch(error => {
// Handle the error
});
{
"data": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
{id} is the zone uuid.
Delete a Shipping Zone
Permanently removes a shipping zone along with its country, province, provider-attachment and rate rows.
- cURL
- JavaScript
curl
-H "Accept: application/json"
-H "Authorization: Bearer <admin JWT token>"
https://<your domain>/api/shippingZones/{id}
fetch('https://<your domain>/api/shippingZones/{id}', {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer <admin JWT token>'
}
})
.then(response => response.json())
.then(data => {
if(data.error) {
// Handle the error
} else {
// Handle the data
}
})
.catch(error => {
// Handle the error
});
{
"data": {
"shipping_zone_id": 3,
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "North America"
}
}
Providers, Methods and Rates
A zone on its own offers nothing. Shipping options come from providers attached to the zone, and — for the built-in Core provider — from the methods and rates configured beneath it.
Those endpoints have their own reference:
| What you want to do | Where |
|---|---|
| Attach, update or detach a provider on a zone | Shipping Provider API |
| Create, update or delete a Core method | Shipping Provider API |
| Create, update or delete a Core rate (flat, price-tiered or weight-tiered) | Shipping Provider API |
| Build a provider of your own | Shipping Provider Development |
Selecting a Method at Checkout
Once zones, providers, methods and rates exist, the storefront reads the available methods from GraphQL and applies one with POST /api/carts/:cart_id/shippingMethods. See the Shipping Method API.