> For the complete documentation index see https://domscan.net/llms.txt. Markdown versions of every docs page are available by appending .md to the page URL.

Source: https://domscan.net/docs/error-codes

# Error codes

Explore Error codes API documentation, request parameters, response fields, code examples, and error handling for DomScan integrations.

### Structured errors

Every API error returns the same JSON shape: an `error` object with a stable `code`, a readable `message`, its `type` and HTTP `status`, whether it is `retryable`, the `request_id` and a `docs_url`. The `request_id` always matches the `X-Request-Id` response header, so include it when you contact support.

```json
{
  "error": {
    "code": "INVALID_DOMAIN",
    "message": "Invalid domain format",
    "suggestion": "Use a registrable domain such as example.com",
    "type": "validation_error",
    "status": 400,
    "retryable": false,
    "request_id": "m5x7k2p-a9f3",
    "docs_url": "https://domscan.net/docs/check-availability"
  }
}
```

### Error fields

| Field | Description |
| --- | --- |
| `code` | Stable machine-readable error code. Codes are never renamed, so you can safely branch on them. |
| `message` | Readable explanation of the error. The wording can change, so do not parse it. |
| `type` | Broad error category, such as `validation_error`, `authentication_error` or `rate_limit_error`. |
| `status` | The HTTP status code, repeated in the body for logs and queues. |
| `retryable` | Whether the same request can succeed if you retry it later. |
| `request_id` | Unique request identifier. Matches the `X-Request-Id` header. |
| `docs_url` | Link to the documentation section that explains this error. |
| `suggestion` | Optional hint on how to fix the request. |
| `details` | Optional structured context, such as the allowed methods or the invalid parameter. |
| `retry_after` | Optional number of seconds to wait before retrying. Also sent as the `Retry-After` header. |

### Common error codes

These are the codes most clients need to handle. Some endpoints return more specific codes that follow the same rules; the full list with status, type and retry behavior is in the OpenAPI specification under `x-domscan-error-codes`. `RATE_LIMIT_EXCEEDED` is still accepted as an alias of `RATE_LIMITED`.

| Code | HTTP status | Type | Retryable | Description |
| --- | --- | --- | --- | --- |
| `BAD_REQUEST` | 400 | `validation_error` | No | Missing or invalid parameters |
| `MISSING_PARAMETER` | 400 | `validation_error` | No | A required parameter is missing |
| `INVALID_PARAMETER` | 400 | `validation_error` | No | A parameter has an invalid value |
| `INVALID_JSON` | 400 | `validation_error` | No | The request body is not valid JSON |
| `INVALID_DOMAIN` | 400 | `validation_error` | No | Invalid domain format |
| `UNSUPPORTED_TLD` | 400 | `validation_error` | No | TLD not supported |
| `SUBDOMAIN_NOT_SUPPORTED` | 400 | `validation_error` | No | This endpoint accepts registrable domains, not subdomains |
| `VALIDATION_ERROR` | 422 | `validation_error` | No | The request is well formed but cannot be processed |
| `AUTH_REQUIRED` | 401 | `authentication_error` | No | No API key or session was provided |
| `INVALID_API_KEY` | 401 | `authentication_error` | No | The API key is invalid or has been revoked |
| `INSUFFICIENT_CREDITS` | 402 | `credits_error` | No | Your account does not have enough credits for this request |
| `FORBIDDEN` | 403 | `permission_error` | No | You do not have permission for this action |
| `NOT_FOUND` | 404 | `not_found_error` | No | The endpoint or resource does not exist |
| `METHOD_NOT_ALLOWED` | 405 | `request_error` | No | The endpoint exists but does not accept this HTTP method. The `Allow` header lists supported methods. |
| `CONFLICT` | 409 | `conflict_error` | No | The request conflicts with the current state of the resource |
| `IDEMPOTENCY_CONFLICT` | 409 | `conflict_error` | No | The idempotency key was already used with a different request |
| `IDEMPOTENCY_KEY_REUSED` | 422 | `validation_error` | No | This `Idempotency-Key` was already used with a different request in the last 24 hours. Use a new key for a new request. |
| `IDEMPOTENCY_IN_PROGRESS` | 409 | `conflict_error` | Yes | A request with this `Idempotency-Key` is still running. Retry after a moment to receive its stored response. |
| `RATE_LIMITED` | 429 | `rate_limit_error` | Yes | Too many requests |
| `INTERNAL` | 500 | `api_error` | No | Unexpected server error. Contact support with the request ID if it persists. |
| `UPSTREAM_ERROR` | 502 | `upstream_error` | Yes | An upstream source returned an unusable response |
| `UPSTREAM_UNAVAILABLE` | 503 | `upstream_error` | Yes | An upstream source is temporarily unavailable |
| `SERVICE_UNAVAILABLE` | 503 | `upstream_error` | Yes | The service is temporarily unavailable |
| `TIMEOUT` | 504 | `timeout_error` | Yes | An upstream source or registry did not respond in time |

### Retry guidance

- Retry only when `retryable` is `true`. For validation, authentication and permission errors, fix the request first.

- When `retry_after` or the `Retry-After` header is present, wait at least that many seconds before the next attempt.

- Otherwise use exponential backoff with jitter, for example 1, 2, 4 and 8 seconds, and stop after a few attempts.

- For batch and job creation, send an `Idempotency-Key` header so a retried request never creates a duplicate job.

- For other POST requests that charge credits, an `Idempotency-Key` header makes a retry return the stored response instead of charging again.

### Compatibility

Since 10 October 2026 every endpoint uses this format. Fields that some endpoints already returned, such as `credits_remaining`, `purchase_url`, `login_url`, `success` or `meta`, are kept during a compatibility period, so existing integrations keep working. Read error details from the `error` object in new code.
