> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.tradespace.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.tradespace.io/_mcp/server.

# Errors

> HTTP statuses and GraphQL errors the API returns.

The API reports errors in two ways, depending on where the request fails.

## Request errors

If the request is rejected before the query runs, the API returns an HTTP error status.

| Status                  | Meaning                                                                                                  |
| ----------------------- | -------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`       | The request has no operation name. Name the query and send the name in `operationName`.                  |
| `401 Unauthorized`      | The API key is missing, unknown, or inactive, or it was created in a different region than the endpoint. |
| `429 Too Many Requests` | The hourly rate limit is exhausted. See [Rate limits](/home/get-started/rate-limits).                    |

The public API returns three kinds of `400`. Only the missing-operation-name case uses an actual HTTP 400. The other two come back as HTTP 200 with 400 in extensions.status.

1. Missing operation name (HTTP 400), rejected before GraphQL runs:

```json
{
  "errors": [
    {
      "message": "Operation name is required",
      "extensions": {
        "code": "BAD_REQUEST",
        "status": 400,
        "request_id": "f295efec-3cb1-4ac0-9a43-70d559b7fd76"
      }
    }
  ]
}
```

2. Query validation error (HTTP 200), e.g. an unknown field. The query never runs, so there's no `data` key, and graphql-ruby's own `code` is kept:

```json
{
  "errors": [
    {
      "message": "Field 'notAField' doesn't exist on type 'ContactCollection'",
      "locations": [{ "line": 1, "column": 29 }],
      "path": ["query Contacts", "contacts", "notAField"],
      "extensions": {
        "code": "undefinedField",
        "typeName": "ContactCollection",
        "fieldName": "notAField",
        "status": 400,
        "request_id": "f295efec-3cb1-4ac0-9a43-70d559b7fd76"
      }
    }
  ]
}
```

3. Bad argument during execution (HTTP 200), e.g. an invalid `sortField`:

```json
{
  "data": null,
  "errors": [
    {
      "message": "sortField must be one of: name, created_at, updated_at",
      "locations": [{ "line": 1, "column": 18 }],
      "path": ["contacts"],
      "extensions": {
        "code": "BAD_REQUEST",
        "status": 400,
        "request_id": "f295efec-3cb1-4ac0-9a43-70d559b7fd76"
      }
    }
  ]
}
```

There are two 401 responses. Both use HTTP 401 and come back before GraphQL runs.

1. A missing, invalid or inactive API key:

```json
{
  "errors": [
    {
      "message": "The API key is missing, invalid, or inactive",
      "extensions": {
        "code": "UNAUTHORIZED",
        "status": 401,
        "request_id": "f295efec-3cb1-4ac0-9a43-70d559b7fd76"
      }
    }
  ]
}
```

2. A valid key whose account is disabled or no longer has app access:

```json
{
  "errors": [
    {
      "message": "You need an active account to access our API",
      "extensions": {
        "code": "ACCOUNT_INACTIVE",
        "status": 401,
        "request_id": "f295efec-3cb1-4ac0-9a43-70d559b7fd76"
      }
    }
  ]
}
```

A rate-limited request gets an HTTP `429`. It also carries the two rate-limit headers, with Remaining at 0:

```
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
```

```json
{
  "errors": [
    {
      "message": "Rate limit exceeded. Try again later.",
      "extensions": {
        "code": "TOO_MANY_REQUESTS",
        "status": 429,
        "request_id": "f295efec-3cb1-4ac0-9a43-70d559b7fd76"
      }
    }
  ]
}
```

`401` and `429` responses have an `error` object:

```json
{
  "error": {
    "message": "The API key is missing, invalid, or inactive",
    "code": 401,
    "status": "unauthorized"
  },
  "meta": {
    "timestamp": "2026-10-02T11:37:57Z",
    "api_version": "v1",
    "request_id": "d4fb189d-9dcb-4f33-beb4-bee8870fb07c"
  }
}
```

Include the `request_id` when you contact Tradespace support about a failed request.

## GraphQL errors

Once the query runs, the response is `200 OK` even when part of it fails. Failures appear in the `errors` array. Each error's `extensions.status` holds an HTTP-style status. A failing field that can be null resolves to null. Single-record queries such as `disclosure` or `patent` cannot be null, so when one of them fails the whole `data` value is null.

| `extensions.status` | Meaning                                                                                                             |
| ------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `400`               | An argument is invalid, for example a `sortField` the query does not support. The message lists the allowed values. |
| `403`               | Your account is not allowed to read this record or module.                                                          |
| `404`               | No record matches the ID or number you passed.                                                                      |

```json
{
  "data": null,
  "errors": [
    {
      "message": "Disclosure not found",
      "extensions": { "status": 404 }
    }
  ]
}
```

Always check `errors` before reading `data`.