Your screen is too small. Please widen your browser window or use a device with a screen width of at least 300px to use this app.
Everything you need to create mock endpoints and call them from your app, no real backend required.
Fake API helps you quickly create mock APIs for developing and testing applications without needing a real backend. It's useful when you want to develop the frontend independently, test different scenarios (success, error, delay), demo an app with simulated data, or quickly experiment with an idea without setting up a server.
Each project you create gets a unique public projectId, and that id is the project's own subdomain. You define the path, JSON body, HTTP status code, and delay for each endpoint, and decide whether that body is served exactly as written or regenerated by AI on every call. The final URL format is:
https://{projectId}.fake-api.dev{your_created_path}You need an account before you can create projects and endpoints.
Enter your name, email, and password. A verification email is sent, click Verify to activate your account.
Use your email and password, or sign in instantly with Login with Google.
Select Forgot Password? on the login page and follow the email instructions to reset it.
You need to verify your email before you can use all features.
After logging in, you'll land on the Project management page, this is where all your mock APIs are organized.
On the Project page, start a new project.
Enter a Name (required) and an optional Description.
Your project appears in the list with its own public_id.
The project list shows each project's Name and its public_id, that's the projectId you'll use in mock API URLs.
The Delete all button removes every project you own and cannot be undone. Use with caution.
Endpoint groups help you organize endpoints by functionality or module, for example users, orders, or products. On desktop, groups appear in the left panel of the project page, on mobile, use the dropdown menu instead. Select a group to view and configure its endpoints.
Endpoints define how the mock API responds when it's called. Select an Endpoint Group, click Create new, and fill in:
| Method | GET, POST, PUT, PATCH, or DELETE |
| Path | Must start with /, at most 255 characters, e.g. /api/users, /api/users/1 |
| Scenario name | What this saved response stands for, up to 25 characters, e.g. Unauthorized or Empty list |
| Response body | A valid JSON object returned to the client exactly as you wrote it, key order and long numbers included, on one compact line. Up to 30000 characters, nested at most 12 levels deep, with at most 50 items in any one list |
| Delay (ms) | Simulated latency from 0 to 60000, default 0 |
| Status Code | Any code from 100 to 599, default 200. At 204 the body is empty |
| AI response variants | Off by default. When on, the ticked fields are regenerated on every call |
Example endpoint configuration:
{
"method": "GET",
"path": "/api/users/1",
"response_body": {
"id": 1,
"name": "John Doe",
"email": "johndoe@example.com"
},
"delay_ms": 500,
"status_code": 200,
"ai_enabled": true,
"ai_fields": ["name", "email"],
"ai_prompt": "keep the email domain example.com"
}One endpoint can hold several saved responses, and only one of them answers at a time. Keep a 200 beside a 401 and an admin-role body, then switch between them while you work, instead of editing the same body back and forth and losing what was there.
The method and path belong to the endpoint, so every scenario answers on the same URL. The status, body, headers, delay and AI settings belong to the scenario. You can keep up to 5 scenarios on one endpoint, or 10 on a VIP account.
https://{projectId}.fake-api.dev{path} URL, ready to paste into your code.An endpoint can answer with the same JSON every time, or with different values on every call. Tick Enable, choose which values are allowed to change, and each request comes back with a fresh version of your body. The shape stays put, only the values you picked move, so a list of users is still a list of users and your app keeps working against the same structure. Every call is different, so a screen that pages through a hundred records shows a hundred different records.
Tick Enable on the AI response variants card in the endpoint form. If you don't see the card, AI isn't switched on for this server.
The list of fields comes straight from your response body. Tick the ones you want to change, anything you leave unticked comes back exactly as you wrote it. On a list you can also tick vary count, so the list is a different length each call.
Use the projectId shown in the API Endpoint card on your project's detail page:
curl -X GET https://k7mqx4rb9dtz.fake-api.dev/api/user/1fetch('https://k7mqx4rb9dtz.fake-api.dev/api/users/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));axios.get('https://k7mqx4rb9dtz.fake-api.dev/api/users/1')
.then(response => console.log(response.data))
.catch(error => console.error('Error:', error));When you call the API, it will:
404 Not Found
No endpoint matches the requested path.
405 Method Not Allowed
The path is correct but the method doesn't match.
Your mock endpoints answer a browser from any origin, so a page on localhost can call them straight away with no setup. Responses come back as JSON and are never cached, so an edit to a body shows up on the very next call.
The Headers tab in the endpoint form is where you add anything else the response should carry. A page count next to a list is the common one, and your app reads it back the way it reads any header:
const response = await fetch('https://k7mqx4rb9dtz.fake-api.dev/api/users');
const total = response.headers.get('X-Total-Count');You can set up to 20 of them per endpoint, and setting Content-Type or Cache-Control replaces what the response would have used. A handful of names belong to Fake API itself and are refused with a message saying so, cookies among them, because those have a tab of their own below. On a redirect status such as 302, a Location is only sent when it stays on your project's own address, like /login, so a mock can never send a visitor to another site.
The Cookies tab sets real cookies on this scenario's response, so you can mock a login that hands back a session and a logout that clears it again. A cookie you set here belongs to your project's own address, k7mqx4rb9dtz.fake-api.dev, and to nothing else. You cannot aim it at another domain, so it never reaches the site you are testing from and never reaches your Fake API account.
curl, Postman and anything server-side get these cookies as they are. A browser is stricter: because the mock answers from a different address than your app, it only keeps the cookie when the call asks for it, and when the project has Send cookies and auth headers turned on under More options with at least one origin named. Without both the response still arrives and the cookie is quietly dropped:
Create a project and get a working endpoint in under a minute.
Click Save, the endpoint list updates right away with the new endpoint.
Prefix a path segment with : to turn it into a dynamic parameter that matches any value, for example /api/users/:id. That single endpoint responds to /api/users/1, /api/users/42, and any other value in that position, so you don't need a separate endpoint per id.
If both a literal path and a dynamic path could match the same request, the literal (exact) match always wins, the dynamic route is only used as a fallback when no exact match is found.
Optional, one line, for example id should be a uuid, prices from 10000 to 500000. A hint is read once and then holds for every call, so being specific pays off.
Preview shows you 3 sample responses before you save, plus a plain summary of where each field's data comes from. New samples costs nothing, so press it as often as you like.
You tick individual values, a piece of text, a number, a yes/no, or an empty value. Whatever shape your body has, there is a box for it:
A few boxes are greyed out. Hover one to see why, the reasons are:
Fields are not filled in one at a time and left to clash. Related values are worked out together, so a response reads like something a real API would have sent:
Calling the endpoint is just as fast with variants on as with them off. The first call after you enable it, or after you change the body, answers with your own response body while the endpoint works out how to vary it, and calls after that come back varied. You also get your own body back if AI cannot be reached at all, so your app never sees an error it did not ask for.
If a field is being filled with the wrong sort of data, open the summary under Preview to see how it was read, add a line to the hint, then press Redesign. The hint always wins over what was guessed from your field names.
| Fields per endpoint | Up to 50 ticked fields |
| Values at a time | Up to 150. A field inside a list counts once per item, and once per item of every inner list when the lists are nested, so this is what a deeply nested pick runs into first |
| List length | Up to 50 items, which is the limit on your response body too |
| List nesting | Lists inside lists, up to 3 deep |
| Hint length | Up to 300 characters |
Only designing costs one of your daily AI designs, which happens when you press Preview or Redesign, or when you change the body, the ticked fields, or the hint. Calling your endpoint and pressing New samples cost nothing.
| Limit | Standard | VIP |
|---|---|---|
| Projects | 5 | 10 |
| Endpoint groups per project | 10 | 20 |
| Endpoints per group | 10 | 20 |
| Scenarios per endpoint | 5 | 10 |
| AI designs per day | 30 | 120 |
The home page has a box where you can build up to 5 endpoints and call them straight away, with no sign up. Those endpoints are for a quick look: they are deleted after 24 hours, anyone holding their URL can change them, and they stay behind when you create an account. Sign in when you want mocks that are yours, organised into projects, with AI response variants.
await fetch('https://k7mqx4rb9dtz.fake-api.dev/api/login', {
method: 'POST',
credentials: 'include',
});Leave Max age empty and the cookie lasts until the browser closes. Set it to 0 and the browser deletes a cookie of that name, which is how a "logged out" scenario undoes what the "logged in" one set. HttpOnly keeps it out of document.cookie while the browser still sends it back on the next call, which is usually the thing you are testing. SameSite starts at None, the one setting that lets a cross-site call keep a cookie at all, and None always travels with Secure because no browser accepts it otherwise. You can set up to 5 cookies per scenario, and switching which scenario answers switches its cookies with it.
Create or edit a project, open its Advanced tab, and the Browser access group holds one switch. Turn it off and browsers stop being able to reach that project's endpoints, which is how you check what your app does when that happens. curl and anything server-side still get an answer, so the mock keeps working while you test.
More options under it lets you limit which origins are allowed, and once you name at least one you can let the browser send cookies along too. Most projects never need either: naming origins only changes what a browser permits, so it keeps nothing private.