What Is API Integration Testing? Testing the Seams Between Resources
API integration testing checks the seams, such as what happens to an order when its user is deleted. Here's how it differs from API testing, the practices that keep it reliable, and a cross-resource test.
This is lesson 6.7 of Test Data, Mocks and End-to-End API Testing. Lesson 6.6 followed a whole journey; this one zooms in on the joins inside it, where two resources or two services meet.
What is API integration testing?
What is API integration testing? It's testing that the parts behind an API work together: an endpoint and its database, one resource and the resources it references, one service and the services it calls. A single-endpoint test asks "does this call do what the contract says?" An integration test asks "when this call changes something, does everything connected to it still make sense?"
API testing vs integration testing
The two overlap more than the names suggest:
| API (endpoint) testing | API integration testing | |
|---|---|---|
| Question | Does this endpoint honour its contract? | Do these parts work together? |
| Scope | One call, its inputs and outputs | Two or more resources, services or stores |
| Dependencies | Often real, sometimes stubbed | Real where you own them |
| Typical check | Status, fields, types, validation errors | Linked records, side effects, consistency across reads |
| Typical bug | A missing field, a wrong status | A delete that orphans data, a write that one read path doesn't see |
A call to a real endpoint that hits a real database is already an integration test of the API and its storage. What makes a test deliberately an integration test is that its assertions are about the seam.
The seams in the sandbox store
The sandbox store has three resources, and orders reference the other two through user_id and product_id. Ask for an order with both links expanded:
/api/v1/orders/dddddddd-dddd-dddd-dddd-dddddddddddd?expand=user,productcurl -X GET 'https://demo.totalshiftleft.ai/api/v1/orders/dddddddd-dddd-dddd-dddd-dddddddddddd?expand=user,product'One response, three resources: the order, its user and its product. That join is a seam, and it raises questions single-endpoint tests never ask:
| Question at the seam | What the store does | The test that pins it down |
|---|---|---|
| What happens to an order when its user is deleted? | The order stays; user_id is kept and the expanded user is null | Delete the user, read the order with expand, assert user is null |
| …and when its product is deleted too? | Same: product becomes null, the order is unchanged | Delete both, read again |
| Can you order for a user that doesn't exist? | Yes: the store accepts it and the expansion is null | Post an order with a nil UUID, expect 201 |
| Is a record written through one interface visible through another? | Yes: a user created over SOAP can be ordered for over REST | Create via SOAP, order via REST, read via GraphQL |
These behaviours come straight from the store's own requirements (scenarios E2E-04 and E2E-10 in /requirements/store.txt). Your API might make different choices: block the delete, cascade it, or reject an unknown user_id with a 400. The point of the integration test is not to prefer one, but to make whichever one you chose impossible to change by accident.
API integration testing best practices
- Assert on the seam, not just the call. After a delete, read the other resource. After a write, read back through a different endpoint or protocol.
- Use real dependencies where you own them. Your database, your queue, your other services. Start them with containers or a shared test environment.
- Stub what you don't own. A payment provider, a partner API. Stubs and mocks keep the suite fast and deterministic (lesson 6.2).
- Give each test its own records. Create the user and product the test changes; never delete seeded data another test reads (lesson 6.4).
- Check what didn't happen. A rejected order should leave the order count unchanged. Integration bugs often hide in partial writes.
- Run on every merge. Integration tests are slower than unit tests but much faster than end-to-end journeys; they belong in the main pipeline.
API integration testing tools
| Need | Common choices |
|---|---|
| Send requests and assert, in code | Rest Assured, pytest with requests or httpx, Jest with supertest, Karate |
| Start real dependencies | Testcontainers, docker compose |
| Replace dependencies you don't own | WireMock, Prism, a platform's mock server |
| Chain calls without code | Workflow or flow editors in API testing platforms |
| Run it all on every merge | Your CI: GitHub Actions, GitLab CI, Jenkins, Azure Pipelines |
Common mistakes
- Mocking your own database. Then nothing is integrated.
- Only testing the happy join. The interesting behaviour is at delete, update and "doesn't exist".
- Shared fixtures. One test deletes the user another test expands.
- Asserting the HTTP status only. A 204 on delete tells you nothing about the order.
A cross-resource test in Shift-Left API
In Shift-Left API, a cross-resource test is a workflow whose steps touch different resources and whose last step checks the seam. It runs on every edition; the free edition allows 10 blocks per workflow, Start and Stop included, and this one needs six.
- Import
https://demo.totalshiftleft.ai/openapi/rest.jsonand make four tests: Create a user, Place an order (productaaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa), Delete the user and Read the order back (expand=user,product). - Click Workflows, create one, and place Start, the four tests and Stop, joined by green connectors in that order.
- On Create a user, extract
data.idasuserId; on Place an order, extractdata.idasorderId. Use blue data connectors to feeduserIdinto the order'suser_idand the delete'sid, andorderIdinto the read-back'sid. - On Read the order back, add three checks: a field-type check that
data.userisnull,data.user_idequals{{userId}}, anddata.product.nameequalsWireless Mouse. - Click Launch Workflow and read the per-block report. The delete passes with 204, and the read-back passes all three checks: the order outlived its user.
The steps run one after another on the server, in the order the green connectors set. The integration test workflows feature page lists every block, and lesson 9.8 shows the editor in detail.
Try it yourself
Build the six-block workflow above and launch it. Then add a step that deletes the product and a second read-back that checks data.product is null too.
Recap
- What is API integration testing: checking that resources, services and stores behind an API work together, with assertions on the seams between them.
- API testing vs integration testing: an endpoint test checks one contract; an integration test checks what happens to everything connected when that call runs.
- API integration testing best practices: real dependencies you own, stubs for the rest, your own data, and read-backs through a different path.
For a code-first version with docker compose and pytest, read API integration testing: strategies, example and CI setup.
Try it: Build a workflow: Create a user, Place an order for that user and product aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa, Delete the user, then Read the order back with expand=user,product. On the last step, assert data.user is of type null, data.user_id equals userId and data.product.name equals Wireless Mouse. Run it.
Frequently asked questions
What is the difference in API testing vs integration testing?+
API testing checks one endpoint's contract: inputs, outputs and errors. Integration testing checks that two or more parts work together: an endpoint and its database, one service and another, or one resource and the resources it references. Many API tests are integration tests in practice, because a real endpoint call goes through the real database.
What are the main API integration testing best practices?+
Test real dependencies where you own them and stub the ones you don't; give each test its own data and clean up; assert on the seam, such as what a linked record looks like after a delete; read back through a different call than the one that wrote; and run the suite on every merge in an environment shaped like production.
Which API integration testing tools do teams use?+
Code-first teams combine an HTTP client and a test runner (Rest Assured, pytest with requests, Jest with supertest), Testcontainers or docker compose to start real dependencies, and WireMock or a mock server for the ones they can't run. No-code and low-code platforms chain requests into workflows with data passed between steps.
Related lessons
End to end API testing follows a business journey across several calls and proves the result. Here's a six-step method, how to decide coverage, and an order lifecycle built as a workflow on the sandbox store.
Microservices testing checks each service alone, the contracts between services, and a few journeys across them. Here are the layers, a store split into three services, and how mocks and a contract pack fit.
One test checks one call. A journey needs steps in order, values carried forward and proof that every step ran. Chain tests on a canvas in Shift-Left API, and let Workflow Doctor find the step that never ran.
Read more on the blog
Is API testing integration testing? Sometimes. This guide explains API integration testing, how it differs from unit, contract and end-to-end tests, how to handle dependencies with Testcontainers, service virtualization and mocks, and walks through a docker-compose + pytest example that runs in CI.
Functional testing and integration testing catch different classes of defect at different scopes. This guide defines both, compares tooling, and shows how modern API platforms collapse the boundary between them.