API reference
Groundbook API
Every route the website uses, open to your own code. Requests act as your account with exactly your permissions. Each endpoint shows curl and the gb command line; assistants reach the same routes through the tools named on it.
Authentication
Create an API key in Connectors → API keys and send it as a bearer token. A read-only key can call GET routes only. Keys never carry admin powers, and you can revoke one at any time.
curl "https://app.groundbook.ai/api/auth/me" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"Assistants use OAuth 2.1 instead: authorization code with PKCE, dynamic client registration, and rotating refresh tokens. Discovery is at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource; the MCP endpoint is https://app.groundbook.ai/api/mcp. An OAuth access token works on every route below in the same way as a key.
The base URL is https://app.groundbook.ai. Bodies are JSON; ids are UUIDs; times are ISO 8601 in UTC.
Errors
Every error is JSON with one plain-English error message you can show to a person.
{ "error": "Wait for every file to finish analyzing before payment." }| Status | Type | Meaning |
|---|---|---|
| 400 | Bad request | A field is missing or out of range. The message says which. |
| 401 | Unauthorized | No key, a revoked key, or an expired OAuth token. Refresh the token or create a new key. |
| 403 | Forbidden | A read-only key on a write route, or an action only the owner can take. |
| 404 | Not found | The id does not exist or your account cannot open it. We do not say which. |
| 409 | Conflict | The check is past editing, payment is in progress, or someone needs project access first (code: "project_access_required"). |
| 429 | Too many requests | Only the OAuth token route and anonymous uploads send this. Wait a minute and retry. |
Account
Who the key or token belongs to.
GET/api/auth/me
The signed-in account: email, organization, and credit balance.
Assistant tools: get_me
curl "https://app.groundbook.ai/api/auth/me" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb whoami{
"user": {
"id": "An9o6aC0tnYvuUqnsIwEp1HLjuk2",
"email": "you@example.com",
"displayName": "Your Name",
"isSuperAdmin": false,
"organization": {
"id": "6c93e7de-cbd9-44c8-a5dd-edafca9138a0",
"name": "Example Engineering",
"role": "admin",
"billingMode": "account"
},
"billing": {
"scope": "account",
"balanceCents": 12000
}
}
}POST/api/billing/purchases
A payment link for credits, which pay for checks, Smart Overlays, and project chat. 1 credit is $1.
Assistant tools: buy_credits
| Parameter | Type | Description |
|---|---|---|
amountCentsbody | integer required | Whole dollars in cents, 2000 ($20) or more. |
curl -X POST "https://app.groundbook.ai/api/billing/purchases" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amountCents":5000}'gb buy_credits --amount-dollars 50{
"url": "https://…payment page…"
}- Nothing is charged until the payment page is completed.
- 403 when the credits belong to an organization and you are not one of its admins.
POST/api/billing/subscription
Starts the account's free 7-day trial on a plan, with no credit card. The trial makes the first project free.
Assistant tools: create_project
| Parameter | Type | Description |
|---|---|---|
actionbody | "trial" required | Start the trial. |
planIdbody | starter | team | business | scale required | The plan the trial is on. |
intervalbody | month | year required | How the plan is billed once the trial ends. |
curl -X POST "https://app.groundbook.ai/api/billing/subscription" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"action":"trial","planId":"starter","interval":"month"}'gb create_project --address "1 Main St"{
"subscription": {
"status": "trialing",
"planId": "starter",
"trialEndsAt": "2026-10-26T20:00:00.000Z"
}
}- create_project starts it on Starter when a new account without a plan creates its first project.
- 402 when the account already used its trial; 403 when an organization admin manages the plan.
Projects
A project holds one set of drawings and its latest check. Every project you can open on the site is here, with the same permissions.
GET/api/projects
Projects this account can open, newest first.
Assistant tools: list_projects
| Parameter | Type | Description |
|---|---|---|
qquery | string | Text to match against the project address or file names. |
statusquery | draft | processing | ready | Repeat to allow several statuses. |
pagequery | integer | Page number, starting at 1. 20 projects per page. |
ownerquery | string | Owner user id; repeat for several. Only useful inside an organization. |
curl "https://app.groundbook.ai/api/projects?status=ready" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb list_projects --status ready{
"projects": [
{
"id": "8c0d0499-7e63-40f6-812f-0b080be21449",
"address": "2465 Semlin Drive, Vancouver, BC",
"isOwner": true,
"ownerEmail": "you@example.com",
"accessSource": "owner",
"checkId": "7100d123-0aac-41eb-898d-98679e1f9694",
"checkStatus": "complete",
"customerStatus": "ready",
"documentCount": 2,
"issueCount": 42,
"primaryDocumentName": "B&S_-_Structural_Dwgs.pdf",
"createdAt": "2026-08-21T01:40:12.000Z",
"updatedAt": "2026-08-21T01:52:23.506Z"
}
],
"owners": [
{
"id": "An9o6aC0tnYvuUqnsIwEp1HLjuk2",
"email": "you@example.com",
"displayName": "Your Name"
}
],
"pagination": {
"page": 1,
"pageSize": 20,
"totalPages": 1,
"totalCount": 1
}
}POST/api/projects201
Creates a draft project with its first check. Name it and add files next.
Assistant tools: create_project
curl -X POST "https://app.groundbook.ai/api/projects" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb create_project --address "12 Main St" --review-instructions "Check the framing plan against the foundation plan."{
"projectId": "0b1b0ef3-9f2d-4c1a-8d0e-3f2a5a6b7c8d",
"checkId": "fed043d1-a9c8-4eab-bd26-047af9d6d34b",
"address": null,
"reviewInstructions": "Find conflicts, inconsistencies, and missing information across the drawings.",
"reviewInstructionsAutoGenerated": true,
"reviewInstructionsTitle": null,
"codeCheckEnabled": true,
"priceCents": 10000
}GET/api/projects/{projectId}
One project with its latest check's settings and totals.
Assistant tools: get_project, update_project
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
curl "https://app.groundbook.ai/api/projects/PROJECT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_project --project-id PROJECT_ID{
"project": {
"id": "8c0d0499-7e63-40f6-812f-0b080be21449",
"address": "2465 Semlin Drive, Vancouver, BC",
"organizationAccessEnabled": false,
"projectDisciplines": [],
"projectIssueStatuses": [
"Needs RFI"
],
"isOwner": true,
"accessSource": "owner",
"ownerEmail": "you@example.com",
"ownerDisplayName": "Your Name",
"updatedAt": "2026-08-21T01:52:23.506Z",
"checkId": "7100d123-0aac-41eb-898d-98679e1f9694",
"checkStatus": "complete",
"reviewInstructions": "Review these plans for coordination conflicts.",
"reviewInstructionsAutoGenerated": false,
"reviewInstructionsTitle": "Coordination",
"codeCheckEnabled": true,
"language": "en",
"languageSource": "detected",
"priceCents": 10000,
"paymentMethod": "credits",
"creditsAppliedCents": 10000,
"paidAt": "2026-08-21T01:52:23.506Z",
"documentCount": 2,
"pageCount": 59,
"codeCount": 0,
"primaryDocumentName": "B&S_-_Structural_Dwgs.pdf"
}
}PATCH/api/projects/{projectId}
Renames a project, or sets the language its findings are written in.
Assistant tools: create_project, update_project
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
addressbody | string | null | The new address or name, up to 500 characters. null clears it. |
languagebody | string | The language findings are written in, as a name or code (Spanish, es). A check started after this writes in it. |
curl -X PATCH "https://app.groundbook.ai/api/projects/PROJECT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address":"12 Main St"}'gb update_project --project-id PROJECT_ID --address "12 Main St"{
"address": "12 Main St",
"language": "en",
"languageSource": "detected"
}DELETE/api/projects/{projectId}204
Permanently deletes a project with its files and issues. Owner only. This cannot be undone.
Assistant tools: delete_project
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
curl -X DELETE "https://app.groundbook.ai/api/projects/PROJECT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb delete_project --project-id PROJECT_ID --yesNo body.- 409 when a payment for the project is still being completed.
PATCH/api/projects/{projectId}/shares
Lets everyone in the owner's organization open the project, or stops that.
Assistant tools: share_project
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
organizationAccessEnabledbody | boolean required | true to open the project to the organization. |
curl -X PATCH "https://app.groundbook.ai/api/projects/PROJECT_ID/shares" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organizationAccessEnabled":true}'gb share_project --project-id PROJECT_ID --organization-access true{
"organizationAccessEnabled": true
}DELETE/api/projects/{projectId}/invitations/{invitationId}204
Cancels a pending invitation.
Assistant tools: remove_project_share
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
invitationIdpath | uuid required | The invitation id, from the shares list. |
curl -X DELETE "https://app.groundbook.ai/api/projects/PROJECT_ID/invitations/INVITATION_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb remove_project_share --project-id PROJECT_ID --invitation-id INVITATION_ID --yesNo body.POST/api/projects/{projectId}/statuses201
Adds a custom issue status to the project, next to open, reviewed, resolved, and dismissed.
Assistant tools: update_project
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
statusbody | string required | The status name, up to 80 characters. |
curl -X POST "https://app.groundbook.ai/api/projects/PROJECT_ID/statuses" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"Needs RFI"}'gb update_project --project-id PROJECT_ID --add-issue-status "Needs RFI"{
"status": "Needs RFI"
}POST/api/projects/{projectId}/disciplines201
Adds a discipline the project can tag issues with.
Assistant tools: update_project
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
disciplinebody | string required | The discipline name, up to 80 characters. |
curl -X POST "https://app.groundbook.ai/api/projects/PROJECT_ID/disciplines" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"discipline":"Fire protection"}'gb update_project --project-id PROJECT_ID --add-discipline "Fire protection"{
"discipline": "Fire protection"
}Checks
A check is one review run over a project's files. Set what it should focus on, add codes, then pay and start it.
GET/api/checks/{checkId}
Where the check is: draft, waiting for payment, a percentage while it runs, complete, or failed.
progressPercent weighs every stage the same: a started stage counts half, a finished one counts in full. It is 100 once the check is complete.
Assistant tools: get_project
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id, from the project. |
curl "https://app.groundbook.ai/api/checks/CHECK_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_project --project-id PROJECT_ID{
"check": {
"id": "7100d123-0aac-41eb-898d-98679e1f9694",
"projectId": "8c0d0499-7e63-40f6-812f-0b080be21449",
"status": "processing",
"progressPercent": 43,
"documentCount": 2,
"pageCount": 59,
"issueCount": 0,
"priceCents": 10000,
"paidAt": "2026-08-21T01:52:23.506Z",
"createdAt": "2026-08-21T01:40:12.000Z",
"updatedAt": "2026-08-21T02:10:00.000Z",
"url": "https://app.groundbook.ai/projects/8c0d0499-7e63-40f6-812f-0b080be21449"
}
}GET/api/checks/{checkId}/review-instructions
What the check focuses on, and the instructions you used on recent projects.
Assistant tools: create_project, set_review_instructions
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
curl "https://app.groundbook.ai/api/checks/CHECK_ID/review-instructions" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb api GET /api/checks/CHECK_ID/review-instructions{
"reviewInstructions": "Check the framing plan against the foundation plan for grid mismatches.",
"reviewInstructionsAutoGenerated": false,
"reviewInstructionsTitle": "Framing vs foundation",
"codeCheckEnabled": true,
"recentReviewInstructions": []
}PATCH/api/checks/{checkId}/review-instructions
Sets what the check focuses on and whether it checks against building codes. Draft checks only.
Assistant tools: create_project, set_review_instructions
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
reviewInstructionsbody | string required | At least 20 characters. |
reviewInstructionsTitlebody | string | null required | A short title, up to 80 characters, or null. |
autoGeneratedbody | boolean required | false when a person wrote the instructions. |
codeCheckEnabledbody | boolean required | Whether to check against building codes. |
reviewSetupbody | object | Saved review settings, including role, roleOther (custom role or scope), and phase. Role and phase are required before starting; unfinished drafts may omit them. |
curl -X PATCH "https://app.groundbook.ai/api/checks/CHECK_ID/review-instructions" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"reviewInstructions":"Check the framing plan against the foundation plan for grid mismatches.","reviewInstructionsTitle":"Framing vs foundation","autoGenerated":false,"codeCheckEnabled":true}'gb set_review_instructions --project-id PROJECT_ID --review-instructions "Check the framing plan against the foundation plan for grid mismatches."{
"reviewInstructions": "Check the framing plan against the foundation plan for grid mismatches.",
"reviewInstructionsTitle": "Framing vs foundation",
"codeCheckEnabled": true
}- 409 once payment has started; the check is no longer editable.
POST/api/checks/{checkId}/code-sources
Adds a building code by public URL, or marks one of the check's files as the code book.
Assistant tools: add_code_source
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
codeNamebody | string required | The code's name, up to 300 characters. |
sourceUrlbody | string | A public URL of the code. Give this or checkDocumentId. |
checkDocumentIdbody | uuid | One of the check's files that is the code book. |
curl -X POST "https://app.groundbook.ai/api/checks/CHECK_ID/code-sources" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"codeName":"2022 California Building Code","sourceUrl":"https://example.com/cbc-2022.pdf"}'gb add_code_source --project-id PROJECT_ID --code-name "2022 California Building Code" --source-url https://example.com/cbc-2022.pdf{
"source": {
"codeName": "2022 California Building Code",
"sourceType": "url",
"sourceStatus": "queued",
"sourceUrl": "https://example.com/cbc-2022.pdf"
},
"priceCents": 12000
}DELETE/api/checks/{checkId}/code-sources
Removes a building code from the check.
Assistant tools: remove_code_source
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
codeNamequery | string required | The code's name. |
curl -X DELETE "https://app.groundbook.ai/api/checks/CHECK_ID/code-sources?codeName=2022+California+Building+Code" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb remove_code_source --project-id PROJECT_ID --code-name "2022 California Building Code" --yes{
"priceCents": 10000
}POST/api/checks/{checkId}/checkout
Pays for and starts the check. The first-project discount and credits are used when available; otherwise you get a payment link.
Assistant tools: start_check
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
curl -X POST "https://app.groundbook.ai/api/checks/CHECK_ID/checkout" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'gb start_check --project-id PROJECT_ID{
"paid": true,
"paymentMethod": "credits",
"projectId": "8c0d0499-7e63-40f6-812f-0b080be21449"
}- Role and project phase must be saved before starting. Use set_review_instructions with role, roleOther when needed, and phase, or include reviewSetup in the review-instructions API request.
- When payment is needed the response is { paid: false, url } and the check starts as soon as the payment completes.
- Pass { allowCheckout: false } to use only existing credits after any first-project discount. ChatGPT always uses this mode: insufficient access returns { paid: false, code: 'insufficient_credits', message, priceCents, balanceCents, accessInfoUrl } without creating checkout.
- 409 with a plain-English reason when a file is still analyzing, no file is marked checked, the instructions are missing, or the check is already paid.
Files
PDFs and DWGs in a check or saved for reuse. Uploads go straight to storage through a signed URL.
GET/api/checks/{checkId}/documents
The check's files with their analysis status, plus its code sources and price.
Assistant tools: get_project, add_saved_files_to_project
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
curl "https://app.groundbook.ai/api/checks/CHECK_ID/documents" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_project --project-id PROJECT_ID{
"documents": [
{
"id": "73808823-a773-4917-a5a6-24168948f498",
"checkDocumentId": "0dcf2ea3-e845-417a-9aba-1b1ce9ea092c",
"name": "B&S_-_Structural_Dwgs.pdf",
"sizeBytes": "48213377",
"pages": 42,
"kind": "drawing",
"saved": false,
"reviewRole": "checked",
"processingStatus": "complete",
"codeMatchingStatus": null,
"language": "en"
}
],
"codeSources": [],
"projectAddress": "2465 Semlin Drive, Vancouver, BC",
"projectLanguage": "en",
"projectLanguageSource": "detected",
"codeCheckEnabled": true,
"priceCents": 10000
}POST/api/uploads201
Step 1 of an upload: reserves a file and returns a signed URL to PUT the original PDF or DWG to.
PUT the bytes to uploadUrl with the returned headers, then call the complete route. The CLI's gb upload does all three steps.
| Parameter | Type | Description |
|---|---|---|
checkIdbody | uuid required | A draft check. |
fileNamebody | string required | Must end in .pdf or .dwg. |
sizeBytesbody | integer required | Positive byte count of the original file. |
curl -X POST "https://app.groundbook.ai/api/uploads" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"checkId":"fed043d1-a9c8-4eab-bd26-047af9d6d34b","fileName":"plans.pdf","sizeBytes":1048576}'gb upload plans.pdf --project PROJECT_ID{
"documentId": "6459b03a-9122-45f3-a915-7949704fdb2d",
"uploadUrl": "https://…signed…",
"headers": {
"Content-Type": "application/pdf"
}
}POST/api/uploads/{documentId}/complete201
Step 3 of an upload: verifies the original upload and starts conversion (DWG) and analysis.
| Parameter | Type | Description |
|---|---|---|
documentIdpath | uuid required | From the create-upload response. |
checkIdbody | uuid required | The same draft check. |
originalNamebody | string required | The file name to show. |
sizeBytesbody | integer required | The size you uploaded. |
codeNamebody | string | Name the file as a code book instead of a drawing set. |
curl -X POST "https://app.groundbook.ai/api/uploads/DOCUMENT_ID/complete" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"checkId":"fed043d1-a9c8-4eab-bd26-047af9d6d34b","originalName":"plans.pdf","sizeBytes":1048576}'gb upload plans.pdf --project PROJECT_ID{
"checkDocumentId": "0dcf2ea3-e845-417a-9aba-1b1ce9ea092c",
"runId": "5925f763-677f-4b04-84ea-9ccd12995f82",
"runStatus": "queued"
}POST/api/checks/{checkId}/documents201
Adds saved PDFs or DWGs to a draft check without uploading them again.
Assistant tools: add_saved_files_to_project
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | A draft check. |
documentIdsbody | uuid[] required | 1 to 50 saved file ids. |
curl -X POST "https://app.groundbook.ai/api/checks/CHECK_ID/documents" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"documentIds":["73808823-a773-4917-a5a6-24168948f498"]}'gb add_saved_files_to_project --project-id PROJECT_ID --document-ids DOC_ID_1,DOC_ID_2{
"documents": [
{
"checkDocumentId": "0dcf2ea3-e845-417a-9aba-1b1ce9ea092c",
"documentId": "73808823-a773-4917-a5a6-24168948f498",
"name": "B&S_-_Structural_Dwgs.pdf"
}
]
}GET/api/integrations/egnyte/folders
Subfolders and PDFs or DWGs in one folder of your connected Egnyte. Connect Egnyte on the Connectors page first.
Assistant tools: list_egnyte_folder
| Parameter | Type | Description |
|---|---|---|
pathquery | string | Folder path; the root when omitted. |
curl "https://app.groundbook.ai/api/integrations/egnyte/folders" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb list_egnyte_folder --path /Shared/Projects{
"path": "/Shared/Projects",
"name": "Projects",
"parentPath": "/Shared",
"folders": [
{
"name": "Decatur",
"path": "/Shared/Projects/Decatur",
"folderId": "7d1c2a4e"
}
],
"files": [
{
"name": "A-101 Floor Plan.pdf",
"path": "/Shared/Projects/A-101 Floor Plan.pdf",
"sizeBytes": 2483112,
"entryId": "0bc1e2f3",
"groupId": "9a8b7c6d",
"checksum": null,
"lastModified": "2026-09-18T17:02:11Z"
}
]
}POST/api/checks/{checkId}/imports/egnyte201
Copies one PDF from your connected Egnyte into a draft check. Importing the same version twice returns alreadyImported.
Assistant tools: import_from_egnyte
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | A draft check. |
pathbody | string required | The PDF's Egnyte path, from the folder listing. |
curl -X POST "https://app.groundbook.ai/api/checks/CHECK_ID/imports/egnyte" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"path":"/Shared/Projects/A-101 Floor Plan.pdf"}'gb import_from_egnyte --project-id PROJECT_ID --paths "/Shared/Projects/A-101 Floor Plan.pdf"{
"checkDocumentId": "0dcf2ea3-e845-417a-9aba-1b1ce9ea092c",
"documentId": "73808823-a773-4917-a5a6-24168948f498",
"alreadyImported": false
}GET/api/integrations/microsoft/roots
Your OneDrive, Shared with me, and your SharePoint sites. Connect SharePoint / OneDrive on the Connectors page first.
Assistant tools: import_from_onedrive, list_saved_files, add_saved_files_to_project
curl "https://app.groundbook.ai/api/integrations/microsoft/roots" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb import_from_onedrive --project-id PROJECT_ID --file-names "A-101 Floor Plan.pdf"{
"roots": [
{
"kind": "drive",
"driveId": "b!Xb3k9",
"itemId": "root",
"name": "OneDrive",
"detail": "Your work files"
},
{
"kind": "shared",
"name": "Shared with me",
"detail": "Files and folders others shared with you"
}
]
}GET/api/integrations/microsoft/browse
Folders and PDFs or DWGs in one OneDrive or SharePoint folder, or a name search across a drive. list_saved_files reads the Copilot and Teams chat upload folders with it.
Assistant tools: import_from_onedrive, list_saved_files, add_saved_files_to_project
| Parameter | Type | Description |
|---|---|---|
driveIdquery | string | The drive, from the roots list. |
itemIdquery | string | A folder id; the drive root when omitted. |
searchquery | string | Match file and folder names across the drive instead of listing one folder. |
curl "https://app.groundbook.ai/api/integrations/microsoft/browse" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb import_from_onedrive --project-id PROJECT_ID --file-names "A-101 Floor Plan.pdf"{
"entries": [
{
"kind": "file",
"driveId": "b!Xb3k9",
"itemId": "01ABCDEF",
"name": "A-101 Floor Plan.pdf",
"path": "/Microsoft Teams Chat Files",
"sizeBytes": 2483112,
"childCount": null,
"revision": "\"{1A2B},3\""
}
]
}POST/api/checks/{checkId}/imports/microsoft201
Copies one PDF or DWG from OneDrive or SharePoint into a draft check. Importing the same version twice returns alreadyImported. add_saved_files_to_project uses it for PDFs uploaded in Copilot or Teams chat.
Assistant tools: import_from_onedrive, add_saved_files_to_project
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | A draft check. |
driveIdbody | string required | From the browse entry. |
itemIdbody | string required | From the browse entry. |
curl -X POST "https://app.groundbook.ai/api/checks/CHECK_ID/imports/microsoft" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"driveId":"b!Xb3k9","itemId":"01ABCDEF"}'gb import_from_onedrive --project-id PROJECT_ID --file-names "A-101 Floor Plan.pdf"{
"checkDocumentId": "0dcf2ea3-e845-417a-9aba-1b1ce9ea092c",
"documentId": "73808823-a773-4917-a5a6-24168948f498",
"alreadyImported": false
}PATCH/api/check-documents/{checkDocumentId}
Marks a file as checked or reference, or sets its file type. Draft checks only.
Assistant tools: set_file_role
| Parameter | Type | Description |
|---|---|---|
checkDocumentIdpath | uuid required | The file's id within the check, from the files list. |
reviewRolebody | checked | reference | checked files are reviewed for issues; reference files are context only. |
fileTypebody | string | Drawing, Specifications, Report, Calculations, Code, or Supporting document. The check reads Drawing files; any other text is saved as a custom label. |
curl -X PATCH "https://app.groundbook.ai/api/check-documents/CHECK_DOCUMENT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"reviewRole":"checked"}'gb set_file_role --check-document-id CHECK_DOCUMENT_ID --role checked{
"fileType": null,
"reviewRole": "checked",
"codeMatchingStatus": null
}DELETE/api/check-documents/{checkDocumentId}204
Removes a file from a draft check. An upload is deleted; a saved file stays in the library.
Assistant tools: remove_file
| Parameter | Type | Description |
|---|---|---|
checkDocumentIdpath | uuid required | The file's id within the check. |
curl -X DELETE "https://app.groundbook.ai/api/check-documents/CHECK_DOCUMENT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb remove_file --check-document-id CHECK_DOCUMENT_ID --yesNo body.GET/api/saved-documents
PDFs and DWGs saved by you or your organization, with the projects that use each one.
Assistant tools: list_saved_files, create_smart_overlay
curl "https://app.groundbook.ai/api/saved-documents" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb list_saved_files{
"organization": {
"id": "6c93e7de-cbd9-44c8-a5dd-edafca9138a0",
"name": "Example Engineering"
},
"documents": [
{
"id": "73808823-a773-4917-a5a6-24168948f498",
"name": "B&S_-_Structural_Dwgs.pdf",
"pages": 42,
"sizeBytes": "48213377",
"scope": "organization",
"projects": [
{
"id": "8c0d0499-7e63-40f6-812f-0b080be21449",
"address": "2465 Semlin Drive, Vancouver, BC"
}
]
}
]
}PATCH/api/documents/{documentId}
Saves a file for reuse, renames it, or changes whether the organization can use it.
| Parameter | Type | Description |
|---|---|---|
documentIdpath | uuid required | The document id. |
savedbody | boolean | true keeps the file after its project; false removes it from the library. |
namebody | string | A new name. |
scopebody | personal | organization | Who may reuse it. Only the person who saved it can change this. |
curl -X PATCH "https://app.groundbook.ai/api/documents/DOCUMENT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"saved":true,"scope":"organization"}'gb api PATCH /api/documents/DOCUMENT_ID --data '{"saved":true,"scope":"organization"}'{
"saved": true,
"removed": false,
"scope": "organization"
}GET/api/documents/{documentId}/content
The PDF preview, generated from DWG when needed. Supports Range requests. Add ?download=1 for the original file, or ?download=1&format=pdf for its PDF.
| Parameter | Type | Description |
|---|---|---|
documentIdpath | uuid required | The document id. |
downloadquery | 1 | Send as an attachment instead of inline. |
curl "https://app.groundbook.ai/api/documents/DOCUMENT_ID/content" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb api GET /api/documents/DOCUMENT_ID/contentThe PDF bytes with Content-Type: application/pdf.Issues
What a check found. Each issue cites the sheets it comes from and carries a status, severity, labels, assignees, and comments.
GET/api/checks/{checkId}/issues
Every issue on a check, most severe first, with references, assignees, and your own feedback.
Assistant tools: list_issues
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
curl "https://app.groundbook.ai/api/checks/CHECK_ID/issues" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb list_issues --project-id PROJECT_ID --severity High --status open{
"issues": [
{
"id": "1f78a5ca-1640-4075-998e-b1495295dcda",
"displayNumber": 1,
"title": "Governing SW3 schedule is unclear between S42 and S43",
"description": "Sheet S42 and sheet S43 both carry a schedule for shear wall SW3 with different bar sizes…",
"severityLabel": "High",
"severityRank": 100,
"disciplines": [
"Structural"
],
"labels": [],
"impact": "The contractor cannot tell which reinforcement to build.",
"recommendation": "Remove one schedule or reference the governing sheet.",
"status": "open",
"assignees": [],
"commentCount": 0,
"feedback": {
"accuracy": null,
"usefulness": null,
"reasons": []
},
"fieldwireTask": null,
"references": [
{
"id": "4d9dabbe-40c4-4e7f-b8b2-e0b4daf32e45",
"documentId": "73808823-a773-4917-a5a6-24168948f498",
"documentName": "B&S_-_Structural_Dwgs.pdf",
"pageIndex": 41,
"pageLabel": "42",
"sheetNumber": "S42",
"referenceLabel": "SW3 schedule",
"citedText": "SW3 … 15M @ 300",
"overlay": null
}
]
}
]
}GET/api/issues/{issueId}
One issue in full, with its project.
Assistant tools: get_issue, update_issue, assign_issue
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
curl "https://app.groundbook.ai/api/issues/ISSUE_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_issue --issue-id ISSUE_ID{
"issue": {
"id": "1f78a5ca-1640-4075-998e-b1495295dcda",
"displayNumber": 1,
"title": "Governing SW3 schedule is unclear between S42 and S43",
"description": "Sheet S42 and sheet S43 both carry a schedule for shear wall SW3 with different bar sizes…",
"severityLabel": "High",
"severityRank": 100,
"disciplines": [
"Structural"
],
"labels": [],
"impact": "The contractor cannot tell which reinforcement to build.",
"recommendation": "Remove one schedule or reference the governing sheet.",
"status": "open",
"assignees": [],
"commentCount": 0,
"feedback": {
"accuracy": null,
"usefulness": null,
"reasons": []
},
"fieldwireTask": null,
"references": [
{
"id": "4d9dabbe-40c4-4e7f-b8b2-e0b4daf32e45",
"documentId": "73808823-a773-4917-a5a6-24168948f498",
"documentName": "B&S_-_Structural_Dwgs.pdf",
"pageIndex": 41,
"pageLabel": "42",
"sheetNumber": "S42",
"referenceLabel": "SW3 schedule",
"citedText": "SW3 … 15M @ 300",
"overlay": null
}
],
"checkId": "7100d123-0aac-41eb-898d-98679e1f9694",
"projectId": "8c0d0499-7e63-40f6-812f-0b080be21449",
"projectLabel": "2465 Semlin Drive, Vancouver, BC"
}
}PATCH/api/issues/{issueId}
Changes severity, status, or labels.
Assistant tools: update_issue
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
severityLabelbody | High | Medium | Low | The new severity. |
statusbody | string | open, reviewed, resolved, dismissed, or a status saved on the project. |
labelsbody | string[] | Replaces the labels. Up to 20, each up to 40 characters. |
curl -X PATCH "https://app.groundbook.ai/api/issues/ISSUE_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"resolved","labels":["grid","coordination"]}'gb update_issue --issue-id ISSUE_ID --status resolved --labels grid,coordination{
"issue": {
"severityLabel": "High",
"severityRank": 100,
"status": "resolved",
"labels": [
"grid",
"coordination"
]
}
}GET/api/issues/{issueId}/comments
The issue's comments, oldest first, with attachments.
Assistant tools: get_issue
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
curl "https://app.groundbook.ai/api/issues/ISSUE_ID/comments" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_issue --issue-id ISSUE_ID{
"comments": [
{
"id": "c1",
"body": "Fixed in revision B.",
"author": {
"id": "u2",
"email": "eng@example.com",
"displayName": "Eng"
},
"mentions": [],
"attachments": [],
"createdAt": "2026-09-14T00:00:00.000Z",
"updatedAt": "2026-09-14T00:00:00.000Z"
}
]
}POST/api/issues/{issueId}/comments201
Adds a comment. Mentioned people are emailed; someone outside the project is invited only when you say so.
Assistant tools: comment_on_issue
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
bodybody | string required | Up to 4000 characters. |
mentionsbody | { email, displayLabel }[] | People to notify, up to 20. |
grantProjectAccessEmailsbody | string[] | Mentioned emails to invite to the project if they cannot open it. |
attachmentIdsbody | uuid[] | Attachments uploaded through the site. |
curl -X POST "https://app.groundbook.ai/api/issues/ISSUE_ID/comments" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"body":"Fixed in revision B.","mentions":[{"email":"eng@example.com","displayLabel":"eng@example.com"}],"grantProjectAccessEmails":[],"attachmentIds":[]}'gb comment_on_issue --issue-id ISSUE_ID --body "Fixed in revision B." --mentions eng@example.com{
"comment": {
"id": "c2",
"body": "Fixed in revision B.",
"author": {
"id": "u1",
"email": "you@example.com",
"displayName": "Your Name"
},
"mentions": [
{
"email": "eng@example.com",
"displayLabel": "eng@example.com"
}
],
"attachments": [],
"createdAt": "2026-09-14T00:00:00.000Z"
}
}- 409 { code: "project_access_required", people } when a mentioned person cannot open the project and grantProjectAccessEmails does not include them.
DELETE/api/issues/{issueId}/comments/{commentId}204
Permanently deletes a comment with its attachments. You can delete only your own comments.
Assistant tools: delete_comment
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
commentIdpath | uuid required | From the issue's comments. |
curl -X DELETE "https://app.groundbook.ai/api/issues/ISSUE_ID/comments/COMMENT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb delete_comment --issue-id ISSUE_ID --comment-id COMMENT_ID --yesNo body.POST/api/issues/{issueId}/assignees201
Assigns the issue to someone by email.
Assistant tools: assign_issue
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
emailbody | string required | Who to assign. |
grantProjectAccessbody | boolean | Invite them to the project if they cannot open it. Default false. |
curl -X POST "https://app.groundbook.ai/api/issues/ISSUE_ID/assignees" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"eng@example.com","grantProjectAccess":false}'gb assign_issue --issue-id ISSUE_ID --email eng@example.com{
"assignee": {
"id": "a1",
"userId": "u2",
"email": "eng@example.com",
"displayName": "Eng",
"pending": false,
"notificationDelivered": true
},
"notificationDelivered": true
}- 409 { code: "project_access_required", people } when the person cannot open the project; call again with grantProjectAccess: true to invite them.
DELETE/api/issues/{issueId}/assignees/{assigneeId}204
Removes an assignee.
Assistant tools: unassign_issue
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
assigneeIdpath | uuid required | From the issue's assignees. |
curl -X DELETE "https://app.groundbook.ai/api/issues/ISSUE_ID/assignees/ASSIGNEE_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb unassign_issue --issue-id ISSUE_ID --assignee-id ASSIGNEE_ID --yesNo body.PATCH/api/issues/{issueId}/feedback
Records whether the issue is correct (one answer per person) and useful (one shared value per issue that anyone on the project can change).
Assistant tools: give_issue_feedback
| Parameter | Type | Description |
|---|---|---|
issueIdpath | uuid required | The issue id. |
accuracybody | correct | incorrect | null required | Whether the finding is right. |
usefulnessbody | useful | not_useful | null | Whether it helps. Replaces the issue's shared value for everyone; null clears it and leaving it out keeps it. |
reasonsbody | string[] required | Any of important, low_importance, strong_evidence, wrong_or_missing_evidence, duplicate, unclear, related_issue, incorrect, not_relevant, not_yet_important, other. |
detailsbody | string | null | Optional explanation for other; null clears it and leaving it out preserves it while other stays selected. |
curl -X PATCH "https://app.groundbook.ai/api/issues/ISSUE_ID/feedback" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"accuracy":"correct","usefulness":"useful","reasons":["important"]}'gb give_issue_feedback --issue-id ISSUE_ID --accuracy correct --usefulness useful --reasons important{
"feedback": {
"accuracy": "correct",
"usefulness": "useful",
"reasons": [
"important"
]
},
"usefulnessSetBy": {
"id": "USER_ID",
"email": "you@example.com",
"displayName": "You"
}
}Exports
A PDF report, marked-up drawings, a Bluebeam FDF, or a CSV of a check's issues. Exports build in the background.
POST/api/checks/{checkId}/exports202
Starts an export. Poll it until it is ready, then download the file.
Assistant tools: export_issues
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
formatbody | report | markup | fdf | csv required | What to build. |
issueIdsbody | uuid[] | null | Only these issues, in this order. Otherwise every open issue. |
markupColorbody | blue | red | green | purple | orange | black | The color of the callouts on marked-up drawings. Default blue. |
curl -X POST "https://app.groundbook.ai/api/checks/CHECK_ID/exports" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"format":"report"}'gb export_issues --project-id PROJECT_ID --format report{
"export": {
"id": "faaef1d5-91cc-4585-9edb-83b5977af77a",
"status": "queued",
"format": "report",
"fileName": "2465 Semlin Drive issues.pdf",
"progressDone": 0,
"progressTotal": null,
"sizeBytes": null,
"error": null
}
}GET/api/exports/{exportId}
Progress of an export you started.
Assistant tools: get_export
| Parameter | Type | Description |
|---|---|---|
exportIdpath | uuid required | The export id. |
curl "https://app.groundbook.ai/api/exports/EXPORT_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_export --export-id EXPORT_ID{
"export": {
"id": "faaef1d5-91cc-4585-9edb-83b5977af77a",
"status": "ready",
"format": "report",
"fileName": "2465 Semlin Drive issues.pdf",
"progressDone": 12,
"progressTotal": 12,
"sizeBytes": 2481920,
"error": null
}
}GET/api/exports/{exportId}/file
The built file. 409 until the export is ready. Files are kept for seven days.
Assistant tools: get_export
| Parameter | Type | Description |
|---|---|---|
exportIdpath | uuid required | The export id. |
curl "https://app.groundbook.ai/api/exports/EXPORT_ID/file" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb download-export EXPORT_ID --out issues.pdfThe file bytes, with Content-Type and Content-Disposition set for the format.Fieldwire
Sends a check's issues to your connected Fieldwire as tasks, pinned on the plan when Fieldwire has that sheet. Connect Fieldwire on the Connectors page first. Sends run in the background.
GET/api/checks/{checkId}/fieldwire
Your Fieldwire connection, the Fieldwire project this check's drawings came from, and the latest send.
Assistant tools: send_issues_to_fieldwire
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
curl "https://app.groundbook.ai/api/checks/CHECK_ID/fieldwire" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb api GET /api/checks/CHECK_ID/fieldwire{
"configured": true,
"connection": {
"id": "9f0c6e1a-2b3c-4d5e-8f90-a1b2c3d4e5f6",
"region": "us",
"accountName": "you@example.com",
"status": "active",
"connectedAt": "2026-09-24T18:00:00.000Z",
"lastUsedAt": "2026-09-29T17:00:00.000Z"
},
"suggestedProjectId": "c0a8012e-6f1d-4c7b-9a52-1d2e3f4a5b6c",
"latestSend": null
}GET/api/integrations/fieldwire/projects
Active Fieldwire projects your connected account can open.
Assistant tools: send_issues_to_fieldwire
curl "https://app.groundbook.ai/api/integrations/fieldwire/projects" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb api GET /api/integrations/fieldwire/projects{
"projects": [
{
"id": "c0a8012e-6f1d-4c7b-9a52-1d2e3f4a5b6c",
"name": "2465 Semlin Drive",
"code": "SEM",
"address": "2465 Semlin Drive, Vancouver, BC"
}
]
}GET/api/integrations/fieldwire/projects/{fieldwireProjectId}/teams
A Fieldwire project's categories (Fieldwire calls them teams), to file tasks under.
Assistant tools: send_issues_to_fieldwire
| Parameter | Type | Description |
|---|---|---|
fieldwireProjectIdpath | string required | The Fieldwire project id, from the projects list. |
curl "https://app.groundbook.ai/api/integrations/fieldwire/projects/FIELDWIRE_PROJECT_ID/teams" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb api GET /api/integrations/fieldwire/projects/FIELDWIRE_PROJECT_ID/teams{
"teams": [
{
"id": "7b1d5c2e-8a9f-4e3b-b6c1-0d2e4f6a8c10",
"name": "Structural"
}
]
}POST/api/checks/{checkId}/fieldwire/sends202
Starts sending issues to a Fieldwire project as tasks. Sending an issue again updates its task. Poll the send until it is done.
Assistant tools: send_issues_to_fieldwire
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
fieldwireProjectIdbody | string required | The Fieldwire project to send to. |
teamIdbody | string | null | A Fieldwire category to file the tasks under. |
issueIdsbody | uuid[] | null | Only these issues. Otherwise every open issue. |
curl -X POST "https://app.groundbook.ai/api/checks/CHECK_ID/fieldwire/sends" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"fieldwireProjectId":"c0a8012e-6f1d-4c7b-9a52-1d2e3f4a5b6c"}'gb send_issues_to_fieldwire --project-id PROJECT_ID{
"id": "5d1f0c1e-6a53-4b0e-9b3f-2f6c0f3a9d11",
"checkId": "7100d123-0aac-41eb-898d-98679e1f9694",
"fieldwireProjectId": "c0a8012e-6f1d-4c7b-9a52-1d2e3f4a5b6c",
"status": "queued",
"progressDone": 0,
"progressTotal": null,
"createdCount": 0,
"updatedCount": 0,
"pinnedCount": 0,
"failedCount": 0,
"error": null,
"createdAt": "2026-09-29T17:00:00.000Z",
"finishedAt": null
}- 409 when Fieldwire is not connected.
GET/api/checks/{checkId}/fieldwire/sends/{sendId}
Progress of a send: tasks created, updated, pinned on a plan, and failed.
Assistant tools: get_fieldwire_send
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
sendIdpath | uuid required | The send id. |
curl "https://app.groundbook.ai/api/checks/CHECK_ID/fieldwire/sends/SEND_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_fieldwire_send --project-id PROJECT_ID --send-id SEND_ID{
"id": "5d1f0c1e-6a53-4b0e-9b3f-2f6c0f3a9d11",
"checkId": "7100d123-0aac-41eb-898d-98679e1f9694",
"fieldwireProjectId": "c0a8012e-6f1d-4c7b-9a52-1d2e3f4a5b6c",
"status": "done",
"progressDone": 12,
"progressTotal": 12,
"createdCount": 12,
"updatedCount": 0,
"pinnedCount": 9,
"failedCount": 0,
"error": null,
"createdAt": "2026-09-29T17:00:00.000Z",
"finishedAt": "2026-09-29T17:01:10.000Z"
}Overlays
Two drawings laid over each other in two colors, so what differs stands out. A check keeps the comparisons it made on the project's Overlays tab. Smart Overlay is the tool for comparing any two drawings yourself; the drawings are read and aligned in the browser when the overlay is opened.
GET/api/checks/{checkId}/overlays
The comparisons on a project's Overlays tab, with what the review concluded and the issues each one supports.
outcome is issue_found, no_issue_found, inconclusive, or pending when no result is recorded yet. transform maps comparison page points onto reference page points; box is the compared area of the reference page, in PDF points from the top-left corner.
Assistant tools: list_project_overlays
| Parameter | Type | Description |
|---|---|---|
checkIdpath | uuid required | The check id. |
curl "https://app.groundbook.ai/api/checks/CHECK_ID/overlays" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb list_project_overlays --project-id PROJECT_ID --outcome issue_found{
"overlays": [
{
"id": "2b7e6a0c-1d4f-4c8a-9e35-7f6a5b4c3d2e",
"reference": {
"documentId": "73808823-a773-4917-a5a6-24168948f498",
"checkDocumentId": "0dcf2ea3-e845-417a-9aba-1b1ce9ea092c",
"documentName": "B&S_-_Structural_Dwgs.pdf",
"pageIndex": 9,
"sheetNumber": "S10",
"pageWidth": 3024,
"pageHeight": 2160
},
"comparisonDocumentName": "Mechanical.pdf",
"overlay": {
"version": 1,
"box": {
"xMin": 420,
"yMin": 310,
"xMax": 2280,
"yMax": 1790
},
"referenceLabel": "P2 FLOOR PLAN",
"comparison": {
"checkDocumentId": "b4a1d9c7-3e52-4f60-8a71-9c0d1e2f3a4b",
"documentId": "e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c",
"pageIndex": 3,
"sheetNumber": "M-200",
"pageWidth": 3024,
"pageHeight": 2160,
"label": "P2 MECHANICAL PLAN"
},
"transform": {
"a": 1,
"b": 0,
"tx": 12.4,
"ty": -8.1
}
},
"outcome": "issue_found",
"summary": "",
"reviewedAt": null,
"issues": [
{
"id": "1f78a5ca-1640-4075-998e-b1495295dcda",
"number": 6,
"title": "P2 floor elevation differs between S10 and M-200",
"referenceId": "4d9dabbe-40c4-4e7f-b8b2-e0b4daf32e45"
}
]
}
]
}GET/api/tools/overlays
Smart Overlays your account saved, newest first.
Assistant tools: list_smart_overlays
curl "https://app.groundbook.ai/api/tools/overlays" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb list_smart_overlays{
"overlays": [
{
"id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"title": "A-201 · SECOND FLOOR PLAN → S-201 · SECOND FLOOR FRAMING PLAN",
"files": [
"Architectural.pdf",
"Structural.pdf"
],
"updatedAt": "2026-09-29T17:00:00.000Z"
}
]
}GET/api/tools/overlays/{overlayId}
One saved Smart Overlay: its files with their sheets, the sheet pairs, and each pair's alignment.
A sheet id is its file id and page, with a view number when a sheet holds several plans: FILE_ID:54 or FILE_ID:54:view:2. viewers is keyed by "referenceId|comparisonId"; a pair is aligned once its transform is set, and aiDraft marks an AI alignment the person has not accepted yet. You can open an overlay you own, or one whose every file you can open.
Assistant tools: get_smart_overlay
| Parameter | Type | Description |
|---|---|---|
overlayIdpath | uuid required | The overlay id. |
curl "https://app.groundbook.ai/api/tools/overlays/OVERLAY_ID" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb get_smart_overlay --overlay-id OVERLAY_ID{
"id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"state": {
"title": "A-201 · SECOND FLOOR PLAN → S-201 · SECOND FLOOR FRAMING PLAN",
"sources": [
{
"id": "73808823-a773-4917-a5a6-24168948f498",
"name": "Architectural.pdf",
"pages": [
{
"id": "73808823-a773-4917-a5a6-24168948f498:12",
"sourceId": "73808823-a773-4917-a5a6-24168948f498",
"page": 12,
"title": "A-201 · SECOND FLOOR PLAN",
"floor": "2",
"discipline": "A",
"area": "",
"isPlan": true,
"width": 3024,
"height": 2160
}
]
},
{
"id": "e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c",
"name": "Structural.pdf",
"pages": [
{
"id": "e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c:4",
"sourceId": "e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c",
"page": 4,
"title": "S-201 · SECOND FLOOR FRAMING PLAN",
"floor": "2",
"discipline": "S",
"area": "",
"isPlan": true,
"width": 3024,
"height": 2160
}
]
}
],
"referenceColor": "#dd3945",
"comparisonColor": "#0097b4",
"sideA": "73808823-a773-4917-a5a6-24168948f498",
"sideB": "e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c",
"pairs": [
{
"id": "73808823-a773-4917-a5a6-24168948f498:12:e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c:4",
"referenceId": "73808823-a773-4917-a5a6-24168948f498:12",
"comparisonId": "e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c:4"
}
],
"viewers": {
"73808823-a773-4917-a5a6-24168948f498:12|e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c:4": {
"transform": {
"a": 1,
"b": 0,
"tx": 14.2,
"ty": -6.5
},
"status": "Automatic alignment",
"opacity": 1,
"showA": true,
"showB": true,
"zoom": 1
}
}
},
"updatedAt": "2026-09-29T17:00:00.000Z"
}POST/api/tools/overlays201
Saves a new Smart Overlay. Name its files with no sheets and it is read, paired, and aligned when someone opens it on the site.
To start an overlay without reading the PDFs yourself, send each file with pages: [] and no pairs. requestedPairs names the sheets to lay over each other, each side a sheet number or a page number (the reference side in the first file, the comparison side in the second); leave it out and matching floors are paired. Each new sheet pair a person opens is one overlay, free at first and then paid with credits; the usage route below says how many free ones are left.
Assistant tools: create_smart_overlay
| Parameter | Type | Description |
|---|---|---|
titlebody | string required | Up to 300 characters. |
sourcesbody | { id, name, pages }[] required | The PDFs by document id, from a project's files or the saved files. pages: [] has the site read the sheets. |
referenceColorbody | string required | The first drawing's color, as #rrggbb. |
comparisonColorbody | string required | The second drawing's color, as #rrggbb. |
sideAbody | string required | The document id of the reference file. |
sideBbody | string required | The document id of the file laid over it; the same id compares sheets within one file. |
pairsbody | { id, referenceId, comparisonId }[] required | Sheet pairs by sheet id. [] before the files are read. |
requestedPairsbody | { reference, comparison }[] | Sheets to pair once the files are read, by sheet number or page number. |
viewersbody | object required | Each pair's alignment and display. {} for a new overlay. |
curl -X POST "https://app.groundbook.ai/api/tools/overlays" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Architectural.pdf, Structural.pdf","sources":[{"id":"73808823-a773-4917-a5a6-24168948f498","name":"Architectural.pdf","pages":[]},{"id":"e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c","name":"Structural.pdf","pages":[]}],"referenceColor":"#dd3945","comparisonColor":"#0097b4","sideA":"73808823-a773-4917-a5a6-24168948f498","sideB":"e2c1a0b9-8d7f-4e6a-b5c4-3d2e1f0a9b8c","pairs":[],"requestedPairs":[{"reference":"A-201","comparison":"S-201"}],"viewers":{}}'gb create_smart_overlay --document-ids DOC_ID_1,DOC_ID_2{
"id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}- Open it at /tools/overlay/{id}.
- 404 when a file is not one you can open.
GET/api/tools/overlay/usage
Free Smart Overlays left, the price of one after that, and the credits available to pay for it.
Assistant tools: list_smart_overlays, create_smart_overlay
curl "https://app.groundbook.ai/api/tools/overlay/usage" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb list_smart_overlays{
"freeLimit": 5,
"freeRemaining": 3,
"priceCents": 100,
"balanceCents": 12000,
"canBuyCredits": true
}GET/api/tools/overlay/files
PDFs and converted DWGs in the projects you can open: the files a Smart Overlay can start from, besides saved files.
Assistant tools: create_smart_overlay
curl "https://app.groundbook.ai/api/tools/overlay/files" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY"gb api GET /api/tools/overlay/files{
"documents": [
{
"id": "73808823-a773-4917-a5a6-24168948f498",
"name": "Architectural.pdf",
"project": "2465 Semlin Drive, Vancouver, BC",
"projectId": "8c0d0499-7e63-40f6-812f-0b080be21449"
}
]
}Ask
The project assistant as one call: a question in, an answer with references out. It reads the sheets, issues, and schedules the same way the chat on the site does, and uses the project's chat credits.
POST/api/projects/{projectId}/ask
Asks a question about a project and waits for the answer.
When the answer takes longer than waitSeconds, status is running: call again with the conversationId and no question to collect it. Use the same conversationId to keep asking in context.
Assistant tools: ask
| Parameter | Type | Description |
|---|---|---|
projectIdpath | uuid required | The project id. |
questionbody | string | Up to 8000 characters. Omit it to collect a pending answer. |
conversationIdbody | uuid | Continue an earlier conversation. |
waitSecondsbody | integer | 0 to 55. Default 45. |
curl -X POST "https://app.groundbook.ai/api/projects/PROJECT_ID/ask" \
-H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Which sheets have unresolved conflicts?"}'gb ask --project-id PROJECT_ID --question "Which sheets have unresolved conflicts?"{
"conversationId": "28eb6c74-3b02-44d5-b7bf-3f967820e7e9",
"turnId": "36e92139-a0fd-41bd-b911-6ecf03b024cf",
"status": "complete",
"answer": "Three sheets still have open conflicts: S42 and S43 disagree on the SW3 schedule (#1), and S10 conflicts with M-200 on the P2 floor elevation (#6)…",
"message": null,
"links": [
{
"label": "Issue #1",
"href": "https://app.groundbook.ai/projects/8c0d0499-7e63-40f6-812f-0b080be21449/documents/73808823-a773-4917-a5a6-24168948f498?issue=1f78a5ca-1640-4075-998e-b1495295dcda&reference=4d9dabbe-40c4-4e7f-b8b2-e0b4daf32e45"
}
],
"url": "https://app.groundbook.ai/projects/8c0d0499-7e63-40f6-812f-0b080be21449?chat=panel&conversation=28eb6c74-3b02-44d5-b7bf-3f967820e7e9"
}- status is locked, with a message, when the project's free chat allowance is used up and the account has no credits. For someone who can pay, links then starts with View plans, the page where plans and credits are bought.