Overview

The Luminous External V1 API provides two dedicated bulk-export endpoints — one for products and one for sales orders — that are designed for downloading large catalogs or running incremental syncs. Unlike the standard list endpoints (which use page/offset pagination and support rich filtering), the export endpoints use cursor-based keyset pagination: they are faster and more stable for large data sets, and each export run is anchored to a consistent snapshot so that records updated mid-run do not cause gaps or duplicates.


Products export

Endpoint: GET /external/api/v1/products/export

How it works

  1. First page — send a since parameter (a date or UTC datetime, e.g. 1970-01-01T00:00:00Z to get all active products). This anchors an internal cutoff timestamp so the entire export sees the same consistent snapshot.
  2. Subsequent pages — drop since and send the cursor value returned as next_cursor in the previous response. Do not send both at the same time.
  3. Keep paging until has_more is false.

Parameters

ParameterWhen to useNotes
sinceFirst request onlyISO 8601 date or datetime, e.g. 1970-01-01
cursorAll follow-up requestsOpaque string — copy from next_cursor
limitOptional on any requestDefault 100, maximum 1000

Response envelope

{
  "data": [ ...product rows... ],
  "next_cursor": "eyJ...",
  "has_more": true,
  "meta": {
    "rows": 100,
    "total_count": 5000   ← only present on the first page
  }
}
  • total_count is only returned on the first page (when you sent since). Use it to show a progress indicator.
  • Each product row includes core fields such as SKU, name, prices, weights, dimensions, alternate SKUs, tags, custom fields, kit items, and shallow BOM references.

What is NOT included in export rows

For performance reasons, the export omits: nested BOM line items, variant SKU child rows, attachments, substitutions, priority lists, and expanded unit conversion rules on alternate SKUs. To retrieve any of those, call GET /products/{id} for the specific product.


Sales orders export

Endpoint: GET /external/api/v1/sales-orders/export

How it works

The pattern is identical to the products export:

  1. First page — send since (lower bound on updated_at).
  2. Subsequent pages — send cursor copied from next_cursor. Do not combine with since.
  3. Stop when has_more is false.

Parameters

ParameterWhen to useNotes
sinceFirst request onlyUTC date or datetime
cursorAll follow-up requestsOpaque string from next_cursor
limitOptionalDefault 1000, maximum 1000

Important: Only since, cursor, and limit are accepted as query parameters on this endpoint. Adding any other filter parameter will result in a validation error.

Response envelope

{
  "data": [ ...sales order rows... ],
  "next_cursor": "eyJ...",
  "has_more": true,
  "meta": { "rows": 1000 }
}

Choosing between export and list endpoints

Export endpointList endpoint
Use caseFull catalog download, incremental syncFiltered/searched queries
PaginationCursor-based (fast, snapshot-consistent)Offset/page-based
FilteringNot supported — only since/cursor/limitFull filter operators supported
Default page size100 (products) / 1000 (sales orders)Up to 100

Use the list endpoint (GET /products or GET /sales-orders) when you need to filter by status, channel, date range, tags, etc. Use the export endpoint when you want to download everything or poll for all records updated since a known timestamp.


Incremental sync pattern

To keep an external system in sync without downloading everything each time:

  1. On the very first run, call the export with since=1970-01-01T00:00:00Z and page through all records. Record the timestamp when you started.
  2. On subsequent runs, pass that recorded timestamp as since. Only records with an updated_at on or after that timestamp will be returned.
  3. After completing a run, update your stored timestamp to the start of the latest run.

Authentication

All External API requests require a bearer token:

Authorization: Bearer {your_api_token}

API tokens are managed in the Luminous admin under the API token settings.


Common errors

StatusMeaning
400Invalid or tampered cursor string
401Missing or invalid bearer token
422Validation failure — e.g. sending both since and cursor together, or an unsupported query parameter