# Formstep Docs — Automation guides

# Automation guides

Step-by-step setup guides for the tools that drive Formstep: connect, pick a trigger or action, map fields, test.

Start with the tool’s connect guide: every other guide for that tool assumes it is done.

## Zapier

The [Formstep app for Zapier](https://zapier.com/apps/formstep/integrations) works on every Formstep plan. Zapier shows it as **Beta**, as it does every new app for its first months. You connect it from inside a Zap; **Open in Zapier** on the workspace Integrations page opens it with ready-made Zaps.

- [Connect Formstep to Zapier](https://formstep.io/docs/guides/zapier/connect/) — Sign in to Formstep from a Zap, pick the workspace Zapier may use, and check that your forms show up.

- [Send public link submissions to another app](https://formstep.io/docs/guides/zapier/public-link-submissions/) — Start a Zap when someone submits, edits or abandons a form through its share link, and send the answers to email, Sheets, Slack or a CRM.

- [Send a request from a Zap](https://formstep.io/docs/guides/zapier/send-a-request/) — Create a Formstep request from any Zapier trigger, prefill and lock the answers you already know, send the link, then find, remind or cancel the request from a later Zap.

- [Act on a request's outcome](https://formstep.io/docs/guides/zapier/request-outcome/) — Start a Zap when a request is completed, expires or is canceled, and branch on whether the recipient approved, declined or asked for changes.

## Make

The [Formstep app for Make](https://www.make.com/en/hq/app-invitation/19b85d47851b8e2054970a52663f8290) is in beta: it is shared by invitation until Make lists it in its app directory. You connect it from inside a scenario.

- [Connect Formstep to Make](https://formstep.io/docs/guides/make/connect/) — Install the Formstep app in your Make organization, sign in from a scenario, and pick the workspace Make may use.

- [Start a scenario from public link submissions](https://formstep.io/docs/guides/make/public-link-submissions/) — Run a Make scenario when someone submits, edits or abandons a form through its share link, and map each answer by its question.

- [Send requests and act on their outcome](https://formstep.io/docs/guides/make/requests/) — Create a Formstep request from a Make scenario, prefill it per field, and run a scenario when the recipient completes it, it expires or is canceled.

## n8n

The Formstep community node runs on self-hosted n8n. It can also pause a workflow until the recipient answers. The last four guides are worked examples.

- [Install the Formstep node in n8n](https://formstep.io/docs/guides/n8n/install-the-node/) — Give a self-hosted n8n a public HTTPS address, install the n8n-nodes-formstep community node, and check that its triggers and actions show up.

- [Connect Formstep to n8n](https://formstep.io/docs/guides/n8n/connect/) — Connect n8n to one Formstep workspace with an API key, or on self-hosted n8n by signing in with OAuth2, and check that your forms show up.

- [Start an n8n workflow from public link submissions](https://formstep.io/docs/guides/n8n/public-link-submissions/) — Run an n8n workflow when someone submits, edits or abandons a form through its share link, and pass the answers to the next node.

- [Send a request and act on its outcome](https://formstep.io/docs/guides/n8n/send-a-request/) — Create a Formstep request from an n8n workflow, prefill and lock what you already know, then wait for the answer in the same workflow or start another one when a request ends.

- [Look up, remind and cancel requests in n8n](https://formstep.io/docs/guides/n8n/manage-requests/) — Find a request by your own External ID, read its status and answers, send the recipient a reminder, or cancel it, all from an n8n workflow.

- [Get a manager's approval in n8n](https://formstep.io/docs/guides/n8n/approval-from-a-manager/) — Example: send an expense claim to the manager who approves it, pause the workflow until they decide, then route each outcome and no answer.

- [Read a PDF with AI, then get it confirmed](https://formstep.io/docs/guides/n8n/read-a-pdf-with-ai/) — Example: an AI model reads a supplier invoice in n8n, a request prefilled with what it read goes to the supplier, and they confirm or correct each value.

- [Collect the documents each case needs in n8n](https://formstep.io/docs/guides/n8n/collect-documents/) — Example: build the form from an insurance claim's checklist inside the request, so each person is asked for exactly the documents their case needs, then save each upload with the claim.

- [Let an AI agent send requests from n8n](https://formstep.io/docs/guides/n8n/ai-agent-tool/) — Example: an onboarding assistant in n8n that has the Formstep node as a tool, so it can send a client a prefilled form, check how the request is going, and remind them.

## AI agents

Claude, ChatGPT, Cursor and other AI tools connect to Formstep over MCP, then build forms, send requests and read the answers.

- [Connect an AI agent to Formstep](https://formstep.io/docs/guides/ai-agents/connect/) — Add Formstep to Claude, ChatGPT, Cursor or any tool that supports remote MCP servers, sign in, and pick the workspace the agent may use.

- [Build a form with an AI agent](https://formstep.io/docs/guides/ai-agents/build-a-form/) — Ask Claude, ChatGPT, Cursor or another connected agent to build a Formstep form, watch it take shape in a preview, change it, and publish it.

- [Send a request with an AI agent](https://formstep.io/docs/guides/ai-agents/send-a-request/) — Ask a connected agent to send a Formstep request to one person, prefill and lock what you already know, and read the answers back when they are done.

## Your own code

Developers who call Formstep from their own code or an HTTP step: start at [Developers](https://formstep.io/docs/developers/overview/).

# Connect Formstep to Zapier

Sign in to Formstep from a Zap, pick the workspace Zapier may use, and check that your forms show up.

## Before you start

- A Formstep account that is a member of the workspace you want to connect.
- At least one published form in that workspace. Zapier lists unpublished forms too, marked _(not published)_, but only a published form sends events and can be requested.
- A Zapier account. Any plan works for connecting.

## 1. Add Formstep to a Zap

In Zapier, click **Create** › **Zaps**, then click the trigger or action step and search for **Formstep**. Pick any event for now; you can change it later. The list shows what the app can do:

![The Formstep app selected in a Zap step, with the Trigger event list open showing Public Link Submission Abandoned, Created and Updated](https://formstep.io/docs/guides/zapier/zapier-trigger-events.png)

The Formstep trigger events. Request Completed, Expired and Canceled are further down the list.

## 2. Sign in to Formstep

Under **Account**, click **Sign in** (or **Change** › **Connect a new account** if you already have one). Zapier opens a window; click **Connect**.

![Zapier's Connect to Zapier window for Formstep with a Connect button](https://formstep.io/docs/guides/zapier/zapier-connect-popup.png)

If you are not signed in to Formstep in this browser, Formstep asks you to sign in first. Then it shows what Zapier may do and asks which workspace to connect.

## 3. Pick the workspace and authorize

Choose the workspace under **Workspace** and click **Authorize**. The window closes and the account appears in the step, named after your Formstep email.

![Formstep's Authorize access screen: Zapier wants to connect to your Formstep workspace, with a list of permissions, a workspace picker set to Acme Inc, and Deny and Authorize buttons](https://formstep.io/docs/guides/zapier/formstep-authorize.png)

The connection reaches only the workspace you pick here.

> **One connection, one workspace**
>
> To use a second workspace, connect a new account and pick the other workspace on this screen. Zapier then shows both connections, and each Zap step uses the one you choose.

![The Account field in a Zap step showing the connected Formstep account, with the account picker open listing admin@formstep.io and a Connect a new account button](https://formstep.io/docs/guides/zapier/zapier-account-connect.png)

## 4. Check the connection

Pick an event and continue to **Configure**. The **Form** dropdown lists the forms of the connected workspace:

![The Configure step with the Form dropdown open, listing the Approval form and its id](https://formstep.io/docs/guides/zapier/zapier-choose-form.png)

If a form is missing, click Refresh. Forms from other workspaces never show here.

## Disconnect

In Zapier, open **App connections**, find Formstep, and remove the connection. Zaps that use it stop until you connect Formstep again and pick the new connection in each of them.

Removing it in Zapier does not end Zapier’s access on the Formstep side. In Formstep, open **OAuth and API Keys** and click **Disconnect** next to Zapier under **Connected apps** as well.

## Next steps

[Send public link submissions to another app](https://formstep.io/docs/guides/zapier/public-link-submissions/) — Start a Zap when someone submits, edits or abandons a form

[Send a request from a Zap](https://formstep.io/docs/guides/zapier/send-a-request/) — Create a request from any trigger, prefilled and locked

# Send public link submissions to another app

Start a Zap when someone submits, edits or abandons a form through its share link, and send the answers to email, Sheets, Slack or a CRM.

## Before you start

You need a [Formstep connection in Zapier](https://formstep.io/docs/guides/zapier/connect/) and a published form with a share link. A submission to a request link does not start these Zaps; see [Act on a request’s outcome](https://formstep.io/docs/guides/zapier/request-outcome/) for that.

## 1. Pick the trigger

Create a Zap, choose **Formstep** as the trigger app, and pick one of the three public link events:

| Trigger | Fires when | Needs |
| - | - | - |
| Public Link Submission Created | A respondent submits the form through a share link. | Nothing extra. |
| Public Link Submission Updated | A respondent edits a submission they already sent. | [Edit after submit](https://formstep.io/docs/submissions-analytics/edit-after-submit/) turned on for the form. |
| Public Link Submission Abandoned | A respondent starts the form and leaves it unfinished for the time you choose, from 12 hours to 1 week. | A Pro or Business plan, which saves [partial submissions](https://formstep.io/docs/submissions-analytics/partial-submissions/#unfinished-drafts). |

![The Formstep trigger event list: Public Link Submission Abandoned, Created and Updated, each marked Instant](https://formstep.io/docs/guides/zapier/zapier-trigger-events.png)

## 2. Choose the form

Pick your account, click **Continue**, and choose the form under **Form**. For the Abandoned trigger, also set **Consider submission abandoned after**. Formstep checks once an hour, so the Zap can start up to an hour after that time.

![The Configure step with the Form dropdown open, listing the Approval form](https://formstep.io/docs/guides/zapier/zapier-choose-form.png)

## 3. Test the trigger

Click **Continue**, then **Test trigger**. Zapier loads a record such as **Public Link Submission A**. Open it to see the fields you can map:

![The test record for Public Link Submission Created, with data › answers listing Your Decision (decision), Signature, What should change? and Your Name, and data › display listing the same questions](https://formstep.io/docs/guides/zapier/zapier-submission-sample.png)

The test record is a sample built from the form's questions (John Doe), not your latest submission.

> **The test record is a sample**
>
> It carries every question of the form with made-up answers, so you can map fields before anyone has submitted. Real runs carry the respondent’s answers. The sample has **Test Event** set to `true`; real submissions have `false`.

Every answer appears twice:

- **answers** holds the value a workflow compares: the [option key](https://formstep.io/docs/requests/field-keys/) of a choice, like `approve`, a number, a date.

- **display** holds the text a person reads: the option’s label (`Approve`), a formatted date.

Where a field key reads differently from its question title, the label names the key in parentheses: **Your Decision (decision)** is the question whose [field key](https://formstep.io/docs/requests/field-keys/) is `decision`. The readable text of the same answer is **Your Decision (decision, display)**. A mapped field shows the same label.

Use **display** in messages and **answers** in filters and lookups. The full shape of both is in the [webhooks reference](https://formstep.io/docs/developers/webhooks-reference/).

## 4. Add the action and map the fields

Click **Continue with selected record** and add the action. The example uses **Email by Zapier** › **Send Outbound Email**. In each field, type `/` or click **+** and search for the question by its title:

![The Insert data panel searching for Your Name, showing it under Data › Answers and under Data › Display](https://formstep.io/docs/guides/zapier/zapier-data-picker.png)

![The Send Outbound Email step: To team@acme.example, Subject 'New approval from' followed by Your Name (display), Body 'Decision:' followed by Your Decision (decision, display)](https://formstep.io/docs/guides/zapier/zapier-map-fields.png)

Subject and body read from display, so the email shows labels, not option keys.

## 5. Publish and check a real run

Click **Publish**. Open the form’s share link, submit it, and open **Zap history** in Zapier. The run appears within seconds:

![Zap history showing a Successful run of the Approval submission to email Zap](https://formstep.io/docs/guides/zapier/zapier-zap-history.png)

Open the run to see the real answers the Zap received.

## If the Zap does not start

- A submission through a request link fires Request Completed, not Public Link Submission Created.
- A Zap that is off never runs. Check the switch next to the Zap’s name.
- The trigger listens to the form in the workspace its connection points at. Check that the Zap uses the right connection.

## Next steps

[Send a request from a Zap](https://formstep.io/docs/guides/zapier/send-a-request/) — Create a request from any trigger, prefilled and locked

[Integrations overview](https://formstep.io/docs/integrations/overview/) — Slack, Sheets and Notion without Zapier

# Send a request from a Zap

Create a Formstep request from any Zapier trigger, prefill and lock the answers you already know, send the link, then find, remind or cancel the request from a later Zap.

## Before you start

You need a [Formstep connection in Zapier](https://formstep.io/docs/guides/zapier/connect/) and a published form. What a request is, and what it can carry, is in [Creating requests](https://formstep.io/docs/requests/creating-requests/). The steps here show where each option sits in Zapier.

For an approval, open **Templates** in Formstep and pick **Approval**. It holds a [Decision question](https://formstep.io/docs/requests/decisions-and-approvals/) with Approve, Decline and Request changes, a text box for the changes, and a signature for approval.

For what the app is good for, and how it replaces Approval by Zapier, see [Formstep for Zapier](https://formstep.io/integrations/zapier/).

## 1. Add the Create Request step

Start with the trigger that should send the request, such as a deal marked won in your CRM or a new row in Google Sheets. Add an action, choose **Formstep**, and pick **Create Request**.

## 2. Pick the form, the recipient and the delivery

- **Form** is the form the recipient completes. It must be published.

- **Recipient Email** and **Recipient Name** usually come from the trigger. The email is needed for email delivery and for reminders.

- **Language** is one of the form’s published languages, like `de`. Leave it empty for the form’s default.

- **Delivery** decides who sends the link. **Email** lets Formstep send the [invitation and reminders](https://formstep.io/docs/requests/invitations-and-reminders/), on Pro and Business. **None**, the default, sends no invitation: a later step of your Zap sends the **Request URL** by Slack, SMS or your own email tool. That makes the Zap three steps, which needs a paid Zapier plan.

![The Create Request step: Form Approval, Recipient Email ada@acme.example, Recipient Name Ada Lovelace, Language empty, Delivery 'None: the Zap sends the link itself'](https://formstep.io/docs/guides/zapier/zapier-create-request-fields.png)

With a Recipient Email, Formstep still emails the form’s scheduled reminders even when Delivery is None. To send none, leave Recipient Email empty.

## 3. Prefill and lock what you already know

Once you pick the form, each question you can prefill appears below as a field. Fill in any answer you already have. Add a question to **Read-only fields** to lock it. Fields marked **(context)** are the form’s hidden fields, and a **Documents** field takes files from earlier steps when the form has a Documents block. What each of these does is in [Prefill, locked fields and hidden fields](https://formstep.io/docs/requests/creating-requests/#three-buckets).

![Test Request set to False, Your Name prefilled with Ada Lovelace, Your Decision and What should change? left empty, and Your Name picked under Read-only fields](https://formstep.io/docs/guides/zapier/zapier-create-request-prefill.png)

The recipient opens the link and finds their name filled in and locked:

![The request form with Your Name showing Ada Lovelace in a greyed-out field and the note 'Filled in by the sender.'](https://formstep.io/docs/guides/zapier/formstep-prefill-locked.png)

## 4. Set an External ID

Put your own id for this piece of work in **External ID**, like the deal number `deal-1042`. A later Zap can then [find the request](#find-a-request) by it. If Zapier runs the step again with the same External ID and the same inputs, you get the same request back instead of a second one. Use a new External ID for each request, and a fresh one when you change a test step’s inputs.

**Reminders**, **Expires At** and **Metadata** are optional. For expiry and reminder defaults, see [Invitations, reminders and expiry](https://formstep.io/docs/requests/invitations-and-reminders/).

## 5. Test the step

Click **Test step**. Formstep creates the request and returns it. **Request URL** is the link for the recipient; map it into the step that sends it.

![The Data out tab of the Create Request test: Created At and Expires At as dates, Deduplicated false, Delivery Status not\_requested, External ID deal-1043, Status pending and a Request URL on form.formstep.io](https://formstep.io/docs/guides/zapier/zapier-create-request-output.png)

Delivery Status is not\_requested because Delivery is None: Formstep sent nothing.

> **Testing the step creates a real request**
>
> Unless **Test Request** is on, the test is a real request: with Email delivery, the recipient gets the invitation. Turn Test Request on while you build the Zap. A test request sends no email, counts nowhere, and does not start any Zap with a [request trigger](https://formstep.io/docs/guides/zapier/request-outcome/). Turn it off before you publish.

To test the whole path, turn Test Request off, set **Delivery** to **None**, use your own email and open the **Request URL** yourself.

## Find, remind and cancel requests

Four more Formstep actions work on a request that already exists. A typical Zap finds the request by the id your system knows it by, then reminds or cancels it. The same actions are on [the Requests page](https://formstep.io/docs/requests/managing-requests/).

### Find a request by External ID

Your CRM knows the deal as `deal-1042`, not by Formstep’s request ID. Add a Formstep action with the event **Find Request** and map your id into **External ID**:

![The Find Request step: External ID deal-1042, Form empty, Include Test Requests empty, and Zapier's options for no results and multiple results](https://formstep.io/docs/guides/zapier/zapier-find-request-fields.png)

- **Form** narrows the search to one form. Leave it empty to search the whole workspace.

- **Include Test Requests** is off by default, so a test request is not found. Turn it on while you build the Zap.

- If several requests share the External ID, the newest comes first, and Zapier uses it unless you change **If multiple search results are found**.

The result is the whole request: its status, outcome, recipient, dates, and what you prefilled and locked.

![The Find Request test result: Test Request false, Language en, Last Activity At and Opened At as dates, Outcome approve, prefill with Your Name Ada Lovelace, and Readonly Keys your\_name](https://formstep.io/docs/guides/zapier/zapier-find-request-output.png)

### Read the answers with Get Request

**Get Request** takes a **Request**: map the Request ID from a Create Request step, a Find Request step or a request trigger. It returns the request, its link, and the answers once it is completed. Pick the request’s form under **Form** so the answers are labelled with the question titles.

### Send a reminder with Remind Request

**Remind Request** emails the recipient a reminder now, on Pro and Business. Scheduled reminders still go out as planned. The request must be pending and have a recipient email, and a test request is never reminded. How often you can remind someone is in [Invitations, reminders and expiry](https://formstep.io/docs/requests/invitations-and-reminders/).

### Withdraw a request with Cancel Request

**Cancel Request** withdraws a pending request. The link stops working, and the recipient sees a withdrawn notice instead of the form. Fill in **Reason** to record why: the [Request Canceled](https://formstep.io/docs/guides/zapier/request-outcome/) trigger carries it, so another Zap can tell your team. A request that is already completed, expired or canceled stays as it is, and the step fails.

## Next steps

[Act on a request's outcome](https://formstep.io/docs/guides/zapier/request-outcome/) — Start a Zap when the recipient approves, declines or asks for changes

[Decisions & approvals](https://formstep.io/docs/requests/decisions-and-approvals/) — The Decision question and its three values

[Zapier templates](https://formstep.io/workflows/) — Three Zaps spelled out step by step: CRM prefill, PDF reading with AI, and onboarding

[Form templates](https://formstep.io/templates/) — Forms to start from, each with its field keys listed

# Act on a request's outcome

Start a Zap when a request is completed, expires or is canceled, and branch on whether the recipient approved, declined or asked for changes.

## Before you start

You need a [Formstep connection in Zapier](https://formstep.io/docs/guides/zapier/connect/) and requests to act on, sent from a Zap as in [Send a request from a Zap](https://formstep.io/docs/guides/zapier/send-a-request/) or from anywhere else: the dashboard, the API or an agent. To branch on a verdict, the form needs a [Decision question](https://formstep.io/docs/requests/decisions-and-approvals/).

## 1. Pick the trigger

Create a Zap, choose **Formstep** as the trigger app, and search for **Request**:

![The Formstep trigger list filtered by Request: Request Canceled, Request Completed and Request Expired, each marked Instant](https://formstep.io/docs/guides/zapier/zapier-request-trigger-events.png)

| Trigger | Fires 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 step, or Formstep cancels it because the form was moved to trash. | The request and the cancel reason. |

Pick **Request Completed**, pick your account, and choose the form. The Zap fires for requests to that form only.

## 2. Test the trigger

Click **Test trigger**. As with public link triggers, Zapier loads a sample built from the form’s questions, so you can map fields before any request is completed:

![The Request B test record: data › answers with Your Decision (decision) approve, data › display with Your Decision (decision, display) Approve, then data › form and data › request](https://formstep.io/docs/guides/zapier/zapier-request-sample.png)

Where a field key reads differently from its question title, the label names the key in parentheses. **Your Decision (decision)** is the answer whose field key is `decision`, and a mapped field shows the same label.

Besides **answers** and **display**, a request event carries a **request** group:

- **Recipient Email**, **Recipient Name**, **Request External ID**, **Metadata** and **Context**: what you set when you created the request. Use the External ID to find the record the request was about.

- **Outcome**: `approve`, `decline` or `changes`, the recipient’s answer to the Decision question. On this form it is the same value as **Your Decision (decision)**, because the Decision question’s key is `decision`. Outcome is missing when the form has no Decision question.

Zapier receives the same event as a callback. Developers: every field is in the [callback reference](https://formstep.io/docs/developers/callbacks/#payload).

## 3. Map the action

Add the action. The example uses **Email by Zapier** › **Send Outbound Email**, with the recipient’s name and their decision in the subject and the External ID in the body:

![The Send Outbound Email step: To is team@acme.example; Subject is Recipient Name, the word answered, then Your Decision (decision, display); Body is External ID followed by Request External ID](https://formstep.io/docs/guides/zapier/zapier-outcome-email.png)

Publish the Zap. When the recipient completes the request, the email arrives with a subject like _Ada Lovelace answered: Approve_, and the run appears in **Zap history**.

## 4. Continue only on approval

To act on one verdict only, add a **Filter** step between the trigger and the action. Set it to continue only if **Your Decision (decision)** exactly matches `approve`:

![A Filter step: Only continue if 1. Your Decision (decision) (Text) Exactly matches approve](https://formstep.io/docs/guides/zapier/zapier-filter-approve.png)

The filter reads the field key, not the label. The Decision question’s field key is always `decision`, so the same filter works on every form, whatever the question’s title. **Outcome** holds the same value.

Compare against the value from **answers**. The label from **display** changes when you rename the option or the recipient answers in another language, while the value stays the same. To handle each verdict differently, use **Paths** instead of a filter, one path per value.

For example, `approve` moves the deal on, `decline` tells the account owner, and `changes` sends the answer to **What should change?** to the account owner.

> **Filters and Paths need a paid Zapier plan**
>
> A Zap with a Filter or Paths step has more than two steps, and Zapier’s Free plan publishes only two-step Zaps. On Free, keep the trigger and one action, and branch in the app the action writes to.

## If the Zap does not start

- A test request never starts a Zap, whether it was created with Test Request on or with **Try it yourself**. Send a real request to check the Zap.

- The trigger listens only to the form you chose in step 1.

- The Zap is off, or uses a connection to another workspace. See the checks in [the public link guide](https://formstep.io/docs/guides/zapier/public-link-submissions/#troubleshooting).

## Next steps

[Find, remind and cancel requests](https://formstep.io/docs/guides/zapier/send-a-request/#manage-requests) — Find a request by External ID, remind the recipient, or withdraw it

[Decisions & approvals](https://formstep.io/docs/requests/decisions-and-approvals/) — The Decision question and its three values

# Connect Formstep to Make

Install the Formstep app in your Make organization, sign in from a scenario, and pick the workspace Make may use.

## Before you start

- A Formstep account that is a member of the workspace you want to connect.
- At least one published form in that workspace.
- A Make account. Any plan works.

> **Beta**
>
> The Formstep app for Make is shared by invitation until Make approves it for its app directory. When you connect it, you tell it which Make zone your organization is in.

## 1. Install the app

Open the [Formstep invitation in Make](https://www.make.com/en/hq/app-invitation/19b85d47851b8e2054970a52663f8290) and install the app in your organization. You can also open it from Formstep: **Integrations** › **Make** › **Open in Make**.

If you skip this step, Make asks for it the first time you run a scenario with a Formstep module: confirm the installation there.

## 2. Add Formstep to a scenario

Create a scenario, click the big **+**, and search for **Formstep**. The app lists its modules:

- **Watch public link submissions** and **Watch requests**: triggers that start the scenario the moment something happens in Formstep.

- **Create a request**, **Get a request**, **Cancel a request**, **Remind a request** and **Search requests**: actions on your requests.

- **Make an API call**: any other method of the [Formstep API](https://formstep.io/docs/developers/rest-api/).

## 3. Sign in and pick the workspace

Pick any module. Next to **Connection**, click **Create a connection** (in a trigger, first click **Create a webhook**) and give it a name. Under **Make zone**, pick the zone of your Make organization: the start of the address you use Make at, such as `eu1` in `eu1.make.com` or `us2` in `us2.make.com`. Click **Save**. Make opens a window.

If you are not signed in to Formstep in this browser, Formstep asks you to sign in first. Then it shows what Make may do and asks which workspace to connect. Choose the workspace and click **Authorize**. The window closes and the connection appears in the module. In **Credentials**, Make shows the workspace name under the connection.

> **The window ends on "Resource not found"**
>
> The **Make zone** does not match your organization. Close the window, create the connection again and pick the zone in your Make address.

> **One connection, one workspace**
>
> To use a second workspace, add another connection and pick the other workspace on Formstep’s screen. Each module then uses the connection you choose.

## 4. Check the connection

Open the **Form** dropdown of the module. It lists the forms of the connected workspace. Forms from other workspaces never show here. If a new form is missing, click **Refresh** next to the field.

## Disconnect

In Make, open **Credentials**, find the Formstep connection and delete it. Scenarios that use it stop until you add a new connection and pick it in each module.

Deleting it in Make does not end Make’s access on the Formstep side. In Formstep, open **OAuth and API Keys** and click **Disconnect** next to Make under **Connected apps** as well.

## Next steps

[Start a scenario from public link submissions](https://formstep.io/docs/guides/make/public-link-submissions/) — Run a scenario when someone submits, edits or abandons a form

[Send requests and act on their outcome](https://formstep.io/docs/guides/make/requests/) — Create a request, then run a scenario when it ends

# Start a scenario from public link submissions

Run a Make scenario when someone submits, edits or abandons a form through its share link, and map each answer by its question.

## Before you start

You need a [Formstep connection in Make](https://formstep.io/docs/guides/make/connect/) and a published form with a share link. A submission to a request link does not start this trigger; [Watch requests](https://formstep.io/docs/guides/make/requests/#watch-requests) covers those.

## 1. Add the trigger

Create a scenario, click the big **+**, search for **Formstep** and pick **Watch public link submissions**. Under **Webhook**, click **Create a webhook**, pick your connection, the **Form**, and the **Event**:

| Event | Fires when | Needs |
| - | - | - |
| Submission created | A respondent submits the form through a share link. | Nothing extra. |
| Submission updated | A respondent edits a submission they already sent. | [Edit after submit](https://formstep.io/docs/submissions-analytics/edit-after-submit/) turned on for the form. |
| Submission abandoned | A respondent starts the form and leaves it unfinished for the time you choose, from 12 hours to 1 week. | A Pro or Business plan, which saves [partial submissions](https://formstep.io/docs/submissions-analytics/partial-submissions/#unfinished-drafts). |

Click **Save**. Formstep now sends that event for that form to Make. For the abandoned event, Formstep checks once an hour, so the scenario can start up to an hour after the time you chose.

> **One trigger, one event**
>
> Each trigger hears one event. To act on new submissions and on edits, add two scenarios, one per event. A submission through a request link never reaches this trigger, so a scenario that watches both requests and public links on the same form runs once per completion.

## 2. Test the trigger

Click **Run once**, then submit the form through its share link. The trigger shows one bundle. Open it to see what arrives:

| Field | Holds |
| - | - |
| Event type | `submission.completed`, `submission.updated` or `submission.abandoned`. |
| Data › Answers | The value a scenario compares: the [option key](https://formstep.io/docs/requests/field-keys/) of a choice, a number, a date. |
| Data › Answers (display) | The text a person reads: the option label, a formatted date. |
| Data › Form | The form the submission belongs to. |
| Data › Submission | The submission's id, time, language and PDF link. |

## 3. Map the answers

Add the next module. In its fields, open the mapping panel: each question of the form is listed under **Answers** and **Answers (display)** by its title. Use **Answers (display)** in messages and **Answers** in filters and lookups.

The list comes from the form’s published questions. If you add a question, publish the form and reopen the module so Make loads it. The full shape of the event is in the [webhooks reference](https://formstep.io/docs/developers/webhooks-reference/).

## 4. Turn the scenario on

Save the scenario and switch it on. Formstep sends every new event as it happens. Deleting the trigger’s webhook in Make removes the subscription in Formstep too.

## Next steps

[Send requests and act on their outcome](https://formstep.io/docs/guides/make/requests/) — Create a request, then run a scenario when it ends

[Webhook API reference](https://formstep.io/docs/developers/webhooks-reference/) — Format, signing and retries, for developers

# Send requests and act on their outcome

Create a Formstep request from a Make scenario, prefill it per field, and run a scenario when the recipient completes it, it expires or is canceled.

![A Make scenario with three Formstep modules: Create a request, Get a request and Make an API call, each with a green check after a run](https://formstep.io/docs/guides/make/make-request-scenario.png)

## Before you start

You need a [Formstep connection in Make](https://formstep.io/docs/guides/make/connect/) and a published form. A request is one recipient’s copy of the form; see [Requests](https://formstep.io/docs/requests/overview/) for how they work.

## 1. Create a request

Add **Formstep** › **Create a request** and pick the **Form**. Picking it loads one input per question under **Prefill**, one per hidden field under **Context**, and the **Read-only fields** picker:

![The Create a request module with the Make smoke test form picked, a Prefill input for Full name and one for Company set to Prefilled Co, and the Read-only fields picker](https://formstep.io/docs/guides/make/make-create-request-prefill.png)

A choice question takes its option key, a date takes YYYY-MM-DD.

| Field | What it does |
| - | - |
| Recipient email and name | Who the request is for. An email is needed to send the invitation and reminders. |
| Delivery | **I deliver the link myself**: the scenario sends the request link, for example by email or SMS. **Email the invitation**: Formstep emails it to the recipient. |
| External ID | Your own id, such as a ticket or order number. Running the module again with the same external ID and inputs returns the same request instead of a second one. |
| Test request | A dry run: nothing is emailed, the link opens and can be completed, and it counts nowhere. Test requests never reach a trigger. |

The module returns the request: **Request ID**, **Request link** and **Status** ( `pending`). Map the link into your email or message module when you deliver it yourself.

## 2. Act when the recipient answers

In a second scenario, add **Formstep** › **Watch requests**. Under **Webhook**, click **Create a webhook**, pick the **Form** and the **Event**:

| Event | Fires when | Carries |
| - | - | - |
| Request completed | The recipient submits the request. | The request, the answers and the submission. |
| Request expired | The request reaches its expiry date unanswered. | The request. |
| Request canceled | Someone cancels the request. | The request, with the reason. |

![A Watch requests bundle for request.completed: Data › Answers lists Company and Full name, Answers (display) lists the same questions, then Form, Request and Submission](https://formstep.io/docs/guides/make/make-watch-requests-bundle.png)

Answers and Answers (display) list each question by its title, the same as in Watch public link submissions.

**Data › Request** holds the request’s id, your external ID, its status, the recipient and, with a [Decision question](https://formstep.io/docs/requests/decisions-and-approvals/), the **outcome**: `approve`, `decline` or `changes`. Add a filter on it to branch on the verdict. Test requests never reach this trigger.

## 3. Look up and manage requests

| Module | Use it to |
| - | - |
| Get a request | Read one request by its id: status, outcome, timeline, and the answers once it is completed. Pick the form so the answers map by question. |
| Search requests | List a form's requests, newest first, by status or external ID. |
| Cancel a request | Withdraw a pending request, with an optional reason. Its link stops working. |
| Remind a request | Email the recipient a reminder now. Needs a recipient email and Pro or Business; see [Invitations, reminders and expiry](https://formstep.io/docs/requests/invitations-and-reminders/). |
| Make an API call | Call any other method of the [Formstep API](https://formstep.io/docs/developers/rest-api/) with the same connection. |

> **When a module fails**
>
> The error message says why in words, for example that the request is already canceled. Reminding too soon after the last reminder, or canceling a request that is no longer pending, fails the same way. Add an error handler to the module to route these cases.

## Next steps

[Field keys](https://formstep.io/docs/requests/field-keys/) — The short names your scenarios prefill and read answers by

[Invitations, reminders & expiry](https://formstep.io/docs/requests/invitations-and-reminders/) — Email the link, chase people who go quiet, close stale requests

# Install the Formstep node in n8n

Give a self-hosted n8n a public HTTPS address, install the n8n-nodes-formstep community node, and check that its triggers and actions show up.

The setup guides were checked on self-hosted n8n 2.40 in Docker with version 0.11.1 of the node, and the examples on n8n 2.44 with version 0.13.0.

## Before you start

- n8n 2.30 or later. The Formstep credential needs it.
- A Formstep account. Everything in these guides works on the Free plan except email invitations, reminders and unfinished drafts, which need Pro or Business. See [Limits and quotas](https://formstep.io/docs/subscription-billing/limits-quotas/).

## Self-hosted n8n

A self-hosted n8n needs two things before it can install the node:

- The owner account or an admin account. Only the owner and admins can install community nodes.

- A public HTTPS address, from a reverse proxy or a tunnel. Formstep sends events and request callbacks only to `https://` URLs on the public internet. An n8n that is reachable only on `localhost` can connect but never receives anything.

### 1. Tell n8n its public address

n8n builds the URLs it hands to Formstep from its own settings, not from the address in your browser. Set these environment variables on the n8n container or process:

- `WEBHOOK_URL`: the public HTTPS address, with a trailing slash, like `https://n8n.example.com/`. n8n builds the URL of a published trigger and the resume URL of [Wait for the Outcome](https://formstep.io/docs/guides/n8n/send-a-request/#wait-for-the-outcome) from it.

- `N8N_EDITOR_BASE_URL`: the same address. n8n builds a trigger’s test URL for **Execute step** from it, and the **OAuth Redirect URL** of the Formstep credential.

- `N8N_PROXY_HOPS`: set it to `1` when n8n runs behind one reverse proxy or tunnel, so n8n reads the proxy’s forwarded headers.

With Docker, that looks like this:

```bash
docker run -d --name n8n -p 5678:5678 \
  -e WEBHOOK_URL=https://n8n.example.com/ \
  -e N8N_EDITOR_BASE_URL=https://n8n.example.com/ \
  -e N8N_PROXY_HOPS=1 \
  -v n8n_data:/home/node/.n8n \
  docker.n8n.io/n8nio/n8n
```

With docker compose or an npm install, set the same variables in n8n’s environment. Point your proxy or tunnel at port `5678`, pass `/webhook/`, `/webhook-test/` and `/webhook-waiting/` through unchanged, and open n8n through the public address from then on.

> **Formstep sends events to HTTPS addresses only**
>
> Formstep refuses to send events to an `http://` URL or a private network address, and the Formstep nodes say so before they try, with the URL n8n handed out. If a trigger shows this on **Execute step**, `N8N_EDITOR_BASE_URL` is not set; on **Publish**, or on a Create request node with **Wait for the Outcome**, `WEBHOOK_URL` is not. Set that variable, restart n8n, and try again. If you change `WEBHOOK_URL` later, unpublish and publish each Formstep workflow again so its trigger registers the new address. With version 0.12 of the node or older, the same problem reads _VALIDATION\_ERROR: targetUrl must use https_.

### 2. Install the community node

Open **Settings** › **Community nodes** and click **Install**. Type `n8n-nodes-formstep` under **npm Package Name**, tick the box that says you understand the risks of installing unverified code, and click **Install**.

![The Install community nodes dialog: npm Package Name n8n-nodes-formstep, the risk checkbox ticked, and an Install button](https://formstep.io/docs/guides/n8n/n8n-install-community-node.png)

After a few seconds the package appears in the list with its two nodes:

![Settings › Community nodes listing n8n-nodes-formstep, version 0.11.1, with 2 nodes: Formstep, Formstep Trigger](https://formstep.io/docs/guides/n8n/n8n-community-node-installed.png)

Update or uninstall the package from the same list. If **Community nodes** is missing from Settings, your n8n was started with `N8N_COMMUNITY_PACKAGES_ENABLED=false`; remove that setting.

## n8n Cloud

> **Not available on n8n Cloud yet**
>
> n8n Cloud installs only community nodes that n8n has verified, and the Formstep node is not verified yet. Until it is, use a self-hosted n8n, or call the [REST API](https://formstep.io/docs/developers/quickstart-send-a-request/) from an **HTTP Request** node. A Cloud instance already has a public HTTPS address, so once the node is available there, only the install steps change.

## Check the node

Open a workflow, click **+** and search for **Formstep**. The node details show six actions and six triggers:

![The node details of Formstep, marked Installed, with Actions (6): Cancel request, Create request, Get request, Get many requests, Remind request recipient and Replay request callback, and a collapsed Triggers (6) section](https://formstep.io/docs/guides/n8n/n8n-node-details.png)

- **Formstep Trigger** starts a workflow on a public link submission that is created, updated or abandoned, or on a request that is completed, expires or is canceled.

- **Formstep** creates a request, gets one or many, reminds the recipient, cancels a request, and replays its callback.

## Next steps

[Connect Formstep to n8n](https://formstep.io/docs/guides/n8n/connect/) — Create the credential, sign in, and pick the workspace

[Automation guides](https://formstep.io/docs/guides/overview/) — Every guide for Zapier, Make, n8n and AI agents

# Connect Formstep to n8n

Connect n8n to one Formstep workspace with an API key, or on self-hosted n8n by signing in with OAuth2, and check that your forms show up.

## Before you start

- The Formstep node installed on your n8n. See [Install the Formstep node in n8n](https://formstep.io/docs/guides/n8n/install-the-node/), which also covers what your n8n needs first.
- A Formstep account that is a member of the workspace you want to connect.
- At least one published form in that workspace.

## Choose how to connect

Each Formstep node has an **Authentication** choice:

- **API Key**, the default, works on n8n Cloud and on self-hosted n8n. You copy a key from Formstep and paste it into n8n.

- **OAuth2** works on self-hosted n8n only. You sign in to Formstep from n8n instead of copying a key. Nodes added before version 0.14.0 of the node use it, and keep using it.

## Connect with an API key

1. In Formstep, open **OAuth and API Keys** in the workspace n8n should use. Click **Create token** and name it after your n8n, for example _n8n_. Under **Expiration**, pick **No expiration**, then click **Create token**.

2. Copy the key. Formstep shows it only once; it starts with `fs_`.

3. In n8n, add a Formstep node to a workflow, open **Credential** and click **Create new credential**. n8n opens a **Formstep API** credential.

4. Paste the key into **API Key** and click **Save**. n8n checks the key with Formstep and saves the credential.

> **Pick No expiration**
>
> A key created with 30 or 90 days stops working on that date, and every workflow that uses it stops with an `UNAUTHORIZED` error. With No expiration, the key works until you delete it. To replace a key, create a new one, paste it into the same credential in n8n and save.

## Connect with OAuth2 (self-hosted n8n)

In the Formstep node, set **Authentication** to **OAuth2**, open **Credential** and click **Create new credential**. You can also start from **Overview** › **Credentials** › **Create** and search for **Formstep OAuth2 API**.

![The Formstep OAuth2 API credential: a Connect button, the OAuth Redirect URL https://n8n.example.com/rest/oauth2-credential/callback, and Allowed HTTP Request Domains set to All](https://formstep.io/docs/guides/n8n/n8n-credential-connect.png)

There is nothing to fill in. n8n registers itself with Formstep when you click **Connect**, including the **OAuth Redirect URL** shown here. The note below that URL asks you to enter it in Formstep; you can ignore it, because Formstep has no place to paste it.

Click **Connect**. n8n opens a Formstep window. If you are not signed in to Formstep in this browser, sign in first. Formstep then shows what n8n may do and asks which workspace to connect:

![Formstep's Authorize access screen: n8n wants to connect to your Formstep workspace from n8n.example.com, with a list of permissions, a workspace picker set to Acme Inc, and Deny and Authorize buttons](https://formstep.io/docs/guides/n8n/formstep-authorize.png)

The connection reaches only the workspace you pick here.

Choose the workspace under **Workspace** and click **Authorize**. The window reports that the connection succeeded, and the credential in n8n shows as connected. Save it. The connection refreshes itself while a workflow uses it at least once every 30 days.

> **One credential, one workspace**
>
> To use a second workspace, create a second credential: a key from that workspace, or another OAuth2 sign-in with the other workspace picked. Rename each credential after the workspace it reaches. Each Formstep node then uses the credential you choose in it.

## Check the connection

Add a **Formstep Trigger** and pick the credential. **Form** lists the forms of the connected workspace, and you can search it by name; to paste a form’s ID instead, switch to **By ID**. A form marked _(not published)_ sends no events and takes no requests until you publish it.

![The Formstep Trigger with Credential Formstep account and Form set to From list, open on a search box above \[Guide\] Supplier onboarding and Approval](https://formstep.io/docs/guides/n8n/n8n-choose-form.png)

Forms from other workspaces never show here. A trigger saved before version 0.15.0 keeps a plain dropdown, Form Name or ID.

## Disconnect

In n8n, delete the credential under **Overview** › **Credentials**. Workflows that use it stop until you pick another credential in each Formstep node.

Deleting it in n8n does not end n8n’s access on the Formstep side. In Formstep, open **OAuth and API Keys**. For an API key, click the bin icon next to the key under **API Keys**. For OAuth2, click the bin icon next to n8n under **Connected apps** and confirm with **Disconnect**.

## Next steps

[Start an n8n workflow from public link submissions](https://formstep.io/docs/guides/n8n/public-link-submissions/) — Run a workflow when someone submits, edits or abandons a form

[Send a request and act on its outcome](https://formstep.io/docs/guides/n8n/send-a-request/) — Create a request, then branch on what the recipient decided

# Start an n8n workflow from public link submissions

Run an n8n workflow when someone submits, edits or abandons a form through its share link, and pass the answers to the next node.

## Before you start

You need a [Formstep credential in n8n](https://formstep.io/docs/guides/n8n/connect/) and a published form with a [share link](https://formstep.io/docs/sharing-publishing/sharing-embedding/#share-links). Your n8n must be reachable from the internet over HTTPS; see [Install the Formstep node in n8n](https://formstep.io/docs/guides/n8n/install-the-node/). A submission to a request link does not start these workflows; see [Act on the outcome](https://formstep.io/docs/guides/n8n/send-a-request/#outcome) for that.

## 1. Add the trigger

Create a workflow, click **+**, search for **Formstep** and pick **Formstep Trigger**. Choose the credential, the form, and one of the three public link events under **Event**:

![The Formstep Trigger's Event dropdown open: Public Link Submission Created, Updated and Abandoned, then Request Completed, Expired and Canceled, each with a short description](https://formstep.io/docs/guides/n8n/n8n-trigger-events.png)

| Event | Runs when | Needs |
| - | - | - |
| Public Link Submission Created | A respondent submits the form through a share link. | Nothing extra. |
| Public Link Submission Updated | A respondent edits a submission they already sent. | [Edit after submit](https://formstep.io/docs/submissions-analytics/edit-after-submit/) turned on for the form. |
| Public Link Submission Abandoned | A respondent leaves the form unfinished for the time under **Consider Abandoned After** (12 hours to 1 week). Formstep checks hourly, so the run can come up to an hour later. | A Pro or Business plan, which saves [partial submissions](https://formstep.io/docs/submissions-analytics/partial-submissions/#unfinished-drafts). |

## 2. Listen for a test event

Click **Execute step**. The node shows _Listening for test event_, and Formstep starts sending this form’s events to the node’s test URL for two minutes. Open the form’s share link in another tab and submit it within that time. The submission arrives in the node within seconds:

![The Formstep Trigger after a test event: Form \[Guide\] Supplier onboarding, Event Public Link Submission Created, and the output with id, type submission.completed, test false and data › answers holding company\_name Nordlys Tekstil AS, contact\_email, vat\_number, the payment terms answer yes, and the uploaded certificate file](https://formstep.io/docs/guides/n8n/n8n-submission-output.png)

n8n has no sample record: the test is a real submission, and `test` is `false`. Every answer appears twice:

- **data.answers** holds the value a workflow compares, under the question’s [field key](https://formstep.io/docs/requests/field-keys/): an option key like `yes`, a number, a date, or a list of files.

- **data.display** holds the text a person reads, like `Yes`.

Use **display** in messages and **answers** in conditions. See the [webhooks reference](https://formstep.io/docs/developers/webhooks-reference/#fields-vs-answers) for both.

Abandoned submissions arrive hours later, so **Execute step** cannot catch one. For that event, publish the workflow and check **Executions**.

## 3. Pick out the answers

Add an **Edit Fields (Set)** node after the trigger. Drag answers from the input panel into **Fields to Set**, or type the expressions yourself:

![An Edit Fields node with three fields: company from $json.data.answers.company\_name, email from $json.data.answers.contact\_email, and payment\_terms from $json.data.display.do\_you\_accept\_our\_30\_day\_payment\_terms, with the output Nordlys Tekstil AS, grace@nordlys.example and Yes](https://formstep.io/docs/guides/n8n/n8n-map-fields.png)

payment\_terms reads from display, so it holds the label Yes rather than the option key yes.

The next node, say Gmail or Google Sheets, reads `{{ $json.company }}` and the other fields from here. When a question is renamed, its field key stays the same, so these expressions keep working.

## 4. Publish and check a real run

Click **Publish**, give the version a name, and confirm. Formstep now sends every new submission to the workflow’s production URL. Unpublishing the workflow stops that.

Submit the form once more and open the **Executions** tab. The run appears within seconds. Runs you started with **Execute step** carry a flask icon; a production run has none:

![The Executions tab of the published workflow: the latest run Succeeded in 48ms with no flask icon, three earlier test runs with a flask icon, and the canvas showing Formstep Trigger passing 1 item to Edit Fields](https://formstep.io/docs/guides/n8n/n8n-production-execution.png)

## If the workflow does not start

- A submission through a request link runs **Request Completed**, not Public Link Submission Created.

- While the workflow is a draft, only **Execute step** listens, and only until the first event arrives or two minutes pass. Publish the workflow.

- If the trigger shows _Formstep sends events to HTTPS addresses only_, your n8n hands out an `http://` or private address. See [Tell n8n its public address](https://formstep.io/docs/guides/n8n/install-the-node/#public-address).

- The trigger listens to the form in the workspace its credential points at. Check that it uses the right credential.

- The trigger rejects events when the n8n host’s clock is more than five minutes off. Keep the clock accurate.

## Next steps

[Send a request and act on its outcome](https://formstep.io/docs/guides/n8n/send-a-request/) — Create a request, then branch on what the recipient decided

[Integrations overview](https://formstep.io/docs/integrations/overview/) — Slack, Sheets and Notion without n8n

# Send a request and act on its outcome

Create a Formstep request from an n8n workflow, prefill and lock what you already know, then wait for the answer in the same workflow or start another one when a request ends.

## Before you start

You need a [Formstep credential in n8n](https://formstep.io/docs/guides/n8n/connect/) 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](https://formstep.io/docs/guides/n8n/install-the-node/). What a request is, and what it can carry, is in [Creating requests](https://formstep.io/docs/requests/creating-requests/).

For a full walkthrough with real payloads, read [Pausing an n8n workflow until the customer confirms their details](https://formstep.io/blog/n8n-wait-for-customer/). For what the node is good for, and how it compares with n8n’s own form, see [Formstep for n8n](https://formstep.io/integrations/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.

![The Create request node: input from Supplier on the left; Form \[Guide\] Supplier onboarding, Recipient Email {{ $json.contact\_email }}, and Values to Send with company\_name and contact\_email mapped from the input; on the right the output with deduplicated true, deliveryStatus not\_requested, externalId supplier-SUP-1042, status pending and a url on form.formstep.io](https://formstep.io/docs/guides/n8n/n8n-create-request.png)

## 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](https://formstep.io/docs/requests/field-keys/), 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.

![Further down the Create request node: Read-Only Field Names or IDs with Company name (company\_name), an empty Documents list, the Wait for the Outcome switch off, and Additional Fields with Delivery None, External ID supplier-{{ $json.supplier\_id }}, Recipient Name Grace Hansen and Test Mode on](https://formstep.io/docs/guides/n8n/n8n-create-request-options.png)

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](https://formstep.io/docs/requests/creating-requests/#three-buckets).

## 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](https://formstep.io/docs/requests/invitations-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](https://formstep.io/docs/guides/n8n/manage-requests/#find-a-request). 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](https://formstep.io/docs/requests/creating-requests/): 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](#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](https://formstep.io/docs/requests/decisions-and-approvals/) 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](https://formstep.io/docs/requests/field-keys/), 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 finished execution: When clicking Execute workflow, Create request, Wait for the answer and a Switch named Outcome, all green, with 1 item leaving the approve output](https://formstep.io/docs/guides/n8n/n8n-wait-for-outcome.png)

- 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](#run-the-node), 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:

![A Switch node named Outcome: the input shows data › request with outcome approve, externalId approval-8 and the recipient Grace Hansen; the routing rules compare {{ $json.data.request.outcome }} with approve and changes, each with a renamed output](https://formstep.io/docs/guides/n8n/n8n-route-outcome.png)

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](https://formstep.io/docs/guides/n8n/public-link-submissions/#troubleshooting).

- Create request fails with _Formstep calls back HTTPS addresses only_ when your n8n hands out an `http://` address. See [Tell n8n its public address](https://formstep.io/docs/guides/n8n/install-the-node/#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

[Look up, remind and cancel requests in n8n](https://formstep.io/docs/guides/n8n/manage-requests/) — Find a request by External ID, remind the recipient, or withdraw it

[Get a manager's approval in n8n](https://formstep.io/docs/guides/n8n/approval-from-a-manager/) — Send a claim to a manager, wait for the decision, route each outcome

[n8n workflow templates](https://formstep.io/workflows/) — Three workflows to import: CRM prefill, PDF reading with AI, and onboarding

[Form templates](https://formstep.io/templates/) — Forms to start from, each with its field keys listed

# Look up, remind and cancel requests in n8n

Find a request by your own External ID, read its status and answers, send the recipient a reminder, or cancel it, all from an n8n workflow.

## Before you start

You need a [Formstep credential in n8n](https://formstep.io/docs/guides/n8n/connect/) and a request created with an External ID, as in [Send a request and act on its outcome](https://formstep.io/docs/guides/n8n/send-a-request/). The same actions exist in the dashboard; see [The Requests page](https://formstep.io/docs/requests/managing-requests/).

## Find a request with Get many requests

Your system knows the supplier as `SUP-1042`, not by Formstep’s request ID. Add a Formstep node, pick **Get many requests**, and filter by the External ID you set when you created the request:

![The Get many requests node: Operation Get Many, Return All off, Limit 50, Scope Workspace, and Filters with External ID supplier-SUP-1042, Include Test Requests on and Status Pending](https://formstep.io/docs/guides/n8n/n8n-find-request.png)

- **Scope** is **Form**, the default, which then asks for the form, or **Workspace**, every request the credential can reach.

- **Filters** narrow the list by **External ID**, **Status** or **Outcome**. **Include Test Requests** is off by default, so a request created with Test Mode on is not found. Turn it on while you build the workflow with test requests.

- The newest request comes first. **Limit** caps the number of items; **Return All** fetches every page.

Each request is one output item, so the nodes after it run once per request. When nothing matches, the node outputs no items and the workflow stops there; turn on **Always Output Data** in the node’s settings to carry on. Every node below takes the request as **Request** › **By ID** `{{ $json.id }}`, or pick one of the newest requests under **From list**.

## Read a request with Get request

**Get request** returns the request. **Output** sets how much of it comes back, and **Get many requests**, **Remind request recipient** and **Cancel request** have it too:

- **Simplified**, the default, returns ten fields: `id`, `status`, `outcome`, `externalId`, `formId`, `recipientEmail`, `answers` once it is completed, as `{{ $json.answers.company_name }}`, and `createdAt`, `expiresAt` and `completedAt` as ISO 8601 dates. Only Get request has answers; the other operations return the remaining nine fields.

- **Raw** returns the whole request: what you prefilled and locked, the documents, the reminders sent, the timeline, and `display`, the answers as text. Its timestamps are Unix time in milliseconds.

- **Selected Fields** returns the request ID and the fields you pick under **Fields**, with the same values as Raw, timestamps included. A field the response does not have is left out: Answers, Display and Timeline come with Get request only, and Form Name and Form Origin with Get many requests only.

**Output** came with version 0.15.0 of the package. A node saved earlier keeps its old **Simplify** switch, or returns the whole request.

## Send a reminder with Remind request recipient

**Remind request recipient** emails the recipient a reminder now, on Pro and Business. Scheduled reminders still go out as planned. The request must be pending and have a recipient email, and a test request is never reminded. How often you can remind someone is in [Invitations, reminders and expiry](https://formstep.io/docs/requests/invitations-and-reminders/).

## Withdraw a request with Cancel request

**Cancel request** withdraws a pending request. The link stops working, and the recipient sees a withdrawn notice instead of the form. Fill in **Reason** to record why: it comes in the [Request Canceled](https://formstep.io/docs/guides/n8n/send-a-request/#trigger) event, so another workflow can tell your team. To see it in this node’s output, set **Output** to **Raw**. A request that is already completed, expired or canceled stays as it is, and the node fails.

## Send the callback again

**Replay request callback** sends a finished request’s callback URL the outcome again, for when your receiver missed it. Developers: see [When a callback never lands](https://formstep.io/docs/developers/callbacks/#replay).

## Next steps

[The Requests page](https://formstep.io/docs/requests/managing-requests/) — The same actions in the dashboard

[Automation guides](https://formstep.io/docs/guides/overview/) — Every guide for Zapier, Make, n8n and AI agents

# Get a manager's approval in n8n

Example: send an expense claim to the manager who approves it, pause the workflow until they decide, then route each outcome and no answer.

The same workflow approves anything one person must sign off: a discount for a deal, a purchase order, a holiday, a contract change. Swap the expense for your own data; the steps stay the same. Checked on self-hosted n8n 2.44 with version 0.13.0 of the node.

![The finished execution: When clicking Execute workflow, Expense claim, Download the receipt, Ask the manager, Wait for the decision and Route by decision, all green, with one item leaving the approve output to Approved: pay it out. The changes, decline and no answer outputs lead to their own nodes.](https://formstep.io/docs/guides/n8n/n8n-approval-workflow.png)

## Before you start

- The Formstep node on an n8n with a public HTTPS address, and a [Formstep credential](https://formstep.io/docs/guides/n8n/connect/). See [Install the Formstep node in n8n](https://formstep.io/docs/guides/n8n/install-the-node/).
- Pro or Business to email the request to the manager. On Free, leave **Delivery** at None and send the request’s link yourself.

Import the whole workflow from

[formstep-expense-approval.json](https://github.com/formstep/n8n-nodes-formstep/blob/main/examples/formstep-expense-approval.json)

(**Workflows** › **Import from File**), then pick your credential and your form in **Ask the manager**.

## 1. Build the approval form

In Formstep, open **Templates**, pick **Approval** and click **Use template**. The template has a [Decision question](https://formstep.io/docs/requests/decisions-and-approvals/) with Approve, Decline and Request changes, a text box that shows when the manager asks for changes, and a signature that shows when they approve. Then make it about the expense:

- Add [hidden fields](https://formstep.io/docs/building-forms/hidden-fields/) for what the manager must see but never edit: `reference` (the template has it), `employee_name`, `amount` and `description`.

- Write them into the text with **@**, for example _@employee\_name asks you to approve an expense of @amount for @description, reference @reference._

- Add a [Documents block](https://formstep.io/docs/building-forms/documents-block/) named Receipt. The workflow attaches the receipt there for this manager only.

Publish the form. This is what the manager opens:

![The request page: Approve an expense, Grace Hansen asks you to approve an expense of NOK 3 700 for Hotel in Bergen, client workshop, reference EXP-1042, the attached Receipt EXP-1042 PDF, Your Name filled in with Maria Berg, Company locked to Acme Inc, and the Approve, Decline and Request changes options](https://formstep.io/docs/guides/n8n/n8n-approval-recipient.png)

## 2. Bring in the expense and its receipt

The example starts with an **Edit Fields** node named _Expense claim_ that holds the claim: `expenseId`, `employeeName`, `employeeEmail`, `managerName`, `managerEmail`, `amount`, `description` and `receiptUrl`. In your workflow, the claim comes from wherever it starts, such as a webhook from your expense tool or a Formstep public link form the employee fills in.

An **HTTP Request** node named _Download the receipt_ fetches `{{ $json.receiptUrl }}` with **Response Format** set to **File**. The file lands in the binary field `data`. If the receipt arrives as an email attachment or a Google Drive file, use that node instead; anything that puts the file in a binary field works.

## 3. Ask the manager

Add a Formstep node, pick **Create request** and choose the approval form. Read the claim from the _Expense claim_ node, as `{{ $('Expense claim').item.json.managerEmail }}`: after the Wait node, `$json` is Formstep’s event, and the same expression still finds the claim.

![The Ask the manager node: Form Expense approval, Recipient Email from the Expense claim node, Values to Send with reference, amount, description and employee\_name marked context, Your Name and Company Acme Inc, Company locked under Read-Only Field Names or IDs, a document from the binary field data named Receipt with the expense ID in the Automatic Documents block, and Wait for the Outcome on](https://formstep.io/docs/guides/n8n/n8n-approval-request-node.png)

- **Values to Send** lists the hidden fields marked _· context_: the manager sees them in the text and cannot change them. **Your Name** and **Company** are prefilled, and **Read-Only Field Names or IDs** locks the company. See [Prefill, locked fields, and context](https://formstep.io/docs/requests/creating-requests/#three-buckets).

- Under **Documents**, the document takes the binary field `data`. **Automatic** puts it in the form’s only Documents block; pick a block when the form has several.

- Turn on **Wait for the Outcome**. Formstep then calls this execution back when the manager answers.

Under **Additional Fields**:

- **Delivery** _Email the Invitation_ emails the manager the link. The request’s reminders follow the form’s schedule.

- **Expires At** `{{ $now.plus({ days: 3 }).toISO() }}` ends the wait after three days.

- **External ID** `{{ $('Expense claim').item.json.expenseId }}-{{ $execution.id }}` ties the request to the claim. The execution ID keeps it unique: every execution has its own resume URL.

- **Test Mode**, on in the example, sends nothing and keeps the request out of your lists. Turn it off when the workflow goes live.

## 4. Wait and route the decision

Add a **Wait** node with **Resume** set to **On Webhook Call**. Then add a **Switch** node with three routing rules, each comparing `{{ $json.body.data.request.outcome }}` with `approve`, `changes` or `decline`, and each with **Rename Output** on. Under **Options**, set **Fallback Output** to **Extra Output** and name it _no answer_: an expired or canceled request has no outcome and goes there.

Each branch reads what it needs from the event and the claim:

```text
Who decided:        {{ $json.body.data.answers.full_name }}
What should change: {{ $json.body.data.answers.requested_changes }}
Why it ended:       {{ $json.body.type }}   (request.completed, request.expired or request.canceled)
The claim:          {{ $('Expense claim').item.json.expenseId }}
```

The example ends each branch in an **Edit Fields** node that writes the message. Put the node that sends it in its place: Gmail or Slack to the employee, your accounting tool for the payout, a second request to finance for _no answer_.

## 5. Run it

Click **Execute workflow**. The execution stops at the Wait node. Open the request’s `url` from the output of _Ask the manager_, decide, and submit: the execution resumes down the matching branch, as in the picture at the top. With Test Mode on, the callback still resumes the workflow; only the email stays unsent.

> **Two people, two steps**
>
> Chain two of these for a two-step approval: when the manager approves, a second Create request node sends the same claim to finance, with the manager’s name as context, and waits again. Each step keeps its own decision.

## Next steps

[Start a workflow from the trigger](https://formstep.io/docs/guides/n8n/send-a-request/#trigger) — Use a Formstep Trigger instead of waiting, for requests sent from anywhere

[Read a PDF with AI, then get it confirmed](https://formstep.io/docs/guides/n8n/read-a-pdf-with-ai/) — Let AI fill the form, and the person who knows check it

# Read a PDF with AI, then get it confirmed

Example: an AI model reads a supplier invoice in n8n, a request prefilled with what it read goes to the supplier, and they confirm or correct each value.

The pattern fits any document someone sends you: an order, a claim, an application, a contract to check. Checked on self-hosted n8n 2.44 with version 0.13.0 of the node.

![The finished execution: Invoice, Download the invoice, Extract the text, Read the invoice with AI with its Claude model, Keep the file, Ask the supplier to confirm, Wait for the supplier, Confirmed? and What the supplier corrected, all green](https://formstep.io/docs/guides/n8n/n8n-invoice-workflow.png)

## Before you start

- The Formstep node on a self-hosted n8n with a public HTTPS address, and a [Formstep credential](https://formstep.io/docs/guides/n8n/connect/). On n8n Cloud, call the REST API from an HTTP Request node instead; see [n8n Cloud](https://formstep.io/docs/guides/n8n/install-the-node/#n8n-cloud).
- A credential for a chat model in n8n: Anthropic, OpenAI, Google Gemini or any other the AI nodes take.
- A form for the confirmation. In Formstep, open **Templates**, pick **Confirm Invoice Details**, click **Use template** and publish it. Its field keys are `supplier_name`, `invoice_number`, `invoice_date`, `due_date`, `total_amount`, `confirmed` and `notes`, and it has a Documents block for the invoice.

Import the workflow from

[formstep-invoice-ai-confirm.json](https://github.com/formstep/n8n-nodes-formstep/blob/main/examples/formstep-invoice-ai-confirm.json)

with **Import from File**. The example pins a sample result on the AI node, so it runs before you add a model; unpin it once your model is connected.

## 1. Get the PDF

The example downloads a [sample invoice](https://formstep.io/docs/guides/n8n/samples/invoice.pdf) with an **HTTP Request** node, **Response Format** **File**, and takes the supplier’s address from an **Edit Fields** node named _Invoice_. In your workflow it is usually a Gmail or Outlook trigger on the invoices inbox, with the attachment in a binary field and the sender as the recipient, or a new file in a Google Drive folder.

## 2. Extract the text

Add an **Extract from File** node with **Operation** **Extract From PDF**. It reads the PDF’s text into `{{ $json.text }}`.

> **Scanned documents**
>
> Extract From PDF reads the text a PDF carries. A scan or a photo has none. For those, use a model node that reads images or PDFs itself instead of these two steps; the later steps stay the same. If you get both kinds, check the length of `text` in an **If** node and route the empty ones to that path.

## 3. Read it with AI

Add an **Information Extractor** node, connect your chat model to it, and set **Text** to `{{ $json.text }}`. Under **Attributes**, add one attribute per value you want, named after the field key it fills:

| Name | Type | Description |
| - | - | - |
| supplier\_name | String | The company that issued the invoice |
| invoice\_number | String | The invoice number, as printed |
| invoice\_date | Date | The invoice date, as YYYY-MM-DD |
| due\_date | Date | The payment due date, as YYYY-MM-DD |
| total\_amount | Number | The total to pay, including VAT, as a number without currency |

![The Information Extractor node: Text {{ $json.text }}, Schema Type From Attribute Descriptions, and the first two attributes supplier\_name and invoice\_number open with their type, description and Required on](https://formstep.io/docs/guides/n8n/n8n-invoice-extractor.png)

The node returns what it read under `{{ $json.output }}`, as `{{ $json.output.total_amount }}`. Naming the attributes after the field keys keeps the mapping in the next step one to one.

## 4. Put the file back

The Information Extractor returns what it read, not the PDF. To attach the invoice to the request, add a **Merge** node with **Mode** **Combine** and **Combine By** **Position**. Connect the HTTP Request node to input 1 and the Information Extractor to input 2. Each item then has the file in `data` and the reading in `output`.

## 5. Ask the supplier to confirm

Add a Formstep **Create request** node and pick the Confirm Invoice Details form. Set **Recipient Email** to the supplier’s address, map each field under **Values to Send** to its value, like `{{ $json.output.invoice_number }}`, and add a document from the binary field `data`, named `Invoice {{ $json.output.invoice_number }}`. Turn on **Wait for the Outcome** and add a **Wait** node after it, **Resume** **On Webhook Call**.

Dates and the amount arrive in their own inputs: the date fields take `2026-10-20`, the amount a number. The supplier sees every value filled in, with the invoice above them, and fixes what is wrong:

![The request page: Check Your Invoice Details, the attached Invoice INV-2026-0187 PDF, Supplier Fjord Office Supplies AS, Invoice Number INV-2026-0187, Invoice Date October 20, 2026, Due Date November 3, 2026, Total Amount 27,235, and the confirmation switch](https://formstep.io/docs/guides/n8n/n8n-invoice-recipient.png)

Formstep emailing the supplier needs Pro or Business. On Free, leave **Delivery** at **None** and send the request’s `url` with your own email node; see [Invitations and reminders](https://formstep.io/docs/requests/invitations-and-reminders/). The request expires after 30 days unless you set **Expires At**, so set it sooner for an invoice due in two weeks; see [Expiry](https://formstep.io/docs/requests/invitations-and-reminders/#expiry).

## 6. See what was corrected

Add an **If** node that checks `{{ $json.body.type }}` is `request.completed`, and on its true output a **Code** node that compares the AI’s reading with the confirmed answers:

```javascript
// Compare what the AI read with what the supplier confirmed.
const read = $('Read the invoice with AI').item.json.output
const confirmed = $json.body.data.answers
const corrected = Object.keys(read).filter((key) => String(read[key]) !== String(confirmed[key]))
return { json: { invoice: confirmed, corrected, notes: confirmed.notes ?? null } }
```

In the test run the model read the total as 27 235. The supplier corrected it to 27 325 and left a note, so `corrected` lists `total_amount`:

![The output of What the supplier corrected: invoice with confirmed true, the dates, the invoice number, the supplier's note, supplier\_name and total\_amount 27325, and corrected with one entry, total\_amount](https://formstep.io/docs/guides/n8n/n8n-invoice-corrected.png)

From here, book the invoice with `invoice` in your accounting tool, and send the ones where `corrected` is not empty to a person for a second look. The false output of the If node catches a request that expired: chase the supplier there.

## Variations

- For documents nobody outside should see again, send the request to someone on your team rather than the sender.

- Lock what you are sure of. Values from your own system, like the order number you issued, go under **Read-Only Field Names or IDs**, so only the AI’s reading is open to correction.

- An If node before the request can send readings that fail the arithmetic to your team instead of the supplier.

- With no form yet, set **Form Source** to **New Form** and build the form from the attributes; see [Collect the documents each case needs](https://formstep.io/docs/guides/n8n/collect-documents/). To show the invoice above the values, use a published form.

## Next steps

[Collect the documents each case needs in n8n](https://formstep.io/docs/guides/n8n/collect-documents/) — Build the form from a checklist and file every upload

[Value shapes](https://formstep.io/docs/developers/requests-api/#value-shapes) — What each field type takes as a prefilled value

[The workflow, ready to import](https://formstep.io/workflows/n8n-pdf-extraction-template/) — The same flow as an n8n workflow JSON, with a sample invoice

[Invoice verification template](https://formstep.io/templates/confirm-invoice-details/) — The form the workflow prefills, with its field keys

# Collect the documents each case needs in n8n

Example: build the form from an insurance claim's checklist inside the request, so each person is asked for exactly the documents their case needs, then save each upload with the claim.

The same steps work for onboarding, loans, rentals, visas: anything where the paperwork depends on the case. Checked on self-hosted n8n 2.44 with version 0.13.0 of the node.

![The finished execution: Claim, Build the checklist, Ask for the documents, Wait for the documents and Completed?, then One item per file, Download each file and Save to the claim folder with 2 items each, all green](https://formstep.io/docs/guides/n8n/n8n-claim-workflow.png)

## Before you start

- The Formstep node on an n8n with a public HTTPS address, and a [Formstep credential](https://formstep.io/docs/guides/n8n/connect/).
- Somewhere to keep the files. The example writes them to n8n’s disk; the last step shows Google Drive instead.

The node is for self-hosted n8n only: n8n Cloud installs only verified community nodes, and ours is not verified yet. See [Install the Formstep node](https://formstep.io/docs/guides/n8n/install-the-node/#n8n-cloud).

Import the workflow from

[formstep-claim-documents.json](https://github.com/formstep/n8n-nodes-formstep/blob/main/examples/formstep-claim-documents.json)

with **Import from File**. It needs no form in Formstep: the request builds one.

## 1. Start from the case

The example starts with an **Edit Fields** node named _Claim_: `claimId`, `claimType` ( `water_damage` or `theft`), `claimLabel`, `firstName` and `email`. In your workflow, it is the record that opens the case, such as a CRM deal or a webhook from your claims system.

## 2. Turn the checklist into blocks

A **Code** node named _Build the checklist_ looks up the documents for the claim type and writes the form as blocks: a greeting, two [hidden fields](https://formstep.io/docs/building-forms/hidden-fields/) the greeting reads, one file question per document, and a note.

```javascript
const checklists = {
  water_damage: [
    { key: 'damage_photos', title: 'Photos of the damage', maxFiles: 10 },
    { key: 'repair_estimate', title: 'Repair estimate from a contractor', maxFiles: 1 },
  ],
  theft: [
    { key: 'police_report', title: 'Police report', maxFiles: 1 },
    { key: 'receipts', title: 'Receipts for the stolen items', maxFiles: 10 },
  ],
}
const documents = checklists[$json.claimType]
if (!documents) throw new Error(`No checklist for claim type ${$json.claimType}`)
const blocks = [
  { type: 'header', content: 'Hi {{first_name}}, a few documents for claim {{claim_id}}' },
  { type: 'paragraph', content: 'Upload each document below. Photos from your phone are fine.' },
  { type: 'hiddenField', key: 'first_name' },
  { type: 'hiddenField', key: 'claim_id' },
  ...documents.map((document) => ({ type: 'file', ...document })),
  { type: 'text', key: 'notes', title: 'Anything we should know?', required: false },
]
return { json: { ...$json, blocks } }
```

The `throw` stops the run on an unknown claim type instead of sending a form with no questions. Adding a claim type is a new entry in the object.

Each block takes `type`, a `key` and the options of its kind; `{{first_name}}` in text shows a hidden field’s value. Every block type and option is in [Create a form and a request in one call](https://formstep.io/docs/developers/inline-forms/#blocks).

## 3. Send the request with a new form

Add a Formstep **Create request** node and set **Form Source** to **New Form**:

![The Ask for the documents node: Form Source New Form, Form Name Documents for your {{ $json.claimLabel }} claim, Form Blocks {{ JSON.stringify($json.blocks) }}, Prefill {}, Context {{ JSON.stringify({ first\_name: $json.firstName, claim\_id: $json.claimId }) }}, Read-Only Field Keys empty, and under Form Options a Cover with a color](https://formstep.io/docs/guides/n8n/n8n-claim-request-node.png)

- **Form Blocks** is `{{ JSON.stringify($json.blocks) }}`, the blocks from the Code node.

- **Context** fills the hidden fields: `{{ JSON.stringify({ first_name: $json.firstName, claim_id: $json.claimId }) }}`.

- **Form Options** sets the look: a cover color, a logo and a theme.

- Set **Recipient Email**, turn on **Wait for the Outcome**, and under **Additional Fields** set **Delivery**, **Expires At** (`{{ $now.plus({ days: 14 }).toISO() }}`) and an **External ID**. **Test Mode** is on in the example.

Email invitations and reminders have plan requirements, and on Free you send the request’s `url` yourself and chase by hand: see [Invitations and reminders](https://formstep.io/docs/requests/invitations-and-reminders/). With Test Mode on, nothing is emailed until you turn it off: see [Try it on yourself first](https://formstep.io/docs/requests/creating-requests/#test-mode).

The customer sees only the documents their claim needs:

![The request page: Hi Ada, a few documents for claim CLM-3107, Upload each document below, a file upload for Photos of the damage with 10 files remaining, one for the Repair estimate from a contractor with 1 file remaining, and an optional note](https://formstep.io/docs/guides/n8n/n8n-claim-recipient.png)

> **One checklist, one form**
>
> Formstep builds a form the first time it sees a definition and reuses it after that: the second water damage claim reuses the first one’s form, and the response says `form.reused: true`. Keep what changes per person, like the name and the claim ID, in **Context** or **Prefill**, never in the blocks or the form name, or every request makes a new form. A workspace makes at most 300 new forms a day this way. See [One definition, one form](https://formstep.io/docs/developers/inline-forms/#reuse).

## 4. Wait, then make one item per file

Add a **Wait** node (**On Webhook Call**) and an **If** node that checks `{{ $json.body.type }}` is `request.completed`. Each file question’s answer is a list of files with a `name`, a `size`, a `type` and a `url`. The other output of the **If** node catches an expired or canceled request. A request expires after 30 days unless you set another date, up to 365: see [Expiry](https://formstep.io/docs/requests/invitations-and-reminders/#expiry). A **Code** node turns the files into one item per file:

```javascript
// One item per uploaded file, named after the question it answers.
const event = $json.body.data
const items = []
for (const [question, answer] of Object.entries(event.answers)) {
  if (!Array.isArray(answer)) continue
  for (const file of answer) {
    if (file.url) items.push({ json: { question, name: `${question} - ${file.name}`, url: file.url } })
  }
}
return items
```

It walks the answers instead of naming the questions, so it works for any claim type.

## 5. Download and save each file

An **HTTP Request** node downloads `{{ $json.url }}` with **Response Format** **File**, once per item. The example then writes each file with **Read/Write Files from Disk**, as `/home/node/.n8n-files/{{ $('Claim').item.json.claimId }} {{ $json.name }}`.

To keep them in Google Drive instead, replace that node with **Google Drive** › **Upload file**: Input Data Field Name `data`, File Name `{{ $json.name }}`, and the claim’s folder as Parent Folder. S3, Dropbox and SharePoint nodes take the binary field the same way. The files went to Formstep, so your form’s payload limit never applied, and each can be up to 1 GiB within your storage: see [File upload](https://formstep.io/docs/building-forms/file-uploads-signatures/#file-upload).

> **Treat a file URL like a password**
>
> Anyone with a file’s `url` can download it, so do not post it in a channel or a ticket. Download the file, as here, and share your own copy. The URL does not expire.

- The event’s `data.submission.pdfUrl`, a PDF of all the answers, is set only when the form keeps a PDF: when it has a Signature question or a webhook subscription. A request that only calls back, as here, has none.

- To send the recipient a document to read or sign as well, use a published form with a Documents block, as in [Get a manager’s approval](https://formstep.io/docs/guides/n8n/approval-from-a-manager/). A new form takes no documents.

## Next steps

[Create a form and a request in one call](https://formstep.io/docs/developers/inline-forms/) — Every block type, option and limit of a new form

[Read a PDF with AI, then get it confirmed](https://formstep.io/docs/guides/n8n/read-a-pdf-with-ai/) — Let AI fill the form, and the person who knows check it

[Let an AI agent send requests from n8n](https://formstep.io/docs/guides/n8n/ai-agent-tool/) — Give an AI Agent Formstep as a tool

[Document collection template](https://formstep.io/templates/document-collection/) — A published form with one labelled upload per file, for cases that share a checklist

# Let an AI agent send requests from n8n

Example: an onboarding assistant in n8n that has the Formstep node as a tool, so it can send a client a prefilled form, check how the request is going, and remind them.

The agent decides when to ask someone and what to fill in; Formstep collects the answers and checks them against the form. Checked on self-hosted n8n 2.44 with version 0.13.0 of the node, by running each tool from n8n’s tool test. **Output**, in step 3, came with version 0.15.0. The conversation itself depends on the model you connect.

![The workflow: When chat message received into the Onboarding assistant agent, with Claude as its chat model, Simple Memory as its memory, and three Formstep tools: Send the onboarding form, Check an onboarding and Remind the client](https://formstep.io/docs/guides/n8n/n8n-agent-workflow.png)

## Before you start

- The Formstep node and a [Formstep credential](https://formstep.io/docs/guides/n8n/connect/). n8n 2.46 lists the node as a tool without further setup. If it does not show up as a tool on an older self-hosted n8n, start n8n with `N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true`.
- A credential for a chat model in n8n.
- A form. In Formstep, open **Templates**, pick **Client Onboarding**, click **Use template** and publish it. It asks the client to check their details and sign, and has a hidden field `customer_id`.

Import the workflow from

[formstep-ai-agent-onboarding.json](https://github.com/formstep/n8n-nodes-formstep/blob/main/examples/formstep-ai-agent-onboarding.json)

with **Import from File**, then pick your credentials and your form.

## 1. Set up the agent

Add a **When chat message received** trigger and an **AI Agent** node. Connect your chat model and a **Simple Memory**, so the agent remembers the request it sent earlier in the chat. Under **Options** › **System Message**, tell it what it is for and where to stop:

```text
You help the Acme Inc team onboard new clients.
To onboard a client, send them the onboarding form with what you already know: their name, email, company and customer number. Ask the team member for anything missing first, and never invent an email address.
After sending, give the team member the link and the request id.
When asked how an onboarding is going, check the request. A completed request has the answers the client confirmed.
Remind a client only when the team member asks you to.
```

## 2. Add a tool that sends the form

Click **+** under the agent’s **Tool** input, search for **Formstep** and pick **Create request**. Name the tool after what it does, here _Send the onboarding form_, and set **Tool Description** to **Set Manually** with a sentence the model reads to decide when to use it.

![The Send the onboarding form tool: its description, Resource Request, Operation Create, Form Source Published Form, Form Client Onboarding, Recipient Email and Values to Send customer\_id, Full Name and Company each filled by $fromAI with a key and a description](https://formstep.io/docs/guides/n8n/n8n-agent-tool.png)

Pick the form yourself, so the agent can only send this one. For each value the agent should fill, click the ✨ button next to the parameter, or write `$fromAI()` with a key and a description the model reads:

```text
Recipient Email   {{ $fromAI('email', 'The client email address, exactly as the team member gave it', 'string') }}
customer_id       {{ $fromAI('customer_id', 'The customer number, such as C-1042', 'string') }}
Full Name         {{ $fromAI('full_name', 'The client contact full name', 'string') }}
Company           {{ $fromAI('company_name', 'The client company name', 'string') }}
```

- Use each key once per tool. Two parameters with the same key get the same value.

- Leave out what the client should type themselves, or what the agent cannot know. They fill in the rest of the form.

- Under **Additional Fields**, **Delivery** _Email the Invitation_ emails the client. **Test Mode**, on in the example, sends nothing while you try it out.

## 3. Add tools to check and remind

Add two more Formstep tools on the same input:

- _Check an onboarding_: **Get request**, with **Request** › **By ID** set to `{{ $fromAI('request_id', 'The id that Send the onboarding form returned for this client', 'string') }}`. **Output** **Simplified**, the default, returns ten fields: the status, the outcome, the client’s email, the dates, and the answers once the client completed the form. That keeps the model’s context small. For even less, set it to **Selected Fields** and pick what the agent needs, like **Status** and **Answers**: the tool returns those and the request ID. **Raw** returns the whole request.

- _Remind the client_: **Remind request recipient**, with the same **Request**. A test request is never reminded, so this tool answers with an error until Test Mode is off.

A new Remind or Cancel tool returns the simplified request unless you set **Output** to **Raw** or **Selected Fields**. New tools are version 5 of the node. Tools saved with version 3 or 4 keep **Simplify** on Get request and return the whole request from Remind and Cancel. See [Read a request with Get request](https://formstep.io/docs/guides/n8n/manage-requests/#get-a-request).

## 4. Test each tool without the model

Open a tool and click **Execute step**. n8n asks for the values the model would send, one box per `$fromAI` key, then runs the tool. _Send the onboarding form_ returns the request’s `id` and `url`; put that `id` into _Check an onboarding_ to see what the agent will read. When a value is refused, the error the agent gets names it, such as _VALIDATION\_ERROR: “email” is not a valid email address_, so the model can ask again.

## 5. Chat with it

Click **Open chat** and write, for example: _Onboard Analytical Engines Ltd, contact Ada Lovelace, <ada@example.com>, customer number C-1042._ The agent calls _Send the onboarding form_ and replies with the link. Later, _How is the Ada Lovelace onboarding going?_ makes it call _Check an onboarding_ with the request ID it kept in memory.

> **Hear back without asking**
>
> The agent only knows what it checks. To act the moment a client completes the form, add a separate workflow with a [Formstep Trigger on Request Completed](https://formstep.io/docs/guides/n8n/send-a-request/#trigger) for the same form, and post the answers to your team or your CRM from there.

- The tools reach only the workspace the credential connects, and only the forms you picked in them.

- Agents outside n8n, like Claude or ChatGPT, can do the same through Formstep’s MCP server; see [Send a request with an AI agent](https://formstep.io/docs/guides/ai-agents/send-a-request/).

## Next steps

[Start a workflow from the trigger](https://formstep.io/docs/guides/n8n/send-a-request/#trigger) — Start a workflow when the client completes the form

[Look up, remind and cancel requests in n8n](https://formstep.io/docs/guides/n8n/manage-requests/) — Every request action, outside an agent

# Connect an AI agent to Formstep

Add Formstep to Claude, ChatGPT, Cursor or any tool that supports remote MCP servers, sign in, and pick the workspace the agent may use.

## Before you start

- A Formstep account that is a member of the workspace you want to connect.
- An AI tool that supports remote MCP servers. Some tools limit this to certain plans; the table below links to each tool’s own guide.

An agent’s work spends no Formstep AI credits; your AI tool bills you under its own pricing. See [AI credits & usage](https://formstep.io/docs/ai/ai-credits-usage/#mcp).

## 1. Add the Formstep server to your AI tool

Every tool asks for the same thing, the server URL:

```text
https://api.formstep.io/api/mcp
```

Leave any client ID, secret or token field empty. The tool finds the sign-in page from the server and registers itself. Where to paste the URL depends on the tool:

| Tool | Where to add the URL | Official guide |
| - | - | - |
| Claude (web, desktop and mobile) | **Customize** › **Connectors** › **+** › **Add custom connector**. A connector added on claude.ai also works in the desktop and mobile apps. On Team and Enterprise, an owner adds it first under **Organization settings** › **Connectors**; on Free you can add one custom connector. | [Anthropic](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp) |
| Claude Code | Run `claude mcp add --transport http formstep https://api.formstep.io/api/mcp`, then type `/mcp` in Claude Code to sign in. | [Anthropic](https://code.claude.com/docs/en/mcp) |
| ChatGPT | Turn on developer mode under **Settings** › **Apps** › **Advanced settings**. Then open **Settings** › **Apps** › **Create**, paste the URL, choose OAuth, click **Scan Tools**, sign in to Formstep, and click **Create**. Developer mode works on the web only. On Pro, ChatGPT can only read: tools that change something, such as sending a request or editing a form, need Business, Enterprise or Edu. On Business, only admins and owners can use developer mode. | [OpenAI](https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt) |
| Cursor | Click [Add to Cursor](https://cursor.com/install-mcp?name=formstep\&config=eyJ1cmwiOiJodHRwczovL2FwaS5mb3Jtc3RlcC5pby9hcGkvbWNwIn0=). Or add `{"mcpServers": {"formstep": {"url": "https://api.formstep.io/api/mcp"}}}` to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for every project. | [Cursor](https://cursor.com/docs/mcp) |

Any other tool that supports remote MCP servers with sign-in works the same way: look for where it adds a server by URL.

## 2. Sign in and pick the workspace

The first time the agent uses Formstep, your AI tool opens a Formstep page in the browser. Sign in if you are asked to. Formstep then shows which tool is asking, the account you are signed in as (**Not you?** switches it), what the tool may do, and the workspaces you belong to:

![The Formstep Authorize access page: Claude Code (formstep) wants to connect to your Formstep workspace, a note that Formstep has not verified the app, the account you are signed in as, a list of permissions, the Acme Inc workspace selected, and Deny and Authorize buttons](https://formstep.io/docs/guides/ai-agents/authorize-access.png)

Pick the workspace and click **Authorize**. The browser returns to your AI tool. The connection reaches that one workspace only; to use another workspace, add Formstep to your tool a second time and pick the other one.

## 3. Check that it works

Ask the agent something only Formstep can answer:

```
List my Formstep forms and whether each one is published.
```

The agent calls Formstep and answers with the forms in the workspace you picked. Some tools, like Claude Code, first say they are loading tool definitions: Formstep lists all its tools at once, and the tool fetches the details of the ones a task needs.

> **Some actions ask first**
>
> Deleting a form, unpublishing it, canceling a request and a few other actions are marked for confirmation, and most AI tools ask you before running them. The prompt comes from your AI tool, so check its own approval settings. The full list is in the [MCP server reference](https://formstep.io/docs/developers/mcp-server/#confirmation).

## See or remove the connection

In Formstep, open **OAuth and API Keys** in the workspace sidebar. Your connection is listed under **Connected apps**, with when it was connected and last used:

![The Connected apps card listing Claude Code (formstep), connected 1 minute ago and last used now, with a Disconnect button](https://formstep.io/docs/guides/ai-agents/connected-apps.png)

Click the **Disconnect** button and confirm. The agent loses access at once, and asks you to sign in again the next time it needs Formstep.

## Next steps

[Build a form with an AI agent](https://formstep.io/docs/guides/ai-agents/build-a-form/) — Describe the form, watch the preview, and publish it

[MCP server](https://formstep.io/docs/developers/mcp-server/) — Every tool, limits, and how to connect with an API token instead

# Build a form with an AI agent

Ask Claude, ChatGPT, Cursor or another connected agent to build a Formstep form, watch it take shape in a preview, change it, and publish it.

## Before you start

You need an AI tool with [Formstep connected](https://formstep.io/docs/guides/ai-agents/connect/). Any wording works for the prompts below, as long as it says what to ask and whether to publish.

## 1. Describe the form

Name the form, list what it should ask, and say that it stays a draft for now:

```
Build a Formstep form called "[Guide] Supplier onboarding". Ask for the company name, a contact email, the company's VAT number, and whether they accept our 30-day payment terms (yes or no). Keep it as a draft and send me the preview link.
```

The agent creates the form in the workspace you connected, adds one question at a time, and reads the form back to check the order. It picks a question type for each item: an email field for the contact email, a single choice for yes or no. When it is done, it replies with the questions it added and a preview link.

## 2. Open the preview

The preview link shows the draft as the recipient will see it, and it follows the agent’s edits live, so keep it open while you ask for changes.

What the agent builds is an ordinary form: it is in Formstep under **Forms**, where you can open it in the editor and change anything by hand.

## 3. Ask for changes

Say what to change in the same conversation, naming the questions by their titles:

```
Make the VAT number optional and add a file upload for their certificate of incorporation at the end.
```

The open preview shows the change as soon as the agent makes it:

![The preview of the Supplier onboarding draft after the change: a note that this is an unpublished version, then Company name, Contact email, VAT number, a Yes or No question about 30-day payment terms, a Certificate of incorporation upload, and a Submit button](https://formstep.io/docs/guides/ai-agents/form-preview.png)

Most of what you set in the editor, you can ask an agent for: required or optional, a description, choice options, conditional logic, the theme, translations. For long forms, ask for one part at a time and check the preview in between.

## 4. Publish and get the field keys

When the preview looks right, ask the agent to publish:

```
Looks good. Publish it, give me the link to share, and list each question's field key.
```

The agent publishes the form and lists the [field keys](https://formstep.io/docs/requests/field-keys/). The first publish always creates a [share link](https://formstep.io/docs/sharing-publishing/sharing-embedding/#share-links) anyone can open, and the agent gives it to you. An agent reads the keys from the published form, so asked before you publish, it says it cannot list them yet.

Each key comes from the question’s title: _Company name_ becomes `company_name`. Keys are how a request prefills a question and how the answers come back, and they [stay the same](https://formstep.io/docs/requests/field-keys/#freeze) when you later rename a question. An agent cannot choose a key. To shorten a long one, edit it in the editor’s [Fields tab](https://formstep.io/docs/requests/field-keys/#where), best before the first publish, while no automation uses it yet.

> **Publishing makes the form live**
>
> Once published, anyone with the share link can submit the form. To take answers only from named people, ask the agent to revoke the share link and [send requests](https://formstep.io/docs/guides/ai-agents/send-a-request/) instead.

## Next steps

[Send a request with an AI agent](https://formstep.io/docs/guides/ai-agents/send-a-request/) — Ask one person to complete the form, prefilled, and read their answers back

[Question types](https://formstep.io/docs/building-forms/field-types/) — Every question type an agent can add

# Send a request with an AI agent

Ask a connected agent to send a Formstep request to one person, prefill and lock what you already know, and read the answers back when they are done.

## Before you start

You need an AI tool with [Formstep connected](https://formstep.io/docs/guides/ai-agents/connect/) and a published form. The examples use the one built in [Build a form with an AI agent](https://formstep.io/docs/guides/ai-agents/build-a-form/). What a request is, and every option it takes, is in [Creating requests](https://formstep.io/docs/requests/creating-requests/).

## 1. Ask for the request

Say which form, who it goes to, what you already know, and how the link reaches them:

```
Send a Formstep request with the "[Guide] Supplier onboarding" form to Ada Lovelace (ada@acme.example). Fill in the company name "Analytical Engines Ltd" and lock it so she cannot change it. Use supplier-2041 as the external ID. Don't email her; give me the link and I will send it myself.
```

The agent finds the form, reads its [field keys](https://formstep.io/docs/requests/field-keys/), and creates the request. It replies with the link for the recipient and when the request expires.

- A filled-in answer is prefilled; a locked one is shown but cannot be changed. See [Prefill, locked fields and hidden fields](https://formstep.io/docs/requests/creating-requests/#three-buckets).

- The external ID is your own id for this piece of work, like a supplier or deal number. You can refer to the request by it later, also in a new conversation.

- Ask the agent to email the recipient and Formstep sends the [invitation and reminders](https://formstep.io/docs/requests/invitations-and-reminders/), on Pro and Business. Otherwise you get the link and send it yourself. If the form has **Send reminders** on, Formstep still emails its scheduled reminders; to prevent that, also say _no reminders_.

> **Try it with a test request first**
>
> Say _send a test request_ while you try this out. A [test request](https://formstep.io/docs/requests/creating-requests/#test-mode) never emails anyone and counts nowhere, so open the link yourself. The Requests page lists it only with the **Show test requests** filter on. To look it up by external ID, tell the agent it is a test request. A test request cannot be reminded.

## 2. The recipient completes the form

The recipient opens the link and finds the company name filled in and locked:

![The request form with Company name showing Analytical Engines Ltd in a greyed-out field and the note 'Filled in by the sender.'](https://formstep.io/docs/guides/ai-agents/request-locked-field.png)

The request shows in Formstep under **Requests**, pending until the recipient submits and completed after:

![The Requests list with Ada Lovelace, ada@acme.example, the Supplier onboarding form, and a Completed badge](https://formstep.io/docs/guides/ai-agents/requests-list.png)

## 3. Read the answers

The agent is not told when the recipient submits. Ask it, in the same conversation or a new one:

```
Has the Formstep request supplier-2041 been answered? Show me the answers.
```

The agent looks the request up by its external ID and, once it is completed, lists each answer. A file answer comes with a download link. If the form has a [decision question](https://formstep.io/docs/requests/decisions-and-approvals/), the reply also says whether the recipient approved, declined or asked for changes.

To act on answers without asking, have a workflow receive a [callback](https://formstep.io/docs/developers/callbacks/) when the request finishes, or start one from [Zapier](https://formstep.io/docs/guides/zapier/request-outcome/).

## Remind or cancel

While a request is pending, ask the agent to _remind Ada about supplier-2041_ to send a reminder email now, or to _cancel_ it. Reminders need the recipient’s email and a Pro or Business plan; how often you can send them is in [Invitations, reminders and expiry](https://formstep.io/docs/requests/invitations-and-reminders/). Canceling is permanent: the link stops working at once, and most AI tools ask you to confirm first.

## Next steps

[The Requests page](https://formstep.io/docs/requests/managing-requests/) — Filters, one request in detail, and what you can do with it

[Field keys](https://formstep.io/docs/requests/field-keys/) — The short names an agent prefills and reads answers by

[MCP server](https://formstep.io/docs/developers/mcp-server/) — Every request tool an agent can call, and the limits

[Form templates](https://formstep.io/templates/) — Forms an agent can send as they are, each with its field keys listed
