Bulk upsert/delete listings
POST
/listings/bulkApply a mixed batch of `upsert` and `delete` operations in one request. Each item is reported independently in the multi-status response; one malformed item does not fail the batch.
When to use
Use this operation to bulk upsert/delete listings.
Endpoint
POST /listings/bulk
| Environment | Base URL |
|---|---|
| Sandbox | https://api-sandbox.snapcaster.ca/api/v1/marketplace |
| Production | https://api.snapcaster.ca/api/v1/marketplace |
marketplaceApiKey-http bearer. Seller-scoped Marketplace API key, presented as `Authorization: Bearer mp_{sellerCode}_{hex}`. The `mp_{sellerCode}_` prefix identifies the Seller; the trailing hex is the secret. Generated by the Seller and pasted into its Platform.
Request
No parameters.
Request body (application/json)
| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
itemsrequired | array of object | maximum items: 1000 | The records included in this page or batch. | [
{
"op": "upsert",
"skuId": 1,
"productId": 1,
"price": 0,
"quantity": 0
}
] (generated) |
items[].oprequired | string | string: allowed values: upsert; string: allowed values: delete | The write operation to apply to this item. | upsert (generated) |
items[].skuIdrequired | integer | integer: exclusive minimum: 0 | Sku Id for the surrounding items item record. | 1 (generated) |
items[].productIdconditional | integer | exclusive minimum: 0 | Product Id for the surrounding items item record. | 1 (generated) |
items[].priceconditional | integer | minimum: 0 | The unit price in minor currency units. | 0 (generated) |
items[].quantityconditional | integer | None | The number of inventory units represented by this record. | 0 (generated) |
items[].externalRef | string | maximum length: 255 | External Ref for the surrounding items item record. | string (generated) |
items[].asOf | string | format: date-time | As Of for the surrounding items item record. | 2026-01-01T00:00:00.000Z (generated) |
Example
Sandbox is the default. These requests use the contract's canonical field examples.
curl --request POST \ --url 'https://api-sandbox.snapcaster.ca/api/v1/marketplace/listings/bulk' \ --header "Authorization: Bearer $MARKETPLACE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "items": [ { "op": "upsert", "skuId": 1, "productId": 1, "price": 0, "quantity": 0 } ]}'Response
200
Per-item multi-status results.
{ "success": true, "data": { "results": [ { "skuId": 0, "op": "upsert", "status": "applied" } ] }}| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
successrequired | boolean | allowed values: true | Whether the operation completed as requested. | true (generated) |
datarequired | object | None | The operation or event payload. | {
"results": [
{
"skuId": 0,
"op": "upsert",
"status": "applied"
}
]
} (generated) |
data.resultsrequired | array of object | None | The outcome recorded for each submitted item. | [
{
"skuId": 0,
"op": "upsert",
"status": "applied"
}
] (generated) |
data.results[].skuIdrequired | integer | None | Sku Id for the surrounding results item record. | 0 (generated) |
data.results[].oprequired | string | allowed values: upsert, delete | The write operation to apply to this item. | upsert (generated) |
data.results[].statusrequired | string | allowed values: applied, unmatched, rejected | Per-item outcome. `unmatched` corresponds to the public per-item code `UNMATCHED` (persisted but not in the Canonical Catalog); `rejected` corresponds to `REJECTED` (failed validation, not persisted; see `reason`). | applied (generated) |
data.results[].reason | string | None | Why the item was rejected; present only when status is "rejected". | string (generated) |
data.results[].externalRef | string | None | Echo of the pushed external_ref, when one was supplied. | string (generated) |
Errors
| Status | Code | Meaning | Do this |
|---|---|---|---|
| 400 | INVALID_REQUEST | The request failed validation (`INVALID_REQUEST`). | Correct the fields named in the error details, then retry the request. |
| 401 | UNAUTHORIZED | Missing or invalid Marketplace API key (`UNAUTHORIZED`). | Send the Marketplace API key for this Seller as a Bearer token, then retry. |
| 409 | SELLER_SOURCE_EXCLUSIVE | The authenticated Seller’s declared inventory source is not `platform` (`SELLER_SOURCE_EXCLUSIVE`). Listing writes through the integration API are reserved for platform-source Sellers; sources are exclusive and never mixed. | Use the Seller’s declared inventory source, or ask Snapcaster to move the Seller to the platform source. |
| 413 | BATCH_TOO_LARGE | The request carried more than the 1,000-item per-request cap (`BATCH_TOO_LARGE`). | Split the write into batches of at most 1,000 items and retry each batch. |
Related
Operations
Concepts
Changelog
Schema
Full schema details (36 fields)
Parameters
None.
Request
| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
itemsrequired | array of object | maximum items: 1000 | The records included in this page or batch. | [
{
"op": "upsert",
"skuId": 1,
"productId": 1,
"price": 0,
"quantity": 0
}
] (generated) |
items[].oprequired | string | string: allowed values: upsert; string: allowed values: delete | The write operation to apply to this item. | upsert (generated) |
items[].skuIdrequired | integer | integer: exclusive minimum: 0 | Sku Id for the surrounding items item record. | 1 (generated) |
items[].productIdconditional | integer | exclusive minimum: 0 | Product Id for the surrounding items item record. | 1 (generated) |
items[].priceconditional | integer | minimum: 0 | The unit price in minor currency units. | 0 (generated) |
items[].quantityconditional | integer | None | The number of inventory units represented by this record. | 0 (generated) |
items[].externalRef | string | maximum length: 255 | External Ref for the surrounding items item record. | string (generated) |
items[].asOf | string | format: date-time | As Of for the surrounding items item record. | 2026-01-01T00:00:00.000Z (generated) |
Response 200 (application/json)
| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
successrequired | boolean | allowed values: true | Whether the operation completed as requested. | true (generated) |
datarequired | object | None | The operation or event payload. | {
"results": [
{
"skuId": 0,
"op": "upsert",
"status": "applied"
}
]
} (generated) |
data.resultsrequired | array of object | None | The outcome recorded for each submitted item. | [
{
"skuId": 0,
"op": "upsert",
"status": "applied"
}
] (generated) |
data.results[].skuIdrequired | integer | None | Sku Id for the surrounding results item record. | 0 (generated) |
data.results[].oprequired | string | allowed values: upsert, delete | The write operation to apply to this item. | upsert (generated) |
data.results[].statusrequired | string | allowed values: applied, unmatched, rejected | Per-item outcome. `unmatched` corresponds to the public per-item code `UNMATCHED` (persisted but not in the Canonical Catalog); `rejected` corresponds to `REJECTED` (failed validation, not persisted; see `reason`). | applied (generated) |
data.results[].reason | string | None | Why the item was rejected; present only when status is "rejected". | string (generated) |
data.results[].externalRef | string | None | Echo of the pushed external_ref, when one was supplied. | string (generated) |
Error 400 (application/json)
| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
successrequired | boolean | allowed values: false | Whether the operation completed as requested. | false (generated) |
errorrequired | object | None | Structured error information returned when the request cannot be completed. | {
"code": "UNAUTHORIZED",
"message": "string"
} (generated) |
error.coderequired | string | allowed values: UNAUTHORIZED, INVALID_REQUEST, UNSUPPORTED_API_VERSION, SELLER_SOURCE_EXCLUSIVE, BATCH_TOO_LARGE, RATE_LIMITED, ORDER_NOT_FOUND, SELLER_NOT_FOUND, INVALID_TRANSITION, CHECKOUT_IDEMPOTENCY_KEY_REUSED, CHECKOUT_MANUAL_SELLER_UNSUPPORTED, CHECKOUT_SELF_PURCHASE_NOT_ALLOWED, CHECKOUT_SELLER_UNAVAILABLE, CHECKOUT_NOT_FOUND, FEATURE_DISABLED | Stable public error code the Platform can branch on. | UNAUTHORIZED (generated) |
error.messagerequired | string | None | A human-readable explanation of the result. | string (generated) |
error.details | unknown | None | Additional structured context for diagnosing the result. | {} (generated) |
Error 401 (application/json)
| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
successrequired | boolean | allowed values: false | Whether the operation completed as requested. | false (generated) |
errorrequired | object | None | Structured error information returned when the request cannot be completed. | {
"code": "UNAUTHORIZED",
"message": "string"
} (generated) |
error.coderequired | string | allowed values: UNAUTHORIZED, INVALID_REQUEST, UNSUPPORTED_API_VERSION, SELLER_SOURCE_EXCLUSIVE, BATCH_TOO_LARGE, RATE_LIMITED, ORDER_NOT_FOUND, SELLER_NOT_FOUND, INVALID_TRANSITION, CHECKOUT_IDEMPOTENCY_KEY_REUSED, CHECKOUT_MANUAL_SELLER_UNSUPPORTED, CHECKOUT_SELF_PURCHASE_NOT_ALLOWED, CHECKOUT_SELLER_UNAVAILABLE, CHECKOUT_NOT_FOUND, FEATURE_DISABLED | Stable public error code the Platform can branch on. | UNAUTHORIZED (generated) |
error.messagerequired | string | None | A human-readable explanation of the result. | string (generated) |
error.details | unknown | None | Additional structured context for diagnosing the result. | {} (generated) |
Error 409 (application/json)
| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
successrequired | boolean | allowed values: false | Whether the operation completed as requested. | false (generated) |
errorrequired | object | None | Structured error information returned when the request cannot be completed. | {
"code": "UNAUTHORIZED",
"message": "string"
} (generated) |
error.coderequired | string | allowed values: UNAUTHORIZED, INVALID_REQUEST, UNSUPPORTED_API_VERSION, SELLER_SOURCE_EXCLUSIVE, BATCH_TOO_LARGE, RATE_LIMITED, ORDER_NOT_FOUND, SELLER_NOT_FOUND, INVALID_TRANSITION, CHECKOUT_IDEMPOTENCY_KEY_REUSED, CHECKOUT_MANUAL_SELLER_UNSUPPORTED, CHECKOUT_SELF_PURCHASE_NOT_ALLOWED, CHECKOUT_SELLER_UNAVAILABLE, CHECKOUT_NOT_FOUND, FEATURE_DISABLED | Stable public error code the Platform can branch on. | UNAUTHORIZED (generated) |
error.messagerequired | string | None | A human-readable explanation of the result. | string (generated) |
error.details | unknown | None | Additional structured context for diagnosing the result. | {} (generated) |
Error 413 (application/json)
| Field | Type | Constraints | Meaning | Example |
|---|---|---|---|---|
successrequired | boolean | allowed values: false | Whether the operation completed as requested. | false (generated) |
errorrequired | object | None | Structured error information returned when the request cannot be completed. | {
"code": "UNAUTHORIZED",
"message": "string"
} (generated) |
error.coderequired | string | allowed values: UNAUTHORIZED, INVALID_REQUEST, UNSUPPORTED_API_VERSION, SELLER_SOURCE_EXCLUSIVE, BATCH_TOO_LARGE, RATE_LIMITED, ORDER_NOT_FOUND, SELLER_NOT_FOUND, INVALID_TRANSITION, CHECKOUT_IDEMPOTENCY_KEY_REUSED, CHECKOUT_MANUAL_SELLER_UNSUPPORTED, CHECKOUT_SELF_PURCHASE_NOT_ALLOWED, CHECKOUT_SELLER_UNAVAILABLE, CHECKOUT_NOT_FOUND, FEATURE_DISABLED | Stable public error code the Platform can branch on. | UNAUTHORIZED (generated) |
error.messagerequired | string | None | A human-readable explanation of the result. | string (generated) |
error.details | unknown | None | Additional structured context for diagnosing the result. | {} (generated) |