HomeGuides › REST API testing

REST API testing: how to test REST endpoints properly

By the Flasqo team · Updated 24 August 2026

In short

Test every REST endpoint on four layers — status code, body schema, headers and latency — then attack the happy path systematically. This guide covers status codes, idempotency, pagination and authentication.

  • Test a REST endpoint on four layers: status code, body schema, headers and latency. A test asserting only on status passes while the API returns the wrong data.
  • GET, PUT and DELETE must be idempotent. Call each twice and confirm the state and status are stable after the first call.
  • The endpoints most likely to be under-tested are the error branches — 400, 401, 403, 409 and 422.
  • Pagination bugs are common and quiet: records appearing on two pages or skipped between them rarely surface until a customer notices.

How to test a REST API

REST testing means sending an HTTP request to an endpoint and asserting on the complete response — not merely that something came back. The workflow is the same for every endpoint: establish the happy path, then systematically attack it.

  1. Send the valid request. Assert the status code, validate the body against a schema, and check the latency against a budget.
  2. Remove each required field in turn. Every one should produce a 400 or 422 with a message naming the offending field — not a 500.
  3. Send wrong types. A string where an integer belongs, an array where an object belongs, a 40,000-character name. Validation should reject these cleanly.
  4. Strip the credentials. Expect 401, and confirm the response body leaks no information about whether the resource exists.
  5. Use another user's credentials. Expect 403 or 404. If you get 200, you have found the most common serious API vulnerability — see security testing.
  6. Request something that doesn't exist. Expect 404, not a 500 from an unhandled null.

HTTP status codes worth asserting

CodeMeansTest that produces it
200 OKSuccessful read or updateValid GET or PUT
201 CreatedResource createdValid POST — assert the Location header too
204 No ContentSuccess, nothing to returnValid DELETE
400 Bad RequestMalformed syntaxInvalid JSON, wrong types
401 UnauthorizedMissing or invalid credentialsOmit the auth header
403 ForbiddenValid credentials, insufficient permissionAnother user's resource
404 Not FoundResource doesn't existA plausible but absent ID
409 ConflictState conflictDuplicate unique field
422 UnprocessableSyntactically valid, semantically wrongEnd date before start date
429 Too Many RequestsRate limitedBurst past the limit — assert Retry-After

Treat any unexpected 500 as a test failure, never a pass. A 500 on malformed input means validation is missing and an unhandled exception reached the top of the stack — which usually also means a stack trace was returned to the caller.

Testing idempotency

An idempotent method produces the same result regardless of how many times it is called. Under the HTTP specification, GET, PUT and DELETE are idempotent; POST generally is not. This matters because clients retry — on timeouts, on network failures, on user impatience.

To test it, issue the same request two or three times and assert the resource state is unchanged after the first call. The revealing case is DELETE: the first call returns 204, and the second should return 204 or 404 — never a 500 from code assuming the record exists.

For POST endpoints that must not double-apply — payments especially — the usual mechanism is an idempotency key supplied by the client. Test that sending the same key twice creates one resource and returns the original result the second time.

Testing pagination

Pagination defects are quiet and common. Cover five cases:

Also test the limits: a page size of 0, of -1, and of 100,000. The last one is a denial-of-service vector if the API obediently serialises a hundred thousand records.

Validating the response body

Spot-checking two fields is the most common weakness in REST suites. Validate the entire body against a schema instead — field names, types, nullability and required properties. That is the difference between an integration test and a contract test, and it is what catches the field that silently changed from a number to a string.

Where a JSON Schema or OpenAPI document exists, use it directly. Where none exists, generate one from live responses and treat it as a baseline — an inferred schema is far better than none.

Authentication in tests

Most meaningful endpoints sit behind authentication, and the way tests handle it determines how much they are worth.

Test your API without writing the tests

Paste a URL. Flasqo discovers your endpoints, generates the suite and runs it — free, no credit card.

Start testing free

Frequently asked questions

How do you test a REST API?

Send a request to the endpoint and assert on four things: the HTTP status code, the response body against a schema, the response headers, and the latency. Then repeat with invalid inputs to confirm the API rejects them with a 4xx rather than a 500 or a silent success.

Which HTTP status codes should REST tests assert?

At minimum: 200 or 201 for success, 400 for malformed input, 401 for missing credentials, 403 for valid credentials without permission, 404 for a missing resource, 409 for conflicts and 422 for semantically invalid input. Treat any unexpected 500 as a test failure, never as a pass.

What is idempotency and how do you test it?

An idempotent method produces the same result no matter how many times it is called. GET, PUT and DELETE must be idempotent; POST usually is not. Test it by issuing the same request two or three times and asserting the resource state and status code are stable after the first call.

How do you test paginated REST endpoints?

Check that page size is respected, that the total count is accurate, that the last page returns fewer items without erroring, that an out-of-range page returns an empty list rather than a 500, and that no record appears on two pages or is skipped between them.

Related reading

API Testing: The Complete Guide API Testing in CI/CD: Gate Every Deploy OpenAPI & Swagger Testing: Generate Tests From Your Spec API Load Testing: Load, Stress, Spike & Endurance API Chaos Testing: Resilience Testing With Fault Injection API Contract Testing: Stop Breaking Your Consumers GraphQL API Testing: Queries, N+1 & Depth Limits Flasqo vs Postman Flasqo vs Insomnia Flasqo vs Bruno Flasqo vs Hoppscotch