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

# Quotas & errors

> Per-tier RPS caps, response envelope shape, and error codes. Phase 1.2a: no monthly cap — usage is gated entirely by requests-per-second.

## Response envelope

The envelope is **not uniform across the surface** — it depends on the endpoint family.

**Enveloped (legacy `/api/v1/*` + raw stats/swaps):**

```json theme={null}
// Success
{ "success": true, "data": { /* payload */ } }

// Error
{ "success": false, "error": { "code": "...", "message": "..." } }
```

These endpoints wrap success payloads: `/api/v1/pairs`, `/api/v1/candles`, `/api/v1/candles/latest`, `/api/v1/stats`, `/api/v1/top-movers`, `/api/v1/protocols` (and the raw `/stats/*`, `/swaps/*` families).

**Top-level (no wrapper):** newer endpoints return the payload directly — no `success`/`data` keys:

* `/screener`, `/search`, `/trending`, `/tokens/{mint}/intel`, `/tokens/{mint}/risk`

For example, `/screener` returns `{ results, total_matches, limit, offset, warnings }` at the top level.

**Errors are always enveloped** (even for the top-level endpoints), but the `error` field shape differs:

* Most endpoints: `{ "success": false, "error": { "code": "...", "message": "..." } }`.
* The `/screener` and `/search` filter-validation 400 returns `error` as a **string**: `{ "success": false, "data": null, "error": "invalid parameter: invalid_filter:mint|creator|mints" }`. A malformed `mint`, `mints[]`, or `creator` triggers this 400; an *unsupported* filter (e.g. `risk_score`) instead stays **200** and adds a note to the `warnings[]` array.

Streaming protocols (WebSocket, gRPC) use protocol-native error frames — see the [WebSocket](/streaming/websocket) and [gRPC](/streaming/grpc) pages.

## Base paths

Endpoints live under different base paths, and one is served by a separate service:

| Family                                                                        | Base path     | Notes                                                                                                                                                                                         |
| ----------------------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `candles`, `candles/latest`, `pairs`, `protocols`, `stats`, `top-movers`      | `/api/v1/...` | Versioned.                                                                                                                                                                                    |
| `screener`, `trending`, `search`, `tokens/*` (intel, risk, holders, audit, …) | `/` (root)    | Unversioned.                                                                                                                                                                                  |
| `tokens/{mint}/audit`                                                         | `/` (root)    | **Separate service (CT106)** — same host (`api.dexploit.dev`) but a different backend. Returns a `200` `indexed: false` sentinel for valid-but-unindexed mints and `400` for malformed mints. |

All paths share the same host, `https://api.dexploit.dev`, and the same `Authorization` / API-key auth.

## Rate limits

Dexploit's pricing model is **capped requests-per-second, unlimited monthly usage.** Pick a tier that matches your sustained throughput; there is no monthly volume to budget against.

| Tier       | Sustained RPS | 60-second burst window |
| ---------- | ------------- | ---------------------- |
| Free       | 20            | 1,200 reqs             |
| Developer  | 100           | 6,000 reqs             |
| Pro        | 500           | 30,000 reqs            |
| Enterprise | unlimited     | unlimited              |

The burst window is the smoothing knob: a Free-tier client can issue up to 1,200 requests in a single second as long as the rolling 60-second sum stays under 1,200. Indexers and backfill jobs benefit from this; steady-state polling never sees the burst headroom.

## Inspecting your usage

Call `GET /credits` at any time to see your current tier, RPS cap, requests used in the current window, and feature flags:

```json theme={null}
{
  "tier": "free",
  "rps_cap": 20,
  "rps_window_secs": 60,
  "current_window_used": 7,
  "current_window_remaining": 1193,
  "current_window_reset_secs": 23,
  "monthly_used": 4321,
  "monthly_used_note": "informational; no monthly cap on Dexploit",
  "tier_features": {
    "smart_money_access": false,
    "whales_access": false
  }
}
```

`monthly_used` is informational. There is no monthly cap on Dexploit — the field shows your cumulative request count for the current calendar month so you can size up your typical load.

## Rate limiting

When you exceed your tier's RPS cap you get HTTP 429 with `code: "RATE_LIMIT_EXCEEDED"`. Back off and retry. Use [`GET /credits`](#inspecting-your-usage) to read your current-window usage and the seconds until it resets (`current_window_reset_secs`).

## Tier-locked features

Some endpoints are paid-tier-only. Free tier callers get **HTTP 200 with `tier_locked: true`** rather than a 429:

```json theme={null}
{
  "mint": "BoMb…",
  "results": [],
  "tier_locked": true,
  "tier_required": "developer",
  "upgrade_url": "https://dexploit.dev/pricing",
  "computed_at": 1779852398772
}
```

This keeps client code simple — same response shape, an extra flag — and lets your UI render an upsell where data would be without an error-handling branch.

Currently tier-locked endpoints: `/tokens/{mint}/smart-money`, `/tokens/{mint}/whales`.

## gRPC stream caps

The `dexploit.v1.SwapStream` service caps concurrent connections per tier:

| Tier       | Max concurrent SwapStream connections |
| ---------- | ------------------------------------- |
| Free       | 1                                     |
| Developer  | 10                                    |
| Pro        | 50                                    |
| Enterprise | unlimited                             |

Exceeding the cap returns `RESOURCE_EXHAUSTED`. The `wallet_tags` filter is Pro+ only — on lower tiers the filter is silently dropped and the response carries `x-dexploit-tier-locked-filter: wallet_tags` metadata. See [gRPC: SwapStream](/streaming/grpc-swaps) for the full reference.

## Error codes

| Code                  | Status | Meaning                                                        | Remedy                                                                                           |
| --------------------- | ------ | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `UNAUTHORIZED`        | 401    | Key missing, malformed, or revoked.                            | Generate a new key in the dashboard.                                                             |
| `FORBIDDEN`           | 403    | Authenticated, but not allowed.                                | Check your tier; some endpoints require Pro or Enterprise.                                       |
| `RATE_LIMIT_EXCEEDED` | 429    | RPS cap exceeded in current window.                            | Back off and retry; check `current_window_reset_secs` from `/credits`.                           |
| `INVALID_PARAM`       | 400    | One of your query params is wrong.                             | See `error.message`. The most common cause is sending `mint` to `/candles` — use `pair_address`. |
| `MISSING_PARAM`       | 400    | A required param is absent.                                    | Add it.                                                                                          |
| `NOT_FOUND`           | 404    | Resource doesn't exist (e.g., unknown mint or `pair_address`). | Verify via [`/api/v1/pairs`](/api-reference).                                                    |
| `UNAVAILABLE`         | 503    | Backend dependency is down.                                    | Retry with backoff.                                                                              |
| `GATEWAY_TIMEOUT`     | 504    | Upstream took too long.                                        | Retry; reduce `limit` if persistent.                                                             |
| `INTERNAL`            | 500    | Server-side error.                                             | Retry. If it persists, [contact support](https://www.dexploit.dev/contact).                      |
