Settings

Reading a commerce app's effective settings on revenexx — GET /v1/settings/apps/{app}, the market → tenant → default precedence, masked values, and what X-Revenexx-Market does on a write.

Almost every "why did it behave that way" question in this section ends at a setting. The commerce apps put policy in settings.json rather than in code, so a merchant changes it and no release happens — and one gateway route reads the resolved answer.

Read an app's effective settings

Request
curl "https://api.revenexx.com/v1/settings/apps/inventories?market=de" \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..."
Response keyIs
appThe app these settings belong to.
settingsSetting key → effective value.
marketThe market the values were resolved for; absent or null when tenant-level.
maskedThe keys of sensitive settings: present here but omitted from settings.

The market query parameter resolves market-scoped settings for that market code and falls back to the tenant value. Omit it for the tenant-level answer.

This is a read route. There is no public write route for app settings — an operator edits them in the Cockpit settings form the app's settings.json generates. If your integration needs to change one, that is a Cockpit action, not an API call you make.

The precedence

text
per-market value  →  tenant value  →  the schema's declared default

Three consequences worth planning for:

  • A setting always has a value. Every declared setting carries a default, so a fresh tenant that has configured nothing still behaves.
  • A market-scoped setting falls back, it does not disappear. Reading one for a market nobody configured gives the tenant value.
  • A tenant-scoped setting ignores market. Passing a market code to a setting declared scope: "tenant" changes nothing.

Sensitive settings are masked

A setting declared sensitive is stored encrypted and never returned in settings — its key appears in masked instead. That is how a form can show "a value is set" without reading it back, and it is the same rule PSP credentials follow in the payments app.

To rotate one, write the new value. There is no way to read the current one.

What a setting looks like

A setting is declared in the owning app's settings.json, which is an App Studio file — see App model. The shape matters here because it is what the route answers about:

settings.json
{
  "$schema": "https://schemas.revenexx.com/settings.schema.json",
  "settings": {
    "allocation_strategy": {
      "title": { "en": "Allocation strategy", "de": "Zuteilungsstrategie" },
      "description": { "en": "How a reservation picks its location." },
      "type": "enum",
      "scope": "market",
      "default": "priority",
      "enum_values": ["priority", "nearest", "single_location"],
      "group": "allocation"
    }
  }
}
FieldNote
typestring, number, boolean, enum or json. It picks the Cockpit form input.
scopetenant (one value globally) or market (per market, with tenant fallback).
defaultRequired in practice — it is what makes a fresh tenant work.
vocabularyA qualified {app}.{name} id supplying the options, instead of retyping them. Use it whenever the owning app lets a tenant edit those values.
enum_valuesThe fallback when vocabulary is also set — used only while the owning app cannot answer.
sensitiveStored encrypted, masked on read.
groupSettings sharing a group render under one collapsible section.

A market-scoped setting requires the markets app as a dependency.

X-Revenexx-Market — what it actually does

This is the header most worth getting right, and its effect on a write and a read are not the same thing.

On a write it assigns

Creating a row with the header records that row against that market, and it is then visible only there. Creating one without leaves it unassigned.

Unassigned means visible in every market, not hidden. That is a property of the stored row, not of the request — so a row created without the header cannot be "fixed" by sending the header on a later read.

On a read it is normally a no-op

The market filter lives in the scoped database views, and capability routes read the underlying tables — so a list or a get returns the same rows whether or not you send the header. Omitting it does not restrict you to global rows.

Two exceptions

POST /v1/prices/resolve and POST /v1/shipping/rates do read through scoped views. There the header restricts the candidate price lists and shipping methods to this market plus the unassigned ones.

It is never a security boundary

The tenant is fixed by the credential. A market is a business context, not an access control.

See Market concept for making your own app's entities market-scoped, and Markets for what a market holds.

Settings named in this section

A partial index, to save you hunting. Read the live definitions from the route above; these are the ones this section's pages refer to.

AppSettings
productsnew_products_enabled_by_default, default_product_family, default_label_attribute, default_asset_family, allow_external_media, external_media_allowed_hosts
customersregistration_mode, registration_reason_disclosed, organization_vat_id_required, primary_contact_required, blocked_contact_behavior, custom_roles_enabled
cartsmulti_cart_enabled, cart_merge_strategy, price_snapshot_mode, convert_reserves_stock, abandon_after_minutes, cart_ttl_days, guest_cart_ttl_days
orderlistsdefault_kind, max_items_per_list, max_lists_per_owner, cart_merge_mode
ordersorder_number_range_code, delivery_number_range_code, return_number_range_code, auto_complete_on, on_hold_blocks, cancel_requires_reason, allow_modification_after_acknowledge, require_approval_above_value, max_items_per_order, default_comment_visibility, default_currency
inventoriesdefault_location_code, allocation_strategy, backorder_policy, reservation_ttl_minutes, movement_reason_required, restock_on_return_default, reorder_point_default, reorder_alert_enabled
pricesdefault_price_list_code, price_list_priority_tiebreak
paymentsdefault_provider, auto_capture_policy, capture_expiry_days, refund_window_days, payment_reminder_after_days, overdue_after_days, webhook_stale_after_minutes, fee_display
shippingshipping_tax_class
marketsfallback_locale, prices_include_tax, locale_granularity, locale_fallback
channelsunassigned_channel_visibility

Where to go next

  • Markets — what a market is, and its readiness.
  • Market concept — declaring your own entities market-scoped.
  • App model — where settings.json sits among an app's files.
  • Value lists — the other configuration surface, which is data rather than settings.
Was this page helpful?