Go to app

Send a request and act on its outcome

A request asks one named recipient to complete a form. Add a Create request node to a workflow, prefill the supplier's company name so they cannot change it, and then branch on what the recipient decided.

Last checked


Before you start

You need a Formstep credential in n8n and a published form. To hear back from Formstep, your n8n must be reachable from the internet over HTTPS; see Install the Formstep node in n8n. What a request is, and what it can carry, is in Creating requests.

For a full walkthrough with real payloads, read Pausing an n8n workflow until the customer confirms their details. For what the node is good for, and how it compares with n8n’s own form, see Formstep for n8n.

1. Add the Create request node

Start with the trigger that should send the request, such as a new row in a sheet or a deal marked won in your CRM. The example uses a manual trigger and an Edit Fields node named Supplier that holds supplier_id, company_name and contact_email. Click + after it, search for Formstep, and pick Create request.

2. Pick the form and the recipient

  • Form is the form the recipient completes. Pick it from the list, or switch to By ID and paste its ID. It must be published.

  • Recipient Email usually comes from the input, like {{ $json.contact_email }}. It is needed for email delivery and for reminders.

3. Prefill and lock what you already know

Once you pick the form, Values to Send lists every question you can prefill by its title and field key, like Company name (company_name). Map the answers you already have; fields left empty are not sent. With Mapping Column Mode set to Map Automatically, every input field named after a field key is sent.

Pick a question under Read-Only Field Names or IDs to lock it. Fields marked · context are the form’s hidden fields. If the form has a Documents block, Documents takes files from a binary field of the input item. What each of these does is in Prefill, locked fields and hidden fields.

4. Add the options you need

Click Add Field under Additional Fields:

  • Delivery decides who sends the link. Email the Invitation lets Formstep send the invitation and reminders, on Pro and Business. None, the default, sends no invitation: a later node sends the request’s url by Slack, SMS or your own email tool.

  • Reminders left out follows the form’s reminder schedule, and those reminders are emailed even when Delivery is None. Add Reminders and leave it empty to send none, or enter a schedule like 2d, 5d, on Pro and Business.

  • External ID is your own ID for this piece of work, like supplier-{{ $json.supplier_id }}. A later workflow can find the request by it. Running the node again with the same External ID and the same parameters returns the same request instead of a second one.

  • Test Mode creates a test request: nothing is emailed and it counts nowhere.

  • Recipient Name, Language, Expires At and Metadata are optional.

  • Callback URL sends the outcome to a URL of your own. To get the outcome back into this workflow, use Wait for the Outcome instead.

5. Run the node

Click Execute step. Formstep creates the request and returns it with its id, status pending, and url, the link for the recipient. Map {{ $json.url }} into the node that sends it.

Act on the outcome

n8n can hear about a request’s outcome in two ways. Both end in a Switch on approve, decline or changes, which needs a Decision question in the form.

WayUse it when
Wait for the OutcomeThe workflow that creates the request should carry on with the answer, holding on to everything it knew before, like the record it was working on.
Formstep TriggerRequests to the form are sent from anywhere: the dashboard, the API, an agent or another workflow. One published workflow handles all of them.

Wait for the outcome in the same workflow

Here the workflow that sends the request pauses until the recipient answers, then carries on.

1. Turn on Wait for the Outcome

In the Create request node, turn on Wait for the Outcome and leave Callback URL empty. Formstep then calls this execution back when the request ends.

Each execution waits on its own address, so an External ID reused from an earlier execution fails. Include {{ $execution.id }} in it, or leave it empty.

2. Add a Wait node

Add a Wait node right after it, with Resume set to On Webhook Call and the HTTP method left at POST. Set Limit Wait Time if you want n8n to give up on its own.

3. Branch on the event

Add a Switch after the Wait node and compare {{ $json.body.data.request.outcome }}. To tell a completed request from an expired or canceled one, compare {{ $json.body.type }} with request.completed, request.expired or request.canceled.

On request.completed, {{ $json.body.data.answers.iban }} reads the confirmed value of one answer. The part after answers. is the question’s field key, which stays the same when you retitle, translate or duplicate the question.

Run the workflow. The execution stops at the Wait node until the recipient submits, then resumes down the matching branch:

  • A run from the editor waits for a real answer too. Test Mode works here: a test request still resumes the workflow.
  • Expiry also resumes the execution, with request.expired. Set Expires At to end the wait sooner.

  • The Wait node relies on its resume address being hard to guess. If that is not enough, use the Formstep Trigger, which checks that every event comes from Formstep.

Start a workflow from the trigger

1. Pick the event

Add a Formstep Trigger, pick the credential and the form, and choose one of the request events under Event:

EventRuns whenCarries
Request CompletedThe recipient submits the form.The request, the outcome and every answer.
Request ExpiredThe request reaches its expiry date unanswered.The request only.
Request CanceledSomeone cancels the request, from the dashboard, the API or a Cancel request node, or Formstep cancels it because the form was moved to trash.The request and the cancel reason.

2. Test it with a real request

A test request never starts a request trigger, so send a real one with Delivery set to None, as in step 5, and open its link yourself. Then click Execute step and submit the form within two minutes.

The event carries a data.request object next to the answers. Its outcome is approve, decline or changes, and its externalId is the ID you set, so you can find the record the request was about.

Expired and canceled events are hard to catch with Execute step. Publish the workflow and check Executions instead.

3. Branch on the outcome

Add a Switch node with one routing rule per verdict. Each rule compares {{ $json.data.request.outcome }} with a value; turn on Rename Output to name the branch after it:

Branch on data.request.outcome. data.answers.decision is empty when the request expired or was canceled, so it cannot tell those branches apart. Compare values, never the labels in data.display, which change when you rename the option or the recipient answers in another language.

Connect a node to each branch, then Publish the workflow. From then on every completed request to the form runs it.

If nothing runs

  • A test request never starts a request trigger, whether it was created with Test Mode on or with Try it yourself.

  • The trigger listens only to the form you chose in it.
  • The workflow is not published, or its credential reaches another workspace. See the checks in the public link guide.

  • Create request fails with Formstep calls back HTTPS addresses only when your n8n hands out an http:// address. See Tell n8n its public address.

  • The Wait node never resumes when Formstep cannot reach your n8n, for example because the tunnel is down or the proxy blocks /webhook-waiting/.

Next steps