On this page
- Endpoints
- List shipping zones
- Query parameters
- Request
- Response 200
- Create a shipping zone
- Request body
- Request
- Response 201
- Get a shipping zone
- Query parameters
- Request
- Response 200
- Update a shipping zone
- Request body
- Request
- Response 200
- Delete a shipping zone
- Request
- Response 204
- Create a rate
- Request body
- Request
- Response 201
- Update a rate
- Request body
- Request
- Response 200
- Delete a rate
- Request
- Response 204
- Get available rates
- Request body
- Request
- Response 200
- Carrier callbacks
- Callback request body
- Expected callback response
- Webhooks
- The shipping zone object
- The shipping rate object
Shipping
Hydra supports flat-rate and carrier-calculated shipping through zones and rates. A shipping zone defines which countries a set of rates applies to. Rates within a zone can be filtered by order subtotal, weight, and currency. The storefront rate lookup endpoint matches a destination to the best zone and returns available rates.
Base URL: https://api.hydrajs.dev
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v1/shipping/zones |
Secret | List shipping zones |
POST |
/v1/shipping/zones |
Secret | Create a shipping zone |
GET |
/v1/shipping/zones/{id} |
Secret | Get a shipping zone |
PATCH |
/v1/shipping/zones/{id} |
Secret | Update a shipping zone |
DELETE |
/v1/shipping/zones/{id} |
Secret | Delete a shipping zone |
POST |
/v1/shipping/zones/{id}/rates |
Secret | Create a rate in a zone |
PATCH |
/v1/shipping/rates/{id} |
Secret | Update a rate |
DELETE |
/v1/shipping/rates/{id} |
Secret | Delete a rate |
POST |
/v1/shipping/rates |
Publishable | Get available rates for a destination |
List shipping zones
GET /v1/shipping/zones
Returns a paginated list of shipping zones. Use expand=rates to include each zone’s rates inline.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 25 |
Results per page (1-100) |
cursor |
string | - | Pagination cursor from a previous response |
sort |
string | position |
Sort field: position, created_at |
order |
string | asc |
Sort direction: asc, desc |
expand |
string | - | Comma-separated: rates |
fields |
string | - | Comma-separated fields to return |
Request
curl "https://api.hydrajs.dev/v1/shipping/zones?expand=rates" \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 200
{
"data": [
{
"id": "shz_abc123",
"name": "United States",
"countries": ["US"],
"is_rest_of_world": false,
"is_active": true,
"carrier_callback_url": null,
"position": 0,
"rate_count": 2,
"rates": [
{
"id": "shr_def456",
"zone_id": "shz_abc123",
"name": "Standard Shipping",
"description": "5-7 business days",
"price": 599,
"currency": "USD",
"min_order_subtotal": null,
"max_order_subtotal": null,
"min_order_weight": null,
"max_order_weight": null,
"min_delivery_days": 5,
"max_delivery_days": 7,
"is_active": true,
"position": 0,
"created_at": "2026-08-10T14:00:00Z",
"updated_at": "2026-08-10T14:00:00Z"
},
{
"id": "shr_ghi789",
"zone_id": "shz_abc123",
"name": "Express Shipping",
"description": "1-2 business days",
"price": 1499,
"currency": "USD",
"min_order_subtotal": null,
"max_order_subtotal": null,
"min_order_weight": null,
"max_order_weight": null,
"min_delivery_days": 1,
"max_delivery_days": 2,
"is_active": true,
"position": 1,
"created_at": "2026-08-10T14:00:00Z",
"updated_at": "2026-08-10T14:00:00Z"
}
],
"created_at": "2026-08-10T14:00:00Z",
"updated_at": "2026-08-10T14:00:00Z"
}
],
"pagination": {
"cursor": null,
"has_more": false,
"total": 1
}
}
ℹPagination
All list endpoints use cursor-based pagination. Pass the cursor value from the response to fetch
the next page.
Create a shipping zone
POST /v1/shipping/zones
Creates a new shipping zone. Each zone covers a set of countries (ISO 3166-1 alpha-2 codes). You can also create a “rest of world” zone as a fallback for unmatched countries.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Zone name (max 255 chars) |
countries |
string[] | No | Array of 2-letter country codes (max 250, default []) |
is_rest_of_world |
boolean | No | Fallback zone for unmatched countries (default false) |
is_active |
boolean | No | Whether the zone is active (default true) |
carrier_callback_url |
string | No | HTTPS URL for carrier-calculated rates (max 2048 chars) |
position |
integer | No | Display order (default 0) |
⚠One rest-of-world zone
Only one rest-of-world zone is allowed per project. Creating a second one returns a 409 Conflict
error.
Request
curl -X POST https://api.hydrajs.dev/v1/shipping/zones \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "United States",
"countries": ["US"],
"is_active": true,
"position": 0
}'
Response 201
{
"data": {
"id": "shz_abc123",
"name": "United States",
"countries": ["US"],
"is_rest_of_world": false,
"is_active": true,
"carrier_callback_url": null,
"position": 0,
"rate_count": 0,
"rates": [],
"created_at": "2026-08-17T10:00:00Z",
"updated_at": "2026-08-17T10:00:00Z"
}
}
Get a shipping zone
GET /v1/shipping/zones/{id}
Returns a single shipping zone by ID. Use expand=rates to include the zone’s rates inline.
Query parameters
| Parameter | Type | Description |
|---|---|---|
expand |
string | Comma-separated: rates |
fields |
string | Comma-separated fields to return |
Request
curl "https://api.hydrajs.dev/v1/shipping/zones/shz_abc123?expand=rates" \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 200
{
"data": {
"id": "shz_abc123",
"name": "United States",
"countries": ["US"],
"is_rest_of_world": false,
"is_active": true,
"carrier_callback_url": null,
"position": 0,
"rate_count": 2,
"rates": [
{
"id": "shr_def456",
"zone_id": "shz_abc123",
"name": "Standard Shipping",
"description": "5-7 business days",
"price": 599,
"currency": "USD",
"min_order_subtotal": null,
"max_order_subtotal": null,
"min_order_weight": null,
"max_order_weight": null,
"min_delivery_days": 5,
"max_delivery_days": 7,
"is_active": true,
"position": 0,
"created_at": "2026-08-10T14:00:00Z",
"updated_at": "2026-08-10T14:00:00Z"
}
],
"created_at": "2026-08-10T14:00:00Z",
"updated_at": "2026-08-10T14:00:00Z"
}
}
Update a shipping zone
PATCH /v1/shipping/zones/{id}
Updates a shipping zone. All fields are optional. Send only the fields you want to change.
Request body
| Field | Type | Description |
|---|---|---|
name |
string | Zone name (max 255 chars) |
countries |
string[] | Array of 2-letter country codes (replaces entire array) |
is_rest_of_world |
boolean | Fallback zone flag |
is_active |
boolean | Active state |
carrier_callback_url |
string | null | Carrier callback URL. Set to null to remove |
position |
integer | Display order |
Request
curl -X PATCH https://api.hydrajs.dev/v1/shipping/zones/shz_abc123 \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "US & Canada",
"countries": ["US", "CA"]
}'
Response 200
Returns the full updated shipping zone object (same shape as Get a shipping zone).
Delete a shipping zone
DELETE /v1/shipping/zones/{id}
Permanently deletes a shipping zone and all its rates. Fires a shipping.zone.deleted webhook event.
Request
curl -X DELETE https://api.hydrajs.dev/v1/shipping/zones/shz_abc123 \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 204
Empty body.
Create a rate
POST /v1/shipping/zones/{id}/rates
Creates a shipping rate within a zone. Rates can be constrained by order subtotal, order weight, and currency.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Rate name (max 255 chars) |
description |
string | No | Short description (max 1000 chars) |
price |
integer | No | Price in cents (default 0 for free shipping) |
currency |
string | Yes | 3-letter ISO currency code |
min_order_subtotal |
integer | No | Minimum order subtotal in cents |
max_order_subtotal |
integer | No | Maximum order subtotal in cents |
min_order_weight |
integer | No | Minimum total weight in grams |
max_order_weight |
integer | No | Maximum total weight in grams |
min_delivery_days |
integer | No | Minimum estimated delivery days |
max_delivery_days |
integer | No | Maximum estimated delivery days |
is_active |
boolean | No | Active state (default true) |
position |
integer | No | Display order within the zone (default 0) |
ℹFree shipping threshold
To offer free shipping above a subtotal, create a rate with price: 0 and min_order_subtotal
set to the threshold (e.g. 5000 for orders over $50).
Request
curl -X POST https://api.hydrajs.dev/v1/shipping/zones/shz_abc123/rates \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Standard Shipping",
"description": "5-7 business days",
"price": 599,
"currency": "USD",
"min_delivery_days": 5,
"max_delivery_days": 7,
"position": 0
}'
Response 201
{
"data": {
"id": "shr_def456",
"zone_id": "shz_abc123",
"name": "Standard Shipping",
"description": "5-7 business days",
"price": 599,
"currency": "USD",
"min_order_subtotal": null,
"max_order_subtotal": null,
"min_order_weight": null,
"max_order_weight": null,
"min_delivery_days": 5,
"max_delivery_days": 7,
"is_active": true,
"position": 0,
"created_at": "2026-08-17T10:00:00Z",
"updated_at": "2026-08-17T10:00:00Z"
}
}
Update a rate
PATCH /v1/shipping/rates/{id}
Updates a shipping rate. All fields are optional. Set nullable fields to null to clear them.
Request body
| Field | Type | Description |
|---|---|---|
name |
string | Rate name (max 255 chars) |
description |
string | null | Short description |
price |
integer | Price in cents |
currency |
string | 3-letter ISO currency code |
min_order_subtotal |
integer | null | Minimum order subtotal in cents |
max_order_subtotal |
integer | null | Maximum order subtotal in cents |
min_order_weight |
integer | null | Minimum weight in grams |
max_order_weight |
integer | null | Maximum weight in grams |
min_delivery_days |
integer | null | Minimum delivery days |
max_delivery_days |
integer | null | Maximum delivery days |
is_active |
boolean | Active state |
position |
integer | Display order |
Request
curl -X PATCH https://api.hydrajs.dev/v1/shipping/rates/shr_def456 \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"price": 499,
"max_delivery_days": 8
}'
Response 200
Returns the full updated rate object.
Delete a rate
DELETE /v1/shipping/rates/{id}
Permanently deletes a shipping rate.
Request
curl -X DELETE https://api.hydrajs.dev/v1/shipping/rates/shr_def456 \
-H "Authorization: Bearer sk_live_YOUR_KEY"
Response 204
Empty body.
Get available rates
POST /v1/shipping/rates
Returns all shipping rates available for a destination. This is the storefront-facing endpoint used during checkout to display shipping options to the customer.
Hydra matches the destination country to the first active zone (by position) that includes it. If no zone matches, the rest-of-world zone is used as a fallback. Rates are filtered by currency, subtotal, and weight, then sorted by price ascending.
If the matched zone has a carrier_callback_url, Hydra also calls the carrier endpoint and merges those rates into the results.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
country |
string | Yes | ISO 3166-1 alpha-2 country code (2 letters) |
state |
string | No | State or province code (max 100 chars) |
postal_code |
string | No | Postal code (max 20 chars) |
subtotal |
integer | Yes | Order subtotal in cents |
currency |
string | Yes | 3-letter ISO currency code |
items |
object[] | No | Cart items for weight calculation. Each: weight_grams (int), quantity (int) |
Request
curl -X POST https://api.hydrajs.dev/v1/shipping/rates \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"country": "US",
"state": "CA",
"postal_code": "94102",
"subtotal": 8999,
"currency": "USD",
"items": [
{ "weight_grams": 500, "quantity": 2 }
]
}'
Response 200
{
"data": [
{
"id": "shr_def456",
"name": "Standard Shipping",
"description": "5-7 business days",
"price": 599,
"currency": "USD",
"min_delivery_days": 5,
"max_delivery_days": 7,
"source": "flat"
},
{
"id": "shr_ghi789",
"name": "Express Shipping",
"description": "1-2 business days",
"price": 1499,
"currency": "USD",
"min_delivery_days": 1,
"max_delivery_days": 2,
"source": "flat"
}
]
}
ℹRate sources
Each rate includes a source field: flat for rates defined in the Hydra admin, or carrier for
rates returned by a carrier callback URL. Carrier rates have generated IDs prefixed with
carrier_.
Carrier callbacks
When a shipping zone has a carrier_callback_url, Hydra sends a POST request to that URL during rate lookup with the destination and cart details. Your endpoint must return a JSON response within 5 seconds.
Callback request body
{
"destination": {
"country": "US",
"state": "CA",
"postal_code": "94102"
},
"items": [{ "weight_grams": 500, "quantity": 2 }],
"subtotal": 8999,
"currency": "USD"
}
Expected callback response
{
"rates": [
{
"name": "FedEx Ground",
"description": "3-5 business days",
"price": 899,
"currency": "USD",
"min_delivery_days": 3,
"max_delivery_days": 5
}
]
}
The rates array accepts up to 10 rates. If the callback fails, times out, or returns invalid data, Hydra silently falls back to flat rates only.
Webhooks
Shipping zone changes fire the following webhook events:
| Event | Trigger |
|---|---|
shipping.zone.created |
A shipping zone is created |
shipping.zone.updated |
A shipping zone is updated |
shipping.zone.deleted |
A shipping zone is deleted |
See Webhooks for subscription setup.
The shipping zone object
| Field | Type | Description |
|---|---|---|
id |
string | Unique ID (prefix: shz_) |
name |
string | Zone name |
countries |
string[] | ISO 3166-1 alpha-2 country codes |
is_rest_of_world |
boolean | Whether this is the fallback zone |
is_active |
boolean | Whether the zone is active |
carrier_callback_url |
string | null | URL for carrier-calculated rates |
position |
integer | Display order |
rate_count |
integer | Number of rates in the zone |
rates |
object[] | Expanded with ?expand=rates |
created_at |
string | ISO 8601 timestamp |
updated_at |
string | ISO 8601 timestamp |
The shipping rate object
| Field | Type | Description |
|---|---|---|
id |
string | Unique ID (prefix: shr_) |
zone_id |
string | Parent zone ID |
name |
string | Rate name |
description |
string | null | Short description |
price |
integer | Price in cents |
currency |
string | 3-letter ISO currency code |
min_order_subtotal |
integer | null | Minimum subtotal for this rate to apply |
max_order_subtotal |
integer | null | Maximum subtotal for this rate to apply |
min_order_weight |
integer | null | Minimum weight in grams |
max_order_weight |
integer | null | Maximum weight in grams |
min_delivery_days |
integer | null | Minimum estimated delivery days |
max_delivery_days |
integer | null | Maximum estimated delivery days |
is_active |
boolean | Whether the rate is active |
position |
integer | Display order within the zone |
created_at |
string | ISO 8601 timestamp |
updated_at |
string | ISO 8601 timestamp |