Structural / Integration · CTFL 4.0, CTAL-TA

API Testing

Test application programming interfaces directly — sending requests, validating status codes, headers, and response bodies — without going through the UI. This is where most of the interesting business logic actually lives.

Senior Test Lead ISTQB CTFL 4.0 · CTAL-TA

What it is

API testing means interacting directly with an application’s backend endpoints — sending HTTP requests and verifying the responses — rather than driving the application through a browser or mobile UI. Because most modern applications are built on top of APIs, testing them directly gives you faster feedback, earlier in the cycle, and with finer-grained assertions than UI testing allows.

An API test asks: given this request (URL, method, headers, body), does the system return the right response (status code, body schema, data values, error messages)? It’s specification-based testing applied to a service contract rather than a user interface.

Why test at the API level? UI tests are slow, brittle, and expensive to maintain. API tests run in milliseconds, don’t break when a button moves, and can be run thousands of times a day in CI. If the API is correct, the UI just needs to call it correctly — a much smaller testing problem.

When to use it

  • When the UI is not yet built — test the backend immediately after backend development, without waiting for frontend work
  • When you need to test business logic independent of the frontend — price calculations, eligibility rules, data transformations
  • When validating integrations between services — does Service A send the right data to Service B?
  • For regression testing after backend changes — fast, repeatable, and doesn’t require a browser
  • For performance and load testing — drive hundreds of concurrent requests directly at the API

Key concepts

HTTP methods

Each HTTP method has a defined semantic meaning. Verify that your API uses them correctly:

HTTP methods and their purpose
MethodPurposeIdempotent?Example
GETRetrieve a resourceYesGET /orders/123
POSTCreate a new resourceNoPOST /orders
PUTReplace a resource entirelyYesPUT /orders/123
PATCHUpdate part of a resourceNoPATCH /orders/123
DELETERemove a resourceYesDELETE /orders/123

Status codes to know

Status codes are the first thing you check. A wrong status code is a bug, even if the response body looks right.

Status codes — what they mean and when they should appear
CodeMeaningWhen to expect it
200 OKSuccessSuccessful GET, PUT, PATCH
201 CreatedResource createdSuccessful POST that creates a new record
400 Bad RequestClient error — malformed inputMissing required field, wrong data type
401 UnauthorisedNot authenticatedNo auth token or invalid token
403 ForbiddenAuthenticated but not allowedUser doesn’t have permission for this resource
404 Not FoundResource doesn’t existGET /orders/99999 where that order doesn’t exist
422 Unprocessable EntityValidation failedInput is syntactically valid but semantically wrong (e.g. invalid NZ postcode)
500 Internal Server ErrorServer crashedUnhandled exception — always a bug

Anatomy of a request

Every API request has four possible components. Understanding what goes where prevents common test setup errors:

  • URL — the endpoint address, including path parameters: https://api.example.co.nz/v1/orders/123
  • Headers — metadata sent with every request. Key ones to test: Authorization: Bearer <token> (authentication) and Content-Type: application/json (tells the server how to parse the body)
  • Query parameters — filtering and sorting options appended to the URL: ?status=pending&limit=10
  • Request body — the data sent with POST/PUT/PATCH requests, usually as JSON

What to validate in the response

A thorough API test checks more than just the status code:

  • Status code — does it match what the spec says?
  • Response body schema — are all expected fields present? No extra unexpected fields?
  • Data types — is price a number (not a string)? Is orderId a string UUID?
  • Required fields — if the spec says customerId is always returned, verify it’s never null or missing
  • Error messages — on 4xx responses, is the error message clear, actionable, and free of internal implementation details?
  • Response time — does the endpoint respond within an acceptable SLA?

Contract testing

If your API has an OpenAPI (Swagger) specification, treat it as your test oracle. The spec defines the contract: what requests the API accepts, what responses it returns, and what each field means. If the live API doesn’t match the spec, that’s a bug — even if the API appears to “work.” Consumers of the API (frontend, mobile app, partner integrations) are coding to the spec, not to whatever the API happens to return today.

NZ worked example

Imagine you’re testing an e-commerce API for a New Zealand retailer. Here’s a sequence of API tests covering the order creation flow:

NZ e-commerce order API — test scenarios
TestRequestExpected statusKey assertions
Create order with valid NZ address POST /orders
body: valid NZ shipping address (e.g. 123 Queen St, Auckland 1010)
201 Created Response contains orderId, status: "pending", total in NZD
Retrieve the created order GET /orders/{orderId} 200 OK Returned order matches what was posted; orderId matches
Create order with invalid NZ postcode POST /orders
body: postcode "9999" (not a valid NZ postcode)
422 Unprocessable Entity Error message mentions postcode; no order created in the database
Create order without auth token POST /orders
No Authorization header
401 Unauthorised No order created; error body does not expose internals
Retrieve order belonging to another customer GET /orders/{otherCustomerOrderId} 403 Forbidden System does not return another customer’s order data (IDOR check)
Get order that does not exist GET /orders/00000000-0000-0000-0000-000000000000 404 Not Found Clear error message; no stack trace in body

Note that the NZ-specific context matters: NZ postcodes are 4-digit numbers (1010 for central Auckland, 6011 for central Wellington, 8011 for central Christchurch). A postcode of “9999” or “12345” is invalid and should be caught at the API layer, not just in the UI.

Common bugs API testing finds

  • 200 when it should be 400 — the API accepts clearly invalid input without complaint, then fails silently later
  • Stack traces in error responses — a 500 response that includes a Java stack trace or file path is a security risk, not just an aesthetic issue
  • Missing required fields — the spec says customerId is always returned, but it’s absent for guest orders
  • Wrong data typesprice returned as a string ("49.99") instead of a number (49.99), breaking downstream calculations
  • No authentication required on protected endpoints — removing the Authorization header and still getting a 200 is a critical security bug
  • CORS headers missing or too permissiveAccess-Control-Allow-Origin: * on an authenticated endpoint allows cross-site requests from any domain
  • Inconsistent IDs — POST returns id: 123 but GET expects /orders/00000123 (zero-padded) — integration breaks

Tools

  • Postman — the most widely used API testing tool; supports collections, environments, and automated test scripts written in JavaScript. Good for manual and automated API testing.
  • Insomnia — lighter-weight alternative to Postman; good for individual API exploration
  • REST-assured — Java library for writing API tests as code; integrates with JUnit/TestNG; preferred in Java-heavy teams
  • k6 — designed for performance and load testing APIs; scripts in JavaScript; can run from CI
  • Newman — Postman’s CLI runner; run your Postman collections from the terminal or CI pipeline without opening the GUI

ISTQB mapping

ISTQB reference
Syllabus refTopicLevel
CTFL 4.0 — 2.2Component integration testing — testing interfaces between componentsFoundation
CTAL-TA 3.3Structural testing at integration level; API contract verificationAdvanced / Senior
CTAL-TA 4.2Test specification for service interfaces and integration pointsAdvanced / Senior

Tips

Read the spec before you test. Start by reading the API documentation (OpenAPI/Swagger) before testing. Treat the spec as your test oracle — if the API doesn’t match the spec, that’s a bug even if the API “works.” Teams often discover that the spec and implementation have quietly diverged, causing silent failures in client applications.

  • Test auth first — before testing happy paths, verify that removing or corrupting the auth token returns 401. If it doesn’t, stop and raise it immediately.
  • Use environments in Postman — store your base URL, tokens, and IDs in environment variables so your test collection runs against dev, staging, and production with a single click.
  • Chain requests — use the ID returned from a POST as input to the subsequent GET, PUT, and DELETE tests. This is more realistic than hardcoded IDs and finds sequencing bugs.
  • Test the boundaries of optional fields — what happens when an optional field is null? Omitted entirely? An empty string? These three are often handled differently.
  • Check idempotency — send the same PUT request twice. The second call should return the same result and not create a duplicate record.

Practice this technique: Try Test Lead Practice 06 — API contract bugs.

NZ example — testing a NZ payments API

A NZ-specific payments API (such as one built on the Payments NZ API Centre standards) has several NZ-specific test cases beyond the generic HTTP contract tests.

  • Bank account format validation — NZ bank accounts follow the BB-bbbb-AAAAAAA-SS format (bank-branch-account-suffix). The API should accept 06-0000-0000000-00 (ASB) but reject 1234567890123456 (card number format). Test the API directly with both formats and verify the response codes and error messages.
  • Currency — the API should only accept NZD amounts. Test with "USD" in the currency field — expect a 400 or 422 with a clear error.
  • Amount precision — NZD amounts must have exactly 2 decimal places. Test 100, 100.0, 100.00, 100.000 — only 100.00 and 100.0 (if normalised) should succeed; 100.000 should be rejected or normalised.
  • POLi integration — POLi is a NZ/AU bank-to-bank payment method. If the API supports POLi, test the redirect flow, the callback handling on success/failure/timeout, and what happens if the bank session expires mid-flow.
  • IBAN — NZ does not use IBAN. Any API that requires or accepts IBAN for NZ accounts has a design defect — test for this.