A mock API is a fake API that behaves like a real one. It accepts the same requests, returns responses in the same shape, and lives at a URL you can call, but behind that URL there is no real database, no business logic, and no real service. The response is something you defined in advance.
That sounds trivial, and the idea is. The value comes from what it lets you do: build and test against an interface before the thing behind it exists or while the real thing is too slow, too costly, or too unreliable to call. This explainer defines the term precisely, separates a mock from the things it gets confused with, and lays out the static-versus-dynamic distinction that decides how a mock behaves.
What a mock API actually is
Strip it down and a mock API is a request-to-response map. A request comes in. The mock matches it against rules you set, picks a response, and sends it back. There is no computation in between unless you ask for it.
A mock has three parts. There is the interface: the routes, methods, and parameters it accepts, which should match the real API exactly. There is the response definition: the bodies, status codes, and headers it returns. And there is the matching logic: how the mock decides which response a given request gets, from a simple path match to rules that branch on query parameters or headers.
Because the interface matches the real API, code that calls the mock does not know it is fake. Swap the base URL and the same client talks to the real service. That interchangeability is the whole point. For a hands-on walkthrough of building one, see this guide to mocking an API for testing.
It helps to be precise about what a mock API is not. It is not a cache, because a cache stores real responses and a mock invents them. It is not a sandbox, because a vendor sandbox runs real, simplified logic while a mock runs no logic at all. And it is not a staging environment, because staging is a full deployment of the real system. A mock is lighter than all three: it is just the front door of an API with predefined answers behind it, and nothing else.
Mock versus stub
People use “mock” and “stub” interchangeably, but in testing they mean different things.
A stub is the simpler idea. It returns a canned answer to a call and nothing more. Ask it for a user, it returns a fixed user. A stub has no opinion about how it was called.
A mock, in the strict testing sense, also verifies the interaction. It can assert that it was called, how many times, and with what arguments. A mock can fail your test because the call was wrong, not just supply a value.
In everyday API work the line is blurry, and “mock API” usually covers both. The useful takeaway: a stub answers, a mock answers and watches. When your test cares only about the data your code receives, a stub-style response is enough. When it cares whether your code made the right call in the right way, you want the verification a true mock adds. For the broader vocabulary, see the difference between validation and verification.
Two more terms sit nearby. A fake is a working but simplified implementation, like an in-memory database used in place of a real one; it has logic, just less of it. A spy wraps a real object and records how it was called without changing its behavior. A mock API, as the term is used in API development, is closest to a stub with optional verification, served over HTTP at a real URL. You do not need to police the vocabulary, but knowing the spectrum helps you read testing documentation without getting lost.
Mock API versus real server
A real server and a mock server can sit at the same URL and return the same JSON, so the difference is what happens behind the endpoint.
| Mock API | Real server | |
|---|---|---|
| Behind the endpoint | Predefined responses | Live logic and a database |
| Response source | Rules you wrote | Computed per request |
| Data | Fixed or generated | Real, persistent |
| Side effects | None | Writes, charges, emails |
| Speed | Fast and constant | Varies with load |
| Correctness | Matches what you defined | Matches actual behavior |
A real server tells you the truth: it runs the actual code and proves the system works. It is also slow, stateful, and capable of real side effects, so a test against it can charge a card or send an email.
A mock server tells you only what you told it. It is fast, free of side effects, and perfectly predictable, which makes it ideal for development and most testing. But a mock can be wrong and never know, because it does not run the real logic. That is why you keep some tests on the real server. The trade-off is covered in depth in mock server versus real server.
Static and dynamic mocks
A mock returns its response in one of two ways, and the choice shapes how the mock feels to use.
A static mock returns a fixed payload. You write the exact JSON once, and every matching request gets that identical body back. Static mocks are predictable, which makes them easy to assert against. Their weakness is realism: a single hardcoded payload will not surface a bug in code that breaks on long strings, empty arrays, or unexpected nulls.
A dynamic mock generates the response per request. Instead of a fixed "id": "user_1001", it produces a fresh UUID each call. Instead of one name, it returns a different realistic name every time. Dynamic mocks usually drive this with a data-generation grammar such as Faker.js, so a field named email yields an email and created_at yields a date. They are more realistic and better at exposing edge cases, at the cost of being harder to assert against exactly.
Most teams use both. Static mocks for assertion-heavy unit tests where you need one known value. Dynamic mocks for development, demos, and fuzz-style coverage where variety matters more than a fixed answer.
A dynamic mock can also be conditional, which is a step beyond simple generation. A conditional mock branches on the request: a request for /orders/404 returns a 404, a request with a bad token returns a 401, and everything else returns a normal 200. One mock endpoint then covers the happy path and several failure paths at once. This is what makes a mock genuinely useful for testing, because it can reproduce the error responses a healthy real server will not produce on demand.
Where a mock API fits in development
A mock API is useful at three points. Early on, it lets frontend and backend teams agree on a contract and build in parallel, so neither waits for the other. During testing, it isolates your code from network flakiness and lets you trigger error responses a real server will not produce on demand. And for demos and prototypes, it supplies controlled, predictable data with no live dependency to fail mid-pitch. Those scenarios are explored further in this guide to API mocking use cases.
The recurring risk is drift. A mock is a snapshot of an interface, and interfaces change. When the real API adds a field or renames one, a disconnected mock keeps serving the old shape and your tests pass against a contract that no longer exists.
The fix is to treat the mock as derived, not authored. Generate it from the same schema the real API publishes, so a contract change regenerates the mock. A mock you typed out by hand is a copy that immediately starts aging; a mock generated from the spec is always a current snapshot. The difference does not show up on day one, but it decides whether the mock is still trustworthy six months in. Apidog works this way: you design the API once, and the mock endpoint is generated from that design with realistic data inferred from field names. The mock, the documentation, and the API contract testing all read from a single source, so they stay in step. To see the design-to-mock flow end to end, Download Apidog.
Frequently asked questions
What is a mock API in simple terms?
A mock API is a fake API that imitates a real one. It exposes the same routes and returns responses in the same shape, but there is no real logic or database behind it. The responses are predefined, which lets you build and test against the interface before the real service exists.
What is the difference between a mock and a stub?
A stub returns a canned response and nothing else. A mock, in the strict testing sense, also verifies the interaction, so it can check that it was called the right number of times with the right arguments. A stub answers; a mock answers and watches.
How is a mock API different from a real server?
A mock returns predefined responses with no real computation, so it is fast, predictable, and has no side effects. A real server runs actual logic against a real database, so it is slower and stateful but proves the system truly works. Use a mock for development, and the real server for contract and end-to-end tests.
Should I use a static or a dynamic mock?
Use a static mock when you need one predictable value to assert against, which suits unit tests. Use a dynamic mock when you want realistic, varied data that catches edge cases, which suits development and demos. Many teams use both.
How do I stop a mock API from becoming inaccurate?
Generate the mock from the same schema the real API publishes rather than writing it by hand. When the contract changes, the mock regenerates. Backing it with scheduled contract tests against the real API catches any remaining drift early.
