0%

Talking to an API · practice

Stop at the Rate Limit

A 429 response says “stop for now.” It does not tell this small command to hide the response behind retries.

Implement inspect_rate_limit(attempt, *, timeout=DEFAULT_TIMEOUT, session=None) as exactly one GET to /scenarios/rate-limit, with params={"attempt": attempt}, the fixed header, and the explicit timeout.

Inspect status 429 before the generic status check. Decode that one error body and require error.code == "practice_rate_limited". Require Retry-After to be a non-empty decimal , convert it to an integer, and return exactly:

{
    "status": 429,
    "retry_after": retry_after,
    "code": "practice_rate_limited",
}

For a non-429 response, call raise_for_status() before json() and return the decoded success document. Any other unsuccessful status raises. Catch nothing.

Attempts 1 and 2 are deterministic 200 responses. Attempts 3 through 10 are deterministic 429 responses with Retry-After: 1. The server is stateless: the attempt query selects the response. Do not add a , sleep, retry adapter, counter, or message claiming a later attempt succeeded.

Notice what this does not do. It does not sleep, it does not loop, and it does not try again. It reads the stop signal, packages it up, and hands it back to whoever asked. Deciding whether to wait a second and retry is a policy, and policy belongs to the caller who knows what the program is for.

What should this project do after one valid 429 response?

Task

Implement inspect_rate_limit as exactly one fixed internal GET. For 429, validate the exact error code and decimal Retry-After, then return the exact three-field stop . For non-429, raise for status before JSON. Add no , sleep, retry, stateful counter, host option, or secret.