---
title: "What should your API return when an agent hits a rate limit?"
description: "Use clear 429 responses, meaningful retry guidance and scoped limits while testing safe recovery without retrying uncertain writes."
canonical: "https://getdedica.com/blog/rate-limit-responses-agents-can-handle"
last-updated: "2026-10-31"
---

# What should your API return when an agent hits a rate limit?

When an agent reaches your request limit, it needs enough information to stop and recover. An HTML challenge or a generic success response containing an error message leaves the integration guessing about what happened.

Return an intentional rate-limit response and document which budget it describes. Keep protections in place. The goal is to make the refusal understandable to a client that is allowed to use the service.

## Give the refusal the right meaning

HTTP `429 Too Many Requests` means the client has sent too many requests in a period. The response can include `Retry-After`. RFC 6585 leaves the counting policy and identification method to the server, so a client cannot infer whether a limit applies to an IP address, account or endpoint from the status alone. [RFC 6585, section 4](https://www.rfc-editor.org/rfc/rfc6585.html#section-4).

Write that scope into your API documentation. For example, distinguish a workspace's export budget from a user's search budget. If a shared network address is the unit, say so. Avoid publishing exact security thresholds when doing so would undermine abuse controls; you can still give a useful recovery instruction.

An illustrative refusal for a read endpoint might be:

```http
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 30
Cache-Control: no-store

{"error":"rate_limited","scope":"workspace_search","retry_after_seconds":30}
```

The JSON fields here are an application design example, not standardized field names. Keep the body and header consistent. A reader should not have to decide between conflicting wait times.

## Be honest about when to retry

`Retry-After` supports either a delay in seconds or an HTTP date. A delay is convenient when you can calculate how much time remains in the current window. An HTTP date requires the client to interpret an absolute time. [MDN Retry-After reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After).

Only provide a precise reset time when the limiter can support it. Some budgets recover gradually as requests age out. Others depend on concurrent work finishing. Document that difference instead of inventing a countdown.

If the client is yours, cap retries and wait at least the indicated delay. Consider adding jitter after that minimum so many paused workers do not all return together. This is an operational recommendation, not a guarantee that a particular vendor client will follow your instructions. Test the actual SDK or agent host you support.

## Reject writes before they take effect

A rate-limit response for a read is usually easy to interpret: the client should stop fetching for now. A write needs a stronger contract. Did the server reject it before creating anything, or did a downstream component fail after a change?

Place the limit check before the side effect where your architecture allows it. Document how callers can look up an operation when the outcome is uncertain. Do not tell an agent to resubmit a purchase or booking simply because it saw an error page.

For application-owned writes, use a durable request identifier and a documented duplicate-handling policy. Keep that concern separate from how often the client is allowed to call. A valid retry can still exhaust a rate budget, and an allowed request can still be a duplicate.

## Test the refusal without stressing production

Use a test environment with a deliberately small budget. Record the request count, endpoint, account and limiter configuration. Then check the first accepted response, the first refusal and recovery after the stated wait.

Include a second workspace in the experiment. Its result tells you whether the scope matches the documentation. Test parallel requests too: a sequential script may never expose a race between workers. Keep the experiment bounded and stop once the expected refusal appears.

Inspect the public gateway as well as the application. If the gateway emits an unrelated HTML page before the API's limiter runs, the client sees the gateway's contract. Assign ownership of that response so support knows which system produced it.

## Distinguish a limit from blocked access

MDN notes that rate limits can be based on different identities or resources. A `429` by itself does not prove a crawler is banned, nor does a successful request prove it has unlimited access. [MDN 429 reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429).

Dedica's [free readiness checker](/) provides public-site findings across Discovery, Access, Usability and Payments. Investigate any access finding with your own request logs and limiter policy. A single scan cannot establish a client's long-running request allowance.

The useful handoff to engineering is the refused request, response body, headers and matching gateway record. That evidence is enough to distinguish a deliberate budget limit from a broken integration.

## Sources

- [Additional HTTP status codes, section 4](https://www.rfc-editor.org/rfc/rfc6585.html#section-4), IETF.
- [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After), MDN.
- [429 Too Many Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429), MDN.
