# Usage and limits

## Units

A unit is a response with status 200. All routes cost the same. A response with an error costs no unit, and [Get dataset details](/docs/api#getMeta) costs no unit.

These responses also have status 200, so each one costs one unit:

- An autocomplete or a search that finds no city.
- An autocomplete or a search with a text of fewer than 2 characters. The API returns no cities for this text.
- A reverse lookup that finds no city. `data` is `null`.

The dashboard shows the units of each day of the month.

## Estimate your units

Count the requests that each feature sends:

| Feature                        | Units                                                                                                           |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| A city field with autocomplete | One for each request while the person types, and one more if your server checks the selected ID with Get a city |
| Reverse lookup                 | One for each position, also in a batch                                                                          |
| An update of stored cities     | One for each city that you read again                                                                           |

A city field that waits for a pause in the typing sends a few requests for each city, and not one for each letter. [Add city autocomplete to a form](/docs/city-autocomplete) shows this delay.

## Monthly limit

[Each plan](/#plans) gives a number of units for each month. The month starts at 00:00 UTC on the first day.

The API accepts requests up to 120% of the plan units, at the same price. Above this limit, the API returns status 429 with the error `quota_exceeded` until the next month. The `Retry-After` header gives the number of seconds until the next month.

If a batch reverse lookup has more positions than the units left in the month, the API refuses the full batch. The `detail` of the error gives the units left.

## Requests per second

Each plan sets a limit of requests per second for the account. The limit applies to all keys of the account together. A batch reverse lookup counts as one request for this limit.

A public key also has a limit of 10 requests per second for each IP network. This limit stops one visitor from using all the requests of the account.

Above a limit of requests per second, the API returns status 429 with the error `rate_limited`. The `Retry-After` header gives the number of seconds to wait.

## Handle status 429

Read the `code` of each response with status 429:

- If the code is `rate_limited`, wait for the seconds in `Retry-After`. Then send the request again.
- If the code is `quota_exceeded`, do not send the request again before the next month.

This function sends a request up to 3 times. After each `rate_limited` error, it waits for the seconds in `Retry-After`.

```js
const MAX_ATTEMPTS = 3

async function requestCityApi(url, options) {
  for (let attempt = 1; ; attempt += 1) {
    const response = await fetch(url, options)
    if (response.status !== 429 || attempt === MAX_ATTEMPTS) {
      return response
    }
    const problem = await response.clone().json()
    if (problem.code !== 'rate_limited') {
      return response
    }
    const seconds = Number(response.headers.get('Retry-After'))
    await new Promise((resolve) => setTimeout(resolve, seconds * 1000))
  }
}
```

A browser can read `Retry-After`, because the API sends it in `Access-Control-Expose-Headers`.

Your form must work also when the API refuses a request. If the city field gets no cities, let the person type the city as text. [Accept text with no selection](/docs/city-autocomplete#accept-text-with-no-selection) tells how to find the city later.
