Contractor payment board that keeps you 1099 ready all year

See every contractor's paperwork, bank details and year to date pay in one table, then run and fund this cycle's payment batch from the same screen.

App
GustoGmailGoogle SheetsFinanceOperationsData SyncEmail Automation
PromptCreate

Build me a contractor operations board that my bookkeeper opens every pay cycle and leans on again at year end, so contractor compliance stops living in a spreadsheet nobody checks until January. It runs on Gusto for contractor records, forms and payments, Gmail for chasing missing paperwork, and Google Sheets as the payment ledger our books reconcile against. The whole design goal is that year to date paid and missing paperwork sit on the same row all year, rather than being discovered in a year end report against payments already made.

Settings the app stores and lets the user edit: the Gusto company, the tax year the year to date totals cover (default the current year), the reporting threshold that pins a contractor to the top (default 600 dollars), the pay period start and end dates plus the payment date for this cycle, the Google Sheets spreadsheet ID and tab holding the ledger, and the sending address and template wording for the chase emails.

The main screen is one table with a row per contractor. Load the roster with Gusto List Contractors. Dismissed contractors keep coming back in that list, so default the view to active and not dismissed using the onboarding and dismissal filters the endpoint supports, and give the user a toggle to bring dismissed contractors back in, because someone dismissed in June still needs a form for the money they were paid. Paginate explicitly with page and per (per maxes at 100) and keep reading until the last page on every list call. A truncated list silently understates year to date totals, which is exactly the failure this board exists to prevent.

Columns: contractor name and whether they are an individual or a business, wage type (hourly or fixed), the rate, onboarding status, payment method on file, bank account on file, missing forms, and year to date paid. Fill them like this. Get Contractor Payment Method tells you whether a method is actually configured and which one. List Contractor Bank Accounts tells you whether a real account exists behind it, because direct deposit selected with no bank account is still a blocker and must read as missing rather than as configured. List Contractor Forms gives the tax and onboarding forms on file and, by absence, the required ones that are not, shown as named chips such as W-9 rather than a bare count. List Contractor Payments across the whole tax year, fetched once with full pagination and grouped by contractor, gives the year to date paid figure.

Gusto returns money and hours as decimal strings such as "1234.56", so do every sum, comparison and threshold check with exact decimal arithmetic and never with floating point. Render amounts as currency with two decimals.

Above the table, pin an attention band: every contractor whose year to date paid has crossed the reporting threshold and who is still missing a required form or a usable payment method. Each pinned row states the exact gap in plain words, for example "paid 4,200 dollars this year, no W-9 on file" or "paid 1,150 dollars this year, direct deposit selected but no bank account". Sort the band by year to date paid descending, show a count so an empty band is obvious at a glance, and keep the band visible while the table scrolls. Also style anyone within a configurable distance below the threshold who is missing paperwork as a softer warning, so gaps get closed before the threshold is crossed.

Give the table search by name plus filters for onboarding status, missing forms only, missing payment details only, over threshold only, and include dismissed. These filters are how the board doubles as the year end review: filter to over threshold with dismissed included and the screen becomes the reporting checklist.

Clicking a row opens a detail drawer with that contractor's full form list from List Contractor Forms, each with its status and a view action. The view action calls Get Contractor Form PDF, which returns JSON containing a temporary s3url rather than the PDF bytes. Fetch that URL as a separate request with no Authorization header, since sending the Bearer token to the storage host fails. The link is short lived, so request it at click time instead of prefetching links when the table loads, and request a fresh one if the user returns to the drawer later.

From the same board the bookkeeper builds this cycle's payment batch. Each row gets an input for the cycle that follows the wage type on the record: hours for hourly contractors, a fixed amount for fixed wage contractors, with optional bonus and reimbursement fields where the payment supports them. As amounts are entered, a sticky summary bar shows how many contractors are in the batch and the exact running total. Rows that cannot legally be paid, meaning onboarding is incomplete or there is no usable payment method and bank account, are disabled with the reason shown in place rather than hidden from the table.

A Preview button calls Preview Contractor Payments for the whole batch and shows the dry run back in the table: per contractor amounts, the total Gusto calculates, and any warnings it returns, without creating anything. Nothing is created or funded until a person confirms. The confirmation step restates the number of contractors and the exact batch total and requires an explicit confirm; never fund automatically off the back of a preview. On confirm, walk the batch one contractor at a time: Create Contractor Payment, then Fund Contractor Payment for the payment just created. Treat created and funded as two distinct states, because a payment can exist unfunded. Each row carries its own status through pending, created, funded and failed, and a Gusto validation error is shown inline on the row that failed while the rest of the batch continues. A row stuck at created but not funded gets a Retry funding action that funds the existing payment rather than creating a second one.

Every row with a gap gets a Request missing details button. It composes an email to that contractor through Gmail Send a Message naming exactly what their row is short of, for example the specific missing form or the fact that no bank account is on file for direct deposit, rather than a generic reminder. Let the user review and edit the draft before it goes. Record when a request was last sent to each contractor and show "requested 5 days ago" on the row so nobody is chased twice in a week, and allow selecting several rows to send each of them their own personalised version in one action.

After a batch finishes funding, append it to the Google Sheets ledger with Append Values: one row per funded payment carrying the payment date, pay period, contractor name, individual or business, wage type, hours or fixed amount, amount paid, payment method, the batch identifier, and that contractor's year to date total after the payment. Append only, never overwrite, so the ledger stays an audit trail the books can reconcile against Gusto. Only funded payments are written; a created but unfunded payment must not appear in the ledger.

Keep a batch history view listing past batches with their date, contractor count, total, and any rows that ended failed or unfunded, so an unfinished batch is easy to find and close out later. Persist batches and the chase email log in the app so state survives a reload and a second bookkeeper sees the same picture.

What does this prompt do?

  • One table of every active contractor showing their type, wage type and rate, onboarding status, whether payment details are genuinely on file, which tax forms are still missing, and how much they have been paid so far this year.
  • Anyone already paid more than 600 dollars this year who is still missing a form or payment details gets pinned to the top of the screen, so the reporting problem surfaces in March instead of the following January.
  • Build this cycle's payment batch on the same board: enter hours or a fixed amount per person, sanity check the run, and see the exact total before anything is funded. Nothing leaves your account until a person confirms it.
  • One click emails a contractor asking for exactly what their row is short of, and every funded batch is appended to a Google Sheets ledger so the books reconcile against payroll.

What do I need to use this?

  • A Gusto account with contractors set up, and an admin who is allowed to create and fund contractor payments
  • A company bank account connected in Gusto, since confirming a batch moves real money
  • A Google account so the chase emails go out from the address your contractors already recognise
  • A Google Sheet with a tab the app can append ledger rows to

How can I customize it?

  • Change the reporting threshold that pins someone to the top, or point the board at a previous tax year to turn it into a clean year end review
  • Edit the wording of the chase email and choose which missing items it asks for
  • Pick which columns land in the ledger sheet, and whether a batch over a certain total needs a second person to confirm it

FAQs

Could this pay someone by accident?
No. You enter the amounts, run a sanity check, and then confirm a screen that restates how many contractors are in the batch and the exact total. Nothing is funded before that confirmation, and anyone without usable payment details cannot be added to a batch at all.
Why do people we stopped working with still show up?
Payroll lists keep returning dismissed contractors, so the board filters them out by default. There is a toggle to bring them back in, which is what you want at year end, since someone you dismissed in June still needs a tax form for the money they were paid.
Can I open the actual tax forms from the board?
Yes. Open a contractor's row and you get their full form list with a view action on each one. The download link is generated fresh at the moment you click, because those links expire quickly.
Does this file our 1099s for us?
No. Filing still happens through Gusto or your accountant. The point of the board is that by the time filing season arrives, every contractor over the threshold already has their paperwork and payment details on file.
What if a contractor is paid a flat fee rather than by the hour?
Each row follows the wage type on the record, so hourly contractors get an hours field and fixed fee contractors get an amount field. The running total covers both.

Related templates

Prospecting desk that builds account lists from the live web

Stop buying stale lists. Reps run a saved search, work the results like an inbox, and only the accounts they approve ever reach your CRM.

Hyperbrowser
HubSpot
Google Sheets
App
Influencer campaign roster board with AI creator briefs

Drag creators through Sourced to Wrapped on a board grouped by campaign, with audience stats on every card and a one-click brief for each creator.

HypeAuditor
Google Sheets
Notion
App
Morning repricing console for Shopify with margin-safe rules

Pick a repricing rule, send an assistant out to check competitor pages, then approve the new prices that clear your margin floor.

Hyperbrowser
Shopify
Google Sheets
App
Pre-flight bounce check before you launch a cold email sequence

See the projected bounce rate for any outbound send before it goes out, and keep the launch button locked until the list is clean enough to be safe.

Hunter
Google Sheets
App
Compare every Hireflix candidate for a role side by side

A calibration board that lines up every candidate's answer to the same question, hides names until your panel has scored, and writes the agreed rating back.

Hireflix
Gmail
App
Per-device electricity cost explorer for your smart home

Pick any date range and see what each device in your home actually cost to run, not just how many kilowatt-hours it used.

Home Assistant
Google Sheets
App

Stop discovering missing contractor paperwork in January.

Give your bookkeeper one board where contractor paperwork, year to date pay and this cycle's payment batch finally live together.