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

Two things hold across all four:

  • The response shape is identical — only the URL and its scoping differ. Use the example switcher above the curl block to flip through them.
  • State IDs come from one global sequence, so id: 66 is Alberta whether you reach it through /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 path referencesOne reference per locale. Fetch GET /api/shop/country_state_translations/{id} to read one. Countries inline their translations, but states do not — keeping the flat 586-row collection 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).

Best Practices

  • Prefer the nested route for a picker/api/shop/countries/{countryId}/states returns just that country's states, while this flat collection pages through every state in the world.
  • Match on code, not on the display name — checkout stores the state code, and names change with the request locale.
  • Cache alongside the country list — the data is static reference data.

Released under the MIT License.