Checklist2-page PDF

API testing checklist

Tick each box as you test an endpoint. Your ticks stay saved in this browser, so you can come back to them later.

Preview of the API testing checklist PDF file

Before you start

  • Read the API docs (Swagger / OpenAPI) for the endpoint
  • Base URL noted for each env: dev, QA, staging
  • Auth type known; a valid token ready for each role
  • Test data ready: users and IDs you can safely change
  • Confirmed which environment you are hitting

Status codes

  • Happy path gives the documented code (200, 201, 204)
  • Create returns 201 with the new ID or Location header
  • Unknown ID returns 404, not 200 with an empty body
  • Bad input returns a 4xx code, never 500
  • Wrong method returns 405 (e.g. DELETE on read-only)
  • No error message hidden inside a 200 response

Response body

  • All documented fields present, with the right names
  • Right data types: 25 vs "25", true vs "true"
  • Null and empty values follow the docs
  • Formats right: dates, emails, phone numbers, amounts
  • Lists have the right count and sort order
  • No extra sensitive data (passwords, tokens, other users)

Headers

  • Content-Type is correct (e.g. application/json)
  • Caching headers make sense (Cache-Control, ETag)
  • CORS allows only expected sites (browser-called APIs)

Authentication and authorization

  • No token: 401 Unauthorized
  • Wrong or expired token: 401
  • Valid token, wrong role: 403 Forbidden
  • User A cannot see or edit User B’s data (swap the ID)
  • Token sent in a header, never in the URL
  • After logout, the old token stops working

Input validation (negative tests)

  • Missing required field: 400 or 422 with a clear message
  • Wrong data type (text in a number field)
  • Value longer than the max length
  • Boundaries: min, max, min-1, max+1, 0, negative
  • Special characters: quotes, &, emoji, Hindi text
  • Empty string vs null vs field left out
  • Duplicate create (same email twice): 409 or clear error
  • Broken JSON body: 400

Business rules

  • Totals add up: price x qty + tax – discount
  • Stock drops after an order, returns after a cancel
  • Status moves only in allowed steps
  • API data matches the UI and the database

Performance basics

  • Response time noted; compare across builds
  • Large lists are paginated (page + limit, or cursor)
  • Huge page size (limit=100000) is capped or rejected

Idempotency and retries

  • Same PUT twice: same final result, nothing extra
  • Same DELETE twice: no 500 (expect 404 or 204)
  • Same POST twice (double click): no duplicate record
  • Timeout + retry does not create a double order

Security basics

  • ' OR '1'='1 in a field is rejected or saved as text
  • <script> never comes back as live HTML
  • Errors show no stack trace, SQL or file path
  • HTTPS only: plain HTTP redirected or refused
  • Login and OTP endpoints are rate limited (429)

A full CRUD run (create, read, update, delete)

Chain the calls and pass the id from one step to the next. Most real API bugs show up between steps, not inside one call.

STEPREQUESTEXPECT
1POST /users with name and email201. Save the new id for the next steps
2GET /users/{id}200. Same name and email you sent
3PUT /users/{id} with a new name200 or 204
4GET /users/{id}200. Shows the new name, nothing else changed
5DELETE /users/{id}204 or 200
6GET /users/{id}404. The user is really gone
7DELETE /users/{id} again404, never 500

Test data for one field: email

Use the same pattern for every input: valid, missing, empty, wrong format, too long, wrong type, duplicate.

SENDEXPECT
asha@example.comAccepted
field left out400 or 422, “email is required”
null or ""Same as missing, clear message
asha@ or asha.example.comInvalid format
" asha@example.com "Spaces trimmed, or rejected
ASHA@example.comSame user as asha@example.com
256 charactersRejected at the max length
12345 (a number)Type error, not a 500
same email twice409 or a clear duplicate error
<b>asha</b>@x.comRejected, or stored as plain text

Postman tests you can paste

Put these in the request’s Scripts > Post-response tab (called Tests in older versions).

pm.test("Status is 201", () => {
  pm.response.to.have.status(201);
});
pm.test("Answers in under 800 ms", () => {
  pm.expect(pm.response.responseTime)
    .to.be.below(800);
});
const body = pm.response.json();
pm.test("New user has a number id", () => {
  pm.expect(body.id).to.be.a("number");
});
pm.test("Email comes back as sent", () => {
  pm.expect(body.email)
    .to.eql("test.one@example.com");
});
// Keep the id for the next request: {{userId}}
pm.collectionVariables.set("userId", body.id);

Query params and pagination

  • Each filter works alone and combined with others
  • Unknown or misspelled param: ignored or a clear 400
  • Sort works on each allowed field, both directions
  • First page, last page, one past the last page
  • page=0, page=-1, limit=0: handled, no 500
  • No item repeated or missing across pages

Contract and versions

  • Response matches the Swagger / OpenAPI schema
  • Renaming or removing a field breaks apps: flag it
  • Old version (/v1) still works if it is promised

Practice on: JSONPlaceholder (writes are faked), Restful Booker (auth and planted bugs), Swagger Petstore, httpbin.org, and ReqRes (free API key).

Tools

  • Postman: collections and tests
  • Playwright API testing: API tests in code
  • curl -i: a quick check that shows headers
  • DevTools Network tab: the real calls the UI makes

More cheat sheets and checklists

All files