One import, with its status, progress and the rows it refused
- Credentials
- OAuth access token
- Scopes
listings:read
status is queued, running, then applied, previewed or failed (failure says why, in the merchant's words). rowsDone of totalRows is the progress. errors holds the first 200 rows refused (row is the line in the file, not counting the header); errorsTruncated says there were more, and summary.error is the count. An import the console recorded reads the same.
Access: OAuth scope listings:read; not write-gated.
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.
runId*stringAn import id, from startProductImport or listProductImports.
OK
application/json- response
data*curl -X GET 'https://api.shopeazy.co/v1/merchant/stores/<storeId>/product-imports/<runId>' \ -H 'Authorization: Bearer <access_token>'{ "data": { "id": "string", "status": "queued", "dryRun": true, "fileName": "string", "totalRows": 0, "rowsDone": 0, "summary": { "create": 0, "update": 0, "unchanged": 0, "error": 0, "newCategories": [ "string" ] }, "errors": [ { "row": 0, "message": "string" } ], "errorsTruncated": true, "profileId": "string", "failure": "string", "createdAt": 0, "startedAt": 0, "finishedAt": 0 }}A signed link to upload the CSV straight to storage POST
Returns a short-lived (10 minutes) signed HTTPS PUT link into the business's upload area, with its `uploadId`. PUT the file's bytes to `uploadUrl` with plain HTTP (for example `curl -T stock.csv -H "Content-Type: text/csv" -H "x-goog-content-length-range: 1,10485760" "<uploadUrl>"`), sending exactly the returned `headers`: the link accepts that content type and 1 byte to 10 MB. No browser CORS is involved. Then pass `{ uploadId }` to startProductImport. A link not used in time stops working, and an unused upload is cleared after a day. Access: OAuth scope `listings:write`; write-gated by the subscription.
Saved import column mappings GET
A profile remembers which of your columns is which field, so a monthly export is an upload and a start. Most recently used first. Access: OAuth scope `listings:read`; not write-gated. Paged: `{ items, nextCursor }`, `limit` (default 50, at most 100) and an opaque `cursor`.