QA Bash Learning
API Playground.
A real sample REST + GraphQL API to practice testing against — CRUD, a state machine, two auth styles, and endpoints built to fail on purpose.
Users
/api/tools/sample-api/usersList all sample users.
Responses
[
{ "id": 1, "name": "Alice Johnson", "email": "alice@example.com", "role": "admin", "active": true, "age": 32 },
{ "id": 2, "name": "Bob Smith", "email": "bob@example.com", "role": "user", "active": false, "age": 28 }
]curl https://www.qabash.com/api/tools/sample-api/users/api/tools/sample-api/users/:idGet a single user by id.
Params
idpath · requiredNumeric user id (try 1, 2, 3, or a bad id for the 404 case)Responses
{ "id": 1, "name": "Alice Johnson", "email": "alice@example.com", "role": "admin", "active": true, "age": 32 }curl https://www.qabash.com/api/tools/sample-api/users/1/api/tools/sample-api/usersCreate a user. Not persisted — echoes back what a real create would return, so every visitor gets a clean demo.
Request body
{ "name": "Dana Lee", "email": "dana@example.com" }Responses
{ "id": 47, "name": "Dana Lee", "email": "dana@example.com", "role": "user", "active": true, "age": null }curl -X POST https://www.qabash.com/api/tools/sample-api/users -H "Content-Type: application/json" -d '{"name":"Dana Lee","email":"dana@example.com"}'/api/tools/sample-api/users/:idUpdate a user. Not persisted — merges your patch onto the seed record and echoes it back.
Params
idpath · requiredNumeric user idRequest body
{ "active": false }Responses
{ "id": 1, "name": "Alice Johnson", "email": "alice@example.com", "role": "admin", "active": false, "age": 32 }curl -X PATCH https://www.qabash.com/api/tools/sample-api/users/1 -H "Content-Type: application/json" -d '{"active":false}'/api/tools/sample-api/users/:idDelete a user. Not persisted.
Params
idpath · requiredNumeric user idResponses
{ "deleted": true, "id": 1 }curl -X DELETE https://www.qabash.com/api/tools/sample-api/users/1Test Cases
/api/tools/sample-api/testcasesList sample test cases. Supports an optional ?status= filter.
Params
statusquerydraft | active | archivedResponses
[
{ "id": 1, "title": "Login with valid credentials", "status": "active", "priority": "P1", "owner": "Alice Johnson" },
{ "id": 2, "title": "Login with locked account", "status": "draft", "priority": "P2", "owner": "Bob Smith" }
]curl "https://www.qabash.com/api/tools/sample-api/testcases?status=active"/api/tools/sample-api/testcases/:idUpdate a test case. Status only moves forward: draft → active → archived. Requesting any other transition returns a 409 with the allowed next states — most practice APIs only demo happy-path CRUD; this one teaches conflict handling too.
Params
idpath · requiredNumeric test case id — try 3 (already archived) to trigger the 409Request body
{ "status": "active" }Responses
{ "id": 2, "title": "Login with locked account", "status": "active", "priority": "P2", "owner": "Bob Smith" }Allowed transitions: draft → active, active → archived. archived has no further transitions.
curl -X PATCH https://www.qabash.com/api/tools/sample-api/testcases/2 -H "Content-Type: application/json" -d '{"status":"active"}'Auth — Bearer Token
/api/tools/sample-api/secureRequires an exact bearer token. Missing or wrong token → 401.
Params
Authorizationheader · requiredBearer demo-token-123Responses
{ "message": "Authenticated.", "scope": "sample-api:read" }curl https://www.qabash.com/api/tools/sample-api/secure -H "Authorization: Bearer demo-token-123"Auth — API Key
/api/tools/sample-api/auth/api-keyRequires an x-api-key header. Deliberately distinguishes missing (401) from present-but-wrong (403) — a nuance most practice APIs collapse into one status code.
Params
x-api-keyheader · requireddemo-key-abc123Responses
{ "message": "Authenticated.", "scope": "sample-api:read" }curl https://www.qabash.com/api/tools/sample-api/auth/api-key -H "x-api-key: demo-key-abc123"Resilience — Flaky
/api/tools/sample-api/flakyFails with a 500 roughly 30% of the time, at random — for practicing retry logic.
Responses
{ "message": "Success." }curl https://www.qabash.com/api/tools/sample-api/flakyResilience — Slow
/api/tools/sample-api/slowResponds after an artificial delay — for practicing timeout handling. Delay is clamped to 8000ms server-side no matter what you request.
Params
delayqueryMilliseconds to wait, 0-8000 (default 1000)Responses
{ "message": "Responded after delay.", "delayMs": 3000 }curl "https://www.qabash.com/api/tools/sample-api/slow?delay=3000"Resilience — Rate Limited
/api/tools/sample-api/rate-limitedAllows 5 requests per 10 seconds per IP, then 429s with a Retry-After header — for practicing backoff logic.
Responses
{ "message": "OK", "remaining": 3, "limit": 5, "windowMs": 10000 }Try the live demo below — it fires 6 requests back to back so you can watch the 429 happen.
curl -i https://www.qabash.com/api/tools/sample-api/rate-limitedLive demo
Fires 6 requests back to back — watch request 6 get a 429.
GraphQL
/api/tools/sample-api/graphqlA minimal GraphQL endpoint resolving "users" and "user(id: ...)" against the same seed data as the REST Users resource.
Request body
{ "query": "{ users { id name email } }" }Responses
{ "data": { "users": [ { "id": 1, "name": "Alice Johnson", "email": "alice@example.com" } ] } }curl -X POST https://www.qabash.com/api/tools/sample-api/graphql -H "Content-Type: application/json" -d '{"query":"{ users { id name email } }"}'QA Bash's API Playground is a real, live sample REST + GraphQL backend for practicing API testing — full CRUD, a draft→active→archived state machine that 409s on invalid transitions, bearer-token and API-key auth (with the 401-vs-403 distinction most practice APIs skip), plus dedicated flaky, slow, and rate-limited endpoints for retry, timeout, and backoff logic. Free, no signup required.
Built for testing, not just CRUD.
A real state machine
Test Cases move draft → active → archived. Request an invalid transition and get a 409 with the allowed next states — not just happy-path CRUD.
401 vs 403, done right
Bearer-token and API-key auth endpoints deliberately distinguish 'missing credential' (401) from 'wrong credential' (403) — a nuance most practice APIs collapse into one code.
A flaky endpoint
Fails ~30% of the time at random. Point your retry logic at it and watch it actually get exercised.
A slow endpoint
Configurable artificial delay for practicing timeout handling — clamped server-side so it can't be abused.
A rate-limited endpoint
5 requests per 10 seconds, then a real 429 with Retry-After. There's a live demo button that fires 6 requests so you can watch it happen.
REST + GraphQL
The same seed data is reachable via REST and a minimal GraphQL resolver, so you can practice both query styles against one dataset.
Frequently asked questions.
Is this a real backend I can hit from my automated tests?
Yes — every endpoint here is a real, live HTTP endpoint. Point curl, Postman, RestAssured, requests, or QA Bash's own API Workbench at it directly.
Does anything I create actually get saved?
No. POST/PUT/PATCH/DELETE all echo back what a real mutation would return, but nothing persists — so your requests never collide with anyone else hitting the same shared demo.
Why does the Test Cases endpoint reject some PATCH requests?
Status only moves forward: draft → active → archived. Requesting any other transition (like archived → draft) returns a 409 Conflict with the allowed next states in the body — deliberately, to give you a real conflict-handling case to test against.
What's the difference between the two auth endpoints?
/secure requires a bearer token; /auth/api-key requires an x-api-key header. Both are here so you can practice the two most common auth shapes, and /auth/api-key specifically demonstrates 401 (missing) vs 403 (wrong) as separate cases.
How is the rate limit tracked?
By IP address, in-memory, on the server — 5 requests per rolling 10-second window. It resets whenever the app redeploys, which is expected for a practice endpoint.
Can I use these endpoints in a CI pipeline?
They're a shared public demo on ordinary hosting, not a guaranteed-uptime SLA service — fine for learning and one-off scripts, not recommended as a dependency in a production test suite.