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
urlby 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.
Running the node creates a real request
Unless Test Mode is on, every run, including Execute step in the editor, is a real request: with email delivery the recipient gets the invitation. Turn Test Mode on while you build the workflow. Before you publish, turn it off and change the External ID, because the old one belongs to the test request.
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.
| Way | Use it when |
|---|---|
| Wait for the Outcome | The 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 Trigger | Requests 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:
| Event | Runs when | Carries |
|---|---|---|
| Request Completed | The recipient submits the form. | The request, the outcome and every answer. |
| Request Expired | The request reaches its expiry date unanswered. | The request only. |
| Request Canceled | Someone 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/.