Testing a REST API means sending a request and checking that the response is what the contract promised — the right status code, the right shape, and a sane response time. Here is the whole loop in SchemaClient.
1. Pick a method and a URL
Open the REST Client tab and enter the endpoint. The method matters more than people expect, because it decides what the server is allowed to do:
- GET — read something. Must not change server state.
- POST — create something, or trigger an action.
- PUT — replace a resource wholesale.
- PATCH — update part of a resource.
- DELETE — remove a resource.
- HEAD — like GET, but headers only. Useful for checking whether something exists without downloading it.
- OPTIONS — ask what the endpoint supports. This is also what a browser sends as a CORS preflight, so it is worth testing directly when CORS misbehaves.
Query parameters
Anything after ? filters or shapes the response rather than identifying the resource:
GET /api/users?status=active&limit=25&sort=-created_at
Two things break here regularly. Values need URL-encoding — a space is %20, an & inside
a value is %26, and an unencoded one silently splits your parameter in half. And arrays
have no single convention: some APIs want ?tag=a&tag=b, others ?tag[]=a&tag[]=b, others
?tag=a,b. Check the docs rather than guessing, because the wrong form usually returns a
200 with the filter ignored.
2. Add headers
Most failures at this stage are header failures. The two that matter most:
Content-Type: application/json
Authorization: Bearer <your-token>
If the API returns 415 Unsupported Media Type, your Content-Type is wrong. If it returns
401, the token is missing, expired, or in the wrong header.
The three auth schemes you will actually meet
Bearer token — Authorization: Bearer <token>. The most common. Tokens expire, and an
expired token gives you a 401 that looks identical to a missing one.
Basic auth — Authorization: Basic <base64 of user:password>. Still common on internal
and legacy services. The base64 is encoding, not encryption; treat the credentials as
plaintext.
API key — sometimes a header (X-API-Key), sometimes a query parameter
(?api_key=…). The query-parameter form leaks keys into server logs and browser history,
so prefer the header when the API offers both.
3. Add a body
For POST, PUT and PATCH, switch to the Body tab and send JSON:
{
"email": "dev@example.com",
"plan": "free"
}
Malformed JSON is the second most common cause of a 400 — a trailing comma is enough to
break it. If you are uploading a file, use multipart form data rather than JSON, and let the
client set the Content-Type boundary itself; hand-writing that header is a reliable way to
get a 400.
4. Send it and read the status code
Status codes tell you who is at fault before you read a single line of the body:
- 2xx — it worked.
- 3xx — it moved. Check the
Locationheader. - 4xx — you got it wrong. Bad input, bad auth, wrong URL.
- 5xx — the server got it wrong. Your request may be fine; retry and check logs.
The ones worth recognising on sight:
| Code | What it usually means | First thing to check |
|---|---|---|
| 400 | Malformed request | JSON syntax, required fields |
| 401 | Not authenticated | Token missing, expired, or wrong header |
| 403 | Authenticated, not allowed | Permissions or scope on the token |
| 404 | Wrong URL, or the resource is gone | Path, IDs, trailing slash |
| 415 | Wrong Content-Type | The header, not the body |
| 422 | Well-formed but semantically invalid | Field-level validation errors in the body |
| 429 | Rate limited | Retry-After header |
| 500 | Server bug | Not your request — check server logs |
| 502 / 504 | Upstream failed or timed out | Infrastructure, not your payload |
There is a fuller reference in HTTP status codes explained.
5. Check the response body, not just the status
A 200 OK can still be wrong. An endpoint that returns {"users": null} instead of an empty
array will pass a status-code check and break your app anyway. This is why it is worth
validating responses against a schema rather
than eyeballing them — and why
a green test suite can still miss a breaking change.
Read the response headers too. Content-Type tells you whether you actually got JSON;
rate-limit headers tell you how much budget is left; and cache headers explain why you are
seeing a stale value.
Use variables instead of pasting values
As soon as you have more than one request, stop pasting the base URL and the token into each one. Put them in environment variables and reference them:
{{baseUrl}}/api/users
Authorization: Bearer {{token}}
Now switching between local, staging and production is changing one environment rather than editing every request, and a rotated token is a single edit.
A short checklist
Before you call an endpoint tested:
- The happy path returns the expected status and the expected shape.
- A missing required field returns a
4xx, not a500. - An invalid or expired token returns
401, not200with empty data. - Asking for something that does not exist returns
404, not an empty200. - The response time is in the range you expect.
Save it for next time
Once a request works, save it into a collection so you are not rebuilding it by hand every week — see collections and cloud sync. If the API you are testing runs on your own machine, you will also want a public URL for localhost. And once the collection is worth keeping green, run it in CI.