Archive API docs

Errors

The Archive API reports failures at three levels. Which one you are looking at is determined entirely by the HTTP status and the shape of the body, so check those first.

The decision tree

1. HTTP status is not 200 → transport error. Authentication, a missing header, or an unknown workspace fails before any of your query’s fields are resolved. The body is a single string under errors (429 is the exception — see the table below):

{ "errors": "<message>" }
400 Bad Request
{
  "errors": "WORKSPACE-ID header is required"
}

2. HTTP status is 200 but the body has an errors array → GraphQL error. The request was transported and parsed, but a field failed. Each entry carries a message, a machine-readable extensions.code, and locations / path pointing into your query:

200 OK
{
  "errors": [
    {
      "message": "Preset \"00000000-0000-0000-0000-000000000000\" was not found in the current workspace.",
      "extensions": {
        "code": "WRONG_VIEW_TYPE_FOR_ITEMS",
        "allowedAccessors": [
          "media_deck",
          "collections"
        ]
      },
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "items"
      ]
    }
  ],
  "data": null
}

Branch on extensions.code — here WRONG_VIEW_TYPE_FOR_ITEMS — not on the message text.

A response can carry both data and errors: when a dependency is temporarily unavailable, the parts that could be resolved are still returned alongside a coded error for the parts that could not. Read errors even when data is populated.

3. HTTP 200 with data and no errors → success, but a mutation may still report a business failure. Every mutation payload has a userErrors array; an empty array means the write succeeded.

200 OK
{
  "data": {
    "createCollection": {
      "collection": {
        "id": "17ccdf4e-19d2-5b30-9787-d4f0886ddf29",
        "name": "Holiday Favorites",
        "itemCount": 0
      },
      "userErrors": []
    }
  }
}

The userErrors pattern

Mutations do not raise validation failures as GraphQL errors — they return them in userErrors, so the request still comes back HTTP 200 with data. Each UserError has the shape:

type UserError {
  field: [String!]
  message: String!
}

Always inspect userErrors on a mutation response before treating it as a success. field points at the offending input path; message is human-readable.

HTTP status reference

StatusBody shapeCause
200data (+ optional errors[])Success, or a GraphQL field error / mutation userErrors
400{"errors":"WORKSPACE-ID header is required"}Missing WORKSPACE-ID on a workspace-scoped operation
401{"errors":"Missing or invalid authentication token"}Missing, invalid, or disabled token
404{"errors":"Shop not found"}Unknown workspace, or one your token can’t reach
429{"errors":[{"message":"Rate limit exceeded…","extensions":{"code":"RATE_LIMIT_EXCEEDED"}}]}Request-frequency wall or weighted-cost budget exhausted — honor Retry-After
5xxtypically {"errors":"<message>"}Infrastructure failure. Most server-side errors arrive as HTTP 200 instead — see the codes below

Server-side errors arrive as HTTP 200

A failure inside the server does not usually change the status code — it comes back in the GraphQL error envelope, so branch on extensions.code rather than waiting for a 5xx:

extensions.codeMeaning
QUERY_TIMEOUTThe query was canceled by the database statement timeout. Narrow the time range or the page size, then retry
INTERNAL_SERVER_ERRORUnexpected server-side failure. Retry with backoff; contact support if it persists
SERVICE_UNAVAILABLEA dependency is temporarily unavailable. The data that could be resolved is still returned — retry later for the rest

For the unknown-workspace case:

404 Not Found
{
  "errors": "Shop not found"
}

See the Rate limits guide for 429 handling and the Authentication guide for 401 handling.