Spree Commerce Markets API
Markets — geographic groupings of countries used for pricing, tax, and fulfillment rules
Markets — geographic groupings of countries used for pricing, tax, and fulfillment rules
openapi: 3.0.3
info:
title: Admin Account / Address Markets API
contact:
name: Spree Commerce
url: https://spreecommerce.org
email: hello@spreecommerce.org
description: "Spree Admin API v3 - Administrative API for managing products, orders, and store settings.\n\n## Authentication\n\nThe Admin API requires a secret API key passed in the `x-spree-api-key` header.\nSecret API keys can be generated in the Spree admin dashboard.\n\n## Response Format\n\nAll responses are JSON. List endpoints return paginated responses with `data` and `meta` keys.\nSingle resource endpoints return a flat JSON object.\n\n## Resource IDs\n\nEvery resource is identified by an opaque string ID (e.g. `prod_86Rf07xd4z`,\n`variant_k5nR8xLq`, `or_UkLWZg9DAJ`). Use these IDs everywhere — URL paths,\nrequest bodies, and Ransack filters all accept them directly.\n\n## Error Handling\n\nErrors return a consistent format:\n```json\n{\n \"error\": {\n \"code\": \"validation_error\",\n \"message\": \"Validation failed\",\n \"details\": { \"name\": [\"can't be blank\"] }\n }\n}\n```\n"
version: v3
servers:
- url: http://{defaultHost}
variables:
defaultHost:
default: localhost:3000
tags:
- name: Markets
description: Markets — geographic groupings of countries used for pricing, tax, and fulfillment rules
paths:
/api/v3/admin/markets:
get:
summary: List markets
tags:
- Markets
security:
- api_key: []
bearer_auth: []
description: 'Returns the markets configured for the current store. Markets are
store-scoped and ordered by `position` (an `acts_as_list` column —
update the order via `PATCH /markets/{id}` with `position`).
**Required scope:** `read_settings` (for API-key authentication).'
x-codeSamples:
- lang: javascript
label: Spree Admin SDK
source: "import { createAdminClient } from '@spree/admin-sdk'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst { data: markets } = await client.markets.list()"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: Authorization
in: header
required: true
schema:
type: string
- name: page
in: query
required: false
schema:
type: integer
- name: limit
in: query
required: false
schema:
type: integer
- name: q[name_cont]
in: query
required: false
schema:
type: string
- name: sort
in: query
required: false
schema:
type: string
- name: expand
in: query
required: false
description: 'Comma-separated associations to embed. Supported: `countries`.'
schema:
type: string
responses:
'200':
description: markets found
content:
application/json:
example:
data:
- id: mkt_UkLWZg9DAJ
name: EU
currency: USD
default_locale: en
tax_inclusive: false
default: false
country_isos:
- DE
supported_locales:
- en
created_at: '2026-06-12T17:24:19.453Z'
updated_at: '2026-06-12T17:24:19.453Z'
meta:
page: 1
limit: 25
count: 1
pages: 1
from: 1
to: 1
in: 1
previous: null
next: null
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Market'
meta:
$ref: '#/components/schemas/PaginationMeta'
required:
- data
- meta
post:
summary: Create a market
tags:
- Markets
security:
- api_key: []
bearer_auth: []
description: "Creates a new market for the current store.\n\n- `country_isos` accepts 2-letter ISO country codes (e.g. `[\"DE\", \"FR\"]`);\n the market must contain at least one country. Unknown codes are\n silently dropped.\n- `supported_locales` accepts an array of locale codes; the\n `default_locale` is always implicitly included.\n- Setting `default: true` automatically demotes the previous default\n market in the store.\n\n\n**Required scope:** `write_settings` (for API-key authentication)."
x-codeSamples:
- lang: javascript
label: Spree Admin SDK
source: "import { createAdminClient } from '@spree/admin-sdk'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst market = await client.markets.create({\n name: 'Europe',\n currency: 'EUR',\n default_locale: 'de',\n supported_locales: ['de', 'en', 'fr'],\n tax_inclusive: true,\n country_isos: ['DE', 'FR', 'IT'],\n})"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: Authorization
in: header
required: true
schema:
type: string
responses:
'201':
description: market created
content:
application/json:
example:
id: mkt_gbHJdmfrXB
name: France only
currency: EUR
default_locale: fr
tax_inclusive: true
default: false
country_isos:
- FR
supported_locales:
- en
- fr
created_at: '2026-06-12T17:24:20.056Z'
updated_at: '2026-06-12T17:24:20.056Z'
schema:
$ref: '#/components/schemas/Market'
'422':
description: validation error
content:
application/json:
example:
error:
code: validation_error
message: Name can't be blank, Currency can't be blank, Default locale can't be blank, and Countries can't be blank
details:
name:
- can't be blank
currency:
- can't be blank
default_locale:
- can't be blank
countries:
- can't be blank
schema:
$ref: '#/components/schemas/ErrorResponse'
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
example: Europe
currency:
type: string
example: EUR
description: ISO 4217 currency code.
default_locale:
type: string
example: de
description: IETF locale tag used as the market default.
supported_locales:
type: array
items:
type: string
description: Locale codes available in this market. The default is always implicitly included.
example:
- de
- en
tax_inclusive:
type: boolean
default: false
description: Display prices with tax included.
default:
type: boolean
default: false
description: Setting to true demotes the previous default.
position:
type: integer
description: Sort order within the store; lower = first.
country_isos:
type: array
items:
type: string
description: 2-letter ISO country codes assigned to this market. At least one is required.
example:
- DE
- FR
required:
- name
- currency
- default_locale
- country_isos
/api/v3/admin/markets/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
get:
summary: Get a market
tags:
- Markets
security:
- api_key: []
bearer_auth: []
description: '**Required scope:** `read_settings` (for API-key authentication).'
x-codeSamples:
- lang: javascript
label: Spree Admin SDK
source: "import { createAdminClient } from '@spree/admin-sdk'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst market = await client.markets.get('market_xxx')"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: Authorization
in: header
required: true
schema:
type: string
- name: expand
in: query
required: false
schema:
type: string
responses:
'200':
description: market found
content:
application/json:
example:
id: mkt_UkLWZg9DAJ
name: EU
currency: USD
default_locale: en
tax_inclusive: false
default: false
country_isos:
- DE
supported_locales:
- en
created_at: '2026-06-12T17:24:20.399Z'
updated_at: '2026-06-12T17:24:20.399Z'
schema:
$ref: '#/components/schemas/Market'
'404':
description: market not found
content:
application/json:
example:
error:
code: record_not_found
message: Market not found
schema:
$ref: '#/components/schemas/ErrorResponse'
patch:
summary: Update a market
tags:
- Markets
security:
- api_key: []
bearer_auth: []
description: 'Updates an existing market. Pass `country_isos` to replace the
market''s country list (full-set update), `supported_locales` to
replace the supported locales, or `position` to reorder the market
within the store.
Setting `default: true` automatically demotes the previous default.
**Required scope:** `write_settings` (for API-key authentication).'
x-codeSamples:
- lang: javascript
label: Spree Admin SDK
source: "import { createAdminClient } from '@spree/admin-sdk'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\n// `country_isos` is a full-set update — the market is reconciled to match\n// the array (adds new countries, removes ones not present). Setting\n// `default: true` demotes the previous default market in the store.\nconst market = await client.markets.update('market_UkLWZg9DAJ', {\n name: 'European Union',\n tax_inclusive: true,\n country_isos: ['DE', 'FR'],\n})"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: Authorization
in: header
required: true
schema:
type: string
responses:
'200':
description: market updated
content:
application/json:
example:
id: mkt_UkLWZg9DAJ
name: European Union
currency: USD
default_locale: en
tax_inclusive: true
default: false
country_isos:
- DE
supported_locales:
- en
created_at: '2026-06-12T17:24:21.018Z'
updated_at: '2026-06-12T17:24:21.314Z'
schema:
$ref: '#/components/schemas/Market'
'422':
description: validation error
content:
application/json:
example:
error:
code: validation_error
message: Name can't be blank
details:
name:
- can't be blank
schema:
$ref: '#/components/schemas/ErrorResponse'
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
currency:
type: string
default_locale:
type: string
supported_locales:
type: array
items:
type: string
tax_inclusive:
type: boolean
default:
type: boolean
position:
type: integer
country_isos:
type: array
items:
type: string
delete:
summary: Delete a market
tags:
- Markets
security:
- api_key: []
bearer_auth: []
description: 'Soft-deletes the market (sets `deleted_at`). The default market and
the last remaining market in a store cannot be deleted — both return
422 with a `validation_error`.
**Required scope:** `write_settings` (for API-key authentication).'
x-codeSamples:
- lang: javascript
label: Spree Admin SDK
source: "import { createAdminClient } from '@spree/admin-sdk'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\n// Soft-deletes the market (sets `deleted_at`). The default market and the\n// last remaining market in a store cannot be deleted — both return 422.\nawait client.markets.delete('market_UkLWZg9DAJ')"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: Authorization
in: header
required: true
schema:
type: string
responses:
'204':
description: market deleted
'422':
description: cannot delete default or last market
content:
application/json:
example:
error:
code: validation_error
message: Market cannot be deleted
/api/v3/store/countries:
get:
summary: List countries
tags:
- Markets
security:
- api_key: []
description: Returns countries available in the store. Use ?expand=market to include market details (currency, locale, tax_inclusive).
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst countries = await client.countries.list()"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: countries found
content:
application/json:
example:
data:
- iso: DE
iso3: IS39
name: Germany
states_required: false
zipcode_required: true
- iso: US
iso3: USA
name: United States of America
states_required: true
zipcode_required: true
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Country_2'
required:
- data
'401':
description: unauthorized
content:
application/json:
example:
error:
code: invalid_token
message: Valid API key required
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v3/store/countries/{iso}:
get:
summary: Get a country
tags:
- Markets
security:
- api_key: []
description: Returns a single country by ISO code. Supports ?expand=states for address forms and ?expand=market for market details.
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst country = await client.countries.get('US')"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: iso
in: path
required: true
description: Country ISO 3166-1 alpha-2 code (e.g., "US", "DE")
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: country found
content:
application/json:
example:
iso: US
iso3: USA
name: United States of America
states_required: true
zipcode_required: true
schema:
type: object
properties:
iso:
type: string
iso3:
type: string
name:
type: string
states_required:
type: boolean
zipcode_required:
type: boolean
required:
- iso
- iso3
- name
- states_required
- zipcode_required
'404':
description: country not found
content:
application/json:
example:
error:
code: record_not_found
message: Country not found
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v3/store/currencies:
get:
summary: List supported currencies
tags:
- Markets
security:
- api_key: []
description: Returns currencies supported by the store (derived from markets)
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst currencies = await client.currencies.list()"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: currencies found
content:
application/json:
example:
data:
- iso_code: USD
name: United States Dollar
symbol: $
- iso_code: EUR
name: Euro
symbol: €
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Currency'
required:
- data
'401':
description: unauthorized
content:
application/json:
example:
error:
code: invalid_token
message: Valid API key required
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v3/store/locales:
get:
summary: List supported locales
tags:
- Markets
security:
- api_key: []
description: Returns locales supported by the store (derived from markets)
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst locales = await client.locales.list()"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: locales found
content:
application/json:
example:
data:
- code: de
name: de
- code: en
name: English (US)
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Locale'
required:
- data
'401':
description: unauthorized
content:
application/json:
example:
error:
code: invalid_token
message: Valid API key required
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v3/store/markets:
get:
summary: List markets
tags:
- Markets
security:
- api_key: []
description: Returns all markets for the current store with their countries, currency, locales, and tax configuration.
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst markets = await client.markets.list()"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: markets found
content:
application/json:
example:
data:
- id: mkt_UkLWZg9DAJ
name: North America
currency: USD
default_locale: en
tax_inclusive: false
default: true
country_isos:
- US
supported_locales:
- en
- es
countries:
- iso: US
iso3: USA
name: United States of America
states_required: true
zipcode_required: true
- id: mkt_gbHJdmfrXB
name: Europe
currency: EUR
default_locale: de
tax_inclusive: true
default: false
country_isos:
- DE
- FR
supported_locales:
- de
- en
- fr
countries:
- iso: DE
iso3: IS66
name: Germany
states_required: false
zipcode_required: true
- iso: FR
iso3: IS67
name: France
states_required: false
zipcode_required: true
schema:
type: object
properties:
data:
type: array
required:
- data
'401':
description: unauthorized
content:
application/json:
example:
error:
code: invalid_token
message: Valid API key required
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v3/store/markets/{id}:
get:
summary: Get a market
tags:
- Markets
security:
- api_key: []
description: Returns a single market by prefixed ID with its countries, currency, locales, and tax configuration.
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst market = await client.markets.get('mkt_xxx')"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: id
in: path
required: true
description: Market prefixed ID (e.g., "mkt_k5nR8xLq")
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: market found
content:
application/json:
example:
id: mkt_gbHJdmfrXB
name: Europe
currency: EUR
default_locale: de
tax_inclusive: true
default: false
country_isos:
- DE
- FR
supported_locales:
- de
- en
- fr
countries:
- iso: DE
iso3: IS70
name: Germany
states_required: false
zipcode_required: true
- iso: FR
iso3: IS71
name: France
states_required: false
zipcode_required: true
schema:
type: object
'404':
description: market not found
content:
application/json:
example:
error:
code: record_not_found
message: Market not found
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v3/store/markets/resolve:
get:
summary: Resolve market by country
tags:
- Markets
security:
- api_key: []
description: Determine which market applies for a given country ISO code. Useful for auto-selecting the correct currency and locale when a customer's location is known.
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst market = await client.markets.resolve('DE')"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: country
in: query
required: true
description: Country ISO 3166-1 alpha-2 code (e.g., "DE", "US")
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: market resolved
content:
application/json:
example:
id: mkt_gbHJdmfrXB
name: Europe
currency: EUR
default_locale: de
tax_inclusive: true
default: false
country_isos:
- DE
- FR
supported_locales:
- de
- en
- fr
countries:
- iso: DE
iso3: IS74
name: Germany
states_required: false
zipcode_required: true
- iso: FR
iso3: IS75
name: France
states_required: false
zipcode_required: true
schema:
type: object
'404':
description: no market for country
content:
application/json:
example:
error:
code: record_not_found
message: Country not found
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v3/store/markets/{market_id}/countries:
get:
summary: List countries in a market
tags:
- Markets
security:
- api_key: []
description: Returns countries belonging to a specific market. Use this for address form country dropdowns during checkout.
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://your-store.com',\n publishableKey: '<api-key>',\n})\n\nconst countries = await client.markets.countries.list('mkt_xxx')"
parameters:
- name: x-spree-api-key
in: header
required: true
schema:
type: string
- name: market_id
in: path
required: true
description: Market prefixed ID
schema:
type: string
- name: fields
in: query
required: false
description: Comma-separated list of fields to include (e.g., name,slug,price). id is always included.
schema:
type: string
responses:
'200':
description: countries found
content:
application/json:
example:
data:
- iso: FR
iso3: IS79
name: France
states_required: false
zipcode_required: true
- iso: DE
iso3: IS78
name: Germany
states_required: false
zipcode_required: true
schema:
type: object
properties:
data:
type: array
required:
- data
/api/v3/store/markets/{market_id}/countries/{id}:
get:
summary: Get a country in a market
tags:
- Markets
security:
- api_key: []
description: Returns a single country by ISO code within a market. Supports ?expand=states for address forms.
x-codeSamples:
- lang: javascript
label: Spree SDK
source: "import { createClient } from '@spree/sdk'\n\nconst client = createClient({\n baseUrl: 'https://yo
# --- truncated at 32 KB (40 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/spree/refs/heads/main/openapi/spree-markets-api-openapi.yml