AgenticWebScore
Scan

Protocol Discovery · Recommended · Medium impact

Rate limits and quotas documented

An agent that does not know the quota discovers it by being throttled, halfway through a task it cannot resume.

  • Recommended
  • Medium impact
  • Experimental standard
Rate limits and quotas documented — Property, Value
Property Value
Check idrate-limits-declared
DimensionProtocol Discovery (25%)
TierRecommended — pool 20 pts
Weight inside tier1
ImpactMedium
MaturityExperimental — An early convention that may still change shape.
ConditionalNo
Publishing skillrate-limits
StandardsRFC 9110

What the scanner requests

  • /rate-limits.json
  • /.well-known/rate-limits.json
  • /docs/rate-limits
  • /docs

It also reads documents it has already fetched: $home.

What is measured

The scanner makes one unauthenticated request to a public endpoint of the API and records any quota declaration the response carries (RateLimit or RateLimit-Policy, or the never-standardised X-RateLimit-* family), then reads the developer documentation and any machine-readable declaration the site links (/rate-limits.json, /.well-known/rate-limits.json and /docs/rate-limits) for a stated limit with its unit, its window, the scope it applies to and the behaviour when it is exceeded. It passes when the documentation states all four and a throttled response carries Retry-After, partially passes when limits are mentioned without numbers or windows, or when quota headers appear with nothing documented, and it is reported as not scored and excluded from the denominator unless the site has been positively identified as an API/developer platform.

Reproduce it yourself

You do not have to take our word for any of this. Run the same measurement against your own domain:

              DOMAIN=https://your-domain.example
{ curl -sS "$DOMAIN/rate-limits.json" | jq -c '{policies:[.policies[]?|{name,scope,limit,unit,window}],onExceeded}' 2>/dev/null || echo 'no rate-limits.json'; curl -sSL "$DOMAIN/docs/rate-limits" | grep -oiE '[0-9,]+ (requests?|calls?) per (second|minute|hour|day)|429|retry-after'; curl -sS -D - -o /dev/null "$DOMAIN/v1/ping" | grep -iE '^(HTTP/|ratelimit|retry-after|x-ratelimit)'; } | head -25
            

The fix

This is the artifact to ship. It is the complete change, not a description of one.

              ## Rate limits

Every endpoint is limited per API key; anonymous requests are limited per IP.

| Scope | Limit | Window | On exceed |
| --- | --- | --- | --- |
| API key | 1000 requests | 1 hour | 429 + Retry-After (seconds) |
| API key, burst | 20 requests | 1 second | 429 + Retry-After (seconds) |
| Anonymous, per IP | 60 requests | 1 minute | 429 + Retry-After (seconds) |

Responses carry `RateLimit-Policy` and `RateLimit`; a throttled request returns `429` (RFC 6585) with `Retry-After` (RFC 9110).
Machine-readable copy, linked from this page: https://your-domain.example/rate-limits.json
```json
{
  "version": 1,
  "policies": [
    { "name": "default", "scope": "per-api-key", "limit": 1000, "unit": "requests", "window": "1h" },
    { "name": "burst", "scope": "per-api-key", "limit": 20, "unit": "requests", "window": "1s" },
    { "name": "anonymous", "scope": "per-ip", "limit": 60, "unit": "requests", "window": "1m" }
  ],
  "onExceeded": { "status": 429, "retryAfter": "seconds" },
  "increase": "https://your-domain.example/docs/rate-limits#increases"
}
```
            

Standards referenced

  • RFC 9110

Related checks

Related checks — Check, Tier, Impact, Same skill
Check Tier Impact Same skill
mcp-card — MCP server cardEssentialHigh—
openapi — OpenAPI definitionEssentialHigh—
oauth-discovery — OAuth discovery documentsEssentialHigh—
api-catalog — API catalogRecommendedMedium—
agent-skills — Agent Skills declarationRecommendedMedium—
a2a-card — A2A agent cardRecommendedMedium—
a2a-signed — Cryptographically signed agent cardEmergingMedium—
auth-md — /auth.md agent authentication guideEmergingMedium—