Errors
One format, with a stable code for your code to handle.
Every error has this body:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request.",
"details": [
{
"origin": "string",
"code": "too_small",
"minimum": 1,
"inclusive": true,
"path": ["name"],
"message": "Too small: expected string to have >=1 characters"
}
]
}
}details comes in two shapes. On a body, query or :id VALIDATION_ERROR, it is the list of validation problems, one per field. In the cases of the table below, it is an object that says what clashed. Other errors have no details. The text of each message may change: use code and details.
| Case | HTTP | details |
|---|---|---|
Seller-Id header missing or malformed | 400 | { "header": "Seller-Id" } |
| marketplace not available in this environment | 400 | { "field": "allowedMarketplaces", "unavailable": ["amazon"] } |
redirectUrl that is not https | 400 | { "field": "redirectUrl" } |
| webhook URL refused | 400 | { "field": "url" } |
Idempotency-Key longer than 255 characters | 400 | { "header": "Idempotency-Key" } |
| marketplace options refused (another marketplace namespace, or a URL, header or credential inside) | 400 | { "field": "marketplaceOptions" }, or "oneTimeMarketplaceOptions" when publishing |
invalid binding: a Variant that does not exist or belongs to another seller, bindingIds that are not the listing's, or eligibleBindingIds from another listing | 400 | { "field": "bindings" }, { "field": "bindingIds" }, or { "field": "eligibleBindingIds" } |
conflict resolution refused: value outside the conflict paths, or a result that is invalid for the group | 400 | { "field": "value" } or { "field": "resolution", "issues": [...] } |
repeated externalId | 409 | { "field": "externalId" } |
| seller with active connections | 409 | { "reason": "active_connections" } |
| link session that is not pending | 409 | { "status": "completed" } (the current status) |
| Connection that is not active (for example, revoked) | 409 | { "reason": "connection_inactive" } |
| publishing with outbound sync off, or a listing with no Variant binding | 409 | { "reason": "outbound_disabled" } or { "reason": "listing_unlinked" } |
publishing content: already published (create), never published (update) or without a variation | 409 | { "reason": "marketplace_product_published" }, "marketplace_product_unpublished" or "marketplace_product_without_variants" |
| archiving a Product or Variant that a listing binding still uses | 409 | { "reason": "product_in_use" } or { "reason": "variant_in_use" } |
| kit BOM with a cycle | 409 | { "reason": "component_cycle" } |
| archiving a Product or Variant that is a component of an active kit | 409 | { "reason": "product_in_kit" } or { "reason": "variant_in_kit" } |
| BOM or listing binding with an archived Variant, or one active in an archived Product | 409 | { "reason": "variant_archived" } or { "reason": "product_archived" } |
| inventory movement on a Variant that MarketAPI does not manage | 409 | { "reason": "inventory_authority" } |
| inventory movement in an archived warehouse | 409 | { "reason": "warehouse_archived", "warehouseId": "…" } |
| movement that would leave the warehouse without enough stock (for a transfer, the source) | 409 | { "reason": "inventory_underflow", "warehouseId": "…" } |
| archiving the seller's default warehouse, or a warehouse with balance | 409 | { "reason": "warehouse_in_use", "uses": ["default", "stock"] } |
| quantity publication with no eligible target | 409 | { "reason": "inventory_target_empty" } |
| resolving a listing conflict that was already resolved | 409 | { "reason": "conflict_not_open" } |
| Connection without the operation's scope | 403 | { "marketplace": "mercadolivre", "capability": "listings.publish" } |
| operation the marketplace does not offer | 422 | { "marketplace": "mercadolivre", "capability": "listings.publish" } |
| HTTP | code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | invalid body, query (page, pageSize, filters), :id that is not a UUID, or Idempotency-Key; Seller-Id header missing or malformed; marketplace not available; redirectUrl that is not https; webhook URL refused; marketplace options refused; invalid binding; request the marketplace itself refused (discovery routes) |
| 401 | UNAUTHORIZED | missing, invalid or revoked API key |
| 402 | PAYMENT_REQUIRED | the account has no subscription in good standing; activate or reactivate it in Billing, in the dashboard |
| 403 | FORBIDDEN | dashboard session with no account created yet; any /v1 route. Does not happen with an API key |
| 403 | CAPABILITY_NOT_GRANTED | the marketplace offers the operation, but the Connection lacks a required scope; the seller authorizes again. In a job, also when the marketplace itself refuses the app the permission for the operation: enable the permission in the app and authorize again |
| 404 | NOT_FOUND | unknown route, or a valid id that does not exist (or belongs to another account) — including the seller in the path or in Seller-Id, and an internal job. On the discovery routes, also a category, product type or catalog product the marketplace does not know |
| 409 | CONFLICT | externalId already in use, Idempotency-Key reused with a different body, seller with active connections, link session that is not pending, inactive Connection, listing state, Product or Variant in use, BOM cycle, inventory MarketAPI does not manage, not enough stock in a warehouse, archived or in-use warehouse, archived Variant or kit component, listing conflict already resolved. Any POST can return the reused Idempotency-Key |
| 422 | CAPABILITY_UNSUPPORTED | the Connection's marketplace does not offer the operation. See Connection capabilities |
| 429 | RATE_LIMITED | API key limit exceeded; see Retry-After |
| 500 | INTERNAL_ERROR | our fault; already logged |
| 503 | MARKETPLACE_UNAVAILABLE | the marketplace did not answer a call of ours, refused the app or limited the requests; try again. details.reason tells a wait from an outage |
| 503 | STORAGE_UNAVAILABLE | file storage is not configured in this environment (asset routes) |
Examples
409 CONFLICT has several causes (listed in the table above). Tell them apart by details; the reused Idempotency-Key is the only one without it.
Repeated externalId, with details.field:
{
"error": {
"code": "CONFLICT",
"message": "A seller with this externalId already exists.",
"details": { "field": "externalId" }
}
}Seller with active connections, on DELETE /v1/sellers/<id>:
{
"error": {
"code": "CONFLICT",
"message": "Seller with active connections cannot be removed. Disconnect them first.",
"details": { "reason": "active_connections" }
}
}Link session that is no longer pending, on DELETE /v1/link-sessions/<id>:
{
"error": {
"code": "CONFLICT",
"message": "Only a pending link session can be revoked.",
"details": { "status": "completed" }
}
}400 for a missing Seller-Id, on GET /v1/connections:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Seller-Id header is required.",
"details": { "header": "Seller-Id" }
}
}Idempotency-Key reused with a different body, no details (see Idempotency and limits):
{
"error": {
"code": "CONFLICT",
"message": "Idempotency-Key already used with a different body."
}
}422 CAPABILITY_UNSUPPORTED, when publishing a listing on a Connection whose marketplace does not publish. 403 CAPABILITY_NOT_GRANTED has the same details. In an inventory batch the error is not in the response: that Connection's item fails in the job, with the code in its message.
{
"error": {
"code": "CAPABILITY_UNSUPPORTED",
"message": "Marketplace mercadolivre does not support listings.publish.",
"details": {
"marketplace": "mercadolivre",
"capability": "listings.publish"
}
}
}402 PAYMENT_REQUIRED (no subscription in good standing; it does not count toward the rate limit):
{
"error": {
"code": "PAYMENT_REQUIRED",
"message": "Subscription required. Add a payment method in the dashboard."
}
}429 RATE_LIMITED comes with the Retry-After header (seconds):
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again after the time given in Retry-After."
}
}500 INTERNAL_ERROR:
{
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal error."
}
}503 MARKETPLACE_UNAVAILABLE, on the Connection discovery and catalog routes, which read the marketplace right away. details.reason tells a wait from an outage:
details.reason | What happened | What to do |
|---|---|---|
| missing | the marketplace did not answer, or refused the app | try again later |
marketplace_rate_limited | the marketplace is limiting the requests of the app | wait a little and try again |
connection_refreshing | the Connection credential is being renewed | try again in a moment |
{
"error": {
"code": "MARKETPLACE_UNAVAILABLE",
"message": "The marketplace is limiting requests. Try again.",
"details": { "reason": "marketplace_rate_limited" }
}
}If the marketplace ended the seller's access in the middle of the call, the answer is not 503: it is 409 CONFLICT with { "reason": "connection_inactive" }, the same as any route of a Connection that is not active. Ask the seller to connect again.
Handle errors by code, not by message: the message may change, the code won't. The message is in English and is meant for logs and debugging.
Each endpoint page shows the errors it can return, with an example body for each status. For example: Create a seller.