Past product imports, newest first
- Credentials
- OAuth access token
- Scopes
listings:read
Runs started through the API and the console's imports; the newest 200 are listed.
Access: OAuth scope listings:read; not write-gated.
Paged: { items, nextCursor }, limit (default 20, at most 50) and an opaque cursor.
merchantOAuth listings:readAuthorizationBearer <token>OAuth 2.1 (authorization code + PKCE S256, public clients, dynamic registration) for connected AI apps. Effective power is scopes granted AND the person's role today AND the plan. orders:refund, billing:write and team:write are opt-in on the consent screen. Write implies read for marketing:read and messages:read, so a grant holding marketing:write passes a marketing:read check, and messages:send passes messages:read.
Scope: listings:read
storeId*stringA store the person can reach. Any other id answers 404, never 403.
cursor?stringThe nextCursor of the previous page, unchanged. A cursor that is not one we gave you is 400 bad_request.
limit?integerPage size: default 20, at most 50 (more is 50; a missing or unusable value is 20).
1 <= value <= 5020OK
application/json- response
data*curl -X GET 'https://api.shopeazy.co/v1/merchant/stores/<storeId>/product-imports' \ -H 'Authorization: Bearer <access_token>'{ "data": { "items": [], "nextCursor": null }}Set the customisation groups on one listing PUT
The groups this listing offers, in order, each with its own prices: `prices` maps a choice id to a price, `variantPrices` maps a variant (or ticket tier) id and then a choice id. An override that repeats the inherited price, or names something the listing no longer has, is dropped. An empty list takes every group off. getProduct returns the same shape in `customisations`. Access: OAuth scope `listings:write`; write-gated by the subscription.
Start a bulk product import from an uploaded CSV POST
Upload the file first (createProductImportUploadLink, then PUT it) and pass its `uploadId`. Say how the columns map with a saved profile (`profileId`, listProductImportProfiles) or an inline `mapping`; one of the fields mapped has to be a product ID, SKU or barcode, so next month's file finds this month's products instead of creating them again. The file is read and staged here (a file with no rows, a missing column or over 20,000 rows is `422` and nothing starts), then a worker applies it in chunks: this answers `202` at once with the run, `status: queued`. Poll getProductImport until `status` is `applied` (written), `previewed` (a `dryRun`: the same run, nothing written) or `failed`. Rows with a match are updated (only what the file has a value for: an empty cell never clears a field) and the rest are created as drafts. New products count against the plan's listing cap as in the console: past it, those rows are refused with a reason. Rows that fail are listed in `errors` (the first 200) and counted in `summary.error`. The same `uploadId` is the same run: asking again returns the run that is there. Needs the Products kit (404 `kit_not_found`) and answers `501 not_available` where bulk import is not switched on. Access: OAuth scope `listings:write`; write-gated by the subscription.