/v3/products or /v3/collections/{collectionId}/products to mirror the Snappy catalog into your own platform, you queue an asynchronous export job and pull a single NDJSON file containing the full result set.
Export is the recommended way to keep a local product mirror up to date - pair a nightly bulk export with Webhooks for incremental product changes between exports.
Exports are NDJSON-only for now. Each line in the file is a single JSON object representing one product, with the same shape as
GET /v3/products/{productId} (plus any include / fields expansions).When to use Export
Use the Export API when:- You need the entire catalog (or a large filtered subset) in a single payload - typically for nightly ingestion into a partner system, search index, or data warehouse.
- The synchronous list endpoints would require dozens or hundreds of paginated requests.
- You’d rather fire-and-forget the job and pick up the result later than hold an HTTP connection open.
GET /v3/products, GET /v3/collections/{collectionId}/products) when:
- You need real-time browse / search inside your UI.
- The result set is small enough to fit in one or two pages.
How export jobs work
Export is a standard async job pattern:Create the job
Call
POST /v3/products/exports (filtered export) or POST /v3/collections/exports (collection-scoped export). Both return 200 OK with an exportId immediately.Status lifecycle
| Status | Description |
|---|---|
pending | Job has been queued; processing has not started. |
processing | Job is actively running. |
completed | Job finished successfully. downloadUrls is populated with signed S3 URLs. |
failed | Job terminated without producing a file. errorMessage contains a human-readable reason. |
Key Concepts & Business Rules
Download URLs are signed and short-lived
When a job completes, the poll response returns adownloadUrls map (keyed by file identifier or location code). These are signed S3 URLs that expire 48 hours after the export record is created. After expiry, you’ll need to re-issue a new export job.
NDJSON, not JSON
Exports produce newline-delimited JSON - one product object per line. This makes it safe to stream-parse multi-gigabyte exports without holding the whole payload in memory.Filtering uses flat body fields (not the JSON:API filter[...] query convention)
V3 list endpoints accept filters as bracketed query parameters (filter[price][gte], filter[brandId]). Export jobs accept the same filters as flat JSON body fields (price.gte, brandId) - this is intentional for JSON ergonomics. Same semantics, different surface.
Idempotency is not currently supported
Repeated calls toPOST /v3/products/exports with identical bodies create separate export jobs. If you need idempotency for nightly runs, persist the exportId of the latest in-flight job on your side and skip creating a new one when one is already pending.
Locations drive price localisation
Thelocations array (ISO 3166-1 alpha-2 country codes) is used to localise prices and availability in the exported file. Defaults to ["US"] on the products export endpoint; required on the collections export endpoint.
Permissions
All Export endpoints require: Requires:products:read
How to Work with Export
Create a filtered product export jobcatalog, format. Optional filters: search, type, brandName, brandId, tagId, productIds, price.gte/price.lte, locations, include, fields. Returns 200 OK with an exportId to poll.
Create a collection export job
collectionId, catalog, locations. Returns 200 OK with an exportId to poll.
Poll export job status
status is completed, includes a downloadUrls map with signed URLs. When status is failed, includes an errorMessage. Polls both products and collections export jobs.