One key. Every engine.
No Shopify required.
The SaltAI Platform API exposes every engine behind our Shopify apps — allergens, menus, subscriptions, delivery, catering and more — as a single REST API. Sign up directly, get one Bearer key, and start calling /v1/*.
Quickstart
Self-serve, email-verified, no Shopify install and no OAuth handshake. Three steps from zero to your first authenticated call.
# 1. Sign up — no Shopify, no OAuth
curl -X POST https://api.saltai.app/api/platform/signup \
-H "Content-Type: application/json" \
-d '{
"email": "you@brand.com",
"storeIdentifier": "your-brand"
}'
# → { "customer_id": "...", "status": "pending", "email_sent": true }
# 2. Check your inbox and click the verification link.
# 3. On verify, your API key is issued (sak_live_…).# Every engine is behind one Bearer key.
export SALTAI_KEY="sak_live_xxx"
curl https://api.saltai.app/v1/allergens/products \
-H "Authorization: Bearer $SALTAI_KEY"Authentication
Every request is authenticated with your API key as a Bearer token in the Authorization header. Keys are stored only as a SHA-256 hash — the plaintext sak_live_ value is shown once at issue, so keep it safe.
Authorization: Bearer sak_live_xxx- Keys must be ACTIVE — revoked, expired or pending keys are rejected with
401. - Each key carries a tier and a set of scopes (e.g.
subscriptions:read). Calling a route your scopes don't cover returns403. - A key is bound to a store identifier. Multi-store plans can target another store via the
X-SaltAI-Storeheader, which must match a store your key owns.
The response envelope
Successful responses share one shape: your resource under data, and request metadata under meta — including the request_id (quote it in support requests) and live rate_limit counters.
{
"data": [
{ "id": "prod_123", "title": "Sourdough Loaf", "allergens": ["gluten"] }
],
"meta": {
"request_id": "req_8f2c…",
"rate_limit": {
"limit": 600,
"remaining": 598,
"reset": 1719840000
}
}
}Errors use application/problem+json with an error object carrying type, title, status and detail.
# A missing or inactive key returns 401 with a problem+json body.
{
"error": {
"type": "unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Provide a valid API key via the Authorization header."
}
}Rate limits
Limits are enforced per key, per minute, and scale with your plan — from 60 requests/min on Free up to 30,000/min on Enterprise. Every response reports your current window under meta.rate_limit (limit, remaining, reset). Exceeding it returns 429 with a Retry-After header. See the plan comparison for the per-tier numbers.
Calling from your code
Any HTTP client works — there is no SDK to install. Read the resource from data and the metadata from meta.
const res = await fetch("https://api.saltai.app/v1/menus/categories", {
headers: { Authorization: `Bearer ${process.env.SALTAI_KEY}` },
})
const { data, meta } = await res.json()
console.log(data) // the resource(s)
console.log(meta.request_id) // quote this in any support request
console.log(meta.rate_limit) // limit / remaining / resetExplore the full API
Every endpoint, grouped by engine, with a copy-paste curl for each.