Error codes
Listings API HTTP status codes, the SYxxxxx error codes, and the two error-envelope shapes the v4 API returns.
The Listings API uses conventional HTTP status codes to report the outcome of a
request. Error codes are SY-prefixed and travel inside the error message
string, formatted as SYxxxxx: <human-readable reason>.
HTTP status codes
HTTP status code summary
Two envelope shapes
Every failure carries an errors array. Where that array lives depends on
whether the request failed before or after it reached the resolver.
1. Request-level: top-level errors[]
Authentication, authorization, and malformed-request failures short-circuit
before the operation runs. They return the matching 4xx status (above) with
the error at the top level of the response.
{ "data": { "createLocation": null }, "errors": [{ "message": "SY90005: Invalid Token" }]}2. Mutation validation: nested data.<operation>.errors[]
A create, update, or publish request that is otherwise well-formed reaches the
resolver, so the transport succeeds with HTTP 200. If the resolver rejects the
input on a business rule, the mutation reports the failure nested under the
operation's own payload in data.<operation>.errors. On success this array is
present and empty ("errors": []).
{ "data": { "createLocation": { "errors": [ { "message": "SY10126: City is Mandatory" }, { "message": "SY10010: state_iso" } ], "location": null } }}Always read data.<operation>.errors on a write, even on a 200 with a
populated data.<operation> object: a mutation can partially fail and report
it here.
Common codes
Common SY error codes
Validation codes in the SY10xxx range correspond to a specific input field;
the message names the field or the rule that failed. Auth and authorization
codes in the SY90xxx range are request-level and arrive at the top level with
the matching status.
Connected-account codes
Codes in the SY810xx range come from the Connected Accounts endpoints that
import or link a publisher listing. They arrive nested in the mutation body
on an HTTP 200 (envelope shape 2 above), so read
data.<operation>.errors even when the status is a success.
SY810xx connected-account and import codes
rate_limited
429 Too Many Requests: the account exceeded its plan's rate limit. The body
is the standard error envelope carrying a retry_after_seconds hint, a
correlation_id to quote in support requests, and a doc_url that links back
to this section:
{ "error": { "code": "RATE_LIMITED", "message": "Too many requests. Slow down.", "retry_after_seconds": 30, "correlation_id": "9f2c1e64-2b1a-4b0e-9f1a-2c7d5e8a1b3c", "doc_url": "https://listingsapi.com/docs/error-codes#rate_limited" }}Wait for retry_after_seconds (or the Retry-After header when present), then
retry with exponential backoff. See Rate limits for the
per-plan limits and a reference backoff implementation.
Dev-portal control-plane errors
Account and key-management endpoints in the developer portal (the dashboard's
own API routes) return a single, structured error envelope: distinct from the
REST errors[] shapes above. Each code carries a correlation_id and a
doc_url that links back to the matching section here.
{ "error": { "code": "AUTH_INVALID_KEY", "message": "Session is invalid or expired.", "correlation_id": "9f2c1e64-2b1a-4b0e-9f1a-2c7d5e8a1b3c", "doc_url": "https://listingsapi.com/docs/error-codes#auth_invalid_key" }}auth_missing_key
401: No credential was provided. Sign in again, or send your key as
Authorization: API <your-key>.
auth_invalid_key
401: The session or key is invalid or expired. Re-authenticate or re-issue a
key from the dashboard.
auth_insufficient_scope
403: The credential is valid but not permitted for this action. A read-scoped
key cannot call write endpoints; issue a write key if you need one.
not_found
404: The requested resource, or a resource addressed by ID, does not exist.
conflict
409: The request conflicts with the current state of the resource (for
example, revoking a key that is already revoked).
validation_failed
422: The request body failed validation. The envelope's field and
details name the offending input.
internal_error
500: An unexpected server-side error. Safe to retry with exponential backoff;
quote the correlation_id if you contact support.
dependency_unavailable
503: A required upstream dependency is temporarily unavailable. Retry with
backoff.
For 429, see rate_limited above.
Handling errors in code
Check the HTTP status first; then, for writes, scan the mutation body for a
nested errors array:
resp = client._request(method="POST", path="/api/v4/locations", body=payload) # `_request` raises on a non-2xx status (AuthenticationError, ValidationError,# and so on). On a 200, a mutation can still report field errors in its payload:op = (resp.get("data") or {}).get("createLocation") or {}if op.get("errors"): messages = [e["message"] for e in op["errors"]] raise RuntimeError(f"Listings API error: {messages}")The Python SDK does both for you: it maps each
HTTP status to a typed exception and also raises on error payloads returned
inside a 200 body.