# Rate Limiting

Canonical URL: https://api-docs.test-printeers.com/guides/rate-limiting

Learn how per-organization rate limits work, how to read the response headers, and how to react to a 429.

The Printeers partner API enforces per-organization rate limits so one API-user cannot saturate the API for everyone else. A healthy integration should never see a 429. Limits are scoped to the organization that owns the API keys, so multiple keys belonging to the same organization share one budget.

## Limits

Every authenticated request consumes from at least one rate-limit bucket:

| Policy | Quota (`q`) | Window (`w`) | Sustainable rate | Applies to |
|---|---|---|---|---|
| `default` | 3000 | 60 seconds | 50 req/sec | every authenticated request |
| `uploads` | 5000 | 24 hours | 5000 per day | `POST /v2/images`, `POST /v2/evidence` |
| `downloads` | 100000 | 24 hours | 100000 per day | `GET /v2/renders/{renderReference}/media`, `GET /v2/renders/{renderReference}/thumbnail`, `GET /v2/products/{productReference}/media/{filename}` |


Upload and download requests consume one token from `default` plus one token from their dedicated bucket.

`default` lets you sustain 50 requests per second indefinitely, or burst up to 3000 requests over 60 seconds before the bucket runs dry. `uploads` caps total uploads per organization per day to bound storage growth. `downloads` caps total media downloads per organization per day to prevent re-fetching the same media indefinitely. All buckets refill continuously.

The rate-limit policies, their numerical values, and which routes consume from which buckets may all change within a major API version as traffic patterns evolve. Tuning these is not considered a breaking change. Always read the live values from the `X-RateLimit-Policy` and `X-RateLimit` response headers; do not hard-code anything from this guide into your integration.

## Response Headers

The two headers below follow the structured-field syntax from the [IETF draft for rate-limit headers](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/), the standardization effort for communicating rate limits over HTTP. We use the `X-` prefix because the draft is not yet a published RFC; partner-api v3 will switch to the unprefixed names (`RateLimit` and `RateLimit-Policy`) once it is. The parameter names (`q`, `w`, `r`, `t`) will not change.

Every authenticated response carries these two headers showing the buckets the request consumed from:

```
X-RateLimit-Policy: "default";q=3000;w=60, "uploads";q=5000;w=86400
X-RateLimit:        "default";r=2987;t=0, "uploads";r=4982;t=0
```

- `X-RateLimit-Policy`: `q` is the bucket capacity, `w` is the refill window in seconds. The long-term sustainable rate is `q/w`.
- `X-RateLimit`: `r` is your remaining tokens, `t` is the seconds until the bucket regains a full token (always `0` while the bucket still has tokens).

Requests that only consume from `default` show a single entry in each header.

If `r` is getting low for a bucket your integration depends on, slow down preemptively rather than waiting for a 429.

## When You Hit a Limit

When any bucket is empty, you receive `HTTP 429 Too Many Requests`:

```
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 12
X-RateLimit-Policy: "default";q=3000;w=60
X-RateLimit:        "default";r=0;t=12

{
  "code": "rate_limited",
  "message": "Rate limit exceeded; see Retry-After and X-RateLimit headers."
}
```

Wait at least the number of seconds in `Retry-After`, then retry. The value already includes jitter so concurrent clients will not synchronize their retries.

For `uploads` denials `Retry-After` is around 17 seconds (plus jitter), the time it takes the daily bucket to refill one token. Once you have hit the cap, you can resume at roughly one upload every 17 seconds until the bucket has filled back up.

For `downloads` denials `Retry-After` is around 1 second (plus jitter), since the daily bucket refills a token roughly every 0.86 seconds.

`Retry-After` follows [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#field.retry-after).

## Need a Higher Limit?

If your integration has a legitimate use case that bumps into these limits regularly, contact [support@printeers.com](mailto:support@printeers.com). Tell us which policy is the bottleneck and roughly what volume you need; we can raise the limits for your organization.
