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 { 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.
| Setting | Value |
|---|---|
| Base URL | https://api.salla.dev/store/v1 by default. See Base URL. |
| Timeout | 8000 ms per attempt |
| Headers | Added to every request, listed below |
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:
- The
apiBasethe server published into the page, so the browser keeps talking to the backend that rendered it. VITE_API_URL, at build time or from the server's environment.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
| Header | Value | When |
|---|---|---|
accept | application/json | Always |
accept-language | Current locale | Always |
s-source, s-theme-type, s-store-api-version, x-requested-with, and a few others | Fixed identification values | Always |
store-identifier | The resolved store | Unless you set one on the request |
s-version-id | Theme version id | When a version applies |
currency | The currency the shopper chose, such as EUR | When the shopper picked one (see getActiveCurrency) |
Authorization | Bearer <token> | When a token exists |
s-scope-id | Scope id | When a scope is active |
s-scope-type, s-scope-allocation-type, s-scope-allocation-id | From the scope | When 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): stringThe 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.
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:
| Setting | Value |
|---|---|
| Retries | 2 (3 attempts in total) |
| Retried methods | get, put, head, delete, options, trace (never post or patch) |
| Retried statuses | 408, 413, 429, 500, 502, 503, 504 (413 only when the response has a Retry-After header) |
| Retried failures | Network errors (offline, DNS, refused connection) on the retried methods |
| Wait before a retry | 300 ms, then 600 ms |
Retry-After | Honoured for 413, 429 and 503 |
| Retry after a timeout | No |
The timeout applies to each attempt. A failure throws HTTPError (non-2xx), TimeoutError or NetworkError.
Next
- Authentication and scope: where the token, scope and version come from.
- Errors, timeouts and retries: handling the errors above.
- Write your own endpoint
Overview
What the shared API client is, why every request should go through it, and how to make a request in a loader, a component or directly.
Authentication and scope
How each request learns who the customer is and which store, branch and theme version it is for, and what that means for your query keys.