> ## 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.

# Create and Manage Your Arbitrage API Keys

> Generate, inspect, and revoke API keys for programmatic access to Arbitrage and market data endpoints from the Developer Console.

API keys let you access Arbitrage data endpoints from your own code without a browser session. You create and manage keys through the Developer Console — either via the web UI or the API itself. Each key carries a set of permissions and a rate limit, and the full key value is shown exactly once at creation, so have somewhere ready to store it before you begin.

<Warning>
  The complete API key is returned **only once** in the creation response. Predexy stores a hashed version and cannot show you the raw key again. If you lose it, revoke the old key and create a new one.
</Warning>

## Prerequisites

* A Arbitrage developer account. Register at [app.revalonlabs.xyz](https://app.revalonlabs.xyz) or via `POST /api/v1/auth/register`.
* A valid session JWT (email/password login) to authenticate Console API calls.

## Create an API key

<Steps>
  <Step title="Open the Developer Console">
    Go to [app.revalonlabs.xyz](https://app.revalonlabs.xyz) and sign in with your developer account. Navigate to **Developer Console → API Keys** and click **New API Key**.

    Fill in a descriptive name (e.g. `Production Trading Bot`), choose the permissions you need, and set a rate limit. Then click **Create**.
  </Step>

  <Step title="Copy and store the key immediately">
    The Console shows the full key — prefixed with `pdx_` — exactly once. Copy it into a secrets manager, environment variable, or vault before closing the dialog.
  </Step>
</Steps>

### Create a key via the API

You can also create keys programmatically using your session JWT.

**Endpoint:** `POST /api/v1/console/keys`

**Request body:**

| Field         | Type    | Required | Description                                                                  |
| ------------- | ------- | -------- | ---------------------------------------------------------------------------- |
| `name`        | string  | Yes      | Human-readable label (1–100 chars)                                           |
| `permissions` | string  | No       | JSON-encoded array of permission strings. Defaults to all three read scopes. |
| `rate_limit`  | integer | No       | Requests per minute (1–10,000). Default: 60.                                 |

**Available permissions:**

* `read:arbitrage` — access arbitrage opportunity endpoints
* `read:markets` — access market browsing and discovery endpoints
* `read:questions` — access canonical question endpoints

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.predexy.com/api/v1/console/keys \
    -H "Authorization: Bearer <your-session-jwt>" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Production Trading Bot",
      "permissions": "[\"read:arbitrage\",\"read:markets\",\"read:questions\"]",
      "rate_limit": 120
    }'
  ```

  ```python Python theme={null}
  import httpx

  response = httpx.post(
      "https://api.predexy.com/api/v1/console/keys",
      headers={"Authorization": "Bearer <your-session-jwt>"},
      json={
          "name": "Production Trading Bot",
          "permissions": '["read:arbitrage","read:markets","read:questions"]',
          "rate_limit": 120,
      },
  )
  data = response.json()
  print(data["data"]["key"])   # Store this — shown once only
  ```
</CodeGroup>

**Example response:**

```json theme={null}
{
  "data": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "Production Trading Bot",
    "key": "pdx_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
    "key_prefix": "pdx_a1b2c3d4",
    "permissions": "[\"read:arbitrage\",\"read:markets\",\"read:questions\"]",
    "rate_limit": 120
  },
  "message": "Save this API key — it will not be shown again."
}
```

The `key` field in `data` is the value you'll use in all subsequent requests. The `key_prefix` (first 12 characters) is what Predexy stores and displays in listings for identification.

## Use your API key

Pass the key in the `X-API-Key` header on every request:

```bash theme={null}
curl https://api.predexy.com/api/v1/external/arbitrage/opportunities \
  -H "X-API-Key: pdx_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
```

<Note>
  API key endpoints are separate from session-authenticated endpoints. The external arbitrage endpoint is `GET /api/v1/external/arbitrage/opportunities` — not the session-only `/api/v1/arbitrage/opportunities`.
</Note>

## List your API keys

Retrieve all keys on your account. The full key is never included — only the `key_prefix` is returned.

**Endpoint:** `GET /api/v1/console/keys`

```bash theme={null}
curl https://api.predexy.com/api/v1/console/keys \
  -H "Authorization: Bearer <your-session-jwt>"
```

**Example response:**

```json theme={null}
{
  "data": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "Production Trading Bot",
      "key_prefix": "pdx_a1b2c3d4",
      "permissions": "[\"read:arbitrage\",\"read:markets\",\"read:questions\"]",
      "rate_limit": 120,
      "is_active": true,
      "last_used_at": "2026-04-25T14:32:10Z",
      "created_at": "2026-04-01T09:00:00Z"
    }
  ],
  "meta": {
    "count": 1
  }
}
```

Each `APIKeyInfo` object includes:

| Field          | Description                                     |
| -------------- | ----------------------------------------------- |
| `id`           | UUID used to revoke the key                     |
| `name`         | Label you set at creation                       |
| `key_prefix`   | First 12 characters for identification          |
| `permissions`  | JSON-encoded permission array                   |
| `rate_limit`   | Configured requests-per-minute limit            |
| `is_active`    | `false` if the key has been revoked             |
| `last_used_at` | Last request timestamp, or `null` if never used |
| `created_at`   | Creation timestamp                              |

## Revoke a key

Revoking a key is immediate and permanent. Any in-flight requests using the key will receive a `401 INVALID_API_KEY` response. Revoked keys cannot be reactivated.

**Endpoint:** `DELETE /api/v1/console/keys/{id}`

```bash theme={null}
curl -X DELETE \
  https://api.predexy.com/api/v1/console/keys/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
  -H "Authorization: Bearer <your-session-jwt>"
```

**Example response:**

```json theme={null}
{
  "data": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "revoked"
  }
}
```

<Tip>
  Rotate keys regularly and create separate keys for different environments (development, staging, production). That way you can revoke a compromised key without affecting other consumers.
</Tip>

## Rate limits

Your key's rate limit (default 60 req/min, maximum 10,000 req/min) is enforced per rolling window. Every response includes these headers:

| Header                  | Description                              |
| ----------------------- | ---------------------------------------- |
| `X-RateLimit-Limit`     | Your configured limit                    |
| `X-RateLimit-Remaining` | Requests remaining in the current window |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets    |

When you exceed the limit, the API returns `429 RATE_LIMITED`. Back off and retry after the `X-RateLimit-Reset` timestamp.
