Client reference

The clients the engine exports, with the headers `api` sets on each request and its timeout and retry numbers.

Look here when you need to know exactly what api sends, or how long it waits. For the reason to use it at all, read the Overview.

import
import { api, cdn, filesCdn } from '@salla.sa/twilight-theme-engine/api/client';

All three are ky instances. ky is a small wrapper around fetch.

api

The client for the Store API. Its methods are api.get, api.post, api.put, api.patch, api.delete and api.head. Each takes a path relative to the base URL and returns a promise with .json(), .text() and so on.

SettingValue
Base URLhttps://api.salla.dev/store/v1 by default. See Base URL.
Timeout8000 ms per attempt
HeadersAdded to every request, listed below
app/lib/example.ts
const { data } = await api.get(`cart/${cartId}`).json<{ data: CartApiResponse }>();

Use paths like 'cart/1'. A per-request timeout, headers, signal or retry option overrides the defaults for that call.

Base URL

The client picks its base URL once, when the module loads, in this order:

  1. The apiBase the server published into the page, so the browser keeps talking to the backend that rendered it.
  2. VITE_API_URL, at build time or from the server's environment.
  3. https://api.salla.dev/store/v1.

A live storefront sets neither, so it uses the default. VITE_API_URL exists to point a preview at another backend.

cdn and filesCdn

Ky instances for static files. cdn has base URL https://cdn.salla.network and filesCdn has https://cdn.files.salla.network; both time out after 5000 ms. They send none of the store, token or scope headers. The translations module uses them.

Headers on every api request

HeaderValueWhen
acceptapplication/jsonAlways
accept-languageCurrent localeAlways
s-source, s-theme-type, s-store-api-version, x-requested-with, and a few othersFixed identification valuesAlways
store-identifierThe resolved storeUnless you set one on the request
s-version-idTheme version idWhen a version applies
currencyThe currency the shopper chose, such as EURWhen the shopper picked one (see getActiveCurrency)
AuthorizationBearer <token>When a token exists
s-scope-idScope idWhen a scope is active
s-scope-type, s-scope-allocation-type, s-scope-allocation-idFrom the scopeWhen the scope has them

The client sets these just before sending, so a value you pass for accept or accept-language is overwritten. Only store-identifier keeps your value. Where the token, scope and version come from is explained in Authentication and scope.

getActiveCurrency

A store can let shoppers see prices in another currency. The Salla SDK keeps the choice in the s-curr cookie. getActiveCurrency() returns that code, such as 'EUR', or null when the shopper kept the store's own currency. Pass a fallback to get it instead of null.

function getActiveCurrency(): string | null
function getActiveCurrency(fallback: string): string

The client sends the same value as the currency header, on the server and in the browser, so the API answers with converted amounts. It reads the request cookie on the server and document.cookie in the browser, and returns only a three-letter code.

app/components/PriceLabel.tsx
import { getActiveCurrency } from '@salla.sa/twilight-theme-engine/api/client';
import { CurrencySymbol } from '@salla.sa/twilight-theme-engine/common';
import type { Product } from '@salla.sa/twilight-theme-engine/types';

export function PriceLabel({ product }: { product: Product }) {
  return (
    <span>
      {product.price} <CurrencySymbol currency={getActiveCurrency(product.currency)} />
    </span>
  );
}

The API converts the amounts but still labels products with the store's own currency (currency: 'SAR' on a Saudi store). Label a converted price with getActiveCurrency(product.currency), not product.currency alone. An amount that has its own currency, such as a past order total, keeps that currency.

useMoney().format already labels amounts with the chosen currency when you pass no currency.

Timeouts and retries

All three keep ky's default retry behaviour:

SettingValue
Retries2 (3 attempts in total)
Retried methodsget, put, head, delete, options, trace (never post or patch)
Retried statuses408, 413, 429, 500, 502, 503, 504 (413 only when the response has a Retry-After header)
Retried failuresNetwork errors (offline, DNS, refused connection) on the retried methods
Wait before a retry300 ms, then 600 ms
Retry-AfterHonoured for 413, 429 and 503
Retry after a timeoutNo

The timeout applies to each attempt. A failure throws HTTPError (non-2xx), TimeoutError or NetworkError.

Next

On this page