Skip to content

Create or update a purchase transaction

For AI assistants: the facts every SparkLayer API call needs
  • 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 409s 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.
  • Read the docs as Markdown: Add .md to 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.
PUT
/api/v1/purchases/{lookupBy}/{identifier}/transactions

Records a transaction, such as a payment or refund, against the purchase that matches lookupBy and identifier. A transaction is identified by its purchase and platform_id (the transaction's ID in the third-party system), so sending a platform_id again updates that transaction. total is positive for a payment and negative for a refund.

With apply_to_balance: true, the transaction counts towards the purchase's payment status, adds an entry to the purchase history shown to the customer, and adjusts the customer's outstanding balance. With false, it's stored for information only, which is useful for pending or failed transactions. Changing it from true to false reverses those effects. full_transaction is stored exactly as sent, so remove sensitive data such as card numbers first. Don't also send the same transaction to your eCommerce platform, or it may be recorded twice.

Authorization

bearerAuth
AuthorizationBearer <token>

Send Authorization: Bearer <access_token>, together with your Site-Id header, on every request. Get the token from POST /api/auth/token with your Site ID in the Site-Id header and a JSON body (not form-encoded, so standard OAuth 2.0 client libraries don't work): {"grant_type": "client_credentials", "client_id": "…", "client_secret": "…"}. Tokens are valid for 3,600 seconds and there is no refresh token: request a new one shortly before it expires. Create API credentials in the SparkLayer Dashboard under Settings > API. See Authentication.

In: header

Path Parameters

lookupBy*string

Which of the purchase's purchase_identifiers identifier is: sparklayer, platform, internal or visible.

Value in

  • "sparklayer"
  • "platform"
  • "internal"
  • "visible"
identifier*|

The purchase identifier, of the kind set by lookupBy. With lookupBy=sparklayer it must be a UUID.

Header Parameters

Site-Id*string

Your SparkLayer Site ID, from Settings > API in the SparkLayer Dashboard.

Length1 <= length

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

platform_id*string

The identifier for this transaction on the e-commerce platform

Length1 <= length
full_transaction*string

A JSON string representing the full details of the transaction

type*string

The type of the transaction e.g. charge, refund

apply_to_balance*boolean

Set to true to signal that the value of this transaction should contribute to customer balances

currency_code*string

The 3 letter currency code used in this transaction

Length3 <= length <= 3
total*string

The amount of this transaction

transaction_date*string

The date the transaction was created

Formatdate-time

Response Body

application/json

application/problem+json

application/problem+json

curl -X PUT "https://app.sparklayer.io/api/v1/purchases/platform/123456789/transactions" \  -H "Authorization: Bearer <ACCESS_TOKEN>" \  -H "Site-Id: jones-climbing" \  -H "Content-Type: application/json" \  -d '{    "platform_id": "123456789",    "full_transaction": "<full_transaction>",    "type": "<type>",    "apply_to_balance": true,    "currency_code": "GBP",    "total": "20.99",    "transaction_date": "2020-01-01T00:00:00+02:00"  }'
{  "id": "63428136-658f-48a6-beb7-7f333dfd9686",  "purchase_spark_id": "63428136-658f-48a6-beb7-7f333dfd9686",  "platform_id": "123456789",  "full_transaction": "string",  "type": "string",  "apply_to_balance": true,  "currency_code": "GBP",  "total": "20.99",  "transaction_date": "2020-01-01T00:00:00+02:00",  "created_at": "2020-01-01T00:00:00+02:00"}