Country States
A country state is any sub-division of a country — state, province, territory, prefecture, etc. Each state belongs to exactly one country and identifies itself with a short code (AL, CA, BC, MH, …).
Endpoints
The same resource is exposed under two URL shapes so clients can choose the access pattern that fits their UI:
| Method | Path | Purpose |
|---|---|---|
| GET | /api/shop/countries/{country_id}/states | Nested — every state for a single country (recommended for cascade pickers) |
| GET | /api/shop/countries/{country_id}/states/{id} | Nested — single state, scoped to its parent country |
| GET | /api/shop/country-states | Flat — every state across every country in one paginated stream |
| GET | /api/shop/country-states/{id} | Flat — single state by global ID |
The response shape is identical in all four — the only difference is the URL/scoping. Use the example switcher above the curl block to flip through them.
Both shapes return state IDs from the same global sequence —
id: 66is "Alberta" whether you reach it via/countries/40/states/66or/country-states/66.
When to use which
| Scenario | Endpoint |
|---|---|
| Country/state cascade dropdown in a checkout form | GET /api/shop/countries/{country_id}/states |
| Resolve a single state ID (e.g. stored on an order address) | GET /api/shop/country-states/{id} |
| Build an offline cache of every state in the world | GET /api/shop/country-states (paginate through) |
| Validate that a state belongs to a specific country | GET /api/shop/countries/{country_id}/states/{id} (404 if mismatched) |
Request Headers
| Header | Required | Description |
|---|---|---|
Accept | Yes | application/json |
X-STOREFRONT-KEY | Yes | Storefront API key (pk_storefront_…) |
Query Parameters (collections only)
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based) |
per_page | integer | 10 | Items per page. Max 50. |
Pagination headers (X-Total-Count, X-Page, X-Per-Page, X-Total-Pages) are emitted on both collection variants. See Pagination.
State Object Fields
| Field | Type | Description |
|---|---|---|
id | integer | State primary key (globally unique across countries) |
countryId | integer | Owning country ID |
countryCode | string | ISO country code of the parent (CA, US, …) |
code | string | State/province code within the country (AB, CA, MH, …) |
defaultName | string | Default English name |
translations | array of IRI strings | One IRI per locale translation. GET /api/shop/country_state_translations/{id} to dereference |
Unlike
Country, wheretranslationsis inlined,country statetranslations are returned as IRI strings. This keeps the flat list (~586 rows) lean. See IRIs & HATEOAS.
Use Cases
- Render a state/province dropdown that depends on the chosen country (use the nested collection).
- Validate a
state_idsaved on an order against itscountry_id(use the nested single — 404 means mismatched). - Resolve a localized state name for a given customer locale by following one of the
translations[]IRIs. - Bulk-export every state for a CSV / SPA cache (use the flat collection with
?per_page=50).
Related Resources
- Countries — the parent resource; emits the same state objects inline under
Country.states[] - Introduction → IRIs & HATEOAS

