Google Sheets integration
Verify contractor licenses in Google Sheets
Paste one script and a ContractorRoster menu appears. Select rows of contractors, click Verify, and get license status, trade, and contact filled in across 28 states. You only pay for the rows we match.
Verify a list without leaving the sheet
Already keeping contractors in a spreadsheet? Check whether each one is licensed and active without exporting anything or learning a new tool.
The script calls our verify endpoint per row and writes back the license status, number, trade, expiration, and any contact on file. Sort or filter on the confidence column to triage what to chase.
1. Get an API key
Emailed in under a minute. The same key works on the REST API and the MCP server. No card, no call.
2. Paste the script
Open Extensions › Apps Script, paste this, set your key, and Save. Reload the sheet and a ContractorRoster menu appears.
// Extensions → Apps Script. Paste this, set your key, Save, then reload the sheet.
// A "ContractorRoster" menu appears. Select rows of [ name, state, city ] and run Verify.
const CR_API_KEY = 'cr_live_YOUR_KEY';
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('ContractorRoster')
.addItem('Verify selected rows', 'verifySelected')
.addToUi();
}
function verifySelected() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getActiveRange();
const out = range.getValues().map(function (row) {
const res = UrlFetchApp.fetch('https://contractorroster.com/api/v1/verify', {
method: 'post',
contentType: 'application/json',
headers: { 'X-API-Key': CR_API_KEY },
payload: JSON.stringify({ name: row[0], state: row[1], city: row[2] }),
muteHttpExceptions: true,
});
const j = JSON.parse(res.getContentText());
const r = j.record || {};
return [j.matched ? r.license_no : '', r.status || '', j.match_confidence || 0, r.phone || '', r.email || ''];
});
// Writes 5 columns (license, status, confidence, phone, email) to the right.
sheet.getRange(range.getRow(), range.getLastColumn() + 1, out.length, 5).setValues(out);
}Put your three columns in name, state, city order, select them, then run ContractorRoster › Verify selected rows. Five columns (license, status, confidence, phone, email) fill in to the right.
Two things to know
- Set
CR_API_KEYto your key before saving. - The first run asks for authorization, since the script makes an outside request. Approve it once.
3. What comes back
Each call returns the matched license plus a confidence score. Use the fields you need from the response: record.license_no, record.status, match_confidence, and the rest.
{
"matched": true,
"match_confidence": 1,
"match_method": "exact",
"record": {
"license_no": "1000002",
"business_name": "RANDALL MARK DOCKERY",
"status": "CLEAR",
"trade": "C57",
"issue_date": "2015-01-10",
"expiration_date": "2027-01-31",
"city": "LODI",
"zip": "95242",
"phone": "(925) 383-0487",
"email": null,
"website": null
}
}No confident match returns { "matched": false } with any near candidates, and never charges you. Gate your flow on match_confidence to set your own bar.
Coverage & pricing
10¢ per match, from a prepaid balance. A miss costs nothing, so you only pay for hits. Top up from $50 via Stripe.
Coverage spans 28 stateswith 17 trades, sourced directly from each state’s licensing board. A contractor in a state we don’t cover yet returns matched: false. New states are added regularly.
Prefer to pull whole lists instead of verifying one at a time? The same key works on the MCP server and the HTTP API.