# Errors

The Deepinfo error formats, the status codes they use, the forms a search filter error takes, and an example request and response for each one.

Source: https://docs.deepinfo.com/getting-started/errors/

Last updated: 2026-10-05

---
The API uses standard HTTP status codes. Errors come in one of the formats below, depending on where
the request stopped.

Errors from the API gateway and from the API service are JSON (`Content-Type: application/json`) and
carry a `deepinfo-request-id` header. Include that value when you contact
[support@deepinfo.com](mailto:support@deepinfo.com).

A few errors are not JSON. When a very large export runs too long, the request ends with **502 Bad
Gateway** and a plain-text body (`error code: 502`). Narrow large exports with filters to avoid it.

## 1. Gateway Errors

These are returned before the request reaches the API service: authentication, plan access, rate limiting
and unknown URLs.

```json
{
  "message": "Unauthorized",
  "request_id": "9b1f3c5d7e9a1b3c5d7e9f1a3b5c7d9e"
}
```

| Status | Message | Cause |
|---|---|---|
| 401 | `No API key found in request` | The `apikey` header is missing |
| 401 | `Unauthorized` | The API key is not valid |
| 403 | `You cannot consume this service` | The endpoint is not included in your plan |
| 404 | `no Route matched with those values` | The URL does not exist (check the path and version) |
| 429 | `API rate limit exceeded` | Rate limit exceeded (see [Rate limits](/getting-started/rate-limits/)) |

The `request_id` in a gateway error body is a different value from the `deepinfo-request-id` header.
When you contact support about a gateway error, include both.

## 2. Application Errors

These are returned by the API service itself: invalid input, missing resources and unexpected errors.

```json
{
  "code": 10400,
  "details": [],
  "parameters": [
    {
      "param": "domain",
      "subcode": 10001,
      "details": ["Domain extension is not given in the input."]
    }
  ],
  "solution": "https://docs.deepinfo.com/reference/"
}
```

| Field | Description |
|---|---|
| `code` | Error code (see below) |
| `details` | Human-readable messages about the error as a whole |
| `parameters` | Per-parameter validation errors, one object per parameter |
| `parameters[].param` | Name of the parameter |
| `parameters[].subcode` | Error subcode |
| `parameters[].path` | Path, when present |
| `parameters[].details` | Human-readable messages about this parameter |
| `solution` | Link to documentation that helps resolve the error |

| Status | Example code | Meaning |
|---|---|---|
| 400 | `10400` | Invalid or missing parameters or body, including a search filter with an operator or a value the field does not accept. See `parameters` for the field-level reason |
| 400 | `410005` | [Darkweb Search](/reference/darkweb/search/): none of the search fields was sent. `details` lists the fields you can send |
| 404 | e.g. `30003` | The requested resource does not exist |
| 400 | `30004` | The requested state change is not allowed for the record's current state. Some searches also return it for a filter operator they do not support (see [Filter Errors](#filter-errors)) |
| 500 | `-1` | Unexpected error. Retry later. If it persists, contact support with the `deepinfo-request-id` |

### Filter Errors

On a search endpoint, a filter with an operator the field does not accept returns **400**. Today the
message comes back in one of three forms, depending on the endpoint. An operator the search does not know
at all, such as `gt` outside Vulnerability Search of the CVE database, returns a fourth:

| Form | `code` | Message in | Message |
|---|---|---|---|
| Invalid query | `10400` | `parameters[].details` | `Invalid query: <field> does not support <operator> query` |
| Supported queries listed | `10400` | `parameters[].details` | `Field '<field>' does not support '<operator>' query. Supported queries are [...]` |
| Not supported yet | `30004` | `details` | `<operator> query type is not supported yet.` |
| Unknown operator | `10400` | `parameters[].details`, with `param` `type` | `Select a valid choice.` |

Invalid query, from [Asset Search](/reference/easm/asset-search/):

**400 Bad Request**

```json
{
  "code": 10400,
  "parameters": [
    {
      "param": "must",
      "path": "filters",
      "details": [
        "Invalid query: open_port_count does not support startswith query"
      ]
    }
  ]
}
```

Supported queries listed, from [Vulnerability Search](/reference/vulnerability/search/) of the CVE
database with `gte` on `id`. This form also lists the operators the field accepts:

**400 Bad Request**

```json
{
  "code": 10400,
  "parameters": [
    {
      "param": "must",
      "path": "filters",
      "details": [
        "Field 'id' does not support 'gte' query. Supported queries are ['eq', 'exists', 'wildcard', 'startswith', 'lt', 'gt']."
      ]
    }
  ]
}
```

Not supported yet, from [Deleted Asset Search](/reference/easm/deleted-asset-search/). This form names the
operator but not the field:

**400 Bad Request**

```json
{
  "code": 30004,
  "details": [
    "wildcard query type is not supported yet."
  ]
}
```

Unknown operator, from [Asset Search](/reference/easm/asset-search/) with `gt`. This form names neither the
field nor the operator: `param` is `type`, and `path` names the list the filter is in:

**400 Bad Request**

```json
{
  "code": 10400,
  "parameters": [
    {
      "param": "type",
      "path": "filters.must",
      "details": [
        "Select a valid choice."
      ]
    }
  ],
  "solution": "https://docs.deepinfo.com/reference/"
}
```

A filter value of the wrong type returns **400** with code `10400` as well, but its message reads
differently, for example `Invalid value true: $eq must be boolean.` There the operator is accepted and the
value is not: send the value as the type the message names.

[Search & Filters](/getting-started/search-and-filters/#filter-errors) shows the filter behind each of
these errors, and where each endpoint lists the operators its fields accept.

## Examples

Each example below shows a request and the response saved for it. The saved responses are anonymized:
the `request_id` and `deepinfo-request-id` values are placeholders.

### 401 Missing API Key

A request sent **without** the `apikey` header. The gateway rejects it with **401**.

```bash
curl "https://api.deepinfo.com/v1/lookup/whois?domain=deepinfo.com" \
  -H "Accept: application/json"
```

**401 Unauthorized**

```json
{
  "message": "No API key found in request",
  "request_id": "9b1f3c5d7e9a1b3c5d7e9f1a3b5c7d9e"
}
```

### 401 Invalid API Key

An **invalid** API key. The gateway rejects it with **401**.

```bash
curl "https://api.deepinfo.com/v1/lookup/whois?domain=deepinfo.com" \
  -H "apikey: invalid-api-key" \
  -H "Accept: application/json"
```

**401 Unauthorized**

```json
{
  "message": "Unauthorized",
  "request_id": "9b1f3c5d7e9a1b3c5d7e9f1a3b5c7d9e"
}
```

### 403 Endpoint Not in Plan

Returned when your API key is valid but the endpoint is **not included in your plan**. Whether you see it
depends on your plan.

```bash
curl "https://api.deepinfo.com/v1/discovery/vulnerability-finder?url=https://deepinfo.com" \
  -H "apikey: YOUR_API_KEY" \
  -H "Accept: application/json"
```

**403 Forbidden**

```json
{
  "message": "You cannot consume this service",
  "request_id": "9b1f3c5d7e9a1b3c5d7e9f1a3b5c7d9e"
}
```

### 404 Unknown URL

A URL that does not exist. The gateway returns **404**.

```bash
curl "https://api.deepinfo.com/v1/lookup/does-not-exist" \
  -H "apikey: YOUR_API_KEY" \
  -H "Accept: application/json"
```

**404 Not Found**

```json
{
  "message": "no Route matched with those values",
  "request_id": "9b1f3c5d7e9a1b3c5d7e9f1a3b5c7d9e"
}
```

### 429 Rate Limit Exceeded

Returned when you exceed your rate limit. Send the same request several times within one second to
reproduce it. See [Rate limits](/getting-started/rate-limits/).

```bash
curl "https://api.deepinfo.com/v1/lookup/ip-whois?ip=8.8.8.8" \
  -H "apikey: YOUR_API_KEY" \
  -H "Accept: application/json"
```

**429 Too Many Requests**

```http
content-type: application/json
ratelimit-limit: 1
ratelimit-remaining: 0
ratelimit-reset: 1
deepinfo-request-id: 5f0c6a8e-1b2d-4c3e-9f4a-7b8c9d0e1f2a
```

```json
{
  "message": "API rate limit exceeded",
  "request_id": "9b1f3c5d7e9a1b3c5d7e9f1a3b5c7d9e"
}
```

### 400 Validation Error

An invalid `domain`. The API returns **400** with a field-level reason in `parameters`.

```bash
curl "https://api.deepinfo.com/v1/lookup/whois?domain=not_a_domain" \
  -H "apikey: YOUR_API_KEY" \
  -H "Accept: application/json"
```

**400 Bad Request**

```json
{
  "code": 10400,
  "parameters": [
    {
      "param": "domain",
      "subcode": 10001,
      "details": [
        "Domain extension is not given in the input."
      ]
    }
  ],
  "solution": "https://docs.deepinfo.com/reference/"
}
```

### 404 Resource Not Found

An External Attack Surface Management (EASM) asset that does not exist. The API returns **404** with an application error code. Requires EASM
access.

```bash
curl "https://api.deepinfo.com/v1/easm/assets/ffffffffffffffffffffffff" \
  -H "apikey: YOUR_API_KEY" \
  -H "Accept: application/json"
```

**404 Not Found**

```json
{
  "code": 30003,
  "details": [
    "Asset does not exist."
  ],
  "solution": "https://docs.deepinfo.com/reference/"
}
```

### 500 Unexpected Error

The shape of an unexpected server error. This request normally succeeds; the example only shows what a
500 looks like. Retry later. If it persists, contact support with the `deepinfo-request-id` header value.

```bash
curl "https://api.deepinfo.com/v1/lookup/whois?domain=deepinfo.com" \
  -H "apikey: YOUR_API_KEY" \
  -H "Accept: application/json"
```

**500 Internal Server Error**

```json
{
  "code": -1,
  "details": [
    "An unexpected error has occurred."
  ]
}
```

> [!NOTE]
> The Deepinfo [Postman collection](/getting-started/postman/) has the requests behind these examples in
> its **Getting Started › Errors** folder.
