Skip to content

A webhook API

Turn a flow into a real, bearer-secured JSON endpoint. This one accepts a POST, validates its input, branches on a field, writes a record to MongoDB, and returns a 201 with the new id — then you call it with curl and check the run in history.

What you'll build

1. Create the flow

Create a new flow file and lay out: Start → Switch → MongoDB → End. The Start node is what makes this flow reachable over HTTP.

2. Configure the Start node as a POST endpoint

Select the Start node and set:

  • Method: POST
  • Auth: Bearer, with the expected token set to ${secrets.API_TOKEN}
  • Input (body): declare the JSON your callers must send. For a sign-up:
json
{
  "type": "object",
  "properties": {
    "email": { "type": "string" },
    "plan":  { "type": "string" }
  },
  "required": ["email"]
}

Add API_TOKEN and your DB_URI to the secrets vault. The request is validated against your schema before the flow runs — a missing or mistyped field returns 400 with a list of what's wrong, and auth is checked first, so a bad token never reaches your data.

NOTE

Auth is fail-closed: if the expected token is empty or an unresolved secret, every request is rejected. See HTTP endpoints and Start & End.

The validated body becomes the flow's starting references. If your Start node is named "Start", the fields are start.email and start.plan.

3. Branch on a field (Switch node)

Configure the Switch node to route on the plan:

  • Source: start.plan
  • Cases: free → port free, pro → port pro
  • Default: the default port for anything else

Wire each port onward (they can converge back on the same MongoDB node, or you can insert into different collections per plan). For a simple yes/no test use an If node instead — it exposes true and false ports. See Switch node.

4. Insert into MongoDB

Configure the MongoDB node:

FieldValue
Connection${secrets.DB_URI}
Databaseapp
Collectionsignups
OperationinsertOne
Query{ "email": "{{start.email}}", "plan": "{{start.plan}}" }
Result variableresult

The {{start.email}} placeholders are interpolated from the request. On success, insertOne stores { "insertedId": … } under result. See MongoDB node.

5. Return a response (End node)

Select the End node and set:

  • Status code: 201
  • Response body: two fields —
    • id bound to the reference result.insertedId
    • status set to the literal "created"

The End node composes its JSON from those bindings, so the caller receives:

json
{ "id": "665f…", "status": "created" }

6. Call it with curl

Your flow is live at /api/run/<projectId>/<flow-file-slug>. The slug is your flow file's name, lower-cased and hyphenated (a file named "Signup API" → signup-api).

bash
curl -X POST https://<host>/api/run/<projectId>/signup-api \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "email": "sam@acme.com", "plan": "pro" }'

Expected responses:

SituationResponse
Valid request201 { "id": "…", "status": "created" }
Missing/invalid token401 { "ok": false, "errors": ["invalid token"] }
Body fails the schema400 { "ok": false, "errors": [ … ] }
A node throws500 with the failing node id

TIP

Add ?_trace=1 to the URL to get the full node-by-node execution trace in the response — invaluable while you're building. See Testing & the trigger URL and The Run API.

7. Check run history

Every call is recorded. Open Run history to see the request as method POST, its duration, the ports taken through the Switch, and — if anything failed — exactly which node and why.

NOTE

The run endpoint is rate-limited per IP (60 requests/minute) and returns 429 with a Retry-After header when you exceed it.

See also

FlowRunner — the no-code platform for small businesses.