Most AI coding agents that touch a REST API in their first session do something predictable: they generate code that fetches a resource, finds it returns 12 fixture users with shallow shapes, write a wrapper that assumes those shapes hold in production, and then break the moment the user points the agent at a real API.
The legacy /api/users endpoint at reqres.in is great for humans learning HTTP. It's the wrong shape for an agent practicing real code. So we built a new one.
Today we're launching the ReqRes Agent Sandbox: a set of endpoints under /agent/v1/* designed specifically for AI coding agents to practice against. Free to use, deterministic, with the kinds of edge cases agents encounter in production.
What's in it
Six endpoints, each chosen to force agents to handle something real-world.
GET /agent/v1/users
Cursor-paginated user list. No ?page=N. Agents have to learn meta.next_cursor and pass it back unchanged. Limits over 100 are silently clamped, so agents have to verify meta.returned matches their requested limit. Sparse fieldsets via ?fields=id,email.
curl https://reqres.in/agent/v1/users?limit=2
Returns 247 users per seed (default seed=42), with nullable nested fields, ULID IDs (usr_01H...), and ISO 8601 timestamps with millisecond precision. The same request always returns the same response.
GET /agent/v1/users/:id
Deeply nested single resource with optional expansion. Without ?expand=, nested resources return as references ({id, object_type}). With ?expand=addresses,activity,organizations, they're inlined. Activity records have heterogeneous shapes -- a login event has ip_address and user_agent, a profile_updated event has changed_fields[] instead. Agents that assume uniform array members break.
POST /agent/v1/auth/login
Two response shapes depending on the email. Normal accounts return a session with token, refresh_token, expires_at, and user object. Accounts with email containing +mfa@ return an MFA challenge with a next_step hypermedia hint pointing to the verification endpoint. Trains agents to handle response shape variation and to use hypermedia for recovery.
Other deterministic test triggers: +wrong@ for invalid_credentials (401), +locked@ for account_locked (401).
GET /agent/v1/orders
Relational data: orders reference users, products, addresses, and payment methods. Money is always {amount, currency, formatted} Stripe-style -- amount is in the smallest currency unit (cents for USD), never a decimal. Some line items reference deleted products, where product.deleted_at is set and product.name/product.price are null. Forces agents to handle the "referenced resource was deleted after the parent was created" case.
GET /agent/v1/scenarios/:scenario
Fifteen deliberate failure modes for testing error handling without trying to force errors on real endpoints:
rate-limited,server-error,bad-gateway,timeout,validation-errorunauthorized,forbidden,not-found,conflict,too-largeslow,partial-content,redirect-loop,malformed-json,empty-response
Every response includes the header X-Agent-Sandbox-Intentional: <scenario-name>. Configure your error reporter (Sentry, Bugsnag) to suppress responses with this header so your agent's training scenarios don't fill up your alert dashboard.
timeout and slow are special: they return immediately with a X-Agent-Sandbox-Simulated-Delay header instead of actually holding the connection open for 30 or 10 seconds. Agents that want to test real timeout handling read the header and delay client-side. Holding open thousands of slow connections would have exhausted our origin's connection pool.
GET /agent/v1/health
Cheap to poll. Returns sandbox status, version, uptime, and the caller's current rate-limit status. Agents can probe this before a burst of requests to know how much quota they have left. Not edge-cached (Cache-Control: no-store) because the response varies by the caller's tier - the numbers you see are always yours.
Why determinism matters
Same (seed, cursor, params) always returns the same response. This is the single most important property of the sandbox.
Agents fail in production all the time. The hard part isn't fixing the failure -- it's reproducing it. With non-deterministic test data, an agent that worked in CI on Tuesday and broke on Wednesday is a haunted-house debugging session. With deterministic test data, you replay the exact same request and get the exact same response, every time. The failure is reproducible. The fix is testable.
This is the same reason Stripe's test mode is deterministic. It's the reason CI test fixtures are checked into version control. Determinism turns "this is broken intermittently" into "here is the reproducer."
Conventions
We picked conventions agents will already be familiar with from working with Stripe, GitHub, and other production APIs:
- IDs: ULID format with type prefix (
usr_,ord_,prd_,adr_). 26 characters after the underscore. Lexicographically sortable. - Timestamps: ISO 8601 with millisecond precision, always UTC.
.000Zsuffix even for whole-second values, for parse consistency. - Money: Always an object
{amount: integer_in_smallest_unit, currency: "ISO 4217 code", formatted: "human-readable"}. Never a decimal number. - Cursors: Opaque base64-encoded JSON with a nonce. Two requests at the same offset produce different cursor strings -- agents must treat cursors as opaque and pass them back unchanged.
- Cache-Control: Data endpoints
max-age=60, s-maxage=300. Scenario endpointsno-store. - Request IDs: Every response sets
X-Request-ID. Include in support requests.
Full conventions in /llm.txt and the OpenAPI spec.
Pricing
The sandbox is free to use with IP-based rate limits - 100 requests/day per IP, no signup. Good for prototyping and first-integration smoke tests. Free tier also exposes 3 sample /scenarios/* (rate-limited, validation-error, malformed-json) so you can wire up error handling before committing.
For production volume, there's a new Agent Developer plan at $49/month that gives you 10 million requests per month (~333,333/day), access to all 15 failure scenarios, and a usage dashboard at app.reqres.in/agents. Subscribers also get Dev plan quotas on the main ReqRes BaaS product (collections, app users, request logs, custom endpoints).
Subscribing provisions an x-agent-id key (format: agt_<64 hex>) which you send on every call to raise the cap. The key is attached to your account in Stripe, not to an agent identity or version string - pass the same key from any agent or environment. Arbitrary strings in the header (e.g. vendor/agent/version) are rejected with 401.
How agents discover the sandbox
We publish three machine-readable manifests:
/llms.txt-- top-level discovery, ~50 lines, points to deeper references/llm.txt-- comprehensive text guide with every endpoint, error shape, and convention/openapi.json-- OpenAPI 3.0.3 spec, full schemas
Point your agent at any of these. The intent is that an agent should be able to fetch one of them once, understand the entire API, and write working code without any human in the loop.
What's next
This is v1. Things we're explicitly NOT shipping in v1:
- Authentication on the agent endpoints (open for now, IP rate-limiting)
- Write operations on
/agent/v1/users - Webhooks or long-polling
- Time-series data endpoints
- GraphQL variant
- SDK on npm (
@reqresin/agent-sandbox-- coming soon)
If you're building an AI coding agent and want endpoints designed for your use case, tell us what you need.
Try it
curl https://reqres.in/agent/v1/users?limit=2
No header, no signup - that's the free tier. Once you're on Agent Developer, add -H "x-agent-id: agt_<your key>" to raise the cap and unlock every scenario.
Kickstart prompt
If you're building against this with an LLM, copy-paste this into Claude Code, Cursor, ChatGPT, or whatever you use, then tell it what to build:
I'm wiring up code against ReqRes for Agents - a deterministic HTTP sandbox for AI coding agents.
Spec (fetch and read first):
https://reqres.in/llm.txt
https://reqres.in/openapi.json
Facts to keep in working memory:
- Base URL: https://reqres.in/agent/v1
- Auth: free tier is open (no header), capped at 100 requests/day per IP. Paid tier sends `x-agent-id: agt_<64 hex>` for 10M requests/month. Keys are issued only via https://app.reqres.in/agents - never invent or guess the value. Arbitrary strings return 401.
- Endpoints: GET /users, GET /users/:id (?expand=addresses,activity,organizations), POST /auth/login, GET /orders, GET /scenarios/:name, GET /health.
- IDs are ULIDs with a type prefix (usr_, ord_, prd_, adr_, act_). 26 chars after the prefix.
- Money is always {amount (integer in smallest unit), currency, formatted}. Never a decimal.
- Pagination is cursor-based. Pass meta.next_cursor back unchanged. Treat cursors as opaque.
- Deterministic: same (seed, cursor, params) → same response. Default seed=42.
- /scenarios/:name exposes 15 deliberate failures for exercising retry/backoff/error paths. Every response sets X-Agent-Sandbox-Intentional; suppress that in your error reporter so training runs don't fill your alert queue.
- Free tier only unlocks 3 of the 15 scenarios (rate-limited, validation-error, malformed-json); the rest return 403 until you're on Agent Developer.
Now please: <tell the agent what to do>
More at reqres.in/for/ai-agents.