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

# Authenticate with the Arbitrage API: Keys and Tokens

> Learn how to get credentials, pass API keys and session tokens in requests, and understand rate limits for each authentication tier.

Arbitrage supports two authentication methods for customers: API keys for programmatic and bot access, and session JWTs for Developer Console users. You pick the method based on how you're accessing the API — if you're building an automated system or trading bot, use an API key; if you're interacting with the Developer Console or the main app, you'll use a session token. This page covers both, plus a brief overview of wallet authentication (SIWE) used on the main application.

## API keys

API keys are the primary credential for external consumers, trading bots, and any automated system making calls to Predexy. Keys give you access to the `/api/v1/external/*` route group, including the arbitrage opportunities endpoint.

### Getting an API key

Create a key in the Developer Console under **Settings → API Keys**, or via the API after logging in:

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

The response returns the full key exactly once:

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

<Warning>
  Copy and store the `key` value immediately. Predexy only stores a hash of your key on the server — the full value is never shown again after this response. If you lose it, revoke the key and create a new one.
</Warning>

Key properties:

* **Prefix:** All keys start with `pdx_` so they're easy to identify in code and logs.
* **One-time reveal:** The full key appears only in the creation response.
* **Revocation:** Delete a key via `DELETE /api/v1/console/keys/{id}`. Revoked keys are deactivated immediately and cannot be reactivated.

### Using an API key in requests

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

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

If your key is invalid or has been revoked, the API returns `401` with `INVALID_API_KEY`:

```json theme={null}
{
  "status": "INVALID_API_KEY",
  "message": "Authentication required"
}
```

***

## Session tokens (JWT)

Session tokens are issued when you log in with email and password. They're used by the Developer Console and for direct API calls against product routes like market discovery.

### Logging in

```bash theme={null}
curl -s -X POST https://api.predexy.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@company.com",
    "password": "your-password"
  }'
```

The response provides an access token (15-minute lifetime) and a refresh token (7-day lifetime):

```json theme={null}
{
  "data": {
    "id": "usr_01hx...",
    "email": "you@company.com",
    "name": "Your Name"
  },
  "tokens": {
    "access_token": "<jwt>",
    "refresh_token": "<jwt>"
  }
}
```

### Using a session token in requests

Pass the access token as a `Bearer` token in the `Authorization` header:

```bash theme={null}
curl -s "https://api.predexy.com/api/v1/discover?limit=10" \
  -H "Authorization: Bearer <your-access-token>"
```

Alternatively, the Developer Console sets a `pdx_access` cookie automatically when you're logged in — browser-based requests pick this up without any extra configuration.

### Refreshing your access token

When your access token expires, exchange your refresh token for a new pair:

```bash theme={null}
curl -s -X POST https://api.predexy.com/api/v1/auth/refresh \
  -H "Authorization: Bearer <your-refresh-token>"
```

***

## Wallet authentication (SIWE)

The main Predexy application supports Sign-In With Ethereum (SIWE) for users who prefer wallet-based authentication. The flow has three steps:

1. **Get a nonce** — `GET /api/v1/siwe/nonce` returns a one-time nonce tied to your session.
2. **Sign the message** — Your wallet signs an EIP-4361 message containing the nonce.
3. **Verify** — `POST /api/v1/siwe/verify` submits the signed message. On success, Predexy issues a session cookie.

<Note>
  SIWE is for the main application, not for Developer Console access or API key issuance. If you're building a bot or integration, use email/password login and API keys instead.
</Note>

***

## Rate limits

Every response from Predexy includes rate-limit headers so your code can back off gracefully before hitting the limit:

| Header                  | Description                                    |
| ----------------------- | ---------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the current window |
| `X-RateLimit-Remaining` | Requests remaining before the window resets    |
| `X-RateLimit-Reset`     | Unix timestamp of when the window resets       |

Rate limits vary by tier:

| Tier                                         | Requests / min | Burst |
| -------------------------------------------- | -------------- | ----- |
| API Key                                      | 600            | 50    |
| Authenticated (session)                      | 60             | 20    |
| Product read (unauthenticated public routes) | 120            | 40    |

When you exceed the limit, the API returns `429` with `RATE_LIMITED`:

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

<Tip>
  API keys have the highest rate limit tier (600 req/min). If you're polling the arbitrage endpoint frequently from a bot, make sure you're authenticating with an API key rather than a session token.
</Tip>

***

## Choosing the right method

| Scenario                                        | Use                                              |
| ----------------------------------------------- | ------------------------------------------------ |
| Trading bot polling arbitrage every few seconds | API key (`X-API-Key`)                            |
| Script fetching market data                     | API key (`X-API-Key`)                            |
| Building against the Developer Console          | Session JWT (`Authorization: Bearer`)            |
| Browser-based app for logged-in users           | `pdx_access` cookie (set automatically on login) |
| Wallet-connected main app user                  | SIWE session                                     |
