---
id: rate-limiting
title: 'Rate Limiting'
description: 'How Agility enforces API rate limits, how to check configured quota policies, and which endpoints expose usage metrics'
sidebar_label: 'Rate Limiting'
sidebar_position: 10
tags: ['guides', 'rate-limiting']
---

API rate limiting protects an Agility instance from misuse and gives every
caller fair, predictable access. On Digital.ai-hosted instances, rate
limiting is in effect with the [hosted limits](#hosted-limits) below.
On-premises, it's off until an administrator enables it and configures
quotas in the instance's application settings. Either way, any
authenticated member can check the policy in force, and a member with the
`ManageConfig` privilege can retrieve usage metrics. Where rate limiting
isn't enabled, every endpoint on this page returns `404`.

## Hosted Limits

Digital.ai-hosted instances apply these limits per access token:

- 600 requests per 60 seconds
- 600 MB of data retrieved per 60 seconds
- 600 seconds of total response time per 60 seconds
- 20 errors per 60 seconds

Call [`QuotaPolicy`](#check-configured-quota-policies) to see the policy in
force on your instance.

## How Rate Limiting Works

Where enabled, quota policies cap API usage by request time, size of data
returned, number of requests, and number of errors returned, each over a
set duration (for example, 60 seconds). Agility tracks these metrics per
API consumer and checks them against the configured policies.

When a caller exceeds a limit, Agility returns an HTTP `429` error that
identifies which limit was exceeded and how long to wait before retrying.
For example, exceeding a threshold of 20 errors within 60 seconds returns:

```json
{
  "Reason": "ErrorLimit",
  "Message": "API request quota exceeded. Maximum of 20 errors per 60 second(s)",
  "RetryAfter": "50"
}
```

`Reason` is one of `RequestLimit`, `ByteLimit`, `DurationLimit`, or
`ErrorLimit`, and a `V1-Limit-Reason` response header carries the same
value. Honor `RetryAfter` and back off rather than retrying immediately.

## Check Configured Quota Policies

Any authenticated user can call `/RateLimit.mvc/QuotaPolicy` to retrieve the
quota policies configured for the instance, returned as XML:

```xml
<throttlePolicy trackAllRequests="True" accessToken="True">
  <quotas>
    <add duration="60" requestLimit="10" byteLimit="10000" errorLimit="5" />
    <add duration="1" requestLimit="5" />
  </quotas>
</throttlePolicy>
```

## Check Your Current Quota Usage

Any authenticated user can call `/RateLimit.mvc/CurrentQuota` to retrieve the
quotas being tracked for the access token that made the request.
`TotalDuration` is in milliseconds:

```json
[
  {
    "InitiatedDate": "2023-05-31T17:05:35.1131409Z",
    "Expires": "2023-05-31T17:06:35.1131409Z",
    "Data": {
      "TotalRequests": 1,
      "TotalDuration": 60,
      "TotalErrors": 0,
      "TotalSize": 1568
    }
  }
]
```

## Retrieve API Usage Metrics

A member with the instance-wide
[`ManageConfig` privilege](/reference/roles-and-permissions) can call the
following endpoints to see which members are using the API, how many calls
they're making, and which requests are being rejected. They report data
only when the quota policy sets `trackAllRequests="True"`.

### Usage Totals per Member

`/RateLimit.mvc/TrackedRequestStats` returns total counts per member for all
API requests accumulated since the last IIS application pool restart:

```json
[
  {
    "UserIdentity": "Member:20",
    "Bytes": 10568,
    "Requests": 40,
    "Duration": 2592,
    "Errors": 0,
    "Rejections": 4
  }
]
```

### Tracked Quotas per Member

`/RateLimit.mvc/SystemBuckets` returns the quotas being tracked per member,
for all members:

```json
[
  {
    "ClientIP": "127.0.0.1",
    "UserIdentity": "Member:20",
    "Buckets": [{ "...": "quota 1" }, { "...": "quota 2" }]
  }
]
```

### Tracked Quotas and Usage Totals Combined

`/RateLimit.mvc/SystemRequestStats` returns the quotas being tracked and the
total counts per member, accumulated since the last IIS application pool
restart:

```json
[
  {
    "ClientIp": "127.0.0.1",
    "CurrentBuckets": [{ "...": "quota 1" }, { "...": "quota 2" }],
    "UserIdentity": "Member:20",
    "Requests": 40,
    "Bytes": 10568,
    "Duration": 2592,
    "Errors": 0,
    "Rejections": 4
  }
]
```

## Related Topics

- [Error handling guide](/guides/error-handling)
- [Performance best practices](/guides/performance)
- [Status codes reference](/reference/status-codes)
