WeWeb's REST API plugin is how a WeWeb app talks to any backend that isn't one of the native integrations β and it comes with a wall their docs state plainly: "WeWeb's REST API plugin only accepts HTTPS requests." Their debugging section lists trying to make an http request as the number-one reason API calls fail. Combine that with the editor being a cloud app running in your browser against WeWeb's servers, and the standard frontend-dev move β json-server on http://localhost:3000 β is unreachable twice over: no HTTPS, and no route from their cloud to your laptop.
So while the backend team is still arguing about the schema, your collections need a real HTTPS URL that returns real JSON. That's exactly what a hosted, stateful mock is. The plugin itself is available regardless of plan β WeWeb's 2023 pricing update made plugins unlimited on all plans, free included. Every curl below was verified against production before publishing.
The public demo project is a seeded e-commerce API over HTTPS. In WeWeb: Data tab β New β REST API (add the plugin first if you haven't), then configure the call like you would in Postman:
| Field | Value |
|---|---|
| Method | GET |
| URL | https://mockbird.mockbird.workers.dev/m/demo/products?limit=20 |
| Result key | (leave empty β the response is already a bare array) |
curl 'https://mockbird.mockbird.workers.dev/m/demo/products?limit=3'
# β [ {"id":1, "name":"β¦", "description":"β¦", "price":358.76,
# "image":"β¦", "category":"β¦", "inStock":true, "rating":4.6}, β¦ ]
Fetch the collection and bind it: drop a Collection List, bind its items to the collection, and bind each row's text/image elements to item.name, item.price, item.image. Every field in every seeded record carries a type-correct value (field types), so bindings never hit the missing-optional-field problem while you're designing.
WeWeb's docs teach the Result key field with their Rick & Morty tutorial API, which nests the records you want inside a wrapper object. Real APIs do this constantly β and you can rehearse it on the mock by asking for any envelope shape with ?mock_envelope:
curl 'https://mockbird.mockbird.workers.dev/m/demo/customers?mock_envelope=data&limit=2'
# β {"data":[ {"id":1,"firstName":"β¦","lastName":"β¦","email":"β¦","phone":"β¦"}, {β¦} ]}
Set Result key to data and the collection contains just the records β the exact move their docs describe for the results object. When your real API's wrapper is decided, mirror it here and your bindings are already correct.
The Rick & Morty response WeWeb's docs use has two parts: an info object "that we could use to setup backend pagination", and results. A custom envelope template reproduces that exact architecture on top of live, pageable data:
# template: {"info":{"count":"$total","page":"$page","hasMore":"$hasMore"},"results":"$data"} (URL-encoded)
curl 'https://mockbird.mockbird.workers.dev/m/demo/customers?_page=1&_limit=3&mock_envelope=%7B%22info%22%3A%7B%22count%22%3A%22%24total%22%2C%22page%22%3A%22%24page%22%2C%22hasMore%22%3A%22%24hasMore%22%7D%2C%22results%22%3A%22%24data%22%7D'
# β {"info":{"count":20, "page":1, "hasMore":true}, "results":[ β¦3 customersβ¦ ]}
Bind a page-number variable into _page=, keep results as the Result key or bind both parts, and "Page X of Y" plus a disabled next-button come straight from info. Prefer headers? Plain paginated calls also send X-Total-Count:
curl -si 'https://mockbird.mockbird.workers.dev/m/demo/products?_page=2&_limit=5' | grep -i x-total-count
# x-total-count: 30 (body: records 6β10)
A project-wide default envelope (set once in settings) keeps the long URL param out of your WeWeb configuration entirely.
WeWeb collections offer frontend filtering and sorting β fine for small sets, but your real API will do this server-side, and the query-string wiring is worth rehearsing. Bind WeWeb variables (a search input, a category dropdown, a sort selector) straight into the URL:
curl 'https://mockbird.mockbird.workers.dev/m/demo/products?sortBy=price&order=desc&limit=2' # highest price first
curl 'https://mockbird.mockbird.workers.dev/m/demo/products?category=toys&limit=3' # exact-match field filter
curl 'https://mockbird.mockbird.workers.dev/m/demo/products?q=chair' # free-text search
Range operators (price_gte=100), substring matches (name_like=β¦), and the rest of the query toolkit work on every collection.
Once the plugin is added you also get the REST API Request workflow action β WeWeb's docs demo it with a POST. Against a read-only tutorial API a POST teaches you nothing; against the mock, the record is really there for the next fetch:
curl -X POST 'https://mockbird.mockbird.workers.dev/m/demo/products' \
-H 'content-type: application/json' \
-d '{"name":"WeWeb guide test","price":12.5}'
# β {"id":31, "name":"WeWeb guide test", "price":12.5}
curl 'https://mockbird.mockbird.workers.dev/m/demo/products/31' # really persisted
curl -X DELETE 'https://mockbird.mockbird.workers.dev/m/demo/products/31'
Wire the full loop: submit-form workflow β REST API Request (POST, body fields bound to inputs) β refetch the collection on success β the new row renders. PUT/PATCH/DELETE complete the CRUD story. The demo dataset resets every 24 hours, so experiments clean themselves up.
Workflows can branch on a failed request β but you can't design the error toast, the retry button, or the empty-state fallback against an API that never fails. One URL param:
https://mockbird.mockbird.workers.dev/m/demo/products?mock_status=500
Run the workflow: the error branch executes and your failure UI shows for the screenshot. Remove the param and the same call is green. For "fails twice then recovers" β what a retry action should survive β use a deterministic sequence:
# 1st request β 503, 2nd β 503, 3rd and later β real 200
'https://mockbird.mockbird.workers.dev/m/demo/products?mock_seq=503,503,200&mock_seq_key=myapp'
# run four times: 503 503 200 200
curl -s -o /dev/null -w '%{time_total}\n' \
'https://mockbird.mockbird.workers.dev/m/demo/products/1?mock_delay=3000'
# 3.76s
Collections expose fetching state you can bind skeletons and spinners to β but on a fast connection the state is gone before you can see whether it looks right. ?mock_delay=3000 (up to 5,000 ms) holds it open long enough to design.
WeWeb makes API calls client-side and offers a "Proxy the request to bypass CORS issues" option for APIs that reject browser requests β with a documented warning that the proxy still exposes everything to the client and isn't a way to hide private keys. Mockbird sends permissive CORS headers on every endpoint, so calls work directly from the editor, the published app, and curl, with the proxy off β one less checkbox in play when something fails, and no temptation to put a real secret where their docs say it doesn't belong.
Their docs' Headers section covers APIs that need an Authorization header. Mockbird's mock auth gives you the whole flow to build against β a login call that returns a real signed JWT for any email/password:
curl -X POST 'https://mockbird.mockbird.workers.dev/m/demo/auth/login' \
-H 'content-type: application/json' \
-d '{"email":"pat@example.com","password":"anything"}'
# β {"token":"eyJhbGciOiJIUzI1NiIsβ¦", "tokenType":"Bearer", "expiresIn":3600, "user":{β¦}}
Make login a REST API Request action, store token in a variable, and bind Authorization: Bearer <token> on your collections' headers. On your own project, protected mode makes every endpoint genuinely require the token β so the logged-out failure path is testable too.
When a workflow POST "should work" but doesn't, the question is what actually left the app after every binding resolved. Point the action at a bin:
curl -X POST 'https://mockbird.mockbird.workers.dev/m/demo/hooks/weweb-form' \
-H 'content-type: application/json' -d '{"app":"weweb-mvp","step":1}'
# β {"ok":true,"caught":"POST /hooks/weweb-form","body":{β¦},"receivedAt":"β¦"}
The demo's catch-all route echoes what it caught, and every hit β method, path, headers, body β lands in the public demo request inspector. Great for catching a number that arrived as a string, or a header binding that resolved to empty.
One curl (or one click), no signup:
curl -X POST https://mockbird.mockbird.workers.dev/api/projects \
-H "content-type: application/json" \
-d '{"preset":"ecommerce"}'
# β {"id":"abc123xyz9", "adminKey":"β¦", ...}
Presets: blog / ecommerce / saas β or define resources matching your app's data, or import an OpenAPI spec, db.json, or CSV so the mock serves your exact field names. Everything is HTTPS with open CORS β WeWeb-ready by default. Projects have a 10,000 requests/day cap; app building barely dents it.
Because the mock speaks the same shapes your real API will β same envelope (Β§3), same pagination params, same auth header β cutover is editing the base URL in your collection and action configs. If the real API's contract exists as an OpenAPI spec, import it into the mock first and build against their exact resource names; every Mockbird project also exports a live OpenAPI spec at /m/<project>/openapi.json to keep the two sides honest.
Fair's fair: if your backend is Xano, Supabase, or Airtable, WeWeb's dedicated plugins for them are deeper than generic REST β auth integration, schema awareness, realtime β and need none of this. The REST API plugin (and this guide) is for the other case: your app talks to a custom or third-party REST backend that isn't built yet, isn't safe to develop against, or won't fail on demand. And the HTTPS-only rule is a good rule β production apps shouldn't call plaintext endpoints. It just means your development mock has to live on a real URL too.
Related: the Adalo version, the Bubble version of this guide, the FlutterFlow version, the Thunkable version, the Retool version, the Appsmith version, the ToolJet version, testing loading and error states, mock JWT auth, and mocking third-party APIs generally.
Verification: all demo curls on this page (limit=3 typed list, mock_envelope=data wrap with Result-key shape, custom nested envelope returning {"info":{"count":20,"page":1,"hasMore":true},"results":[β¦]}, _page=2&_limit=5 returning records 6β10 with x-total-count: 30, sortBy/category/q filters, POSTβGET-backβDELETE with id 31, mock_status 500, seq 503β503β200β200, 3.76s measured delay, auth login token shape, bin echo, create-project preset β created and deleted) were run against production on 21 Sep 2026 before publishing. WeWeb facts β the REST API plugin's HTTPS-only requirement and its place atop their documented debugging list, the Result key field and the Rick & Morty info/results tutorial example, the REST API Request workflow action, the CORS proxy option and its not-for-private-tokens warning, and plugins being unlimited on all plans since the August 2023 pricing update β are from WeWeb's official docs and changelog as of September 2026. We don't run your WeWeb app; if a step here doesn't work, that's a bug: tell us.