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

# Rate Limits & Quotas

> Understanding rate limits, quotas, and handling 429 responses.

Truthlocks enforces rate limits to ensure fair usage and platform stability. This guide explains limits by tier and how to handle rate limiting gracefully.

## Limits by Tier

| Tier             | Requests/min | Attestations/day | Issuers   | Keys/Issuer |
| ---------------- | ------------ | ---------------- | --------- | ----------- |
| **Free**         | 60           | 100              | 2         | 2           |
| **Starter**      | 300          | 10,000           | 10        | 5           |
| **Professional** | 1,000        | 100,000          | 50        | 10          |
| **Enterprise**   | Custom       | Custom           | Unlimited | Unlimited   |

<Info>
  **Burst Capacity:** All tiers include 2x burst capacity for up to 10 seconds.
  This allows handling traffic spikes without immediate rate limiting.
</Info>

## Per-Endpoint Limits

Some endpoints have additional specific limits:

| Endpoint                     | Limit    | Window | Reason                   |
| ---------------------------- | -------- | ------ | ------------------------ |
| `POST /v1/attestations/mint` | 100/min  | 60s    | Signing is CPU-intensive |
| `POST /v1/verify`            | No limit | -      | Public endpoint, cached  |
| `POST /v1/issuers`           | 10/hour  | 1h     | Prevent issuer spam      |
| `POST /v1/api-keys`          | 20/day   | 24h    | Security measure         |
| `GET /v1/audit/events`       | 30/min   | 60s    | Database-heavy query     |

## Rate Limit Headers

Every API response includes headers to help you track your usage:

```http theme={null}
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1705147260
X-RateLimit-Policy: "1000;w=60"
```

| Header                  | Description                                  |
| ----------------------- | -------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the window       |
| `X-RateLimit-Remaining` | Requests remaining in current window         |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets        |
| `X-RateLimit-Policy`    | Policy description (requests;window=seconds) |

## Handling 429 Responses

When you exceed the rate limit, you'll receive a 429 status code:

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 32
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705147260

{
  "code": "RATE_LIMITED",
  "message": "Rate limit exceeded. Retry after 32 seconds.",
  "http_status": 429,
  "details": {
    "limit": 1000,
    "window_seconds": 60,
    "retry_after_seconds": 32
  }
}
```

<Warning>
  **Important:** Always respect the `Retry-After` header. Repeatedly hitting
  rate limits may result in temporary IP blocks.
</Warning>

## Best Practices

### Exponential Backoff

```typescript theme={null}
async function withBackoff<T>(
  fn: () => Promise<T>,
  maxRetries = 5,
  baseDelayMs = 1000,
): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status !== 429 || attempt === maxRetries - 1) {
        throw error;
      }

      const retryAfter = error.headers?.["retry-after"]
        ? parseInt(error.headers["retry-after"]) * 1000
        : baseDelayMs * Math.pow(2, attempt);

      const jitter = Math.random() * 1000;
      await new Promise((r) => setTimeout(r, retryAfter + jitter));
    }
  }
  throw new Error("Max retries exceeded");
}
```

### Request Batching

```typescript theme={null}
// Instead of minting one at a time:
for (const user of users) {
  await client.attestations.mint({ ... });
}

// Batch with controlled concurrency:
import pLimit from 'p-limit';

const limit = pLimit(10); // Max 10 concurrent requests
const results = await Promise.all(
  users.map(user =>
    limit(() => client.attestations.mint({ ... }))
  )
);
```

### Monitor Usage

```typescript theme={null}
// Track remaining quota in your metrics
function trackRateLimit(response: Response) {
  const remaining = response.headers.get("X-RateLimit-Remaining");
  const limit = response.headers.get("X-RateLimit-Limit");

  metrics.gauge("truthlock.ratelimit.remaining", parseInt(remaining));
  metrics.gauge(
    "truthlock.ratelimit.usage_percent",
    (1 - parseInt(remaining) / parseInt(limit)) * 100,
  );
}
```

## Requesting Quota Increases

If your usage requires higher limits:

1. **Starter/Professional:** Contact support with your use case and expected volume
2. **Enterprise:** Custom limits are negotiated during contract discussions
3. **Temporary Increase:** For events or migrations, request a temporary burst increase 48 hours in advance

<Info>
  **Tip:** Include metrics showing your current usage patterns and growth
  projections when requesting increases.
</Info>

## Next Steps

<CardGroup cols={2}>
  <Card title="Health & Readiness" icon="heart-pulse" href="/ops/health">
    Monitor API health and your integration status.
  </Card>

  <Card title="SDK Examples" icon="code" href="/guides/sdk-examples">
    See rate limit handling in real code.
  </Card>
</CardGroup>
