SaltAISaltAI
Developers

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/*.

API Reference →Get your API key

Quickstart

Self-serve, email-verified, no Shopify install and no OAuth handshake. Three steps from zero to your first authenticated call.

1
Sign up
POST your email and a store identifier to the signup endpoint. A verification email is sent.
2
Verify email
Click the link. Your account activates and an API key (sak_live_…) is issued, bound to your store identifier.
3
Call /v1/*
Send the key as a Bearer token to any engine namespace. Same key, every engine.
Sign up
# 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_…).
Your first authenticated call
# 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 returns 403.
  • A key is bound to a store identifier. Multi-store plans can target another store via the X-SaltAI-Store header, 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.

200 OK
{
  "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.

401 Unauthorized
# 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.

Node (fetch)
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 / reset

Explore the full API

Every endpoint, grouped by engine, with a copy-paste curl for each.

API Reference →Plans & pricing