Skip to content

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:

MethodPathPurpose
GET/api/shop/countries/{country_id}/statesNested — 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-statesFlat — 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: 66 is "Alberta" whether you reach it via /countries/40/states/66 or /country-states/66.

When to use which

ScenarioEndpoint
Country/state cascade dropdown in a checkout formGET /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 worldGET /api/shop/country-states (paginate through)
Validate that a state belongs to a specific countryGET /api/shop/countries/{country_id}/states/{id} (404 if mismatched)

Request Headers

HeaderRequiredDescription
AcceptYesapplication/json
X-STOREFRONT-KEYYesStorefront API key (pk_storefront_…)

Query Parameters (collections only)

ParameterTypeDefaultDescription
pageinteger1Page number (1-based)
per_pageinteger10Items 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

FieldTypeDescription
idintegerState primary key (globally unique across countries)
countryIdintegerOwning country ID
countryCodestringISO country code of the parent (CA, US, …)
codestringState/province code within the country (AB, CA, MH, …)
defaultNamestringDefault English name
translationsarray of IRI stringsOne IRI per locale translation. GET /api/shop/country_state_translations/{id} to dereference

Unlike Country, where translations is inlined, country state translations 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_id saved on an order against its country_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).

Released under the MIT License.