> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.mindrift.art/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mindrift.art/_mcp/server.

# Rate Limits & Concurrency

To ensure reliable performance, predictable capacity and equitable access to GPU compute across all accounts, the Mindrift API enforces rate limits on every endpoint.

Rate limits are enforced at the account level, not per individual API key. Creating multiple API keys divides your account's quota rather than multiplying it.

---

## Tier System

Your account is assigned an API Tier (Tier 1 through Tier 5). Each tier defines your throughput capacity across three distinct request categories, as well as the maximum number of asynchronous generation tasks that can run concurrently.

New accounts start on Tier 1 by default. As your production usage scales, your account can advance to higher tiers with increased throughput.

| **Tier**             | **Generation RPM** | **Concurrent Tasks** | **Polling RPM** | **General RPM** |
| -------------------- | ------------------ | -------------------- | --------------- | --------------- |
| **Tier 1** (Default) | 30 req/min         | 3 tasks              | 180 req/min     | 60 req/min      |
| **Tier 2**           | 60 req/min         | 5 tasks              | 360 req/min     | 120 req/min     |
| **Tier 3**           | 120 req/min        | 10 tasks             | 720 req/min     | 240 req/min     |
| **Tier 4**           | 300 req/min        | 25 tasks             | 1,500 req/min   | 480 req/min     |
| **Tier 5**           | 600 req/min        | 50 tasks             | 3,000 req/min   | 1,000 req/min   |

#### Generation RPM

Applies to endpoints that initiate or retry GPU workloads, such as `POST /v1/text-to-image/subscribe/:model` and `POST /v1/tasks/:task_id/retry`. Because image generation is computationally intensive, these endpoints have dedicated limits tailored to prevent cluster saturation.

#### In-Flight Concurrency

Restricts the number of generation tasks belonging to your account that can exist simultaneously in pending (`queued`) or processing states. Once a task reaches completed or failed, its concurrency slot is freed immediately for your next job.

#### Polling RPM

Applies to status checks via `GET /v1/tasks/:task_id`. Polling quotas are intentionally sized generously (6x to 10x the generation quota) so client applications can query task progression without exhausting their general API capacity.

#### General RPM

**General RPM (**`general`**):**
Applies to metadata, model lookups, account status (GET /v1/me), and non-generation queries.

---

## Rate Limit vs. Monthly Budget

It is important to distinguish between rate limits and monthly budgets:

* **Rate Limits** restrict request frequency and simultaneous workloads (RPM and concurrency) within rolling 60-second windows to protect infrastructure stability. They apply to your entire account.
* **Monthly Spend Budgets** are financial spending caps configured on individual API keys in the developer dashboard. When a key reaches its monthly budget limit, it returns an HTTP `429 Too Many Requests` with code `MONTHLY_BUDGET_EXCEEDED` until the budget resets on the 1st of the next month at 00:00 Europe/Paris time.

---

## HTTP Rate Limit Headers

Every response returned by the Mindrift API includes headers that reflect your account's rate limit status for the requested endpoint category:

| **Header**            | **Description**                                                                  | **Example**  |
| --------------------- | -------------------------------------------------------------------------------- | ------------ |
| X-RateLimit-Limit     | The total number of requests allowed in the current 60-second window.            | `60`         |
| X-RateLimit-Remaining | The number of requests remaining in the current 60-second window.                | `25`         |
| X-RateLimit-Reset     | The Unix timestamp (in seconds) when the current window resets.                  | `1789056000` |
| Retry-After           | Returned only on `429` responses. The number of seconds to wait before retrying. | `12`         |

You can inspect these headers in your application to proactively monitor your consumption and avoid hitting limits.

---

## Handling Rate Limit Errors (HTTP 429)

If your application exceeds an RPM quota or attempts to queue more concurrent tasks than your tier allows, the API immediately returns an HTTP `429 Too Many Requests` response.

### Request Rate Exceeded (`RATE_LIMIT_EXCEEDED`)

Returned when your application sends more requests in a 60-second window than allowed by your tier for that category:

```http
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1789056060
Retry-After: 18
x-request-id: e9c1a538-2d88-4f1e-9271-9df382b610fa
```

```json
{
  "error": {
    "type": "rate_limit_error",
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded for generation requests. Your quota is 30 requests per minute. Please retry in 18 seconds.",
    "request_id": "e9c1a538-2d88-4f1e-9271-9df382b610fa"
  }
}
```

### Concurrency Limit Reached (`CONCURRENCY_LIMIT_REACHED`)

Returned when you attempt to dispatch a new generation task while your active queue (`pending` + `processing`) is already at maximum capacity for your tier:

```http
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 5
x-request-id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
```

```json
{
  "error": {
    "type": "rate_limit_error",
    "code": "CONCURRENCY_LIMIT_REACHED",
    "message": "Concurrency limit reached: you currently have 3 active tasks in progress. Your plan (Tier 1) allows up to 3 concurrent generation tasks. Please wait for an existing task to complete.",
    "request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }
}
```

---

## Best Practices for High-Volume Integrations

### Respect the Retry-After Header

When you receive an HTTP 429 status code, do not immediately resubmit the request. Parse the `Retry-After` HTTP header from the response and pause execution for that exact duration before attempting a retry.

### Implement Exponential Backoff with Jitter

For automated background workers, implement exponential backoff with random jitter. This prevents a "thundering herd" problem where multiple worker threads or servers simultaneously retry requests at the exact same second the rate limit window resets.

### Tune Your Polling Intervals

Generating an image takes a few seconds depending on the chosen model and complexity. Rapidly polling `GET /v1/tasks/:task_id` multiple times per second is unnecessary and quickly consumes your polling allowance. We recommend polling every 1.5 to 2.5 seconds.

### Manage Queues on Your Backend

If your application serves consumer-facing traffic where users can trigger image generations concurrently, buffer incoming user requests in your own backend queue (such as Redis, BullMQ, SQS, or Celery). Dispatch tasks to Mindrift only when your active concurrency count is below your tier allowance.

---

## Checking Your Tier & Requesting Upgrades

You can check your account's assigned tier programmatically at any time by calling the `/v1/me` endpoint:

```json
{
    "object": "account",
    "data": {
        "id": "abcdef12-3456-7890-abcd-ef1234567890",
        "name": "John",
        "pseudo": "Doe",
        "email": "johndoe@domain.com",
        "balance": 10.4785,
        "credits": 150,
        "tier": "Tier 1",
        "tier_level": 1,
        "rate_limits": {
            "generation_rpm": 30,
            "max_concurrent_tasks": 3,
            "polling_rpm": 180,
            "general_rpm": 60
        }
    }
}
```

If your project is scaling or your production workload requires higher throughput or custom concurrency thresholds, please contact our support team at [**support@mindrift.art**](mailto:support@mindrift.art) to discuss tier upgrades and dedicated infrastructure.