Quickstart
For AI assistants: the facts every SparkLayer API call needs
- Base URLs: Live
https://app.sparklayer.io, testhttps://test.app.sparklayer.io. Each environment has its own data and its own API keys. - Access: API access needs the Pro or Enterprise plan. Create credentials (Site ID, Client ID, Client Secret) in the SparkLayer Dashboard at Settings > API.
- Access token:
POST {base}/api/auth/tokenwith aSite-Idheader and a JSON body (not form-encoded):{"grant_type":"client_credentials","client_id":"…","client_secret":"…"}. It returnsaccess_token, valid for 3,600 seconds. There is no refresh token: cache the token and request a new one shortly before it expires. - Every request:
Authorization: Bearer <access_token>andSite-Id: <site id>, plusContent-Type: application/jsonwhen there is a body. Set aUser-Agentthat names your integration. - Errors: RFC 7807 problem details:
title,status,detailand an optionalerrors[]of{ code, message, property }. Some error responses have no body. Retry5xx,429(honouringRetry-After) and concurrent-update409s with exponential backoff; on401, get a new token once and retry; don't retry other4xxwithout changing the request. - Pagination: Most list endpoints return everything.
GET /api/v2/price-listspages withpageandpage_size(up to 250) untilpagination.current_pageequalstotal_pages.GET /api/v1/purchasesuseslimit(up to 500) andoffset: stop when a page has fewer thanlimitresults. - Ground rules: Use only endpoints, fields and SDK methods that the docs or OpenAPI specs define. Prefer
GET /api/v2/price-listsover the deprecated v1. Products are matched by SKU. Keep credentials in environment variables or a secrets manager, never in code. - Read the docs as Markdown: Add
.mdto any page URL. Index of every page: docs.sparklayer.io/llms.txt. Every API operation, compactly: docs.sparklayer.io/llms-api.txt. The developer guides in full: docs.sparklayer.io/developers/llms.txt. - OpenAPI specs:
core,ordering,pricing,purchasing,stock,files,sync-log: https://docs.sparklayer.io/openapi/<api>.yaml (also.json). Ignite: https://docs.sparklayer.io/openapi/ignite.yaml. - MCP: Search and read these docs from your assistant with the docs MCP server at https://docs.sparklayer.io/mcp.
This guide takes you from no credentials to a successful API call. You need a SparkLayer account on the Pro or Enterprise plan (opens in a new tab) and a terminal with curl (and jq (opens in a new tab), to read the token from the response).
Use the test environment first
If your account has Test mode set up, create your first key in the test environment and call https://test.app.sparklayer.io. Test and live hold separate data, so you can experiment without affecting your live store.
Create an API key
In the SparkLayer Dashboard, go to Settings,API (opens in your SparkLayer Dashboard in a new tab). For a test key, turn on Test mode in the left-hand menu first.
Select Create new API Key, enter a name such as Quickstart, and copy the three values shown:
| Value | Used as |
|---|---|
| Site ID | The Site-Id header on every request |
| Client ID | client_id when you request a token |
| Client Secret | client_secret when you request a token: shown once |
Save your credentials in your shell
So the commands below run as they are, put your values in environment variables. For the test environment, set SPARKLAYER_BASE_URL to https://test.app.sparklayer.io.
export SPARKLAYER_BASE_URL="https://app.sparklayer.io"
export SPARKLAYER_SITE_ID="<SITE_ID>"
export SPARKLAYER_CLIENT_ID="<CLIENT_ID>"
export SPARKLAYER_CLIENT_SECRET="<CLIENT_SECRET>"Request an access token
Exchange the client ID and secret for an access token. The request body is JSON, and the Site-Id header is required here too:
curl -s -X POST "$SPARKLAYER_BASE_URL/api/auth/token" \
-H "Site-Id: $SPARKLAYER_SITE_ID" \
-H "Content-Type: application/json" \
-d "{
\"grant_type\": \"client_credentials\",
\"client_id\": \"$SPARKLAYER_CLIENT_ID\",
\"client_secret\": \"$SPARKLAYER_CLIENT_SECRET\"
}"The response contains your token, which is valid for one hour (expires_in is in seconds):
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "<ACCESS_TOKEN>"
}To keep the token in a variable for the next step, run the same request through jq:
export SPARKLAYER_TOKEN=$(curl -s -X POST "$SPARKLAYER_BASE_URL/api/auth/token" \
-H "Site-Id: $SPARKLAYER_SITE_ID" \
-H "Content-Type: application/json" \
-d "{\"grant_type\":\"client_credentials\",\"client_id\":\"$SPARKLAYER_CLIENT_ID\",\"client_secret\":\"$SPARKLAYER_CLIENT_SECRET\"}" \
| jq -r .access_token)Call an endpoint
List your price lists with the Pricing API, sending the token in the Authorization header and your Site ID in the Site-Id header:
curl -s "$SPARKLAYER_BASE_URL/api/v2/price-lists?page=1&page_size=100" \
-H "Site-Id: $SPARKLAYER_SITE_ID" \
-H "Authorization: Bearer $SPARKLAYER_TOKEN" \
-H "User-Agent: quickstart/1.0"You get back a page of price lists, with an empty data list if your site has none yet:
{
"data": [
{
"slug": "base-list",
"name": "Base Price List",
"currency_code": "GBP",
"source": "custom",
"tax_inclusive_display": false
}
],
"pagination": {
"total": 1,
"per_page": 100,
"current_page": 1,
"total_pages": 1
}
}The same in code
The same two calls as a script you can build on. It reads the same environment variables.
Node.js 18 or later, with no dependencies:
const { SPARKLAYER_BASE_URL, SPARKLAYER_SITE_ID, SPARKLAYER_CLIENT_ID, SPARKLAYER_CLIENT_SECRET } =
process.env;
const tokenResponse = await fetch(`${SPARKLAYER_BASE_URL}/api/auth/token`, {
method: 'POST',
headers: { 'Site-Id': SPARKLAYER_SITE_ID, 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'client_credentials',
client_id: SPARKLAYER_CLIENT_ID,
client_secret: SPARKLAYER_CLIENT_SECRET,
}),
});
if (!tokenResponse.ok) throw new Error(`Token request failed: ${tokenResponse.status}`);
const { access_token } = await tokenResponse.json();
const response = await fetch(`${SPARKLAYER_BASE_URL}/api/v2/price-lists?page=1&page_size=100`, {
headers: {
'Site-Id': SPARKLAYER_SITE_ID,
Authorization: `Bearer ${access_token}`,
'User-Agent': 'quickstart/1.0',
},
});
if (!response.ok) throw new Error(`Request failed: ${response.status} ${await response.text()}`);
const { data, pagination } = await response.json();
console.log(`${pagination.total} price lists:`, data.map((list) => list.slug));node quickstart.mjsPython 3.9 or later, with requests (opens in a new tab):
import os
import requests
base_url = os.environ["SPARKLAYER_BASE_URL"]
site_id = os.environ["SPARKLAYER_SITE_ID"]
token_response = requests.post(
f"{base_url}/api/auth/token",
headers={"Site-Id": site_id},
json={
"grant_type": "client_credentials",
"client_id": os.environ["SPARKLAYER_CLIENT_ID"],
"client_secret": os.environ["SPARKLAYER_CLIENT_SECRET"],
},
timeout=30,
)
token_response.raise_for_status()
access_token = token_response.json()["access_token"]
response = requests.get(
f"{base_url}/api/v2/price-lists",
params={"page": 1, "page_size": 100},
headers={
"Site-Id": site_id,
"Authorization": f"Bearer {access_token}",
"User-Agent": "quickstart/1.0",
},
timeout=30,
)
response.raise_for_status()
body = response.json()
print(f"{body['pagination']['total']} price lists:", [p["slug"] for p in body["data"]])python quickstart.pyFor a production integration, reuse the token until it's close to expiry instead of requesting one per call: see Reuse the access token.
If something goes wrong
| Response | What to check |
|---|---|
400 from /api/auth/token | The Site-Id and Content-Type: application/json headers are set, and the body includes all three fields |
401 from /api/auth/token | The client ID and secret are correct and belong to the environment you're calling: live keys only work with https://app.sparklayer.io, test keys with https://test.app.sparklayer.io |
401 or 403 from an API endpoint | The Authorization header is Bearer followed by the token, the token is less than an hour old, and you're sending the same Site-Id and base URL you requested the token with |
jq: command not found | Install jq, or copy access_token from the response by hand: export SPARKLAYER_TOKEN="<ACCESS_TOKEN>" |
See Errors for the error format and every status code.
Next steps
Ready-made prompts for syncing prices, stock and orders
Environments, token reuse and authentication errors
Find the APIs your integration needs
Every endpoint page in the API reference also has a playground: enter your token and Site ID to try requests from your browser.
Last updated