BuilderGrid API
The BuilderGrid API gives you programmatic access to your construction data. Use it to build custom integrations, sync data with other tools, or automate your workflows.
Base URL
https://buildergrid.com/api/v1Authentication
All API requests require authentication using an API key. Pass your key in the Authorization header using the Bearer scheme.
Create and manage API keys in Developer Settings.
curl https://buildergrid.com/api/v1/projects \
-H "Authorization: Bearer bg_live_your_api_key"API keys follow the format bg_live_[32 hex characters] for production and bg_test_[32 hex characters] for testing.
Rate Limits
Rate limits are enforced per API key on a sliding 60-second window. When you exceed the limit, the API returns 429. Check the response headers to know your current limit status.
| Plan | Requests per minute |
|---|---|
| Starter | 100 |
| Pro | 500 |
| Enterprise | 2,000 |
Response headers: X-RateLimit-Remaining and X-RateLimit-Reset
Error Codes
Errors return a JSON object with an error field describing what went wrong.
| Status | Meaning | |
|---|---|---|
400 | Bad Request | Invalid or missing parameters |
401 | Unauthorized | Invalid or missing API key |
403 | Forbidden | API key lacks the required scope |
404 | Not Found | Resource does not exist |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Error | Something went wrong on our end |
{
"error": "Invalid API key."
}Projects
/v1/projectsList projects
Returns a paginated list of all projects for your company.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by status. Values: active, completed, on_hold, archived |
page | integer | No | Page number (default: 1) |
per_page | integer | No | Results per page, max 100 (default: 20) |
curl https://buildergrid.com/api/v1/projects \
-H "Authorization: Bearer bg_live_abc123..."{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Smith Residence Remodel",
"status": "active",
"type": "renovation",
"contract_value": 185000,
"start_date": "2026-01-15",
"end_date": "2026-06-30",
"address": "742 Evergreen Terrace, Springfield, IL",
"created_at": "2026-01-10T14:00:00Z",
"updated_at": "2026-03-22T09:15:00Z"
}
],
"meta": {
"total": 24,
"page": 1,
"per_page": 20
}
}/v1/projectsCreate a project
Creates a new project. Required scope: projects:write
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name |
status | string | No | Default: active |
type | string | No | Default: new_construction |
contract_value | number | No | Total contract value in dollars |
start_date | string | No | ISO date string (YYYY-MM-DD) |
end_date | string | No | ISO date string (YYYY-MM-DD) |
address | string | No | Project site address |
curl -X POST https://buildergrid.com/api/v1/projects \
-H "Authorization: Bearer bg_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"name": "Johnson Kitchen Renovation",
"status": "active",
"contract_value": 42500,
"start_date": "2026-05-01",
"address": "123 Oak Street, Denver, CO"
}'/v1/projects/{id}Get a project
Returns a single project by ID.
curl https://buildergrid.com/api/v1/projects/a1b2c3d4 \
-H "Authorization: Bearer bg_live_abc123..."Clients
/v1/clientsList clients
Returns a paginated list of clients.
| Parameter | Type | Required | Description |
|---|---|---|---|
search | string | No | Search by name or email |
page | integer | No | Page number (default: 1) |
per_page | integer | No | Results per page, max 100 |
{
"data": [
{
"id": "b2c3d4e5-...",
"first_name": "Margaret",
"last_name": "Johnson",
"email": "margaret@example.com",
"phone": "555-0142",
"address": "123 Oak Street, Denver, CO",
"created_at": "2026-02-14T10:00:00Z"
}
],
"meta": { "total": 38, "page": 1, "per_page": 20 }
}/v1/clientsCreate a client
Creates a new client. Required scope: clients:write
| Parameter | Type | Required | Description |
|---|---|---|---|
first_name | string | Yes | Client first name |
last_name | string | Yes | Client last name |
email | string | No | Email address |
phone | string | No | Phone number |
address | string | No | Mailing address |
Invoices
/v1/invoicesList invoices
Returns a paginated list of invoices with optional filters.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by status: draft, sent, paid, partial, overdue, cancelled |
project_id | string | No | Filter by project |
date_from | string | No | Filter invoices on or after this date (YYYY-MM-DD) |
date_to | string | No | Filter invoices on or before this date (YYYY-MM-DD) |
/v1/invoices/{id}/sendSend an invoice
Marks an invoice as sent and triggers the invoice.sent webhook event. Required scope: invoices:write
/v1/invoices/{id}/record-paymentRecord a payment
Records a payment against an invoice. Updates the balance and status automatically. Triggers payment.received and invoice.paid if fully paid.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | number | Yes | Payment amount in dollars |
payment_method | string | No | check, credit_card, bank_transfer, cash, other |
payment_date | string | No | ISO date string. Defaults to today. |
notes | string | No | Optional payment notes |
Estimates
/v1/estimatesList estimates
Returns estimates with optional status and project filters.
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | draft, sent, approved, declined, expired |
project_id | string | No | Filter by project ID |
Daily Logs
/v1/daily-logsList daily logs
Returns daily field reports.
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id | string | No | Filter by project |
date_from | string | No | Start date (YYYY-MM-DD) |
date_to | string | No | End date (YYYY-MM-DD) |
{
"data": [
{
"id": "c3d4e5f6-...",
"project_id": "a1b2c3d4-...",
"log_date": "2026-04-02",
"weather": "Partly cloudy",
"temperature": 68,
"crew_count": 6,
"work_summary": "Framing second floor east wing completed.",
"delays": null,
"created_at": "2026-04-02T17:30:00Z"
}
],
"meta": { "total": 45, "page": 1, "per_page": 20 }
}Schedule
/v1/scheduleList schedule items
Returns schedule tasks sorted by start date.
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id | string | No | Filter by project |
status | string | No | not_started, in_progress, completed, cancelled |
Leads
/v1/leadsList leads
Returns leads. Useful for syncing with external CRM systems.
/v1/leadsCreate a lead
Creates a new lead. Use this to push leads from your website or external CRM into BuilderGrid. Triggers lead.created.
| Parameter | Type | Required | Description |
|---|---|---|---|
first_name | string | Yes | Lead first name |
last_name | string | Yes | Lead last name |
email | string | No | Email address |
phone | string | No | Phone number |
source | string | No | Where this lead came from (e.g. website, referral, Houzz) |
estimated_value | number | No | Estimated project value |
Photos
/v1/photosList photos
Returns photo metadata including public URLs.
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id | string | No | Filter photos by project |
/v1/photos/upload-urlGet an upload URL
Returns a signed upload URL for uploading a photo directly to Supabase Storage. Upload your file to this URL using a PUT request, then the record is stored in BuilderGrid.
| Parameter | Type | Required | Description |
|---|---|---|---|
file_name | string | Yes | File name (e.g. foundation.jpg) |
project_id | string | Yes | Project to associate the photo with |
{
"data": {
"upload_url": "https://your-project.supabase.co/storage/v1/...",
"file_path": "company_id/project_id/1712000000000_photo.jpg",
"instructions": "Upload your file using a PUT request to the upload_url."
}
}Webhooks
Webhooks let you receive HTTP POST notifications when events happen in BuilderGrid. Configure webhook endpoints in Developer Settings or via the API.
Each delivery includes a signed payload. Verify the signature before processing to ensure requests are genuine.
Events reference
| Event | Description |
|---|---|
project.created | A new project was created |
project.updated | A project was modified |
project.completed | A project was marked complete |
invoice.created | A new invoice was created |
invoice.sent | An invoice was sent to a client |
invoice.paid | An invoice was fully paid |
invoice.overdue | An invoice passed its due date |
payment.received | A payment was recorded |
estimate.approved | An estimate was approved |
estimate.declined | An estimate was declined |
change_order.approved | A change order was approved |
change_order.declined | A change order was declined |
daily_log.created | A daily field report was submitted |
client.created | A new client was added |
lead.created | A new lead was created |
lead.status_changed | A lead status was updated |
warranty_request.created | A warranty request was submitted |
warranty_request.resolved | A warranty request was resolved |
time_entry.approved | A time entry was approved |
Verifying signatures
Each webhook request includes an X-BuilderGrid-Signature header. Verify it using your webhook secret to confirm the payload is genuine.
const crypto = require('crypto')
function verifyWebhook(payload, signature, secret) {
const expected = 'sha256=' +
crypto.createHmac('sha256', secret)
.update(payload)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
)
}
// In your Express handler:
app.post('/webhook', (req, res) => {
const signature = req.headers['x-buildergrid-signature']
const rawBody = JSON.stringify(req.body)
if (!verifyWebhook(rawBody, signature, "whsec_your_webhook_secret_here")) {
return res.status(401).send('Invalid signature')
}
const { type, data } = req.body
console.log('Event received:', type, data)
res.sendStatus(200)
})Example webhook payload
{
"id": "evt_7f3a2b1c-8d4e-4f5a-9b6c-1d2e3f4a5b6c",
"type": "invoice.paid",
"created_at": "2026-04-01T14:30:00Z",
"data": {
"id": "inv_a1b2c3d4-...",
"invoice_number": "INV-0023",
"total": 15000,
"balance_due": 0,
"status": "paid",
"client_id": "b2c3d4e5-...",
"project_id": "c3d4e5f6-..."
}
}Retries
If your endpoint returns a non-2xx status or times out (10 seconds), BuilderGrid retries the delivery up to 3 times with exponential backoff:
- -Attempt 1: 5 minutes after the first failure
- -Attempt 2: 30 minutes after the first failure
- -Attempt 3: 2 hours after the first failure
If a webhook records 10 consecutive failures, it is automatically disabled and you receive an in-app notification. Re-enable it in Developer Settings after fixing the issue.
Zapier Integration
BuilderGrid does not have an official Zapier app yet, but you can connect BuilderGrid to any Zapier-supported app using Zapier Webhooks and BuilderGrid webhooks.
Setup guide
- 1Create a new Zap and select Webhooks by Zapier as the trigger.
- 2Choose Catch Hook as the trigger event.
- 3Copy the Zapier webhook URL provided.
- 4Go to BuilderGrid Developer Settings and add a new webhook using that URL.
- 5Select the events you want to trigger the Zap.
- 6Test the connection using the Send test event button in BuilderGrid.
- 7Finish configuring your Zap action.
Example Zaps
- -When an invoice is paid in BuilderGrid, add a row to Google Sheets
- -When a new lead comes in, create a contact in HubSpot
- -When a daily log is submitted, send a Slack message to the team
- -When a project is completed, create a task in Asana
- -When an estimate is approved, create a project in Monday.com