---
title: "API rate limits"
description: "QuotWay API rate limits: 120 requests per minute per key and 300 per store, the X-RateLimit headers, and how to handle 429 with Retry-After."
url: "https://www.quotway.com/fr/docs/api/rate-limits"
type: "documentation"
category: "api"
updated: "2026-09-30"
locale: "fr"
source: "QuotWay - B2B Quote & Negotiation App for Shopify"
---

# API rate limits

**Read time:** 3 minutes.
**Who it's for:** Developers sizing a sync job or handling `429` responses.

## What are the limits?

| Limit | Burst | Sustained |
|---|---|---|
| Per API key | 120 requests | 2 per second (120 per minute) |
| Per store (all of its keys together) | 300 requests | 5 per second (300 per minute) |

Both limits are **token buckets**. A bucket starts full; every request takes one token; tokens refill
continuously at the sustained rate. So an idle key can make 120 requests at once, then settles at
two a second. A request must fit inside **both** buckets.

Every authenticated request counts - including ones that then fail validation, and idempotent
replays. Requests rejected before the rate-limit check (an invalid key, a missing scope, the wrong
method) don't count against the key.

## Is there a limit on emails to buyers?

Yes. Three calls can put an email in a buyer's inbox - `POST /v1/quotes` (your automation rules may
reply or send a proposal), a buyer-facing `POST /v1/quotes/{id}/messages`, and
`POST /v1/quotes/{id}/send-proposal`. Together they share a **daily allowance per store**:

| Store | Requests per day |
|---|---|
| Paid Enterprise plan | 2,000 |
| On a trial | 200 |
| Development store, or any `qw_test_` key | 50 |

The allowance refills evenly over 24 hours. Over it, those calls return `429`
[`email_quota_exceeded`](/docs/api/errors#email_quota_exceeded) with `Retry-After`; internal notes,
reads and webhook management are unaffected.

## Which headers tell me where I stand?

Responses that reach the rate-limit check carry:

| Header | Meaning |
|---|---|
| `X-RateLimit-Limit` | The bucket's size (120 for a key, 300 for a store). |
| `X-RateLimit-Remaining` | Whole requests left in the bucket right now. |
| `X-RateLimit-Reset` | Seconds until the bucket is completely full again. |

The headers describe the **key's** bucket, unless the store-wide bucket is the one that ran out  - 
then they describe the store's.

## What happens when I hit the limit?

You get `429` with code [`rate_limited`](/docs/api/errors#rate_limited) and a `Retry-After` header
in seconds (at least 1). Wait that long, then retry. Hammering a limited bucket doesn't lock you out
for longer - the wait is never more than one refill interval away.

```http
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 1
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 60
```

The API can also return `503` [`api_disabled`](/docs/api/errors#api_disabled) with
`Retry-After: 300` during maintenance or an incident. Treat it the same way: wait, then retry.

## How do I stay under the limits?

- **Use webhooks instead of polling.** A webhook tells you the moment a quote changes; you only call
  the API to fetch the detail you need.
- **Sync incrementally.** Page through `GET /v1/quotes?sort=updated_at&updated_at[gte]=<watermark>`
  with `limit=50` rather than re-reading everything. See [Pagination](/docs/api/pagination).
- **Honour `Retry-After`** and add jitter so parallel workers don't retry in lockstep.
- **Give each integration its own key.** Each key has its own 120-request bucket, but remember the
  300-per-minute store limit is shared by every key.

## Related

- [Errors](/docs/api/errors)
- [Pagination](/docs/api/pagination)
- [Webhooks](/docs/api/webhooks)
