Learn API testing fundamentals with free online tools. Master REST API testing, HTTP methods, status codes, headers, authentication, and debugging techniques.
The first time I tested an API, I typed a URL into a browser address bar and stared at a wall of JSON. No formatting, no syntax highlighting, no way to set headers. I copy-pasted the response into a text editor, manually searched for the field I needed, and declared the API "working."
That was testing the way cavemen made fire — it technically worked, but there were better options.
API testing doesn't have to be complicated. You don't need to install heavyweight desktop applications or pay for enterprise subscriptions. You don't even need to leave your browser. This guide covers everything from basic HTTP methods to authentication debugging, using free tools you can use right now.
API testing is the process of sending requests to an API endpoint and verifying that the response is correct — the right status code, the right data format, the right values, within an acceptable time frame.
It matters because APIs are the connective tissue of modern software. Your frontend talks to your backend through APIs. Your backend talks to third-party services through APIs. Your mobile app, your CLI tool, your webhook handler — all APIs. When an API breaks, everything downstream breaks with it.
There are different levels of API testing:
This post focuses on functional testing — the kind you do most often, the kind you can start doing in the next five minutes with a free API Tester.
Every REST API is built around HTTP methods. Understanding them is step one.
GET requests retrieve data without modifying anything on the server. They're safe and idempotent — you can call them a hundred times and the server state won't change.
GET /api/users/42
Response:
{
"id": 42,
"name": "Jane Doe",
"email": "jane@example.com",
"role": "admin",
"createdAt": "2026-01-15T09:30:00Z"
}GET requests often support query parameters for filtering and pagination:
GET /api/users?role=admin&page=2&limit=25
POST requests create new resources. The request body contains the data for the new resource.
POST /api/users
Content-Type: application/json
{
"name": "John Smith",
"email": "john@example.com",
"role": "user"
}
A successful POST typically returns 201 Created with the newly created resource, including its server-generated ID.
PUT requests replace an existing resource entirely. If you send a PUT with only two fields, the resource will have only those two fields after the update.
PUT /api/users/42
Content-Type: application/json
{
"name": "Jane Doe",
"email": "jane.doe@newdomain.com",
"role": "admin"
}
There's also PATCH, which updates only the fields you send. In practice, many APIs use PUT and PATCH interchangeably, which is technically wrong but extremely common.
DELETE requests remove a resource. The response is usually 204 No Content (empty body) or 200 OK with a confirmation message.
DELETE /api/users/42
Most APIs implement soft deletes behind the scenes — the record gets a deletedAt timestamp rather than being physically removed. But from the API consumer's perspective, it's gone.
Status codes are the first thing I check when an API response comes back. Before looking at the body, before parsing JSON — the status code tells you whether the request succeeded, failed, or something in between.
| Code | Meaning | When You'll See It |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH, or DELETE |
| 201 | Created | Successful POST that created a resource |
| 204 | No Content | Successful DELETE with no response body |
| Code | Meaning | Common Cause |
|---|---|---|
| 400 | Bad Request | Malformed JSON, missing required fields, invalid data types |
| 401 | Unauthorized | Missing or expired authentication token |
| 403 | Forbidden | Valid token, but insufficient permissions |
| 404 | Not Found | Wrong URL or resource doesn't exist |
| 405 | Method Not Allowed | Using POST on a GET-only endpoint |
| 409 | Conflict | Trying to create a resource that already exists |
| 422 | Unprocessable Entity | Valid JSON, but the values fail validation |
| 429 | Too Many Requests | Rate limit exceeded — slow down |
| Code | Meaning | What To Do |
|---|---|---|
| 500 | Internal Server Error | Report it. Check the API's status page. |
| 502 | Bad Gateway | The server behind the proxy is down. Wait and retry. |
| 503 | Service Unavailable | Server overloaded or in maintenance. Retry with backoff. |
| 504 | Gateway Timeout | Upstream server didn't respond in time. Try again. |
The difference between 401 and 403 catches people constantly. 401 means you're not authenticated — the server doesn't know who you are. 403 means you're authenticated but not authorized — the server knows who you are, and you don't have permission.
HTTP headers carry metadata about the request and response. Most beginners ignore them. Most debugging sessions end with "oh, I forgot a header."
Content-Type tells the server what format your request body is in:
Content-Type: application/json
Get this wrong and the server will either reject your request with a 400 or try to parse your JSON as form data and return garbage.
Accept tells the server what format you want the response in:
Accept: application/json
Authorization carries your authentication credentials (more on this below).
X-RateLimit-Remaining tells you how many requests you have left before hitting the rate limit. Not all APIs include this, but the good ones do.
X-Request-Id is a unique identifier for your request. If you need to report a bug to the API provider, this is the value they'll ask for.
Cache-Control tells you whether and how long the response can be cached. If you're getting stale data, this header is the first place to look.
You can inspect all of these headers easily with a free online API Tester — most browser-based tools display response headers in a dedicated tab.
Most APIs require authentication. Here are the three patterns you'll encounter most often.
The simplest form. You get a key from the API provider's dashboard and include it in your requests, usually as a header or query parameter.
GET /api/data
X-API-Key: sk_live_abc123def456
Or as a query parameter (less secure — the key shows up in server logs and browser history):
GET /api/data?api_key=sk_live_abc123def456
API keys are easy to use but hard to manage at scale. They don't expire automatically, they can't carry permissions, and if one leaks, you have to rotate it manually.
The most common pattern in modern APIs. You authenticate once (with a username/password, OAuth flow, or similar), receive a JWT, and include it in subsequent requests:
GET /api/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
JWTs are base64-encoded JSON with three parts: header, payload, and signature. You can decode them without the secret key to inspect their contents — the JWT Decoder tool is useful for this. You can also use a Base64 Encoder to manually decode individual JWT segments.
When testing JWT-authenticated APIs, check these things:
exp claim. If it's in the past, you need a fresh token.iss and aud claims. A token from the wrong environment (staging vs. production) will be rejected.read:users scope won't work on an endpoint that requires write:users.OAuth is a framework, not a single flow. The most common flows for API testing are:
Authorization Code Flow — The user logs in through a browser, gets redirected back with a code, and you exchange that code for an access token. This is what "Login with Google" uses.
Client Credentials Flow — Server-to-server authentication. You send your client ID and secret directly:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=YOUR_ID&client_secret=YOUR_SECRET
The response includes an access token you use as a Bearer token in subsequent requests.
Here's the workflow I follow when testing an API for the first time. This applies whether you're integrating with a third-party API or testing your own.
I know, obvious. But I mean actually read it — the authentication section, the rate limits, the error format. Five minutes of reading saves thirty minutes of debugging. If the API is publicly listed, you can browse it through the Public API Directory to find documentation links and base URLs.
Start with the simplest endpoint that requires the least authentication. Most APIs have a health check or version endpoint:
GET /api/health
If this works, your base URL is correct and the server is reachable. If it doesn't, fix that before trying anything else.
Make a request to an authenticated endpoint. If you get a 401, your credentials are wrong. If you get a 403, your credentials work but lack permissions. If you get a 200, you're in.
For each endpoint, test:
Raw JSON responses are hard to read. Use a JSON Formatter to pretty-print and syntax-highlight responses. This makes it much easier to verify that the data structure matches what you expect.
These are the problems I see most often — both in my own work and when helping others debug their API integrations.
Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000'
has been blocked by CORS policy
CORS errors only happen in browsers. If your API request works in an API testing tool but fails in your frontend code, CORS is the issue. The fix is on the server side — the API needs to include Access-Control-Allow-Origin headers. As a quick workaround during development, test directly in a tool like the API Tester which isn't subject to browser CORS restrictions.
If you're sending special characters in URLs — spaces, ampersands, Unicode — they need to be percent-encoded. A space becomes %20, an ampersand becomes %26. The URL Encoder handles this automatically.
The same applies to request bodies. If your Content-Type is application/x-www-form-urlencoded, the body needs to be form-encoded. If it's application/json, it needs to be valid JSON. Mixing these up produces cryptic errors.
Many APIs paginate results by default. You request /api/users expecting all 500 users and get back 25. The remaining 475 are on subsequent pages.
Check for pagination metadata in the response:
{
"data": [...],
"pagination": {
"page": 1,
"perPage": 25,
"total": 500,
"totalPages": 20
}
}Or look for Link headers with rel="next" URLs.
Hit an API too fast and you'll get 429 Too Many Requests. Check the Retry-After header to know when you can try again. During testing, add a small delay between requests, or use the X-RateLimit-Remaining header to know when you're getting close.
If requests hang and eventually time out, the problem is usually one of:
X-Response-Time header or their status page.Not every API returns JSON. Some return XML, CSV, or plain text. Some return different formats based on the Accept header you send. When testing, always verify that:
Content-Type response header matches what you expectFor JSON responses specifically, pipe the response through a JSON Formatter to catch structural issues immediately — missing closing brackets, trailing commas, and other syntax problems become obvious when the formatter refuses to parse the input.
Good API testing isn't a one-time activity. Here's what I do:
During development: Test each endpoint as I build it. Verify happy paths, error cases, and edge cases before moving on.
Before deployment: Run through the full endpoint list. Test authentication flows end-to-end. Verify that error messages are helpful and don't leak internal details.
After deployment: Hit the production endpoints with read-only requests to verify they're live and responding correctly. Never test write operations against production unless you have a designated test account.
On a schedule: APIs change. Third-party APIs deprecate endpoints, change response formats, adjust rate limits. Periodic testing catches these changes before your users do.
API testing is a skill that compounds. The more APIs you test, the faster you get at spotting issues. The patterns repeat — authentication problems, missing headers, encoding bugs, pagination gotchas. Once you've debugged each of these once, you recognize them instantly the next time.
Start with a free browser-based API Tester, pick an API from the Public API Directory, and send your first request. Start simple — a GET to a public endpoint. Then add headers. Then add authentication. Then try POST, PUT, DELETE. Before you know it, you'll be testing APIs faster than you can read their documentation.
The best API testing tool is the one you actually use. The best testing practice is the one you actually follow. Start simple, stay consistent, and build from there.