Markets

Markets on revenexx — locales, currencies and tax classes as sub-resources, the storefront bootstrap, the readiness diagnosis, and clone, backfill and make-default.

A market is a distinct business context inside a tenant: a country, a region, or a storefront segment such as B2C versus B2B. It has a base currency, the locales it renders in, the currencies it trades in, and its own tax classes.

Base path: https://api.revenexx.com/v1/markets.

The row

FieldMeaning
codeStable identifier. Most routes on this page accept it in place of the uuid.
name, labelsDisplay name, and localized names.
currencyThe market's base currency.
statusactive or inactive.
is_defaultA tenant has one default market — what every call naming none falls back to.
positionSort order.

Do not create a market — clone one

Request
curl -X POST https://api.revenexx.com/v1/markets \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..." \
  -H "Content-Type: application/json" \
  -d '{"code":"at","name":"Austria","currency":"EUR"}'

POST /v1/markets needs a code and a name, and it leaves a row that cannot serve anybody: no locale to render in, no currency registered to price in, no rate to tax with.

Request
curl -X POST "https://api.revenexx.com/v1/markets/de/clone" \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..." \
  -H "Content-Type: application/json" \
  -d '{"code":"at","name":"Austria"}'

Clone takes the source market's locales, traded currencies and tax classes with it in a single call, so what comes back is a market that can trade. The path id is the source. It resolves by uuid or by market code.

The three sub-resources

Each is a full CRUD collection under a market, and each carries a code, an is_default flag and a position.

Sub-resourcePath
Locales/v1/markets/{market_id}/locales
Currencies/v1/markets/{market_id}/currencies
Tax classes/v1/markets/{market_id}/tax_classes

market_id is filled from the route path on write and never read out of the body. Deleting the market cascades to all three.

Locales

Locale
{ "code": "de-AT", "language": "de", "country": "AT", "is_default": true, "position": 0 }

code is language-COUNTRY, unique per market, and it is the key a translation is stored under. language and country are stored separately so a client can group markets by language without parsing.

country here is a spelling of the language, not a shipping destination — a market may register de-AT and ship nowhere near Austria.

is_default is the locale a storefront renders when the request asks for none. At most one per market; where none carries the flag, the lowest position wins.

Currencies

Currency
{ "code": "CHF", "is_default": false, "position": 10 }

One entry per currency this market trades in, as opposed to the single base currency on the market row. is_default is what is offered first to a buyer stating no preference, and it should be the market's base currency — readiness reports it when it is not.

Nothing converts. A price list in another currency simply does not price the item. Registering a currency here does not create prices in it.

Tax classes

Tax class
{ "code": "reduced", "name": "Reduced rate", "rate": 7, "is_default": false,
  "labels": { "de-DE": "Ermäßigter Satz" } }

code is the rate bucket a product or a shipping method is assigned to — standard, reduced, zero — and other apps resolve against it by code. A product's tax_class column and a shipping method's tax class are both plain text naming one of these.

rate is in percent, 0–100. 20 means 20 %, not 0.2. Whether a stored price already contains it is a separate question, answered per price list.

is_default is applied to a line naming none. labels is a flat {locale: label} map for storefronts and invoices.

The storefront bootstrap

Request
curl "https://api.revenexx.com/v1/markets/{id}/context" \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..."

One call instead of five, and — more to the point — one place the resolution rules live rather than a slightly different copy in every storefront. It answers:

KeyIs
marketThe market row.
locales, currencies, tax_classesAll three collections in position order, capped at 200 each.
default_localeWhich locale to render in, and source naming where that answer came from — a locale flagged default, the first by position, or a tenant fallback.
locale_policyThe key a client writes a translation under, and the order it reads — resolved, not named.
pricingWhether a stored price in this market is net or gross.
readinessWhether any of it is trustworthy.
This route resolves the market by id only. Unlike readiness, clone and backfill, a market code here is a 400, not a lookup.

locales being empty is a real answer — read default_locale before assuming a language.

For a surface that stands in no market at all — a Cockpit editing a tenant-level default rather than one market's value — GET /v1/markets/locale-policy answers the union of every market's locales, each already resolved to the key it is written under, and each naming the markets that asked for it. A tenant-level value has to be readable by every market, and an editor listing six inputs without saying who needs them invites translations nobody will read.

Readiness is a diagnosis, not a yes/no

Request
curl "https://api.revenexx.com/v1/markets/at/readiness" \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..."

Every check runs on every call and comes back with its own severity.

  • Blocking turns ready false: no currency registered means nothing to price in; no tax class means nothing to tax with.
  • Warning leaves the market serviceable: no locale of its own, while the tenant declares a fallback that covers for it.

Resolves by uuid or market code.

Repairing a market

Request
curl -X POST "https://api.revenexx.com/v1/markets/at/backfill" \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..." \
  -H "Content-Type: application/json" \
  -d '{"source":"de"}'

Repairs the market in the path out of a source market that is already right. The two are compared by code, collection by collection, and only the codes the target does not already carry are added — so a locale, currency or tax class it already holds is left exactly as the merchant left it, rate included, and is never overwritten.

Idempotent: running it twice adds nothing the second time. Both ids resolve by uuid or code.

Moving the default flag

Request
curl -X POST "https://api.revenexx.com/v1/markets/at/make-default" \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..." \
  -H "Content-Type: application/json" \
  -d '{}'

One call promotes the market in the path and demotes whoever held the flag, in the same operation. Doing it from a client as promote-then-demote leaves two defaults when the second write does not land, and none when the first does.

It writes once per row that was actually wrong and touches nothing else. It answers the market plus the codes it demoted; repeating the call writes nothing. Accepts an id or a code.

Where to go next

  • Channels — the other scoping axis.
  • Price lists — what resolves against a currency and a tax class.
  • Settings — per-market configuration, and the header's effect on writes.
  • Market concept — making your own app's entities market-scoped.
Was this page helpful?