Guides

9 Types of API Testing You Need to Know

Sushant JoshiUpdated Aug 20, 202613 min read

Quick answer

There are 9 distinct types of API testing: smoke (is the build alive), functional (is behavior correct), integration (do services work together), contract (do provider and consumer agree), regression (did anything break), load and performance (does it hold up under traffic), security (auth, injection, OWASP), fuzz (random or malformed input), and end-to-end (the full user journey). No single type is "API testing" on its own — a mature suite runs several at different stages.

Reviewed by Parveen Kumari

Share:
Timeline showing when each of the nine API testing types runs relative to a deployment

API testing is not one activity — it's at least 9 distinct types, each designed to catch a different class of failure. A suite that only runs functional tests can still ship an API that breaks under load, silently changes its contract with a consumer, or has an authorization hole no functional test was written to find. This guide covers all 9, what each one actually catches, and when it belongs in your pipeline.

In this guide

  1. Smoke Testing
  2. Functional Testing
  3. Integration Testing
  4. Contract Testing
  5. Regression Testing
  6. Load and Performance Testing
  7. Security Testing
  8. Fuzz Testing
  9. End-to-End Testing
  10. How These Types Fit into One Pipeline
  11. One endpoint, tested nine ways
  12. Which types to run when
  13. How the types overlap
  14. Common mistakes

1. Smoke Testing

A small, fast set of checks confirming a deployment is minimally functional — the API starts, a health-check endpoint returns 200, the database connection is alive. Smoke testing answers "is this build worth testing further," not "is it correct." It runs immediately after every deployment, in seconds to a couple of minutes. See Smoke Testing vs Regression Testing for exactly where the boundary between the two sits.

For services that speak gRPC rather than HTTP+JSON, the gRPC testing tools roundup covers grpcurl, ghz, the k6 gRPC module and the contract options.

Estates that still run SOAP alongside REST need a second toolchain — SOAP and WSDL testing in 2026 covers what is still maintained and what WS-Security costs you.

Streaming endpoints need different assertions again — the WebSocket testing tools roundup covers ordering, reconnection and protocol conformance.

If you are on the other side of this — being asked about it rather than doing it — API testing interview questions covers what each round is actually assessing.

The wider framing — testing from outside the implementation versus inside it — is in black box vs white box testing.

GraphQL moves the contract into the schema and adds depth-limiting and introspection to the checklist — how to test GraphQL APIs covers both.

The assertions change when the protocol does — REST vs GraphQL vs gRPC testing covers what transfers and what does not.

If you are being asked to test an MCP server rather than the API behind it, how to test MCP servers has the handshake, tool-schema and injection cases.

2. Functional Testing

Verifies that an endpoint does what it's supposed to: correct status codes, correct response body, correct business logic for a given input. This is the type most tutorials mean by "API testing" and the foundation every other type builds on — see our pytest, REST Assured, or Playwright tutorials for how to write it.

3. Integration Testing

Verifies that the API behaves correctly when it actually talks to its real dependencies — a database, a cache, a message queue, a downstream service — rather than the mocked versions functional tests typically use. A function that's perfectly correct in isolation can still fail once it hits a real database connection pool limit or a downstream service's actual (not mocked) error response. See Functional Testing vs Integration Testing for the full comparison.

4. Contract Testing

Verifies that an API's actual shape — field names, types, required-ness — matches what its consumers expect, independent of whether the business logic behind it is correct. A service can pass every functional test and still break a consumer if a field silently changes type or disappears. This matters most in microservices architectures where many teams consume the same API independently. See What Is API Contract Testing? for the full breakdown.

5. Regression Testing

Re-runs the existing suite after a change to confirm nothing that used to work has broken. It's not a separate set of test cases so much as a discipline: running the full functional (and often integration) suite on every meaningful change, not just the code path that changed. Fast API-based regression suites (minutes, not tens of minutes) fit on every pull request; slower E2E-based ones typically run nightly.

6. Load and Performance Testing

Measures how the API behaves under concurrent traffic — response time, throughput, and error rate at realistic (and peak) load, not just correctness for a single request. This is a fundamentally different question than functional testing answers, and needs different tools: see JMeter or k6 for how to build this suite.

Ready to shift left with your API testing?

Try our no-code API test automation platform free. Generate tests from OpenAPI, run in CI/CD, and scale quality.

7. Security Testing

Verifies the API resists the specific attack classes that actually compromise APIs in production: broken authentication, broken object-level authorization (BOLA), injection, excessive data exposure, and the rest of the OWASP API Security Top 10. Security testing is frequently under-invested relative to functional testing despite causing a disproportionate share of real incidents.

8. Fuzz Testing

Sends random, malformed, or unexpected input — truncated JSON, wildly out-of-range numbers, unexpected types, unusual encodings — to find crashes, hangs, or undefined behavior that deliberately-written negative test cases don't anticipate. Where a negative test case checks a specific, known-bad input you thought to write, fuzz testing finds the ones nobody thought to write a test case for. It's closely related to chaos and fault-injection testing at the system level.

9. End-to-End Testing

Confirms a full user journey works correctly through both the UI and the APIs behind it — not the API in isolation, but the complete path a real user or client takes. It's the slowest and most brittle of the nine types (a UI change can break an E2E test unrelated to the API's own correctness), which is why mature teams push as much coverage as possible down into pure API-level functional testing and reserve E2E for a small number of critical journeys. See API Testing vs UI Testing for the full tradeoff.

How These Types Fit into One Pipeline

No single type above is "API testing" by itself — a complete strategy runs several, at different stages, gated to how long each takes:

TypeTypical triggerTypical duration
SmokeEvery deploymentSeconds–minutes
FunctionalEvery pull requestMinutes
IntegrationEvery pull request or pre-mergeMinutes
ContractEvery pull requestMinutes
RegressionPre-merge to mainMinutes
Security (basic)Every pull requestMinutes
Load / PerformanceSchedule or pre-releaseTens of minutes
FuzzScheduleTens of minutes–hours
End-to-EndPre-release or nightlyTens of minutes

See the API testing checklist for the specific items each type should cover, and how to write API test cases for turning any of these into a concrete, automatable test.

One endpoint, tested nine ways

The types are easiest to tell apart when they all point at the same endpoint. Each of these is a different question about POST /v1/orders:

# 1. smoke — is it alive?
curl -so /dev/null -w '%{http_code}\n' "$API/health"

# 2. functional — does it do what the spec says?
curl -s -XPOST "$API/v1/orders" -H "Authorization: Bearer $T" \
  -H 'Content-Type: application/json' -d '{"sku":"A-1","qty":2}' | jq .status

# 3. integration — did the downstream side effect happen?
curl -s "$API/v1/inventory/A-1" -H "Authorization: Bearer $T" | jq .reserved

# 4. contract — does the response still match the schema consumers rely on?
schemathesis run openapi.yaml --url "$API" --checks response_schema_conformance

# 5. regression — do the previously-fixed edge cases still hold?
pytest -m regression tests/test_orders.py

# 6. load — does it hold at 50 concurrent users?
k6 run --vus 50 --duration 2m load.js

# 7. security — is authorization enforced per object?
curl -so /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $OTHER" "$API/v1/orders/42"

# 8. fuzz — does malformed input produce a 4xx rather than a 5xx?
schemathesis run openapi.yaml --url "$API" --checks all --hypothesis-max-examples 200

# 9. end-to-end — does the whole journey complete?
pytest tests/e2e/test_checkout_journey.py

Nine types, one endpoint, nine different failure modes. A suite that runs only type 2 is the most common shape in practice, and it is why "all our tests pass" and "production broke" coexist so comfortably.

Which types to run when

Nine types is a menu, not a checklist to run on every commit. What makes a suite usable is putting each type where its cost matches its value.

TriggerTypes that runBudget
Every commit / pull requestSmoke, functional, contract, integrationUnder 10 minutes
Every merge to mainThe above, plus regressionUnder 20 minutes
NightlyFull regression, fuzz, end-to-endUnbounded
Before a releaseLoad and performance, securityScheduled, on a stable environment
On a schedule, in productionSmoke against live, synthetic monitoringContinuous

Two placements are worth arguing about. Security testing is on the release line here, but the cheap parts — authentication and authorization checks on protected endpoints — belong on every pull request, because they are fast and the failure they catch is the most expensive one. Load testing cannot run per commit, but a scaled-down performance smoke test that fails when p95 doubles is affordable and catches the obvious regressions early.

Free Guided worksheet

Build Your Testing Strategy in 30 Minutes

A structured worksheet that walks you through defining your testing strategy in 30 minutes. Cover architecture, tools, layers, and team responsibilities.

Download Free

The rule underneath the table: a type belongs in the gate if it is fast, deterministic, and its failure means "do not merge". Everything else belongs on a schedule, where a failure creates a ticket rather than blocking a queue.

How the types overlap

The nine categories are not disjoint, and treating them as separate suites produces duplicated coverage and slow runs.

Contract and functional testing overlap heavily at the boundary. A contract test proves the response matches the schema; a functional test proves the value is right. If both assert the shape, drop it from the functional test and let the contract layer own it.

Regression testing is not a distinct type. It is a reason for running the others — every functional, integration and contract test becomes a regression test the moment the feature ships. Treating regression as a separate suite is how teams end up with two copies of the same case.

Fuzz and security testing converge. Property-based fuzzing against a schema finds the same input-handling defects a security scanner reports, arriving from a different direction. Running both is reasonable; expecting them to find disjoint sets of bugs is not.

Integration and end-to-end differ by scope, not kind. Integration verifies that two components agree; end-to-end verifies a user-visible journey across all of them. The distinction matters because their costs differ by an order of magnitude, and teams routinely write end-to-end tests for things integration tests would have caught faster.

The practical consequence: decide which layer owns each assertion, and delete it from the others. A suite where every layer checks everything is slow, and its failures point everywhere at once.

Common mistakes

Running everything on every commit. The suite becomes slow, then flaky, then bypassed. Speed is a correctness property of a gate, because a gate people skip catches nothing.

Skipping the types that require a decision. Load and security testing need a threshold and an owner, so they get postponed indefinitely. Set a deliberately loose threshold and tighten it later — a weak gate beats no gate.

Assuming coverage of one type implies another. Full functional coverage says nothing about behaviour under load, and passing a load test says nothing about correctness. They are orthogonal.

Testing types the architecture does not have. Contract testing between two services deployed together as one unit adds ceremony without value. Match the types to your actual coupling.

Frequently asked questions about API testing types

What are the main types of API testing? Nine distinct types: smoke, functional, integration, contract, regression, load and performance, security, fuzz, and end-to-end testing — each catching a different failure class.

What is the difference between functional and integration testing for APIs? Functional testing verifies one endpoint's behavior in isolation, typically with mocked dependencies. Integration testing verifies the API against its real dependencies — a database, a queue, a downstream service.

Is contract testing a type of functional testing? Related but distinct — functional testing checks business logic correctness; contract testing checks that the API's shape matches what consumers expect, independent of whether the logic behind it is correct.

Do I need to run all 9 types on every build? No. Smoke, functional, and basic security tests belong on every pull request. Load, fuzz, and deeper security testing are usually gated to a schedule or pre-release.

What is fuzz testing and why does it matter for APIs? Sending random or malformed input to find crashes and undefined behavior that deliberately-written negative test cases don't anticipate — it catches the failure modes nobody thought to write a specific test for.

Which type of API testing should a team start with? Functional testing first, since it catches the most common bugs and is the foundation the others build on — then smoke, security, contract, and load testing as the API matures.

Sources and further reading

Key takeaways

  • No single type is "API testing" on its own — a mature suite runs several, gated to how long each takes.
  • Functional and integration testing answer different questions — isolated correctness vs. correctness against real dependencies.
  • Contract testing catches breakage functional testing can't — a service can be functionally perfect and still break a consumer.
  • Security testing is consistently under-invested relative to functional testing, despite causing a disproportionate share of real incidents.
  • Fuzz testing finds the failure modes nobody thought to write a test case for — it's a complement to negative testing, not a replacement.
  • E2E testing should cover a small number of critical journeys, not be the primary coverage mechanism — push coverage down into API-level functional tests wherever possible.

Cover More of These Types Automatically

Hand-writing functional, negative, boundary, and security test cases across all nine types scales linearly with your API's size. Total Shift Left generates functional, negative, and boundary test cases directly from your OpenAPI spec — covering the functional, regression, and much of the security testing surface automatically, regenerated every time your spec changes.

Start your free trial to see generated coverage for your own API, or see plans and pricing if you're already evaluating.

Ready to shift left with your API testing?

Try our no-code API test automation platform free.