Supercommerce API Docs
Store API

Settings Module — Storefront

HTTP surface for the storefront to read public, platform-wide settings (branding, contact details, currency hints, store toggles, etc.). The whole storefront-public configuration…

HTTP surface for the storefront to read public, platform-wide settings (branding, contact details, currency hints, store toggles, etc.). The whole storefront-public configuration is keyed by a registry that flags each setting as either public: true (exposed here) or admin-only (never exposed here, regardless of group).

Source: api-modules/settings/src/controllers/store-settings.controller.ts.

Admin and vendor settings (key registration, scoped overrides, secrets) live in sibling docs.


Conventions

Authentication

EndpointAuth
GET /store/settingsnone (public)
GET /store/settings/paymentnone (public)
GET /store/settings/:groupnone (public)
GET /store/settings/:group/:keynone (public)

There is no auth on this surface — the only safety is the registry's public flag. Keys without that flag are never exposed here. Unknown groups and keys deliberately return 404 rather than empty payloads so an attacker can't probe for the existence of admin-only configuration.

The flag is scope-independent: most public keys are store-scope, but an admin-scope key flagged public: true is served here too. That is deliberate — an operator-tuned rule the storefront must mirror (reward caps, the points conversion rate) is registered in the admin scope but has to reach the UI. secret: true always wins over public: true, so a mis-flagged credential can't leak through this path. When a group name exists in both scopes (e.g. email), the public keys from each merge into one object.

The one exception is the derived payment group (and its dedicated GET /store/settings/payment route): it is not registry-backed but a curated read exposing only the publishable Razorpay key id — the same value already shipped to the SDK on every payment. Never the key secret or webhook secret.

Response envelope

{
  "data": <payload>,
  "message": "Success",
  "statusCode": 200
}

Error envelope

statusCodeerrorCode examples
404NOT_FOUND
500INTERNAL_SERVER_ERROR, DATABASE_ERROR

Domain types

ScopeSettingsResponse

/** Full-scope response — nested by group, with unknown-typed values. */
type ScopeSettingsResponse = Record<string, Record<string, unknown>>;

GroupSettingsResponse

/** Single-group response — flat key→value. */
type GroupSettingsResponse = Record<string, unknown>;

SettingValueResponse

/** Single-key response — uniform { value } wrapper regardless of underlying type. */
type SettingValueResponse = { value: unknown };

Consumers narrow on known keys at the call site; the response surface keeps unknown because typing every key would drift as the registry evolves.


Endpoints

GET /store/settings — All public settings

Returns the entire public storefront configuration as { <group>: { <key>: <value> } }. Use this for the initial app bootstrap so the storefront has a consistent snapshot of branding, currency, etc. Admin-only keys are filtered out at the service layer.

Response 200

{
  "data": {
    "store_config": {
      "currency_name": "INR",
      "currency_symbol": "₹"
    },
    "branding": {
      "name": "Example Shop",
      "admin_app_name": null, // null → the admin panel shows "Example Shop Admin"
      "vendor_app_name": "Example Shop Sellers",
      "admin_primary_color": "#1e3a8a", // null → panel keeps its built-in theme
      "admin_primary_color_dark": null, // null → derived from the light colour
      "vendor_primary_color": null,
      "vendor_primary_color_dark": null,
      "logo_url": "branding/logo-abc.png", // storage key — prefix NEXT_PUBLIC_ASSETS_URL to render
      "favicon_url": "branding/favicon.png",
      "footer_logo": "branding/footer-logo.png"
    },
    "contact": {
      "email": "help@example.com",
      "phone": "+91 90000 00000"
    },
    "seo": {
      "site_title": "Example Shop",
      "meta_title": "{page} — Example Shop",
      "meta_description": "Shop the best of Example.",
      "og_image": "seo/og-default.png", // storage key
      "twitter_card": "summary_large_image",
      "organization": {
        "name": "Example Shop",
        "url": "https://shop.example.com",
        "same_as": ["https://instagram.com/example"]
      },
      "breadcrumbs": [{ "name": "Home", "url": "/" }]
    }
  },
  "message": "Success",
  "statusCode": 200
}

Asset values are storage keys, not URLs. branding.logo_url, branding.favicon_url, branding.footer_logo, seo.og_image, and organization.logo store an opaque object key (e.g. branding/logo-abc.png). The storefront renders them by prefixing NEXT_PUBLIC_ASSETS_URL.

Public storefront groups

GroupKeys (selected)
store_configcurrency_name (e.g. INR), currency_symbol (e.g. ) — used to render money across the storefront and admin panel
brandingname, admin_app_name, vendor_app_name, admin_primary_color, admin_primary_color_dark, vendor_primary_color, vendor_primary_color_dark, logo_url, favicon_url, footer_logo — the admin and vendor panels read this group anonymously to brand their tab title, sidebar, sign-in logo and theme. Either *_app_name may be null, falling back to "<name> Admin" / "<name> Vendor". A blank *_primary_color leaves that panel on its built-in theme; a blank *_primary_color_dark derives the dark-theme variant from the light one
contactemail, phone
seosite_title, site_description, meta_title, meta_description, meta_keywords, canonical_base_url, robots, og_title, og_description, og_image, twitter_card, twitter_handle, organization (schema.org Organization), breadcrumbs (schema.org BreadcrumbList)
storefront_urlsstore_url (storefront base, e.g. https://shop.example.com), content_page_path, product_path, category_path, brand_path, product_tag_path, ingredient_path, vendor_path — each path carries a :slug placeholder; defaults mirror the live storefront routes. Used by the dashboards to build "open on store" links
sold_last_monthenabled only — whether product pages show a "sold last month" count (see Product Sold Metrics). The render_rules key in this group is admin-only and never exposed here.
product_cartbuy_now_enabled — whether the product page shows Buy Now. show_stock_quantity — whether stock.availableQuantity carries a number on GET /store/products/:slug (the count is withheld server-side when false, so this key is informational for the storefront, not the gate). gift_progress_bar_enabled — whether the cart exposes the free-gift spend ladder for GET /store/cart/gifts/progress to render as a milestone bar; turning it off leaves the rules firing (gifts still attach) but the bar disappears. show_available_coupons — whether the cart and checkout render the 'Available Coupons' browser over GET /store/cart/coupons/eligible; manual code entry stays available either way. show_product_page_coupons — whether the product page renders the coupons from GET /store/discounts/applicable. auto_apply_coupon — whether a cart line change auto-applies the highest-saving eligible show-on-cart coupon; fires at most once per cart, and never overrides a coupon the customer applied themselves (see Cart). The low_stock_threshold key in this group is admin-only.
back_in_stockenabled, guest_enabled — whether to offer "notify me" on a sold-out variant, and whether a shopper without an account may use it (see Back in Stock). The max_active_per_email and expiry_days keys in this group are admin-only.
appapi_base_url, app_update, google_auth_visibility — launch-time configuration for the native apps (see below)
reviewsrequire_verified_purchase — whether the storefront should hide its review form from customers without a completed order for the product (see Reviews). Every other key in the reviews group (vendor moderation permissions, auto_approve, max_images_per_review) is admin-only.
klaviyopublic_api_key — the Klaviyo site id the native apps and onsite JS pass to the Klaviyo client SDK (see below). Every other key in the klaviyo group is admin-only.
paymentrazorpay{ keyId } (derived — see below)

Klaviyo client SDK key

klaviyo.public_api_key is the operator's Klaviyo public API key (site id) — the value Klaviyo's own iOS/Android SDKs and onsite JS embed in shipped clients. It is registered in the admin scope but flagged public, so the apps read it anonymously alongside the rest of the launch config, or on its own:

// GET /store/settings/klaviyo
{
  "data": { "public_api_key": "AbC123" },
  "message": "Success",
  "statusCode": 200
}

An empty string means the operator hasn't set one — skip SDK initialisation rather than passing a blank key. The private API key that drives server-side sync is never exposed here; it lives in integration_credentials and is set from the admin connect flow.

App configuration

The native apps read this group at launch, before anyone signs in — fetch it on its own with GET /store/settings/app, which returns the three keys flat:

{
  "data": {
    "api_base_url": "https://api.example.com",
    "app_update": {
      "android_build_version": "1.54.26",
      "android_build_number": "98",
      "ios_build_version": "1.54.26",
      "ios_build_number": "1",
      "is_required": true,
      "is_forcefully": true,
      "appstore_link": "https://apps.apple.com/in/app/beauty-barn-korean-skincare/id1598317441",
      "playstore_link": "https://play.google.com/store/apps/details?id=com.beautybarn.mobile",
      "update_message": ""
    },
    "google_auth_visibility": {
      "ios_version": "1.54.26",
      "ios_build": "1",
      "google_auth_button_is_visible": true
    }
  },
  "message": "Success",
  "statusCode": 200
}

api_base_url is the origin the apps route their API calls through, so a backend move ships without an app-store release. The app needs an origin compiled in to make this call in the first place — a blank value means "keep using that one", not "no API".

app_update carries the build each platform should be on plus how hard to push users there: is_required prompts an update, is_forcefully blocks use until it happens, and update_message overrides the default copy when non-empty. Build numbers are strings because the stores treat them as opaque.

The registry defaults for app_update and google_auth_visibility are the current live build and store links, not neutral placeholders — a deployment for another operator must override them under Settings → Store → App Settings before the apps read this endpoint.

google_auth_visibility hides the Google sign-in button on the single iOS build identified by ios_version + ios_build — the switch for a build under App Store review. Other builds are unaffected; blanking both keeps the button visible everywhere.

GET /store/settings/payment — Publishable payment config

The publishable Razorpay key id, so the storefront or a mobile app (Flutter / Android / iOS) can initialise the Razorpay SDK from a single anonymous fetch — no admin token, no checkout round-trip. The same object is included under the payment group of GET /store/settings.

Only the publishable key is exposed; key_secret and webhook_secret are never returned. Which Razorpay flows (standard / Magic) are live is read separately from the per-platform enabled-providers settings, so it is intentionally not duplicated here.

Response 200

{
  "data": {
    "razorpay": {
      "keyId": "rzp_test_xxxxxxxx" // "" when unset
    }
  },
  "message": "Success",
  "statusCode": 200
}

GET /store/settings/:group — Public settings for one group

Returns the flat { <key>: <value> } map for a single group. The whole group must contain at least one public key — a group whose keys are all admin-only returns 404.

Path params

NameNotes
groupGroup identifier (e.g. branding, contact, commerce). Case-sensitive.

Response 200

{
  "data": {
    "logo_url": "https://cdn.example/logo.png",
    "store_name": "Example Shop"
  },
  "message": "Success",
  "statusCode": 200
}

Errors

StatusCodeWhen
404NOT_FOUNDGroup has no public keys registered (either the group doesn't exist or every key in it is admin-only)

GET /store/settings/:group/:key — Single public setting

Returns { value: <unknown> } for a single key.

Path params

NameNotes
groupGroup identifier
keySetting key within the group

Response 200

{
  "data": { "value": "https://cdn.example/logo.png" },
  "message": "Success",
  "statusCode": 200
}

Errors

StatusCodeWhen
404NOT_FOUNDKey is not registered, or is not flagged public

  • Admin / vendor settings surfaces — share the same underlying SettingsService, but expose admin- and vendor-scoped registry keys. See docs/separated/admin/settings.md and docs/separated/vendor/settings.md.

On this page