> ## Documentation Index
> Fetch the complete documentation index at: https://docs.revalonlabs.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Arbitrage API Error Codes and Responses

> A complete reference of Predexy error status codes, their HTTP equivalents, when each occurs, and how to handle them in your integration.

When something goes wrong, the Arbitrage API always returns a structured error response with a machine-readable status code and a human-readable message. This consistent format means you can handle errors programmatically using the `status` field while surfacing useful context to your users or logs via the `message` field. Internal server details are never exposed — only safe, descriptive messages reach your client.

## Error response format

Every error from the Arbitrage API follows this envelope:

```json theme={null}
{
  "status": "MACHINE_CODE",
  "message": "Human-readable description of what went wrong."
}
```

* Use `status` for programmatic branching in your code — it never changes for a given error condition.
* Use `message` for logging and user-facing display — it may include dynamic context like a countdown or a field name.

## Error codes

The table below covers every status code defined in the API. HTTP status codes are listed alongside each to help you triage at the transport layer before parsing the body.

| Status code            | HTTP status | When it occurs                                                   | How to handle it                                                                        |
| ---------------------- | ----------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `INVALID_REQUEST`      | 400         | Malformed or missing request parameters                          | Validate inputs before sending; check `message` for the offending field                 |
| `UNAUTHORIZED`         | 401         | Missing, expired, or invalid authentication credentials          | Re-authenticate or check that your token/key is being sent correctly                    |
| `FORBIDDEN`            | 403         | Valid credentials but insufficient permissions for this endpoint | Check your API key's permission scopes in the Developer Console                         |
| `NOT_FOUND`            | 404         | The requested resource does not exist                            | Verify the ID or path in your request                                                   |
| `RATE_LIMITED`         | 429         | Request rate exceeds your tier's limit                           | Back off and retry after `X-RateLimit-Reset`; see [rate limits](/reference/rate-limits) |
| `INTERNAL_ERROR`       | 500         | An unexpected error occurred on the server                       | Retry with backoff; contact support if persistent                                       |
| `SERVICE_UNAVAILABLE`  | 503         | The service is temporarily down or under maintenance             | Retry with backoff; monitor status page                                                 |
| `MARKET_NOT_FOUND`     | 404         | The specific market ID does not exist                            | Confirm the market ID is valid and still active                                         |
| `QUESTION_NOT_FOUND`   | 404         | The canonical question ID does not exist                         | Confirm the question UUID; it may have been removed                                     |
| `EMBEDDING_FAILED`     | 502         | The semantic matching service returned an error                  | Retry; this is a transient upstream error                                               |
| `PLATFORM_UNAVAILABLE` | 502         | Upstream platform data is temporarily unavailable                | Retry later; the specific platform may be experiencing downtime                         |
| `INVALID_API_KEY`      | 401         | The API key does not exist or has been revoked                   | Check the key in your Developer Console; generate a new one if revoked                  |
| `API_KEY_REQUIRED`     | 403         | The endpoint requires API key authentication                     | Add your `X-API-Key: pdx_...` header                                                    |
| `QUOTA_EXCEEDED`       | 429         | Your usage quota for the billing period has been reached         | Upgrade your plan or wait for the quota to reset                                        |
| `MATCH_NOT_FOUND`      | 404         | No cross-platform match exists for the requested market          | The market may not yet be indexed or matched                                            |
| `INVALID_PRICE`        | 400         | A price value is outside the valid range (0–1)                   | Ensure all price values are probabilities between 0 and 1                               |
| `EMAIL_EXISTS`         | 409         | The email address is already registered                          | Use a different email or log in with the existing account                               |

## Example error responses

<CodeGroup>
  ```json 400 Invalid request theme={null}
  {
    "status": "INVALID_REQUEST",
    "message": "Invalid request parameters"
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "status": "UNAUTHORIZED",
    "message": "Authentication required"
  }
  ```

  ```json 401 Invalid API key theme={null}
  {
    "status": "INVALID_API_KEY",
    "message": "API key not found or has been revoked"
  }
  ```

  ```json 403 Forbidden theme={null}
  {
    "status": "FORBIDDEN",
    "message": "Access denied"
  }
  ```

  ```json 403 API key required theme={null}
  {
    "status": "API_KEY_REQUIRED",
    "message": "This endpoint requires API key authentication"
  }
  ```

  ```json 429 Rate limited theme={null}
  {
    "status": "RATE_LIMITED",
    "message": "Rate limit exceeded. Try again in 42 seconds."
  }
  ```

  ```json 429 Quota exceeded theme={null}
  {
    "status": "QUOTA_EXCEEDED",
    "message": "Monthly usage quota reached"
  }
  ```

  ```json 500 Internal error theme={null}
  {
    "status": "INTERNAL_ERROR",
    "message": "An internal error occurred"
  }
  ```

  ```json 503 Service unavailable theme={null}
  {
    "status": "SERVICE_UNAVAILABLE",
    "message": "Service temporarily unavailable"
  }
  ```
</CodeGroup>

## Handling errors in Python

The pattern below covers the most common error categories you'll encounter in production:

```python python theme={null}
import requests

def handle_response(response: requests.Response) -> dict:
    if response.ok:
        return response.json()

    body = response.json()
    status = body.get("status")
    message = body.get("message", "Unknown error")

    if status == "RATE_LIMITED":
        reset_at = response.headers.get("X-RateLimit-Reset")
        raise Exception(f"Rate limited. Reset at Unix timestamp {reset_at}. {message}")

    if status == "QUOTA_EXCEEDED":
        raise Exception(f"Quota exceeded. Upgrade your plan or wait for reset.")

    if status in ("UNAUTHORIZED", "INVALID_API_KEY"):
        raise Exception(f"Authentication error: {message}")

    if status == "FORBIDDEN":
        raise Exception(f"Permission denied: {message}")

    if status in ("NOT_FOUND", "MARKET_NOT_FOUND", "QUESTION_NOT_FOUND", "MATCH_NOT_FOUND"):
        raise Exception(f"Resource not found: {message}")

    if status in ("INTERNAL_ERROR", "SERVICE_UNAVAILABLE", "EMBEDDING_FAILED", "PLATFORM_UNAVAILABLE"):
        raise Exception(f"Server error (retryable): {message}")

    raise Exception(f"API error [{status}]: {message}")
```

<Note>
  The `message` field is always safe to log and display to end users. It never contains internal stack traces, database details, or secrets.
</Note>

<Tip>
  For automated retries, treat `INTERNAL_ERROR`, `SERVICE_UNAVAILABLE`, `EMBEDDING_FAILED`, and `PLATFORM_UNAVAILABLE` as transient — they typically resolve within seconds. Treat `UNAUTHORIZED`, `FORBIDDEN`, `INVALID_API_KEY`, and `QUOTA_EXCEEDED` as permanent until you take corrective action.
</Tip>
