>_ Analyst Engineering

API Testing: How to Test an API End to End

Cover for a practitioner guide on API testing, covering status codes, schemas, request chaining, and error contracts.

API testing is about verifying the whole contract: the status code, the response schema, the side effects, and the error behavior, for valid and invalid inputs alike. Clicking through a UI tests a fraction of the system. Testing the API tests most of it.

To test an API end to end, you send requests and assert four things on every response: the status code, the response body against its schema and expected values, the side effects the call triggers such as an event or a database write, and the error behavior when the input is invalid. Then you cover the full matrix: the happy path, every validation failure with its specific error code, authentication and authorization, and the edge cases like duplicates and timeouts. The analyst who only checks that the happy path returns 200 is testing maybe a third of the API, because most of an API’s real behavior lives in how it responds to inputs that are wrong.

In payments, the API is the system. The screens are thin; the logic, the validation, the state transitions, and the events all happen behind the endpoints. That makes API testing the highest-leverage skill a QA analyst can build, and it is the foundation of how I learn and verify any system, which I walk through end to end in You Don’t Understand the System Until You Test It. The full path through these technical skills is mapped in The Technical Skills Guide for BAs.

What do you actually check when testing an API?

You check the full response, not just the status line. A complete API check asserts the status code, the body, the timing, the headers, and the side effects, because any one of them can be wrong while the others look fine.

Start with the status code, but know what each one means in context. A 202 on a payment endpoint means received and not yet validated, which is a very different guarantee than a 200 meaning done. Then the response body: assert it matches the schema, then assert the specific field values you expect, the assigned id, the echoed reference, the initial status. A response that is structurally valid but has the wrong status value is still a defect. Then the side effects: did the call publish the event it was supposed to, write the row it was supposed to, leave the system in the right state. The response can be a clean 202 while the event silently never fired, and only a side-effect check catches that.

This is the difference between confirming an endpoint responds and confirming it is correct. The response is the visible part; the side effects are where the real work happened, and where the expensive defects hide. Asserting the event a call publishes is its own skill in an event-driven system, which is exactly what Automate Kafka Validation with Postman is built to teach.

How does request chaining test a real flow?

Request chaining captures values from one response and feeds them into the next request, so a sequence of calls mirrors a single transaction moving through the system. It is what turns a pile of isolated endpoint checks into a test of an actual flow.

Here is the pattern. You POST a payment and capture the identifiers the rest of the flow needs into variables. Then every later call reuses them: the status poll, the downstream check, the callback assertion.

// 1) Create the payment, capture the ids for the chain
bru.setEnvVar("paymentId", res.body.paymentId);
bru.setEnvVar("uetr", res.body.uetr);
expect(res.status).to.equal(202);

// 2) Poll status using the captured id
// GET /payments/{{paymentId}}
expect(res.body.status).to.be.oneOf(["RCVD", "ACCP", "ACSP"]);

Now the test follows one payment the way the system does, which surfaces behavior no single-endpoint test would. You feel the latency between the POST and the moment the status becomes meaningful. You see whether the id is consistent across calls. You catch the case where the create succeeds but the status endpoint never reflects it. Chaining is the backbone of testing event-driven systems, where one transaction has to prove the whole pipeline, and it is a core developer-analyst technique because it is light scripting in service of analysis.

How do you test API error handling?

You test error handling by sending every invalid input the endpoint should reject and asserting the exact status code, error code, and message, plus confirming no unintended side effect occurred. This is where most of the real testing work is, because the error contract is most of the API.

Go through the failure matrix deliberately. A malformed payload should return a 400 with a clear error and publish no event. A missing required field should be rejected with a message naming the field. An invalid value, an unsupported currency, an amount of zero, a creditor name over the scheme limit, should each return its specific error code. Authentication and authorization failures should return 401 and 403 respectively, never leak information, and never process the request. A duplicate request with the same idempotency key should return a 409 or be safely ignored, not processed twice. A downstream timeout should leave the system in a defined, recoverable state, not a stuck one.

For each, the assertion has two halves: the right error response, and the absence of side effects. A rejected payment that still published an event or wrote a row is a serious defect, and you only catch it by checking the side effect on the failure path, not just the response. This systematic break-it-on-purpose approach is the core of good test design, which I cover in depth in negative test design. The error responses themselves should be specified before you test them, which is the API requirements work that makes the error contract testable in the first place.

API testing versus UI testing: where each fits

API testing exercises the system at the service layer; UI testing drives it through screens. For most modern systems, and nearly all payment systems, API testing reaches far more of the real behavior, faster and more reliably, because the logic lives behind the endpoints and much of it has no UI at all.

The practical advantages compound. API tests are faster, running in milliseconds without rendering a page. They are more stable, not breaking when a button moves or a label changes. And they reach behavior the UI never exposes: the event published to a topic, the row written in the background, the intermediate status that exists for half a second. A customer never sees those, but they are where payments succeed or fail. Testing only through the UI means trusting that everything behind it worked, which is exactly the assumption that lets defects through.

This does not make UI testing worthless; it tests the thing the customer actually touches, and that matters. But it should sit on top of a thick layer of API tests, not replace it. The QA analyst who can test at the API layer covers the system; the one limited to the UI covers the surface. Building that API-layer capability, including the scripting to chain and assert, is part of the developer-analyst skill set every modern tester needs.

A practical checklist for testing an endpoint

Before you call an endpoint tested, run it against this list. Does the happy path return the right status code, body, and side effects? Is the response body asserted field by field, not just structurally? Is every validation failure tested with its specific error code? Are authentication and authorization failures covered? Are boundary values, zero, maximum, just over the limit, tested? Is idempotency verified by repeating the call? Is a downstream timeout or failure handled into a recoverable state? Are side effects checked on the failure paths, not just the happy one?

If you can answer yes across that list, you have tested the contract, not just the endpoint. That is the standard that catches defects before production instead of after. The complete method, applied to a real payment flow hop by hop, is in You Don’t Understand the System Until You Test It, and the broader skills behind it are in The Technical Skills Guide for BAs.

The takeaway

API testing means verifying the whole contract: status code, response schema and values, side effects, and error behavior, across valid and invalid inputs. Chain requests so one test follows a real transaction, check side effects on both the happy and unhappy paths, and treat the error contract as the main event rather than an afterthought. Test the API and you cover the system; test only the UI and you cover the surface.

Start with Automate Kafka Validation with Postman for the event-driven side and The Technical Skills Guide for BAs for the full skill path, or browse everything at The Tech BA Toolkit.

Ahmed is a Senior Technical Business Analyst with 10+ years in banking and payments. He builds practical guides and tools for analysts at The Tech BA Toolkit.

Tags: Software Testing, API Testing, QA, Automation, Banking

Newsletter

Subscribe

Practical, no-fluff playbooks for technical analysts who analyze, code, test, and support. New articles straight to your inbox.

No spam. Unsubscribe anytime.