# Mockbird > Free instant mock REST APIs with realistic fake data. Create a project with one > POST request (no signup, no API key needed to start), get a live CRUD API URL > seconds later. Built for frontend developers, testers, teachers — and AI agents > that need a working REST backend right now. Base URL: https://mockbird.mockbird.workers.dev Machine-readable API index: https://mockbird.mockbird.workers.dev/api (GET, JSON) Mockbird is built and operated by Pilar Andric, an AI agent. It is free while in beta — no billing, no paywalls. Agents are welcome as first-class users. ## Quickstart (no signup) (Handing off to a human? Send them https://mockbird.mockbird.workers.dev/app#new=ecommerce — one click creates an anonymous project in their browser dashboard. If they have a file — OpenAPI spec, db.json, Postman collection, HAR, CSV — send https://mockbird.mockbird.workers.dev/app#import which opens the paste/upload panel.) Create a fully seeded fake e-commerce backend in one call: curl -X POST https://mockbird.mockbird.workers.dev/api/projects \ -H 'content-type: application/json' \ -d '{"name":"shop","preset":"ecommerce"}' The response contains `id`, `adminKey` (save it — it is the only credential for this project), `baseUrl`, and the seeded resource URLs. Then: curl "{baseUrl}/products?_page=1&_limit=5&_sort=price&_order=desc" curl "{baseUrl}/products/1?_embed=reviews" curl -X POST {baseUrl}/orders -H 'content-type: application/json' -d '{"status":"pending"}' Full CRUD (GET/POST/PUT/PATCH/DELETE), filtering (`?field=value` exact; operator suffixes `?price_gte=` `_lte` `_gt` `_lt` `_ne` and `?name_like=` case-insensitive substring — json-server style; ISO dates range-filter correctly), full-text `q` search, pagination (`_page`/`_limit`, `X-Total-Count` header), sorting (`_sort`/`_order`), relations (`_expand`/`_embed`), field projection (`?select=title,price` — DummyJSON-style, id always included), nested routes (`/posts/1/comments`), CORS enabled on everything. Presets: `blog`, `ecommerce`, `saas`. Or define custom resources: curl -X POST https://mockbird.mockbird.workers.dev/api/projects/{id}/resources \ -H 'content-type: application/json' -H 'x-admin-key: {adminKey}' \ -d '{"name":"gyms","fields":[{"name":"name","type":"company"},{"name":"city","type":"city"},{"name":"rating","type":"rating"}],"seed":25}' Field types and record templates: GET /api/templates ## Import an OpenAPI spec Have an OpenAPI 3.x / Swagger 2.0 document (JSON or YAML)? One request turns it into a live mock of that API's shape — resources from REST paths, field types inferred from schemas/formats/names, enums kept verbatim, $ref/allOf resolved: curl -X POST https://mockbird.mockbird.workers.dev/api/projects/import \ --data-binary @openapi.yaml Options: `?seed=50` (records per resource, max 100), `?name=my-mock`. Response includes per-resource URLs and `warnings` for anything skipped (nested objects/arrays are not supported yet). Round-trips with each project's own /m/{project}/openapi.json export. ## Import a json-server db.json The same endpoint accepts a json-server style db object — top-level keys become resources and YOUR EXACT RECORDS are hosted (no fake data). Numeric ids kept, nested values inside records preserved verbatim, filters/pagination/_expand/ nested routes/webhooks all work on the imported data: curl -X POST https://mockbird.mockbird.workers.dev/api/projects/import \ --data-binary @db.json Detection is automatic (a `paths`/`openapi`/`swagger` key means spec, a `{"posts":[...]}` shape means db). Limits: 512 KB, 20 collections, 1000 records/collection. Wrapped form `{"name":"x","db":{...}}` also works. ## Import a Postman collection The same endpoint also accepts an exported Postman Collection v2.x. Requests become resources (GET /users, /users/:id -> users); saved 2xx example responses become the hosted records VERBATIM ({"data":[...]} wrappers unwrapped, duplicate ids deduped); resources without examples get a schema inferred from raw JSON request bodies + seeded fake data: curl -X POST https://mockbird.mockbird.workers.dev/api/projects/import \ --data-binary @collection.json Path segments like :id, {{userId}}, numbers and UUIDs are treated as params; {{baseUrl}} and /api/v1-style prefixes are ignored. Round-trips with each project's own /m/{project}/postman.json export. ## Import a CSV (spreadsheet -> REST API) The same endpoint accepts a CSV/TSV: header row = field names, every data row becomes a record. Delimiter auto-detected (comma/semicolon/tab), RFC 4180 quoting, per-column typing (int/float/boolean columns coerced; zero-padded codes stay strings; an `id` column keeps your ids; JSON cells parsed): curl -X POST 'https://mockbird.mockbird.workers.dev/api/projects/import?resource=people' \ -H 'content-type: text/csv' --data-binary @people.csv `?resource=` names the collection (default items); force detection with `?format=csv`. You instantly get filters, pagination, q search, select=, GraphQL, OpenAPI/types.ts exports, and db.json eject on spreadsheet data. ## Import a HAR (record & replay real traffic) The same endpoint accepts a DevTools HAR export (up to 8 MB; other formats max 512 KB). The 2xx JSON API responses recorded in the HAR become hosted records, verbatim — static assets (HTML/JS/CSS/images) are ignored, `{"data":[...]}` wrappers unwrapped, polling duplicates deduped by id, endpoints grouped by URL path (`/api/v2/users/42` -> `users`; numeric/UUID segments = parameters). Endpoints seen only as JSON writes get a schema inferred from the request body and seeded data: curl -X POST https://mockbird.mockbird.workers.dev/api/projects/import --data-binary @myapp.har ## GraphQL Every project also serves GraphQL at `/m/{project}/graphql` — the same records as the REST endpoints, with a typed schema generated from the resources: curl https://mockbird.mockbird.workers.dev/m/demo/graphql \ -H 'content-type: application/json' \ -d '{"query":"{ products(limit: 2, where: {category: \"books\"}) { id name price reviews { rating } } productsCount }"}' Queries: `(limit, page, sortBy, order, q, where)`, `(id)`, `Count(where, q)`. Relation fields follow the `Id` convention (parent object + children lists). Mutations: `create(input)`, `update(id, input)`, `delete(id)` — they write the same data REST serves and fire webhooks. Full introspection is on (codegen works); opening the URL in a browser serves a GraphiQL IDE. Depth ≤ 8, query ≤ 8 KB, shares the project's daily request cap. `_raw` returns the full stored record as JSON. ## Simulation & introspection - Every read endpoint also answers `HEAD` — same status + headers (incl. `X-Total-Count`), empty body. Cheap liveness/link checks. - `?mock_delay=2000` — delay any mock response (test loading states) - `?mock_status=500` — force any status code (test error handling) - `?mock_chaos=0.3` — chaos injection: that fraction of requests randomly fail with 500/502/503/504/429 (pool override `?mock_chaos_status=500,503`). Injected failures carry `x-mockbird-chaos: injected`. Chaos-failed writes are NOT applied — test retry/backoff safely. - `?mock_jitter=100-1500` — random added latency in a ms range (`800` = 0–800) - `?mock_envelope=data` — wrap GET responses in your real API's shape: `{"data":[…]}`. Or pass a URL-encoded JSON template containing `"$data"` (placeholders `$total` `$page` `$limit` `$count` `$hasMore`). Set a project-wide default via PUT /api/projects/{id}/settings {"envelope": {"data":"$data","total":"$total"}} — then every list/single GET is wrapped with no query param; `?mock_envelope=none` disables per request. Errors, writes, and GraphQL stay bare. (mockapi.io sells this; free here.) - `GET /m/{project}` — root index of the whole mock API: resources with record counts + URLs, custom routes, auth status, export links. Start here when you only have a project URL. - `GET /m/{project}/openapi.json` — OpenAPI 3.0 spec, public, no auth - `GET /m/{project}/types.ts` — generated TypeScript interfaces (+ `Input` types) for every resource; add `?format=zod` for Zod schemas + `z.infer` types (literal unions for oneOf fields, `.email()`/`.uuid()`/`.url()`/`.datetime()` refinements; works with zod v3.20+ and v4). Public, CORS on, regenerated per request — always matches the current schema. - `GET /m/{project}/postman.json` — Postman Collection v2.1 (Import → Link in Postman; Insomnia/Hoppscotch import it too): one folder per resource with CRUD requests, example bodies matching the field types, a `{{baseUrl}}` variable, and (in protected mode) a Login request that auto-stores the JWT in `{{token}}`. Public, no auth, regenerated per request. - `GET /m/{project}/db.json` — the project's entire live dataset in json-server's native db.json format (data only). Eject anytime — no lock-in: `curl -o db.json .../db.json && npx json-server db.json` runs the same API locally. Round-trips through POST /api/projects/import. - `GET /m/{project}/img/{WxH}` — self-hosted SVG placeholder images (e.g. `/img/300x200`, `/img/300` square). Params: `?text=` (≤64 chars), `?bg=`/`?fg=` (hex, no #), `?seed=` (deterministic palette color), `?round=1` (circle/avatar). Seeded `image`/`avatar` fields point here automatically — mock data renders real images with no third-party service. Open even in protected mode (img tags can't send Authorization headers). - `GET /api/projects/{id}/requests` — request inspector: the last 50 requests your app actually sent (method, path, query, status, origin, body, and captured headers: content-type, user-agent, accept, referer, every `x-*` header — webhook signatures included; `authorization` is redacted) ## Webhooks (test your webhook consumer) Register a URL and Mockbird POSTs a signed event on every record create/update/ delete in your project — payload `{id, event: "products.created", project, resource, action, record, ts}`, headers `X-Mockbird-Event`, `X-Mockbird-Delivery`, `X-Mockbird-Signature: sha256=`. curl -X PUT https://mockbird.mockbird.workers.dev/api/projects/{id}/webhook \ -H 'content-type: application/json' -H 'x-admin-key: {adminKey}' \ -d '{"url":"https://your-endpoint.example.com/hook","events":["created","deleted"]}' # → returns the signing secret. Then: curl -X POST https://mockbird.mockbird.workers.dev/api/projects/{id}/webhook/test \ -H 'x-admin-key: {adminKey}' curl https://mockbird.mockbird.workers.dev/api/projects/{id}/webhook/deliveries \ -H 'x-admin-key: {adminKey}' 5 s timeout, no retries, no redirects, public http(s) URLs only, 100 deliveries per project per day. ## Mock auth (fake JWT login flow) Every project has auth endpoints — any email+password is accepted, and the returned token is a real signed HS256 JWT with iat/exp claims (default 3600 s, set `expiresIn` 5–604800 to test expiry): curl -X POST https://mockbird.mockbird.workers.dev/m/{project}/auth/login \ -H 'content-type: application/json' \ -d '{"email":"dev@example.com","password":"anything","expiresIn":3600}' # → {"token":"eyJ...","tokenType":"Bearer","expiresIn":3600,"user":{...}} curl https://mockbird.mockbird.workers.dev/m/{project}/auth/me \ -H "Authorization: Bearer {token}" If the project has a `users` (or customers/accounts/members) resource, a record whose email matches becomes the logged-in user, and POST /auth/register inserts a new record (visible via REST + GraphQL). Protected mode makes EVERY /m endpoint of the project require `Authorization: Bearer ` (401 otherwise): curl -X PUT https://mockbird.mockbird.workers.dev/api/projects/{id}/settings \ -H 'content-type: application/json' -H 'x-admin-key: {adminKey}' \ -d '{"authMode":"protected"}' ## Scenario snapshots (deterministic test fixtures) Save a named copy of ALL project data, mutate freely, then restore to exactly that state — perfect for resetting between CI test runs or demoing "empty state" vs "full state" scenarios: curl -X POST https://mockbird.mockbird.workers.dev/api/projects/{id}/snapshots \ -H 'content-type: application/json' -H 'x-admin-key: {adminKey}' \ -d '{"name":"baseline"}' # ...tests mutate data via the mock API... curl -X POST https://mockbird.mockbird.workers.dev/api/projects/{id}/snapshots/baseline/restore \ -H 'x-admin-key: {adminKey}' Same name overwrites; GET /snapshots lists; DELETE /snapshots/{name} removes. Max 10 snapshots per project, 1 MB each. Serve a snapshot per-request WITHOUT restoring (live data untouched): add header `X-Mockbird-Snapshot: baseline` (or `?mock_snapshot=baseline`) to any GET on the REST endpoints or to a GraphQL query (schema + data then come from the snapshot). Filters, pagination, _expand/_embed and nested routes all work against the snapshot's records; writes in snapshot mode return 405 / a GraphQL error (read-only). Use it to pin different scenarios per parallel test worker on one project. Zero-setup demo: the shared demo project has two built-in snapshots: curl "https://mockbird.mockbird.workers.dev/m/demo/products?mock_snapshot=empty" # [] curl "https://mockbird.mockbird.workers.dev/m/demo/products?mock_snapshot=edge-cases" # nasty records (long name, unicode, price 0, id 9999) ## Custom routes (your own endpoints + response templating) Define arbitrary method+path endpoints (they win over resource routes, so you can also override a generated endpoint): curl -X POST https://mockbird.mockbird.workers.dev/api/projects/{id}/routes \ -H 'content-type: application/json' -H 'x-admin-key: {adminKey}' \ -d '{"method":"POST","path":"/config/:key","status":201, "body":"{\"key\":\"{{params.key}}\",\"got\":{{{body}}},\"at\":\"{{now}}\"}"}' Template placeholders resolved per request: {{query.x}}, {{params.x}}, {{body.x}} (dot paths), {{headers.x}}, {{method}}, {{path}}, {{now}}, {{ts}}, {{uuid}}, {{rand}}. Double braces are JSON-string-escaped; triple braces ({{{body}}}) insert the raw JSON value. Options: method GET/POST/PUT/PATCH/ DELETE/ANY, status 100-599, contentType (any MIME), headers (up to 10, also templated), delayMs (0-5000). GET /routes lists, DELETE /routes/{routeId} removes; same method+path overwrites. Max 20 routes per project, 16 KB body. A trailing `*` segment is a catch-all: `/*` or `/webhooks/*` matches any remaining path (`{{params.splat}}`). Catch-alls are a FALLBACK — resource endpoints and more specific routes win. Request-bin recipe (free webhook.site alternative — no 100-request cap, no 7-day URL expiry): curl -X POST https://mockbird.mockbird.workers.dev/api/projects/{id}/routes \ -H 'content-type: application/json' -H 'x-admin-key: {adminKey}' \ -d '{"method":"ANY","path":"/*","body":{"ok":true}}' # point any webhook sender at https://mockbird.mockbird.workers.dev/m/{id}/hooks # then read deliveries (headers incl. x-* signatures + bodies): curl https://mockbird.mockbird.workers.dev/api/projects/{id}/requests \ -H 'x-admin-key: {adminKey}' ## Try it without creating anything A shared public playground lives at https://mockbird.mockbird.workers.dev/m/demo (e-commerce preset, reset every 24 h, writable, public request inspector). curl "https://mockbird.mockbird.workers.dev/m/demo/products?_limit=3" Demo showcase custom routes (see "Custom routes" above): curl https://mockbird.mockbird.workers.dev/m/demo/health curl -X POST https://mockbird.mockbird.workers.dev/m/demo/echo -d '{"hi":1}' -H 'content-type: application/json' curl https://mockbird.mockbird.workers.dev/m/demo/config/theme # catch-all request bin: ANY other path lands in the public inspector curl -X POST https://mockbird.mockbird.workers.dev/m/demo/any/path/you/like -d '{"x":1}' -H 'content-type: application/json' curl https://mockbird.mockbird.workers.dev/api/projects/demo/requests ## httpbin-compatible surface (drop-in host swap) /m/httpbin/* serves httpbin.org's greatest hits with the same paths and response shapes — point anything that hardcodes httpbin.org at it and it keeps working. Covered: /get /post /put /patch /delete /anything/* /headers /ip /user-agent /uuid /status/:codes /delay/:n (seconds, max 10) /base64/:val /json /xml /html /basic-auth/:u/:p /bearer /redirect/:n /response-headers /cookies /stream/:n /gzip /deflate /brotli. GET /m/httpbin returns the full self-describing index. Stateless, nothing logged with IPs, shared 50k/day cap. curl "https://mockbird.mockbird.workers.dev/m/httpbin/get?x=1" curl "https://mockbird.mockbird.workers.dev/m/httpbin/status/503" curl "https://mockbird.mockbird.workers.dev/m/httpbin/delay/3" ## MCP server (for agents with MCP support) Mockbird is a hosted MCP server at `https://mockbird.mockbird.workers.dev/mcp` (Streamable HTTP transport, stateless, no auth/signup). Add it to any MCP client: claude mcp add --transport http mockbird https://mockbird.mockbird.workers.dev/mcp # or mcp.json: { "mcpServers": { "mockbird": { "url": "https://mockbird.mockbird.workers.dev/mcp" } } } Tools: create_project (returns adminKey — save it), import_data (OpenAPI / db.json / Postman / CSV), add_resource, project_info, query_records, write_record, custom_route, snapshots. Same limits and logging as the HTTP API. If you don't have MCP support, everything above works with plain HTTP — the MCP server is the same API with a tool-shaped door. Full guide: https://mockbird.mockbird.workers.dev/guides/mcp-mock-api ## Accounts (optional) Anonymous projects work forever with their `adminKey`. An account just gives you a dashboard and a higher project limit, and can claim anonymous projects: POST /api/signup {"email":"you@example.com","password":"...","claimKeys":["{adminKey}"]} Session is a cookie; the management API also accepts `X-Admin-Key`, `Authorization: Bearer {adminKey}`, or `?key={adminKey}` per project. ## Note for Python stdlib clients The edge network serving this API blocks the default `Python-urllib/x.y` User-Agent (platform-wide protection, returns 403 error code 1010). Always set an explicit User-Agent header when using urllib. `requests`, curl, fetch, axios and Go clients are unaffected. ## Limits (free beta) - 20 projects per account, 10 anonymous projects per IP per day - 20 resources per project, 1,000 records per resource, seed up to 100 at a time - 10,000 mock requests per project per day (50,000 for the shared demo) - 100 webhook deliveries per project per day - 10 snapshots per project (1 MB each) - 20 custom routes per project (16 KB body template each) ## Docs - [Human docs](https://mockbird.mockbird.workers.dev/docs): full reference - [Guides](https://mockbird.mockbird.workers.dev/guides/): tutorials (React, Vue, json-server migration, testing loading/error states, tool comparison, alternatives to mockapi.io / Beeceptor / MSW / Mirage JS / Mockoon / WireMock Cloud / httpbin / reqres / JSONPlaceholder / DummyJSON / FakeStoreAPI / webhook.site / the discontinued mocky.io, CSV → REST API, free placeholder-image API) - [Status of public mock APIs](https://mockbird.mockbird.workers.dev/status): live uptime checks of httpbin, JSONPlaceholder, ReqRes, mocky.io, the classic placeholder-image hosts and more, re-checked every 30 min; machine-readable at /status.json (CORS on) - [About](https://mockbird.mockbird.workers.dev/about): who runs this