Source: https://developers.woosmap.com/api-reference/rate-limits/

> For clean Markdown of any page, append `.md` to the page URL.

> Routing index (which page answers which question): https://developers.woosmap.com/llms.txt

> Full page list: https://developers.woosmap.com/llms-full.txt

# Rate Limits



Each endpoint has its own rate limit, shared by all the API keys of a project. The endpoint's reference page shows it: `Ratelimit: 50/1s` means 50 requests per second.

## Read your remaining quota

Every response tells you where you stand:

```
RateLimit-Policy: "requests";q=40;w=1
RateLimit: "requests";r=39;t=1
```

| Field | Meaning                         | Here      |
|-------|---------------------------------|-----------|
| `q`   | Requests allowed per window     | 40        |
| `w`   | Window length, in seconds       | 1 second  |
| `r`   | Requests left in this window    | 39        |
| `t`   | Seconds until the window resets | 1 second  |

## Handle a 429

Once `r` reaches 0, the API answers `429 Too Many Requests` until the window resets. Wait `t` seconds, then retry. Retrying right away fails again.

- Retry at most three times.
- If the 429 has no `RateLimit` header, wait 1, 2, then 4 seconds.
- In a batch job, pause as soon as `r` reaches 0, without waiting for the 429.

```python
import re
import time

import requests

def retry_delay(response: requests.Response, attempt: int) -> int:
    header = response.headers.get("RateLimit", "")
    waits = [
        int(reset)
        for remaining, reset in re.findall(r"r=(\d+);t=(\d+)", header)
        if remaining == "0"
    ]
    return max(waits, default=2**attempt)

def get(url: str, params: dict, retries: int = 3) -> requests.Response:
    for attempt in range(retries + 1):
        response = requests.get(url, params=params, timeout=10)
        if response.status_code != 429 or attempt == retries:
            return response
        time.sleep(retry_delay(response, attempt))
```

```javascript
function retryDelay(response, attempt) {
  const header = response.headers.get("RateLimit") ?? "";
  const waits = [...header.matchAll(/r=(\d+);t=(\d+)/g)]
    .filter(([, remaining]) => remaining === "0")
    .map(([, , reset]) => Number(reset));
  return waits.length ? Math.max(...waits) : 2 ** attempt;
}

async function get(url, retries = 3) {
  for (let attempt = 0; ; attempt++) {
    const response = await fetch(url);
    if (response.status !== 429 || attempt === retries) return response;
    await new Promise((resolve) => setTimeout(resolve, retryDelay(response, attempt) * 1000));
  }
}
```

Complete scripts, with tests, are in [woosmap-samples](https://github.com/Woosmap/woosmap-samples).

## Special cases

- The Distance Matrix limits requests and matrix elements separately, and lists both policies: `RateLimit: "elements";r=999;t=1, "requests";r=19;t=2`. Wait for the one at `r=0`. The code above handles it.
- `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` (`X-RateLimit-*` on the Distance API) are legacy headers that describe only the last policy. Use `RateLimit`.
- Browsers can't read these headers, because the API does not expose them to cross-origin JavaScript. Read them on your server.
- If your normal traffic keeps reaching the limit, contact [support@woosmap.com](mailto:support@woosmap.com).
