API Client Overview
Introduction to WhataloClient — the typed REST client for accessing store data from your plugin's server-side code.
The WhataloClient is a typed REST client for accessing store data from your plugin's server-side code. Every method maps directly to a Whatalo REST endpoint and returns fully-typed responses.
Security Model
The Whatalo API uses API keys for authentication. API keys are server-side credentials only — they must never be included in client-side JavaScript, browser code, or plugin frontend code.
Architecture
Plugin Frontend (iframe) Plugin Backend (your server) Whatalo API
│ │ │
│ 1. sessionToken() │ │
│──────────────────────────► │ │
│ 2. Bearer <session-token> │ │
│──────────────────────────► │ │
│ 3. Verify token with WHATALO_CLIENT_SECRET │
│ │ │
│ 4. X-API-Key: wk_live_* │
│ │──────────────────────────►│
│ │ 5. Response data │
│ │◄──────────────────────────│
│ 6. Filtered data back │ │
│◄───────────────────────── │ │What Goes Where
| Component | Has API Key? | Has Session Token? | Calls API Directly? |
|---|---|---|---|
| Plugin Frontend (iframe) | No — never | Yes — short-lived JWT | No — never |
| Plugin Backend (your server) | Yes — WHATALO_API_KEY | Yes — validates from frontend | Yes |
| Whatalo Admin (host) | N/A | Yes — issues tokens | N/A |
The WhataloClient is intended exclusively for your backend. See Session Tokens for how your frontend authenticates with your backend, and Authentication for the full picture.
Choosing Between Frontend and Backend Access
Use the smallest layer that fits the job:
| Need | Recommended layer |
|---|---|
Session context in the iframe (storeId, storeName, locale, theme) | useWhataloContext() |
Read-only store data in the iframe (orders, products, store.timezone) | useWhataloData() |
| Writes, webhooks, exports, or trusted server logic | WhataloClient |
If your plugin only needs read-only data in the frontend, prefer Data Bridge over creating a backend just to proxy reads.
Installation
The client ships inside @whatalo/plugin-sdk — no additional package needed.
import { WhataloClient } from "@whatalo/plugin-sdk";
const client = new WhataloClient({
apiKey: process.env.WHATALO_API_KEY!,
// baseUrl defaults to "https://api.whatalo.com/v1"
});Constructor Options
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Required. Store-scoped API key (wk_live_* or wk_test_*) |
baseUrl | string | https://api.whatalo.com/v1 | API base URL |
timeout | number | 30000 | Request timeout in milliseconds |
retries | number | 0 | Retry count for 5xx errors (0–3). Exponential backoff: 2s, 4s, 8s |
fetch | Function | globalThis.fetch | Custom fetch implementation (useful for testing) |
onRequest | Function | — | Callback invoked before each request |
onResponse | Function | — | Callback invoked after each response (includes duration) |
Authentication
Every request automatically includes:
X-API-Key: <apiKey>
Content-Type: application/jsonYour apiKey is store-scoped. It is issued when a merchant installs your plugin. Never expose it client-side.
Rate Limit Headers
The client reads rate limit headers from every response and exposes them via client.rateLimit:
const products = await client.products.list({ page: 1, per_page: 25 });
// Read current rate limit state after any request
console.log(client.rateLimit);
// { limit: 100, remaining: 97, reset: 1709280000 }| Field | Description |
|---|---|
limit | Maximum requests per window |
remaining | Requests remaining in the current window |
reset | Unix timestamp when the window resets |
Resource Namespaces
The client exposes 8 resource namespaces. Each namespace covers one area of the merchant's store.
| Namespace | Description |
|---|---|
client.products.* | Product catalog management |
client.orders.* | Order retrieval and status updates |
client.customers.* | Customer data access |
client.categories.* | Product category management |
client.discounts.* | Discount code management |
client.store.* | Store configuration and metadata |
client.inventory.* | Inventory tracking and adjustments |
client.webhooks.* | Webhook subscription management |
Quick Example
import { WhataloClient } from "@whatalo/plugin-sdk";
const client = new WhataloClient({
apiKey: process.env.WHATALO_API_KEY!,
});
// List the first page of active products
const { data, pagination } = await client.products.list({
page: 1,
per_page: 25,
status: "active",
});
console.log(`${pagination.total} total products`);
// Fetch a single order by ID
const order = await client.orders.get("order-id-123");
console.log(order.status);
// Read current store information
const store = await client.store.get();
console.log(store.currency);Retry Behaviour
When retries is set, the client automatically retries on 5xx responses using exponential backoff:
const client = new WhataloClient({
apiKey: process.env.WHATALO_API_KEY!,
retries: 3, // Retry up to 3 times on server errors
});| Attempt | Delay before retry |
|---|---|
| 1st retry | 2 seconds |
| 2nd retry | 4 seconds |
| 3rd retry | 8 seconds |
On 429 Rate Limited responses, the client does not retry automatically unless retries > 0. Use the RateLimitError.retryAfter field to schedule your own delay. See Errors & Rate Limits for full details.