---
title: "Errors"
description: "Error format, HTTP status codes, machine-readable error codes and rate-limit behaviour and headers for the Edge REST API, with example responses."
url: "https://edge.network/docs/api/errors"
section: "REST API"
---

# Errors

The API uses conventional HTTP status codes and returns a consistent JSON body for every error, with a human-readable message and a stable machine-readable code.

## Error format

```http
HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "VM not found",
  "code": "NOT_FOUND"
}
```

Requests rejected by schema validation additionally include a `details` array describing each failed field:

```http
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "Validation error",
  "code": "VALIDATION_ERROR",
  "details": [
    {
      "path": ["name"],
      "message": "Required"
    }
  ]
}
```

## Error codes

| HTTP status | Code | Meaning |
|---|---|---|
| 400 | `VALIDATION_ERROR` | The request body or parameters are invalid. Check `details` if present. |
| 401 | `AUTHENTICATION_ERROR` | Missing, invalid, expired or revoked API key. |
| 403 | `AUTHORIZATION_ERROR` | Authenticated, but not permitted to perform this action. |
| 404 | `NOT_FOUND` | The resource doesn't exist or belongs to a different account. |
| 409 | `CONFLICT` | The request conflicts with current state (e.g. duplicate name). |
| 429 | `RATE_LIMIT` | Too many requests. Back off and retry after `Retry-After` seconds. |
| 500 | `INTERNAL_ERROR` | Something went wrong on our side. Safe to retry with backoff. |

Individual endpoints may return more specific codes (e.g. `SCRIPT_NOT_FOUND`). Always branch on the HTTP status first and treat `code` as a refinement.

## Rate limits

The API allows **600 requests per minute per IP**, measured over a sliding window. Every response carries the IETF standard rate-limit headers ([draft-ietf-httpapi-ratelimit-headers](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/)) so clients can self-throttle in real time. The legacy `X-RateLimit-*` pair is also sent for older clients.

| Header | Meaning |
|---|---|
| `RateLimit-Limit` | Maximum requests allowed in the window |
| `RateLimit-Remaining` | Requests remaining in the current window |
| `RateLimit-Reset` | Seconds until the quota resets |
| `RateLimit-Policy` | The quota policy: `600;w=60` means 600 requests per 60-second window |
| `Retry-After` | Seconds to wait before retrying (on 429 responses only) |
| `X-RateLimit-Limit` / `X-RateLimit-Remaining` | Legacy pair, kept for older clients. Prefer the `RateLimit-*` headers. |

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 12
RateLimit-Limit: 600
RateLimit-Remaining: 0
RateLimit-Reset: 12
RateLimit-Policy: 600;w=60
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0

{
  "error": "Too many requests. Try again in 12s.",
  "code": "RATE_LIMIT"
}
```
