Skip to main content
The Export API powers bulk catalog ingestion. Instead of paging through /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.
Want to understand how Export fits into the bigger picture? See Snappy Core Concepts & Data Models.
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 an export-only variants array containing every variant with per-country availability. See NDJSON export format below for the full shape.

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.
Use the synchronous list endpoints (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:
1

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.
2

Poll for status

Call GET /v3/products/exports/{exportId} until the job reaches a terminal state.
3

Download the file

When status is completed, the response includes a downloadUrls map of signed URLs. Download the file(s) before the export record expires.

Status lifecycle


Key Concepts & Business Rules

Download URLs are signed and short-lived

When a job completes, the poll response returns a downloadUrls 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 (with its variants) 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 to POST /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

The locations 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

NDJSON export format

Each line in the export file is a full Product JSON with one export-only addition: a variants array containing every variant on that product.

Per-line shape

  • Product fields - identical to GET /v3/products/{productId}, including any include (brand, tags) and fields (priceRange, variantsCount) expansions you requested.
  • variants - an array of the product’s variants, each with its full details plus an availability object.

Variant availability

Each variant in the export includes an availability object with one entry per country listed in your locations filter. Each entry follows the same shape as GET /v3/variants/{variantId}/availability:
  • isAvailable - whether the variant is orderable in that country.
  • price - the localised price for that country.
  • priceBreakdown - a breakdown of itemPrice, shippingFee, and ddp (duties, taxes, and paid-on-delivery fees). Partner pricing is reflected here when applicable.
fields does not control variants in the export. Variant data is always fully included on every line - you can’t opt into a subset. If you don’t need variant details, ignore the variants array on the consumer side. Variant-level fields (e.g. price, priceBreakdown, details, brand) apply only to the synchronous variant endpoints, not to the export.

Example line


How to Work with Export

Create a filtered product export job
Queues an async export of products matching the supplied filters. Required: catalog, format. Optional filters: search, brandName, brandId, tagId, productIds, price.gte/price.lte, locations, include, fields. Returns 200 OK with an exportId to poll. Create a collection export job
Queues an async export of every product in a single collection. Required: collectionId, catalog, locations. Returns 200 OK with an exportId to poll. Poll export job status
Returns the current status of an export job. When status is completed, includes a downloadUrls map with signed URLs. When status is failed, includes an errorMessage. Polls both products and collections export jobs.
Last modified on July 29, 2026