# Developer documentation

URL: https://docs.sparklayer.io/developers

Build on SparkLayer with the REST APIs, JavaScript SDK, storefront templates and Ignite, and make your first authenticated API call in a few minutes.

SparkLayer adds B2B ordering to the eCommerce platform you already use, such as Shopify. These pages are for developers who connect SparkLayer to other systems, or change how it works on a store.

New to SparkLayer? Start with [How SparkLayer connects](https://docs.sparklayer.io/developers/architecture.md). It explains which system holds which data, and that decides what you need to build.

## Choose what to build

- [REST APIs](https://docs.sparklayer.io/developers/api.md): Send price lists, stock levels and orders between your business systems, such as an ERP, and SparkLayer.
- [Frontend integration](https://docs.sparklayer.io/developers/frontend.md): Add SparkLayer to your store's theme, hide retail-only parts of the page from B2B customers, and match it to your design.
- [JavaScript SDK](https://docs.sparklayer.io/developers/javascript-sdk.md): Write your own code to change how SparkLayer behaves on your store, or build a headless storefront.
- [Templates](https://docs.sparklayer.io/developers/templates.md): Change the invoice and quote PDFs, and the emails SparkLayer sends, with Liquid templates.
- [Ignite](https://docs.sparklayer.io/ignite.md): Use SparkLayer on an eCommerce platform it doesn't have a ready-made integration for.
- [Data and limits](https://docs.sparklayer.io/developers/data.md): Look up metafield keys for product, customer and order data, and the limits to design around.

Not sure which you need? [Building integrations](https://docs.sparklayer.io/developers/building-integrations.md) compares building on the API yourself with using a middleware partner, or [ask our support team](https://docs.sparklayer.io/help/support.md).

## Make your first API call

**Step 1.** **Check your plan**

API access is on the [Pro and Enterprise plans](https://www.sparklayer.io/pricing/).

**Step 2.** **Follow the quickstart**

The [quickstart](https://docs.sparklayer.io/developers/quickstart.md) takes you from no credentials to a working API call: create an API key, get an access token and call an endpoint.

**Step 3.** **Learn the rules every call follows**

How to [authenticate](https://docs.sparklayer.io/developers/authentication.md), what the APIs return when something goes wrong ([errors](https://docs.sparklayer.io/developers/errors.md)), and how long lists come back in pages ([pagination](https://docs.sparklayer.io/developers/pagination.md)).

**Step 4.** **Pick the APIs you need**

The [API overview](https://docs.sparklayer.io/developers/api.md) says what each API does and which ones most integrations use.

## Build with AI

These docs are written to work with AI assistants. Pick a ready-made prompt below, add a line about your setup, and open it in Claude or ChatGPT. Each prompt tells the assistant which pages to read and what a finished, production-ready result looks like. [Build with AI](https://docs.sparklayer.io/developers/build-with-ai.md) has every prompt, plus the docs MCP server and the OpenAPI specs.

### Sync prices from your ERP

Push price lists and SKU prices from your ERP or PIM into SparkLayer on a schedule.

```text
I want you to build a scheduled job that keeps my B2B price lists and prices in SparkLayer in step with my ERP, using SparkLayer, the B2B ordering platform.
My setup: [describe your system, language and hosting]

Before writing any code, read these SparkLayer docs (Markdown versions):
- https://docs.sparklayer.io/developers/authentication.md: getting and using an access token
- https://docs.sparklayer.io/developers/api/pricing.md: how price lists and prices fit together
- https://docs.sparklayer.io/developers/api/pricing/get-price-lists-v2.md: listing existing price lists (paginated)
- https://docs.sparklayer.io/developers/api/pricing/create-a-price-list.md: creating missing price lists
- https://docs.sparklayer.io/developers/api/pricing/update-pricing-by-price-list.md: updating the prices in one price list
- https://docs.sparklayer.io/developers/api/pricing/update-pricing-for-multiple-price-lists.md: updating prices across price lists in one call
- https://docs.sparklayer.io/developers/api/sync-log.md: recording each sync so it shows in the SparkLayer Dashboard
- https://docs.sparklayer.io/developers/errors.md: error format and retries
- https://docs.sparklayer.io/developers/pagination.md: paging through price lists
If you can use MCP, connect to the SparkLayer docs MCP server (https://docs.sparklayer.io/mcp) to search the docs and fetch any API operation.

Facts that apply to every SparkLayer API call:
- Base URLs: Live `https://app.sparklayer.io`, test `https://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/token` with a `Site-Id` header and a JSON body (not form-encoded): `{"grant_type":"client_credentials","client_id":"…","client_secret":"…"}`. It returns `access_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>` and `Site-Id: <site id>`, plus `Content-Type: application/json` when there is a body. Set a `User-Agent` that names your integration.
- Errors: RFC 7807 problem details: `title`, `status`, `detail` and an optional `errors[]` of `{ code, message, property }`. Some error responses have no body. Retry `5xx`, `429` (honouring `Retry-After`) and concurrent-update `409`s with exponential backoff; on `401`, get a new token once and retry; don't retry other `4xx` without changing the request.
- Pagination: Most list endpoints return everything. `GET /api/v2/price-lists` pages with `page` and `page_size` (up to 250) until `pagination.current_page` equals `total_pages`. `GET /api/v1/purchases` uses `limit` (up to 500) and `offset`: stop when a page has fewer than `limit` results.
- Ground rules: Use only endpoints, fields and SDK methods that the docs or OpenAPI specs define. Prefer `GET /api/v2/price-lists` over the deprecated v1. Products are matched by SKU. Keep credentials in environment variables or a secrets manager, never in code.

Steps:
1. Read the price lists and prices (including any quantity price breaks) from my ERP.
2. Fetch every SparkLayer price list with `GET /api/v2/price-lists`, following the pagination.
3. Create any price list that exists in my ERP but not in SparkLayer with `POST /api/v1/price-lists`, as the Pricing API docs describe for price lists managed by an external system.
4. Send the prices for each price list with `PATCH /api/v1/price-lists/{slug}/pricing`, or several price lists at once with `PATCH /api/v1/batch-update-pricing`, matching products by SKU and keeping each request within the documented limits.
5. Record each run with the Sync Logging API: a full sync for a complete run, a partial sync for changes only.

Requirements:
- Keep credentials (Site ID, Client ID, Client Secret) in environment variables or a secrets manager, never in code.
- Cache the access token and request a new one shortly before it expires.
- Retry 5xx, 429 (honouring Retry-After) and concurrent-update 409 responses with exponential backoff; on a 401, get a new token once and retry. Log every failed request with its status, `title` and `detail`.
- Make each run safe to repeat, so a failed run can simply be run again.
- Add a dry-run mode that logs what would change without calling the write endpoints.
- Only send prices that changed since the last successful run, if my ERP can tell me.
- Report SKUs that SparkLayer rejects, with the reason from the error response.
- Use only endpoints, fields and SDK methods that the docs define. If something I need isn't documented, say so instead of guessing.

Start by asking me anything you need to know about my setup. Then give me a short plan, the complete code, how to configure and run it, and how to test it against the SparkLayer test environment first.
```

### Keep stock levels in sync

Send stock levels per SKU and location from your ERP or WMS every few minutes.

```text
I want you to build a scheduled job that keeps SparkLayer stock levels in step with my stock system, using SparkLayer, the B2B ordering platform.
My setup: [describe your system, language and hosting]

Before writing any code, read these SparkLayer docs (Markdown versions):
- https://docs.sparklayer.io/developers/authentication.md: getting and using an access token
- https://docs.sparklayer.io/developers/api/stock.md: stock levels and stock locations
- https://docs.sparklayer.io/developers/api/stock/list-stock-locations.md: the stock locations SparkLayer knows about
- https://docs.sparklayer.io/developers/api/stock/update-stock-levels.md: updating stock for many SKUs in one call
- https://docs.sparklayer.io/developers/api/sync-log.md: recording each sync
- https://docs.sparklayer.io/developers/errors.md: error format and retries
If you can use MCP, connect to the SparkLayer docs MCP server (https://docs.sparklayer.io/mcp) to search the docs and fetch any API operation.

Facts that apply to every SparkLayer API call:
- Base URLs: Live `https://app.sparklayer.io`, test `https://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/token` with a `Site-Id` header and a JSON body (not form-encoded): `{"grant_type":"client_credentials","client_id":"…","client_secret":"…"}`. It returns `access_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>` and `Site-Id: <site id>`, plus `Content-Type: application/json` when there is a body. Set a `User-Agent` that names your integration.
- Errors: RFC 7807 problem details: `title`, `status`, `detail` and an optional `errors[]` of `{ code, message, property }`. Some error responses have no body. Retry `5xx`, `429` (honouring `Retry-After`) and concurrent-update `409`s with exponential backoff; on `401`, get a new token once and retry; don't retry other `4xx` without changing the request.
- Pagination: Most list endpoints return everything. `GET /api/v2/price-lists` pages with `page` and `page_size` (up to 250) until `pagination.current_page` equals `total_pages`. `GET /api/v1/purchases` uses `limit` (up to 500) and `offset`: stop when a page has fewer than `limit` results.
- Ground rules: Use only endpoints, fields and SDK methods that the docs or OpenAPI specs define. Prefer `GET /api/v2/price-lists` over the deprecated v1. Products are matched by SKU. Keep credentials in environment variables or a secrets manager, never in code.

Steps:
1. Read current stock levels per SKU (and per warehouse, if I have several) from my stock system.
2. Map my warehouses to SparkLayer stock locations from `GET /api/v1/stock-locations`, and tell me if any are missing rather than guessing.
3. Send the levels with `POST /api/v1/batch-update-stock`, matching products by SKU, in batches within the documented limits.
4. Record each run with the Sync Logging API.

Requirements:
- Keep credentials (Site ID, Client ID, Client Secret) in environment variables or a secrets manager, never in code.
- Cache the access token and request a new one shortly before it expires.
- Retry 5xx, 429 (honouring Retry-After) and concurrent-update 409 responses with exponential backoff; on a 401, get a new token once and retry. Log every failed request with its status, `title` and `detail`.
- Make each run safe to repeat, so a failed run can simply be run again.
- Add a dry-run mode that logs what would change without calling the write endpoints.
- Send only SKUs whose stock changed since the last run, if my system can tell me.
- Never send a negative stock level unless the docs say it is allowed.
- Use only endpoints, fields and SDK methods that the docs define. If something I need isn't documented, say so instead of guessing.

Start by asking me anything you need to know about my setup. Then give me a short plan, the complete code, how to configure and run it, and how to test it against the SparkLayer test environment first.
```

### Send B2B orders to your ERP

Pick up new and updated B2B orders from SparkLayer and create them in your ERP.

```text
I want you to build a job that picks up new and updated B2B orders from SparkLayer and creates or updates them in my ERP, using SparkLayer, the B2B ordering platform.
My setup: [describe your system, language and hosting]

Before writing any code, read these SparkLayer docs (Markdown versions):
- https://docs.sparklayer.io/developers/authentication.md: getting and using an access token
- https://docs.sparklayer.io/developers/api/purchasing.md: what a purchase is and how orders, quotes and carts differ
- https://docs.sparklayer.io/developers/api/purchasing/get-purchases.md: listing orders with filters
- https://docs.sparklayer.io/developers/api/purchasing/get-purchase.md: fetching one order in full
- https://docs.sparklayer.io/developers/pagination.md: offset paging through purchases
- https://docs.sparklayer.io/developers/errors.md: error format and retries
If you can use MCP, connect to the SparkLayer docs MCP server (https://docs.sparklayer.io/mcp) to search the docs and fetch any API operation.

Facts that apply to every SparkLayer API call:
- Base URLs: Live `https://app.sparklayer.io`, test `https://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/token` with a `Site-Id` header and a JSON body (not form-encoded): `{"grant_type":"client_credentials","client_id":"…","client_secret":"…"}`. It returns `access_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>` and `Site-Id: <site id>`, plus `Content-Type: application/json` when there is a body. Set a `User-Agent` that names your integration.
- Errors: RFC 7807 problem details: `title`, `status`, `detail` and an optional `errors[]` of `{ code, message, property }`. Some error responses have no body. Retry `5xx`, `429` (honouring `Retry-After`) and concurrent-update `409`s with exponential backoff; on `401`, get a new token once and retry; don't retry other `4xx` without changing the request.
- Pagination: Most list endpoints return everything. `GET /api/v2/price-lists` pages with `page` and `page_size` (up to 250) until `pagination.current_page` equals `total_pages`. `GET /api/v1/purchases` uses `limit` (up to 500) and `offset`: stop when a page has fewer than `limit` results.
- Ground rules: Use only endpoints, fields and SDK methods that the docs or OpenAPI specs define. Prefer `GET /api/v2/price-lists` over the deprecated v1. Products are matched by SKU. Keep credentials in environment variables or a secrets manager, never in code.

Steps:
1. List orders with `GET /api/v1/purchases`, filtered to orders updated since the last successful run (use the documented date filters, not my own), paging with `limit` and `offset`.
2. Fetch each order in full if the list response lacks fields I need, and map it to my ERP's sales order format, including lines, prices, tax, shipping and the customer.
3. Create the order in my ERP, or update it if it was already sent, keyed on the SparkLayer order ID so nothing is created twice.
4. Store the timestamp of the last order processed and resume from it on the next run.

Requirements:
- Keep credentials (Site ID, Client ID, Client Secret) in environment variables or a secrets manager, never in code.
- Cache the access token and request a new one shortly before it expires.
- Retry 5xx, 429 (honouring Retry-After) and concurrent-update 409 responses with exponential backoff; on a 401, get a new token once and retry. Log every failed request with its status, `title` and `detail`.
- Make each run safe to repeat, so a failed run can simply be run again.
- Add a dry-run mode that logs what would change without calling the write endpoints.
- Don't write anything back to SparkLayer unless the docs show an endpoint for it.
- Show me the field mapping as a table before writing the code.
- Use only endpoints, fields and SDK methods that the docs define. If something I need isn't documented, say so instead of guessing.

Start by asking me anything you need to know about my setup. Then give me a short plan, the complete code, how to configure and run it, and how to test it against the SparkLayer test environment first.
```
