Credit first: the Platzi Fake Store API (api.escuelajs.co) is one of the most real fake APIs on the internet. Built by Platzi for their courses, it's a genuine relational backend: REST and GraphQL over the same data, JWT auth with working access and refresh tokens, a file-upload endpoint, filters (?title=, ?price_min=&price_max=, ?categoryId=) โ and, unlike JSONPlaceholder or FakeStoreAPI, writes actually persist. All of it keyless and free. That's why it's in so many React and e-commerce tutorials.
The catch is the flip side of that realness: it's one shared, world-writable database for the whole internet. Everything below was verified hands-on with curl on September 4, 2026:
DELETE /products/1 and 404 your demo. Minutes after a fresh reseed, product 1's updatedAt had already been changed by someone. If a course screenshot shows different data than your screen, this is why.creationAt timestamp from less than fifteen minutes earlier โ the whole database had just been rebuilt. Anything you create is ephemeral, on a schedule you don't control.images. A PUT /products/:id with the docs' own example body ({"title":โฆ,"price":โฆ}) answers {"statusCode":500,"message":"Internal server error"}. Include an images array and the same request succeeds.GET /products/99999 returns HTTP 400 and a TypeORM EntityNotFoundError body (internal query included). Any if (res.status === 404) handling in your app misses it./users is public โ including the password field. GET /users lists every account anyone has created, passwords in plain text. Fine for fake data; never type anything real into it.Rebuild the products/categories shape as your own isolated project โ every command below ran against production before this page was published. No signup:
P=$(curl -s -X POST https://mockbird.mockbird.workers.dev/api/projects \
-H 'content-type: application/json' -d '{"name":"my-store","blank":true}')
ID=$(echo "$P" | grep -o '"id": *"[^"]*"' | head -1 | cut -d'"' -f4)
KEY=$(echo "$P" | grep -o '"adminKey": *"[^"]*"' | cut -d'"' -f4)
curl -s -X POST "https://mockbird.mockbird.workers.dev/api/projects/$ID/resources" \
-H "x-admin-key: $KEY" -H 'content-type: application/json' -d '{
"name":"categories","seed":20,"fields":[
{"name":"name","type":"category"},{"name":"image","type":"image"}]}'
curl -s -X POST "https://mockbird.mockbird.workers.dev/api/projects/$ID/resources" \
-H "x-admin-key: $KEY" -H 'content-type: application/json' -d '{
"name":"products","seed":20,"fields":[
{"name":"title","type":"title"},{"name":"price","type":"price"},
{"name":"description","type":"paragraph"},{"name":"image","type":"image"},
{"name":"categoryId","type":"refId"}]}'
(The categoryId naming is what powers the nested routes and joins below. Prefer clicking? One-click e-commerce preset gives you products/orders/customers/reviews instantly.)
curl 'https://mockbird.mockbird.workers.dev/m/<ID>/products?page=1&limit=10' # their offset/limit, 1-based
curl 'https://mockbird.mockbird.workers.dev/m/<ID>/products?price_gte=100&price_lte=500' # their price_min/price_max
curl 'https://mockbird.mockbird.workers.dev/m/<ID>/products?title_like=chair' # their ?title= substring filter
curl 'https://mockbird.mockbird.workers.dev/m/<ID>/products?categoryId=3&_expand=category'
curl 'https://mockbird.mockbird.workers.dev/m/<ID>/categories/3/products' # their /categories/:id/products
curl -X POST 'https://mockbird.mockbird.workers.dev/m/<ID>/products' \
-H 'content-type: application/json' \
-d '{"title":"Handmade Chair","price":149.5,"description":"solid oak","categoryId":3}'
# โ {"id":21} โ persists, and ONLY in your project. Nobody else can touch it.
curl -X PATCH 'https://mockbird.mockbird.workers.dev/m/<ID>/products/21' \
-H 'content-type: application/json' -d '{"price":99.5}'
# โ partial update just works โ no images array required, no 500
curl 'https://mockbird.mockbird.workers.dev/m/<ID>/products/999' # โ a proper 404, not a 400 + ORM dump
GraphQL rides along on the same records (theirs is real too โ credit where due; ours adds mutations on the same data as REST):
curl -X POST 'https://mockbird.mockbird.workers.dev/m/<ID>/graphql' \
-H 'content-type: application/json' \
-d '{"query":"{ products(limit:2, sortBy:\"price\", order:\"desc\") { id title price category { name } } }"}'
And the JWT login flow their auth tutorials use works here without a shared user table โ any email/password pair answers a real signed JWT, and if you add a users resource, logins match those records (mock-auth guide). Passwords are never stored in responses, and your users aren't listed on a public URL.
| On api.escuelajs.co | On Mockbird |
|---|---|
GET /api/v1/products?offset=20&limit=10 | GET /m/<id>/products?page=3&limit=10 (page-based, 1-indexed) |
?title=shirt (substring) | ?title_like=shirt โ same semantics |
?price_min=100&price_max=500 | ?price_gte=100&price_lte=500 (each also works alone) |
?categoryId=1 | ?categoryId=1 โ identical; add &_expand=category for the joined object |
GET /categories/:id/products | GET /m/<id>/categories/:id/products โ identical nested route |
| Writes persist โ for everyone at once | writes persist in your project only |
PUT 500s without images | PUT replaces, PATCH merges โ no required fields |
| Missing id โ HTTP 400 + TypeORM error dump | proper 404 JSON |
| Shared JWT auth (users public, passwords listed) | per-project mock JWT auth, password fields stripped |
GraphQL at /graphql | GraphQL per project, queries + mutations |
| Error testing: none | ?mock_status=503, ?mock_delay=2000, chaos injection |
| Platzi Fake Store API | Mockbird | |
|---|---|---|
| First request | keyless curl | keyless curl |
| Writes | real โ into one database shared by every user on the internet | real โ into your own project |
| Data survives | until the next reset (unannounced; full reseed observed mid-test) | persists; snapshots to save/restore states on purpose |
| Other people's interference | anyone can rename/delete anything, including the seed data | impossible โ isolated per project |
| Auth | real JWT + refresh tokens (genuinely good for auth tutorials) | mock JWT per project, any credentials, expiry configurable |
| Schema | fixed: products / categories / users (+ file upload โ ours has no equivalent) | any collections, any typed fields, custom routes |
| Product images | placeholder images in the seed data (placehold.co) as of Sep 2026 | picsum/dicebear-style generated URLs, or bring your own |
| Failure simulation | โ | status/delay/chaos per request |
| Exports | โ | OpenAPI, Postman, TypeScript/Zod, db.json eject |
Where Platzi's API wins, plainly: it's free, keyless, open about what it is, and its auth flow โ real access + refresh tokens against known seed users โ is the best free way to follow a JWT tutorial without standing anything up. Its file-upload endpoint has no Mockbird equivalent. If you're doing a read-only product grid and don't mind the occasional stranger-renamed product, it's fine. This page is for the moment your writes need to survive, your demo needs to not depend on the whole internet behaving, or your error-handling needs a real 404.
curl 'https://mockbird.mockbird.workers.dev/m/demo/products?limit=2&sortBy=price&order=desc'
curl -X POST https://mockbird.mockbird.workers.dev/m/demo/products \
-H 'content-type: application/json' -d '{"name":"Test product","price":9.99}'
# โ it persists โ GET it back by the id you received.
This page is written by the Mockbird maker โ bias disclosed. Platzi Fake Store API facts verified hands-on with curl on September 4, 2026: the world-visible POST (we created a clearly-labeled test product and deleted it ourselves), the uniform creationAt timestamps minutes after a reseed, the PUT-without-images โ 500 (and with โ 200), the missing-id โ HTTP 400 EntityNotFoundError body, the plaintext password fields on GET /users, the working john@mail.com/changeme JWT login, and the live GraphQL endpoint. We touched no one else's records. Their filters/params are from their documentation and confirmed live. Every Mockbird command on this page was run against production before publishing (scratch project deleted after). Anonymous projects have a per-IP daily creation cap; sign up (free) to keep projects permanently. Current status of this and 50+ other free dev APIs: /status.
Full API reference in the docs. More guides: FakeStoreAPI alternative ยท DummyJSON alternative ยท JSONPlaceholder alternative ยท GoRest alternative. Create your API โ