---
title: "Automate Vendor Onboarding with MS Forms and Power Automate"
description: "Build a vendor intake process with Microsoft Forms, a SharePoint list with unique vendor columns, and a Power Automate flow that blocks duplicates."
canonical: "https://adamtheautomator.com/vendor-onboarding-power-automate-forms/"
---

# Automate Vendor Onboarding with MS Forms and Power Automate

> Build a vendor intake process with Microsoft Forms, a SharePoint list with unique vendor columns, and a Power Automate flow that blocks duplicates.

Source: https://adamtheautomator.com/vendor-onboarding-power-automate-forms/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Automate Vendor Onboarding with MS Forms and Power Automate](https://adamtheautomator.com/wp-content/uploads/publisher/3ec5d9c85b2b8166a0c8fe5c6a6e2cf0/02115bb49a2ca8bd82d69f35a6bd416a877bdf2ea5758c16798be49cd0933db8.webp)

# Automate Vendor Onboarding with MS Forms and Power Automate

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)27 October 202614 min. read

Categories: [Business Process Automation](/category/business-process-automation/)

Tags:[Power Automate](/tag/power-automate/)[SharePoint](/tag/sharepoint/)[Microsoft 365](/tag/microsoft-365/)[Automation](/tag/automation/)[Microsoft Teams](/tag/microsoft-teams/)

Table of Contents

*   [Prerequisites](#prerequisites)
*   [Design the Vendor Onboarding Form the Flow Can Trust](#design-the-vendor-onboarding-form-the-flow-can-trust)
*   [The Question Set That Survives Approval](#the-question-set-that-survives-approval)
*   [Where Forms Stops and the Flow Starts](#where-forms-stops-and-the-flow-starts)
*   [File Uploads Change the Ownership Model](#file-uploads-change-the-ownership-model)
*   [Make the SharePoint List the Record of Truth](#make-the-sharepoint-list-the-record-of-truth)
*   [Script the List So You Can Rebuild It](#script-the-list-so-you-can-rebuild-it)
*   [Build the Vendor Onboarding Flow in Power Automate](#build-the-vendor-onboarding-flow-in-power-automate)
*   [Read the Response Payload Correctly](#read-the-response-payload-correctly)
*   [Write the Item, Then Ask for Approval](#write-the-item-then-ask-for-approval)
*   [Notify the People Who Need to Know](#notify-the-people-who-need-to-know)
*   [Stop Duplicates Before They Become Vendors](#stop-duplicates-before-they-become-vendors)
*   [The Pre-Check Gives the Good Error](#the-pre-check-gives-the-good-error)
*   [Concurrency Control Cannot Be Turned Off](#concurrency-control-cannot-be-turned-off)
*   [Make the Trigger Itself Idempotent](#make-the-trigger-itself-idempotent)
*   [Handle the Failures Nobody Demos](#handle-the-failures-nobody-demos)
*   [Wrap the Write in a Scope](#wrap-the-write-in-a-scope)
*   [Set the Retry Policy on Purpose](#set-the-retry-policy-on-purpose)
*   [Log What Run History Forgets](#log-what-run-history-forgets)
*   [Govern the Record: Access, Retention, and DLP](#govern-the-record-access-retention-and-dlp)
*   [Least Privilege Starts With the Connection Owner](#least-privilege-starts-with-the-connection-owner)
*   [Retention Lives on the List](#retention-lives-on-the-list)
*   [DLP Will Block Your First Save](#dlp-will-block-your-first-save)
*   [Measure Cycle Time and Document Completeness](#measure-cycle-time-and-document-completeness)
*   [Set the Baseline From the Mailbox You Just Searched](#set-the-baseline-from-the-mailbox-you-just-searched)
*   [Instrument It in a View](#instrument-it-in-a-view)
*   [Ship the First Version This Week](#ship-the-first-version-this-week)

Do not let a shared mailbox become your vendor master record. Search your accounts payable (AP) team’s inbox for W-9, count the threads, then count how many end with someone asking the same vendor to send the same document twice. That mailbox is your vendor onboarding process. It has no schema, no duplicate check, and no record of who approved what.

You are about to replace it with three objects that hand work to each other: a Microsoft Forms intake form for internal requesters, a [SharePoint list](https://support.microsoft.com/en-us/sharepoint/lists/get-started-with-sharepoint/introduction-to-lists) that holds the vendor record with a unique constraint on the email address, and a [Power Automate cloud flow](https://learn.microsoft.com/en-us/power-automate/overview-cloud) that validates each response, blocks duplicates, writes the item, routes an approval, and stamps the outcome back onto the record. The build runs in that order because the form decides what the flow can read and the list decides what the flow can store. The diagram below shows the three objects in order, ending with the approval and the two notification channels.

![Intake to approval flow](https://adamtheautomator.com/wp-content/uploads/publisher/c7fb4df534e67bf31ef6803b4a975313570205aaaa37ecf85705af389711b0bf.jpg)

## Prerequisites

If you want to follow along in a live tenant, you need:

*   **Microsoft 365 licensing that includes Forms, SharePoint, Approvals, Outlook, and Teams.** Every connector here is a standard connector, and the [Microsoft Forms connector reference](https://learn.microsoft.com/en-us/connectors/microsoftforms/) lists one current trigger plus its deprecated duplicate, and two actions; only Get response details reads a response.
    
*   **Edit rights on a SharePoint team site where you can create a list.** A team site keeps membership aligned with the AP group you will grant list access to later.
    
*   **Permission to create a cloud flow in the default Power Platform environment.** Approvals needs a [Dataverse database](https://learn.microsoft.com/en-us/power-apps/maker/data-platform/data-platform-intro), and the default environment provisions one automatically. In a non-default environment, the first person to run an approval flow needs an admin role so that database can be created.
    
*   **A disposable copy of the form for testing.** Point the flow at the copy until the duplicate and failure branches behave, then repoint it at production.
    

The five services update continuously, so this walkthrough names connectors and action labels instead of a build number.

## Design the Vendor Onboarding Form the Flow Can Trust

Microsoft Forms captures answers and hands them to a single action, so the question set has to carry the structure the flow cannot add later.

### The Question Set That Survives Approval

Build one form with five short sections and a small required set.

1.  Company identity: legal name (required), DBA, entity type, country of incorporation.
    
2.  Contacts: AP contact name and AP email (both required), phone, escalation contact.
    
3.  Tax and compliance: federal tax classification, last four digits of the tax ID (required), W-9 upload, certificate of insurance upload, backup withholding question.
    
4.  Payment: preferred method, remittance email, whether the vendor requires a purchase order.
    
5.  Business context: what the vendor supplies, estimated annual spend, contract reference.
    

The federal tax classification has to match [line 3a of the W-9](https://www.irs.gov/pub/irs-pdf/fw9.pdf), because it drives 1099 reporting later and a mismatch forces AP to reopen the record. The tax ID question asks for the last four digits only, with a subtitle that says so: “Enter the last four digits only. Do not enter a full EIN or SSN.”

### Where Forms Stops and the Flow Starts

[Open-text response validation](https://techcommunity.microsoft.com/blog/microsoftformsblog/validate-open-text-responses-in-microsoft-forms/4189615) has been in Forms since July 2024, and it lets you restrict a Text question to Email, URL, Number, or a length range, so a malformed address cannot be submitted at all. What it cannot do is check an answer against what you already hold: no custom regular-expression pattern, no comparison across fields, no uniqueness test against the vendor list. Normalization and duplicate prevention stay with the flow.

Forms also has ceilings. A form holds [200 questions and 5,000,000 responses](https://support.microsoft.com/en-us/forms/form-question-response-and-character-limits-in-microsoft-forms) on Microsoft 365 business plans, and “one response per person” is guaranteed only within a continuous set of 50,000 responses. That number is why the Forms setting cannot be your duplicate control.

### File Uploads Change the Ownership Model

File upload questions accept a maximum of 10 files, and they work only for internal respondents. Microsoft’s [file upload help page](https://support.microsoft.com/en-us/forms/add-questions-that-allow-for-file-uploads-in-microsoft-forms) restricts them to “Only people in my organization can respond” or “Specific people in my organization can respond”, which rules out an anonymous vendor portal on top of Forms.

Uploads land in the form owner’s OneDrive for an individual form, and on the Microsoft 365 group’s SharePoint site for a group form. If the owner leaves and their OneDrive is deprovisioned, the W-9s leave with it. Build the form as a group form, and expect that [converting an individual form to a group breaks the existing upload questions](https://learn.microsoft.com/en-us/troubleshoot/microsoft-365-apps/forms/resolve-file-upload-errors-forms), because the published fix is to delete and recreate them.

* * *

_**Warning: Do not collect a full EIN or SSN in a form field. The response payload is visible to anyone with run-history access to the flow, so a full tax ID in an answer becomes a full tax ID in a run log.**_

* * *

The list closes the gaps the form cannot, because it can enforce rules at the data layer.

## Make the SharePoint List the Record of Truth

The tempting shortcut is an Excel workbook. Microsoft’s [Forms to Excel workflow guidance](https://support.microsoft.com/en-us/forms/setting-up-an-automated-workflow-between-microsoft-forms-and-excel-through-power-automate) shows that the flow needs a real Excel table rather than a range. The mapping breaks when the workbook moves or the table is renamed, and nothing in the file enforces a unique vendor email.

A SharePoint list gives you typed columns, unique constraints, item-level permissions, versioning, retention labels, and a queryable data set, which is what makes it the system of record.

| Column | Type | Why it exists |
| --- | --- | --- |
| Title | Single line (built-in) | Composed as vendor name plus submission date |
| VendorName | Single line, required | Legal entity name |
| VendorEmail | Single line, required, unique | Primary duplicate key |
| TaxIdLast4 | Single line | Last four digits only |
| Status | Choice | Submitted, Pending Review, Approved, Rejected, Blocked |
| SubmissionDate | Date and time | Stamped by the flow, not the form |
| W9Received | Yes/No | Gate for approval |
| Reviewer | Person or Group | Assigned from a routing table |
| ResponseId | Single line, unique | [A replay-safe intake key](https://adamtheautomator.com/power-automate-document-intake-pipeline/) |

### Script the List So You Can Rebuild It

There is a click path: **New**, **List**, **Blank list**, then a column at a time. The repeatable version is a [SharePoint site script](https://learn.microsoft.com/en-us/sharepoint/dev/declarative-customization/site-design-json-schema) you can apply to a dev site, then a test site, then production.

```json
{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/site-design-script-actions.schema.json",
  "actions": [
    {
      "verb": "createSPList",
      "listName": "Vendor Onboarding",
      "templateType": 100,
      "subactions": [
        {
          "verb": "addSPField",
          "fieldType": "Text",
          "displayName": "Vendor Name",
          "internalName": "VendorName",
          "isRequired": true,
          "addToDefaultView": true,
          "id": "a1b2c3d4-1111-4a01-9f01-000000000001"
        },
        {
          "verb": "addSPField",
          "fieldType": "Text",
          "displayName": "Vendor Email",
          "internalName": "VendorEmail",
          "isRequired": true,
          "enforceUnique": true,
          "addToDefaultView": true,
          "id": "a1b2c3d4-1111-4a01-9f01-000000000002"
        },
        {
          "verb": "addSPField",
          "fieldType": "Text",
          "displayName": "Response Id",
          "internalName": "ResponseId",
          "isRequired": true,
          "enforceUnique": true,
          "addToDefaultView": false,
          "id": "a1b2c3d4-1111-4a01-9f01-000000000003"
        },
        {
          "verb": "addSPFieldXml",
          "addToDefaultView": true,
          "schemaXml": "<Field ID=\"{a1b2c3d4-1111-4a01-9f01-00000000000a}\" Type=\"Choice\" DisplayName=\"Status\" Required=\"TRUE\" Format=\"Dropdown\" StaticName=\"Status\" Name=\"Status\"><Default>Submitted</Default><CHOICES><CHOICE>Submitted</CHOICE><CHOICE>Pending Review</CHOICE><CHOICE>Approved</CHOICE><CHOICE>Rejected</CHOICE><CHOICE>Blocked</CHOICE></CHOICES></Field>"
        }
      ]
    }
  ]
}
```

Two details do the work. `enforceUnique` on **Vendor Email** and **Response Id** creates a real database constraint, so a duplicate write fails instead of silently adding a row. `addSPFieldXml` handles the Choice column because the plain `addSPField` verb supports only Text, Note, Number, Boolean, User, and DateTime.

Indexes are not exposed by those verbs. Add them in **List settings**, **Indexed columns** for **Status**, **SubmissionDate**, and **VendorEmail**, and turn on versioning under **Versioning settings** so every approval edit is attributable. Keep single-line text under 255 characters, and avoid lookup columns, since [`Get items` fails when a list has more than 12 lookup columns](https://learn.microsoft.com/en-us/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers).

The list now refuses duplicates at the storage layer.

## Build the Vendor Onboarding Flow in Power Automate

Create an automated cloud flow and choose **When a new response is submitted** from the Forms connector. That connector has one current trigger plus a deprecated duplicate, and two actions; only **Get response details** reads a response, so the response ID from the trigger is the only key the flow needs.

The capture below shows those actions in order, including the duplicate branch into **Terminate**.

![Flow steps in the designer](https://adamtheautomator.com/wp-content/uploads/publisher/80b8a546a271b971377d715bcba380a8dd843649b65327bdbab88bf081d20bf9.jpg)

| Step | Action | Connector |
| --- | --- | --- |
| 1 | When a new response is submitted | Microsoft Forms |
| 2 | Get response details | Microsoft Forms |
| 3 | Compose, normalized email | Data Operation |
| 4 | Get items, duplicate check | SharePoint |
| 5 | Condition, duplicate or not | Control |
| 6 | Terminate, duplicate branch | Control |
| 7 | Create item | SharePoint |
| 8 | Start and wait for an approval | Approvals |
| 9 | Condition, outcome | Control |
| 10 | Update item, approved or rejected | SharePoint |
| 11 | Send an email (V2) and post to Teams | Outlook, Teams |

### Read the Response Payload Correctly

Response field keys are question IDs such as `r1a2b3c4d5e6f`, not display names. Copy them from **Peek code** on **Get response details**.

```text
trim(toLower(outputs('Get_response_details')?['body']?['r1a2b3c4d5e6f']))
```

The `trim` and `toLower` pair makes `AP@Acme.example` and `ap@acme.example` compare equal later. Keep the null-safe `?` on both lookups: inside a condition branch, a skipped step makes a plain `body()` reference throw.

The list item’s **Title** combines the vendor name with the submission date:

```text
concat(outputs('Get_response_details')?['body']?['rVendor'], ' - ', formatDateTime(utcNow(),'yyyy-MM-dd'))
```

### Write the Item, Then Ask for Approval

**Create item** maps the answers onto the list and stamps three fields the form never sees: **ResponseId** from `triggerOutputs()?['body/responseId']`, **Status** as Submitted, and **SubmissionDate** from `utcNow()`.

Approval type changes the process, and the value at stake should pick it. Use one AP manager for a routine reorder or renewal, and AP plus Legal for every new vendor or any vendor whose estimated annual spend crosses the tier your controller sets. [Four approval types](https://learn.microsoft.com/en-us/power-automate/get-started-approvals) are documented, and three fit vendor intake:

*   Approve/Reject, first to respond: one AP manager, fastest turnaround.
    
*   Approve/Reject, everyone must approve: AP plus Legal, where a single rejection ends the request.
    
*   Custom responses, wait for one response: Approve, Request more info, Reject.
    

The [approvals connector reference](https://learn.microsoft.com/en-us/connectors/approvals/) warns that custom-response approvals assigned to many users with “Everyone must approve” can fail because of data-size limits in the results field, so keep that combination to small approver counts. Basic Approve and Reject responses are case-sensitive, and the flow creator is always shown in the approval details to prevent spoofing.

```text
if(equals(outputs('Start_and_wait_for_an_approval')?['body/outcome'], 'Approve'), 'Approved', 'Rejected')
```

### Notify the People Who Need to Know

Use **Send an email (V2)** rather than the older **Send an email** action, and do not build follow-up logic that looks for the sent message later: V2 does not return a message ID. Post the outcome with **Post a message in a chat or channel**, which cannot post to a private channel and cannot mark a message urgent.

* * *

_**Pro Tip: Point the Teams post at the list item, not at the approval. The approval link expires with the run, and the list item is the thing people will still need in three weeks.**_

* * *

Submit the same form twice in a row and you have two vendors.

## Stop Duplicates Before They Become Vendors

Forms triggers get retried, and anyone with edit rights can resubmit a run from the history. A pre-check alone cannot stop both submissions in a race.

| Layer | Where it runs | What it stops | Weakness |
| --- | --- | --- | --- |
| One response per person | Form setting | Repeat submissions by one person | Guaranteed only to 50,000 responses |
| Get items pre-check | Flow | Obvious duplicates, with a friendly message | Race-prone under concurrent runs |
| Unique columns | List | Any duplicate write | Fails the action, needs a failure branch |
| Trigger condition | Trigger | Replay of a processed response | No run history when it fires |

### The Pre-Check Gives the Good Error

Add **Get items** with the list address, a filter on the email column, and **Top Count** set to 1. Then a **Condition** on `empty(outputs('Get_items')?['body/value'])`: if the collection is not empty, the vendor already exists.

```text
VendorEmail eq 'ap@acme.example'
VendorEmail eq 'ap@acme.example' and Status eq 'Pending Review'
SubmissionDate ge '@{formatDateTime(addDays(utcNow(),-30),'yyyy-MM-dd')}'
```

Those filters use the operators the SharePoint connector supports, including `eq`, `ne`, `lt`, and `startswith`. Spaces in a column name become `_x0020_`, and the filter should target an indexed column or the query scans the list. Microsoft’s [Get items guidance](https://learn.microsoft.com/en-us/sharepoint/dev/business-apps/power-automate/guidance/working-with-get-items-and-get-files) states: “The default item limit is 100 and items are paginated by default as well.” Set **Top Count** explicitly so a lookup cannot quietly return a partial page.

In the duplicate branch, **Terminate** with status Succeeded and a message naming the existing item ID. A duplicate is not an error, and marking it Failed pollutes every failure dashboard you build later.

### Concurrency Control Cannot Be Turned Off

The pre-check is only meaningful if two runs cannot pass it simultaneously. Open the trigger’s **Settings**, set **Concurrency Control** to On, and set the degree of parallelism to 1. The default is off, which means unlimited concurrent runs.

Concurrency control cannot be turned off once it is enabled. Disabling it requires deleting and re-adding the trigger, and the connector documents a `CannotDisableTriggerConcurrency` error that needs a JSON export workaround.

### Make the Trigger Itself Idempotent

Add a [trigger condition](https://learn.microsoft.com/en-us/power-automate/customize-triggers) that tests whether the incoming response ID already exists in the list. A condition that evaluates false stops the run before it starts, produces no run history, and spends no Power Platform requests.

Duplicates now fail at three separate points, and the friendly message comes from the cheapest one. The next problem is the run that dies halfway through, after the vendor has been told their paperwork arrived.

## Handle the Failures Nobody Demos

Most tutorials end at the notification. Real intake fails in the middle: [an approval sits past its timeout](https://adamtheautomator.com/power-automate-expense-approval-flow/), SharePoint throttles a write, or a connection breaks when its owner changes roles.

The capture below shows a wrapped failure: scope failed, parallel branch succeeded.

![Failed run and branch](https://adamtheautomator.com/wp-content/uploads/publisher/63236d75a32d5149521e51cea558962eb3f6abcf0e4af796c690acdfcf0f749a.jpg)

### Wrap the Write in a Scope

Put **Create item**, the approval, and the updates inside a **Scope** action. Add a parallel branch below it and use **Configure run after** on that branch to fire when the scope has failed. The branch posts to Teams and writes a row to a **Flow Log** list with the run ID, response ID, stage, and error message.

[Configure run after](https://adamtheautomator.com/stop-copilot-auto-approvals-human-loop/) exposes four conditions: has failed, is skipped, has timed out, and is successful. The difference matters: an approval that times out does not report as a failure everywhere downstream.

### Set the Retry Policy on Purpose

Default retries follow the owner’s license. Microsoft 365 plans put a flow in the low performance profile, which [retries twice at increasing intervals](https://learn.microsoft.com/en-us/power-automate/limits-and-config); medium and high profiles retry up to twelve times. If **Get response details** fails intermittently, set a custom policy on that action: four retries with a PT30S exponential interval.

An outbound synchronous request times out at 120 seconds, so a step that validates a tax ID against an external service needs the asynchronous pattern.

### Log What Run History Forgets

A run lasts at most 30 days including time spent waiting on an approval, and run history is kept for 30 days. A vendor approval that takes six weeks ends as a timed-out run whose evidence has expired by the time anyone asks about it.

* * *

_**Reality Check: The 30-day run duration is also your approval deadline. If Legal routinely takes longer, the flow needs a reminder cadence and a resubmission path.**_

* * *

Flows with continuous errors are disabled after 14 days, and flows with no trigger activity for 90 days may be turned off, with premium-licensed flows exempt. The [flow limits documentation](https://learn.microsoft.com/en-us/power-automate/limits-and-config) is the page to reread when a flow that used to work stops appearing in the history.

A flow that fails loudly and leaves a row behind is auditable. A flow running under an AP clerk’s personal connection is a governance problem waiting for that clerk to change jobs.

## Govern the Record: Access, Retention, and DLP

The data includes a partial tax ID, a W-9, an insurance certificate, and sometimes remittance instructions. Two rules hold without legal advice: collect the last four digits only, and never collect bank details in a form field.

### Least Privilege Starts With the Connection Owner

Create the flow’s connections under a service account with Contribute on the vendor list and nothing else, instead of under the AP clerk building it. Break permission inheritance on the list itself so the site’s Members group does not automatically see tax data, give Legal Read at the list level only, and turn off external sharing on the site.

Ownership has a documented cost. Microsoft Learn’s [flow limits page](https://learn.microsoft.com/en-us/power-automate/limits-and-config) states: “If the original owner leaves the organization, the flow reverts to the Low performance profile.” The low profile also caps daily Power Platform requests at 10,000, which is plenty for vendor intake and a surprise during month-end reporting.

### Retention Lives on the List

[Microsoft Purview retention](https://learn.microsoft.com/en-us/purview/retention) policies and labels cover SharePoint, OneDrive, Exchange, Teams, Viva Engage, and Copilot content. Forms responses are not in that list of workloads, so a retention policy will never govern your form’s answer store. Apply the label to the SharePoint list, which is the copy Purview can hold.

Deleting a form from the **Deleted forms** tab permanently deletes the form and every response with it. If the list is the system of record, that click costs you a form. If it is not, that click costs you the intake history.

### DLP Will Block Your First Save

Connectors are classified into Business, Non-Business, and Blocked groups, and data cannot flow between connectors in different groups. New policies put all connectors in Non-Business by default, so a tenant where IT moved SharePoint into Business but never moved Forms will refuse to save this flow. The [connector classification documentation](https://learn.microsoft.com/en-us/power-platform/admin/dlp-connector-classification) covers the model; the fix is an admin moving Forms, Approvals, Teams, and Outlook into the Business group.

Governance is also where a Forms build shows its edges: if the process needs a portal or bank-change controls, [Adam’s automation consulting work](https://adamtheautomator.com/about-adam/) covers that build. The record now outlives the run, and whether the process improved is a question the flow cannot answer for you.

## Measure Cycle Time and Document Completeness

Pick the measurements before you switch the form on, while the mailbox still holds the baseline.

| Measure | What it counts | Where it comes from |
| --- | --- | --- |
| Time to onboard | Submission date to approved date | SubmissionDate, ApprovedDate |
| Approver response time | Approval start to outcome | Approval timestamps, read in UTC |
| Rework rate | Records returned for missing documents | Status changes back to Pending Review |
| Document completeness | Vendors approved with a W-9 on file | W9Received on approved items |
| Duplicate attempts | Terminated duplicate runs | Flow Log rows with stage Duplicate |

### Set the Baseline From the Mailbox You Just Searched

Take the last 20 onboardings and timestamp two events for each: the first request and the vendor’s first payment run. The gap is your before number.

### Instrument It in a View

Add an **ApprovedDate** column that the approval branch stamps, then build three views: pending more than five days, approved this month, and approved with **W9Received** set to No. Those cover throughput, backlog, and document gaps without a reporting tool.

Keep view filters on indexed columns. A query that exceeds the [5,000 item list view threshold](https://support.microsoft.com/en-us/sharepoint/lists/data-and-lists/list-view-threshold-for-large-lists-and-libraries) is blocked and raises an error, so the view fails outright. Partial results come from a separate limit: `Get items` without pagination returns only its first page. Three numbers and three views are enough to argue for the next change.

## Ship the First Version This Week

Build in this order, and resist adding a step until the previous one is boring:

1.  Create the list from the site script, then add the indexes and turn on versioning.
    
2.  Build the form so each question maps to a column you just created.
    
3.  Build the flow against a copy of the form, with the duplicate pre-check, the unique columns, and concurrency control on.
    
4.  Run three test submissions: one clean, one with an email that already exists, and one with a required field deliberately blank.
    
5.  Turn on the approval and the failure branch, then watch the first ten real submissions by hand.
    

The first version will not handle contract renewals, certificate-of-insurance expiry, or sanctions screening. Add a recertification view when the list passes a few hundred rows, and keep the flow short enough that one person can read it end to end.

Microsoft’s [overview of Forms and Power Automate](https://learn.microsoft.com/en-us/power-automate/forms/overview) is the reference for the connector behavior this build depends on. Everything else is a decision you make once, in the design, instead of every time a vendor emails a W-9.

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fvendor-onboarding-power-automate-forms%2F&text=Automate%20Vendor%20Onboarding%20with%20MS%20Forms%20and%20Power%20Automate)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fvendor-onboarding-power-automate-forms%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fvendor-onboarding-power-automate-forms%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/publisher/3ec5d9c85b2b812d96aaea8aa772a1e7/1406d20d337f1ef7937f468af2feb30f4a99e0ac228d4316500d0d14b5868bd7.png)

### [Power Automate: Streamline Invoice Approvals in Teams](/power-automate-invoice-approvals-teams/)

Build a Power Automate flow that routes invoice approvals through Teams, stores documents in SharePoint, and preserves an audit trail.

![](https://adamtheautomator.com/wp-content/uploads/publisher/3ec5d9c85b2b81b19274c73baf4c55f3/98f4af306255355a84e7293721f7eba0ae787ac2055f021d4fddbae4f4385bee.webp)

### [Automate Expense Report Approvals with Power Automate](/power-automate-expense-approval-flow/)

Build a Power Automate approval flow on a SharePoint list that routes expense reports, closes the self-trigger loop, and exports approved spend for finance.

![](https://adamtheautomator.com/wp-content/uploads/2026/07/featured_image-3.webp)

### [Power Automate: Build a Reliable AI Document Intake Pipeline](/power-automate-document-intake-pipeline/)

Build a Power Automate intake pipeline that deduplicates Outlook attachments, extracts fields with AI Builder, and routes low-confidence results to Teams.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
