Customers API
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, and the Customers API (/api/v2/customers) over the legacyDELETE /api/v1/customersin the Core API. 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:
customers,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.
The Customers API holds your B2B customers: who they are, how they buy, and their addresses, account balance, shopping lists and favourites. Use it to keep customers in step with your ERP or CRM, or to find a customer's SparkLayer ID before you send data that belongs to them.
On Shopify, Shopify owns the customer
SparkLayer's Shopify integration writes each B2B customer through this API whenever they change in Shopify, and replaces what's there. Keep Shopify as the source of those customers' details, and use the Customers API to look them up or for customers who aren't in Shopify. Customers you create here aren't sent to your eCommerce platform.
Common uses
| You want to | What to do |
|---|---|
| Find a customer's SparkLayer ID, for example to send their orders with the Purchasing API | Get a customer by their platform ID or email address, and use the id in the response |
| Create or update customers from your ERP or CRM | Create or update a customer, sending the whole customer each time |
| Change a few fields, such as a customer's price lists or credit limit | Update a customer with only those fields |
| Add past customers before an order history import, without letting them sign in | Create or update a customer with status set to inactive |
| Set what a customer owed on a date, so only later orders and payments count | Adjust a customer's account balance with type set to opening_balance |
Look up a customer
Every endpoint finds the customer from the URL: /api/v2/customers/{lookupBy}/{identifier}.
lookupBy | identifier |
|---|---|
sparklayer | The customer's SparkLayer ID, the id in responses (a UUID). Legacy cu_ IDs also work, except for shopping lists and favourites. |
platform | The customer's ID on your eCommerce platform, their external_id, such as the Shopify customer ID. |
email | The customer's email address. |
- Email lookups are exact and case-sensitive. URL-encode the address, and write
+as%2B, or it's read as a space. - Inactive and archived customers are found, and deleted customers aren't.
Create and update customers
Create or update a customer (PUT) creates the customer if none matches, and otherwise replaces them.
- The body must contain the identifier in the URL. A
PUTto/api/v2/customers/platform/7843024560291needs"external_id": "7843024560291". - Send the whole customer every time. Fields you leave out are cleared, and if you leave out
addresses, every address is deleted. To change only some fields, use Update a customer (PATCH) instead. groupandrolemust exist. Usebasefor the default customer group andmainfor a customer's main account. Price list slugs aren't checked, so make sure the price lists exist.- Emails and platform IDs are unique across your customers, deleted customers aside. Reusing one returns
409.
{
"external_id": "7843024560291",
"accounting_id": "C-1042",
"email": "buyer@example.com",
"first_name": "Sam",
"last_name": "Taylor",
"company_name": "Example Trading Ltd",
"status": "active",
"group": "base",
"role": "main",
"price_lists": ["trade-gbp"],
"payment_on_account": {
"credit_limit": 5000,
"currency_code": "GBP",
"net_terms": "30_days",
"balance": 1250.00,
"balance_date": "2026-11-01T00:00:00Z"
},
"addresses": [
{
"external_id": "addr-1042-1",
"first_name": "Sam",
"last_name": "Taylor",
"company": "Example Trading Ltd",
"address_line1": "1 Example Street",
"city": "London",
"region_code": null,
"postal_code": "SW1A 1AA",
"country_code": "GB"
}
]
}Customer status
status | What it means |
|---|---|
active | The customer can sign in and buy. |
inactive | The customer is kept, with their orders, but can't sign in. |
archived | A former B2B customer, such as one whose b2b tag was removed in Shopify. They're kept, but left out of searches and sales reps' customer lists. |
The account balance
When you use pay on account, the balance in My Account comes from a ledger of entries for each customer. SparkLayer adds an entry for each order you send with the Purchasing API, and for each purchase transaction with apply_to_balance.
- Without an opening balance, the balance is every entry added together.
- With an opening balance, it's the opening balance plus the orders and payments dated on or after its date.
Set an opening balance with Adjust a customer's account balance, or with balance and balance_date in payment_on_account when you create or update the customer. Sending payment_on_account without balance_date sets the balance to balance, or 0 if you leave it out, as of now. Once a customer has an opening balance, these updates no longer change it.
Endpoints
- GETGet a customer
- PUTCreate or update a customer
- DELDelete a customer
- PATCHUpdate a customer
- PUTSet a customer's company roles
- GETList a customer's addresses
- POSTCreate a customer address
- GETGet a customer address
- DELDelete a customer address
- PATCHUpdate a customer address
- POSTAdjust a customer's account balance
- GETList shopping lists
- POSTCreate a shopping list
- GETGet a shopping list
- DELDelete a shopping list
- PATCHUpdate a shopping list
- GETGet the favourites list
- PUTReplace the favourites list
Next steps
- Send orders to SparkLayer: build orders that show correctly in My Account and Pulse.
- Authentication: get an access token for your requests.
- Core API: customer groups, discounts and settings.
Last updated