Authentication
API keys, the X-API-Key header, scopes, and the server-side-only rule.
Every Static Ads Lab API request requires an X-API-Key header.
The header
X-API-Key: sal_live_your_key_hereThat's it. There's no Authorization: Bearer flow, no OAuth. Just one header.
Verify your key
const response = await fetch("https://api.staticadslab.com/v1/account", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const { data } = await response.json();
console.log(data.organization.name);
console.log(data.api_key.scopes);If the key is valid, this returns the organization name and the scopes the key carries. If not, you get 401 UNAUTHORIZED.
Key format
API keys are issued by the dashboard at Settings → API Keys. They have these properties:
- Always start with
sal_live_. - Shown only once — store them in a secrets manager immediately.
- Tied to one organization.
- Carry one or more scopes (see below).
- Can be rotated or revoked at any time from the dashboard.
Scopes
Each key carries a set of scopes. The default scopes cover read/write across the public resources:
| Scope | What it permits |
|---|---|
brands:read / brands:write | List/get brands; create/update/delete brands |
products:read / products:write | List/get products and variants; create/update/delete |
audiences:read / audiences:write | List/get audiences; create/update/delete |
images:read / images:write | List/get images; upload/delete |
design_templates:read / design_templates:write | List/get templates; create/update/delete |
image_ads:read / image_ads:write | List/get ads; generate, patch, delete, sync |
Create one broad key for trusted backend code. Create scoped keys (e.g., read-only) for services that don't need to mutate data.
Server-side only
Never call the Static Ads Lab API from a browser. API keys carry full org permissions and would be exfiltrated. Always:
- Store the key in a secrets manager (Vercel/Railway env vars, AWS Secrets Manager, etc.).
- Call the API from your backend.
- If you need real-time progress in the browser, push updates to the client via your own WebSocket or SSE connection (see Async jobs).
The API does not currently support short-lived client-side tokens. Issue scoped keys per backend service instead.
Rate limiting
The API enforces a rate limit per key (default 100 req / 60 s). If you exceed it, you'll get 429 RATE_LIMIT_EXCEEDED with a Retry-After header. See Rate limits.
Errors
| Status | Code | When |
|---|---|---|
401 | UNAUTHORIZED | Missing or invalid API key |
403 | Various | Valid key, missing scope for the requested action |
429 | RATE_LIMIT_EXCEEDED | Too many requests on this key |
See Errors for the full table.