Developers

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
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.

json
{ "error": "Wait for every file to finish analyzing before payment." }
StatusTypeMeaning
400Bad requestA field is missing or out of range. The message says which.
401UnauthorizedNo key, a revoked key, or an expired OAuth token. Refresh the token or create a new key.
403ForbiddenA read-only key on a write route, or an action only the owner can take.
404Not foundThe id does not exist or your account cannot open it. We do not say which.
409ConflictThe check is past editing, payment is in progress, or someone needs project access first (code: "project_access_required").
429Too many requestsOnly 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

Request
curl "https://app.groundbook.ai/api/auth/me" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb whoami
Response
{
  "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

ParameterTypeDescription
amountCents
body
integer requiredWhole dollars in cents, 2000 ($20) or more.
Request
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
Response
{
  "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

ParameterTypeDescription
action
body
"trial" requiredStart the trial.
planId
body
starter | team | business | scale requiredThe plan the trial is on.
interval
body
month | year requiredHow the plan is billed once the trial ends.
Request
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"
Response
{
  "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

ParameterTypeDescription
q
query
stringText to match against the project address or file names.
status
query
draft | processing | readyRepeat to allow several statuses.
page
query
integerPage number, starting at 1. 20 projects per page.
owner
query
stringOwner user id; repeat for several. Only useful inside an organization.
Request
curl "https://app.groundbook.ai/api/projects?status=ready" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb list_projects --status ready
Response
{
  "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

Request
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."
Response
{
  "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

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
Request
curl "https://app.groundbook.ai/api/projects/PROJECT_ID" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb get_project --project-id PROJECT_ID
Response
{
  "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

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
address
body
string | nullThe new address or name, up to 500 characters. null clears it.
language
body
stringThe language findings are written in, as a name or code (Spanish, es). A check started after this writes in it.
Request
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"
Response
{
  "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

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
Request
curl -X DELETE "https://app.groundbook.ai/api/projects/PROJECT_ID" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb delete_project --project-id PROJECT_ID --yes
Response
No body.
  • 409 when a payment for the project is still being completed.

GET/api/projects/{projectId}/shares

Who can open the project: editors, pending invitations, and organization access.

Assistant tools: get_project, share_project

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
Request
curl "https://app.groundbook.ai/api/projects/PROJECT_ID/shares" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb api GET /api/projects/PROJECT_ID/shares
Response
{
  "owner": {
    "id": "An9o6aC0tnYvuUqnsIwEp1HLjuk2",
    "email": "you@example.com",
    "displayName": "Your Name"
  },
  "editors": [
    {
      "id": "u2",
      "email": "eng@example.com",
      "displayName": "Eng",
      "sharedAt": "2026-09-01T00:00:00.000Z",
      "source": "direct"
    }
  ],
  "invitations": [
    {
      "id": "c79a143e-9ac5-48b4-86c3-67e352e8a05f",
      "email": "new@example.com",
      "createdAt": "2026-09-14T00:00:00.000Z"
    }
  ],
  "organization": {
    "id": "6c93e7de-cbd9-44c8-a5dd-edafca9138a0",
    "name": "Example Engineering"
  },
  "organizationAccessEnabled": false,
  "canChangeOrganizationAccess": true
}

POST/api/projects/{projectId}/shares201

Invites someone by email. An existing account gets access at once; a new one gets an invitation.

Assistant tools: share_project

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
email
body
string requiredThe person to invite.
Request
curl -X POST "https://app.groundbook.ai/api/projects/PROJECT_ID/shares" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"eng@example.com"}'
gb share_project --project-id PROJECT_ID --email eng@example.com
Response
{
  "editor": {
    "id": "u2",
    "email": "eng@example.com",
    "displayName": "Eng"
  },
  "delivered": true
}
  • For an email without an account the response is { invitation, delivered } instead.

PATCH/api/projects/{projectId}/shares

Lets everyone in the owner's organization open the project, or stops that.

Assistant tools: share_project

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
organizationAccessEnabled
body
boolean requiredtrue to open the project to the organization.
Request
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
Response
{
  "organizationAccessEnabled": true
}

DELETE/api/projects/{projectId}/shares/{userId}204

Removes a person's access.

Assistant tools: remove_project_share

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
userId
path
string requiredThe editor's user id, from the shares list.
Request
curl -X DELETE "https://app.groundbook.ai/api/projects/PROJECT_ID/shares/USER_ID" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb remove_project_share --project-id PROJECT_ID --user-id USER_ID --yes
Response
No body.

DELETE/api/projects/{projectId}/invitations/{invitationId}204

Cancels a pending invitation.

Assistant tools: remove_project_share

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
invitationId
path
uuid requiredThe invitation id, from the shares list.
Request
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 --yes
Response
No 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

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
status
body
string requiredThe status name, up to 80 characters.
Request
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"
Response
{
  "status": "Needs RFI"
}

POST/api/projects/{projectId}/disciplines201

Adds a discipline the project can tag issues with.

Assistant tools: update_project

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
discipline
body
string requiredThe discipline name, up to 80 characters.
Request
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"
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id, from the project.
Request
curl "https://app.groundbook.ai/api/checks/CHECK_ID" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb get_project --project-id PROJECT_ID
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
reviewInstructions
body
string requiredAt least 20 characters.
reviewInstructionsTitle
body
string | null requiredA short title, up to 80 characters, or null.
autoGenerated
body
boolean requiredfalse when a person wrote the instructions.
codeCheckEnabled
body
boolean requiredWhether to check against building codes.
reviewSetup
body
objectSaved review settings, including role, roleOther (custom role or scope), and phase. Role and phase are required before starting; unfinished drafts may omit them.
Request
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."
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
codeName
body
string requiredThe code's name, up to 300 characters.
sourceUrl
body
stringA public URL of the code. Give this or checkDocumentId.
checkDocumentId
body
uuidOne of the check's files that is the code book.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
codeName
query
string requiredThe code's name.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
Request
curl "https://app.groundbook.ai/api/checks/CHECK_ID/documents" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb get_project --project-id PROJECT_ID
Response
{
  "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.

ParameterTypeDescription
checkId
body
uuid requiredA draft check.
fileName
body
string requiredMust end in .pdf or .dwg.
sizeBytes
body
integer requiredPositive byte count of the original file.
Request
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
Response
{
  "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.

ParameterTypeDescription
documentId
path
uuid requiredFrom the create-upload response.
checkId
body
uuid requiredThe same draft check.
originalName
body
string requiredThe file name to show.
sizeBytes
body
integer requiredThe size you uploaded.
codeName
body
stringName the file as a code book instead of a drawing set.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredA draft check.
documentIds
body
uuid[] required1 to 50 saved file ids.
Request
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
Response
{
  "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

ParameterTypeDescription
path
query
stringFolder path; the root when omitted.
Request
curl "https://app.groundbook.ai/api/integrations/egnyte/folders" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb list_egnyte_folder --path /Shared/Projects
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredA draft check.
path
body
string requiredThe PDF's Egnyte path, from the folder listing.
Request
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"
Response
{
  "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

Request
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"
Response
{
  "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

ParameterTypeDescription
driveId
query
stringThe drive, from the roots list.
itemId
query
stringA folder id; the drive root when omitted.
search
query
stringMatch file and folder names across the drive instead of listing one folder.
Request
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"
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredA draft check.
driveId
body
string requiredFrom the browse entry.
itemId
body
string requiredFrom the browse entry.
Request
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"
Response
{
  "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

ParameterTypeDescription
checkDocumentId
path
uuid requiredThe file's id within the check, from the files list.
reviewRole
body
checked | referencechecked files are reviewed for issues; reference files are context only.
fileType
body
stringDrawing, Specifications, Report, Calculations, Code, or Supporting document. The check reads Drawing files; any other text is saved as a custom label.
Request
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
Response
{
  "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

ParameterTypeDescription
checkDocumentId
path
uuid requiredThe file's id within the check.
Request
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 --yes
Response
No 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

Request
curl "https://app.groundbook.ai/api/saved-documents" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb list_saved_files
Response
{
  "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.

ParameterTypeDescription
documentId
path
uuid requiredThe document id.
saved
body
booleantrue keeps the file after its project; false removes it from the library.
name
body
stringA new name.
scope
body
personal | organizationWho may reuse it. Only the person who saved it can change this.
Request
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"}'
Response
{
  "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.

ParameterTypeDescription
documentId
path
uuid requiredThe document id.
download
query
1Send as an attachment instead of inline.
Request
curl "https://app.groundbook.ai/api/documents/DOCUMENT_ID/content" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb api GET /api/documents/DOCUMENT_ID/content
Response
The 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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
Request
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
Response
{
  "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

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
Request
curl "https://app.groundbook.ai/api/issues/ISSUE_ID" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb get_issue --issue-id ISSUE_ID
Response
{
  "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

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
severityLabel
body
High | Medium | LowThe new severity.
status
body
stringopen, reviewed, resolved, dismissed, or a status saved on the project.
labels
body
string[]Replaces the labels. Up to 20, each up to 40 characters.
Request
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
Response
{
  "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

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
Request
curl "https://app.groundbook.ai/api/issues/ISSUE_ID/comments" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb get_issue --issue-id ISSUE_ID
Response
{
  "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

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
body
body
string requiredUp to 4000 characters.
mentions
body
{ email, displayLabel }[]People to notify, up to 20.
grantProjectAccessEmails
body
string[]Mentioned emails to invite to the project if they cannot open it.
attachmentIds
body
uuid[]Attachments uploaded through the site.
Request
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
Response
{
  "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

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
commentId
path
uuid requiredFrom the issue's comments.
Request
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 --yes
Response
No body.

POST/api/issues/{issueId}/assignees201

Assigns the issue to someone by email.

Assistant tools: assign_issue

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
email
body
string requiredWho to assign.
grantProjectAccess
body
booleanInvite them to the project if they cannot open it. Default false.
Request
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
Response
{
  "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

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
assigneeId
path
uuid requiredFrom the issue's assignees.
Request
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 --yes
Response
No 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

ParameterTypeDescription
issueId
path
uuid requiredThe issue id.
accuracy
body
correct | incorrect | null requiredWhether the finding is right.
usefulness
body
useful | not_useful | nullWhether it helps. Replaces the issue's shared value for everyone; null clears it and leaving it out keeps it.
reasons
body
string[] requiredAny of important, low_importance, strong_evidence, wrong_or_missing_evidence, duplicate, unclear, related_issue, incorrect, not_relevant, not_yet_important, other.
details
body
string | nullOptional explanation for other; null clears it and leaving it out preserves it while other stays selected.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
format
body
report | markup | fdf | csv requiredWhat to build.
issueIds
body
uuid[] | nullOnly these issues, in this order. Otherwise every open issue.
markupColor
body
blue | red | green | purple | orange | blackThe color of the callouts on marked-up drawings. Default blue.
Request
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
Response
{
  "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

ParameterTypeDescription
exportId
path
uuid requiredThe export id.
Request
curl "https://app.groundbook.ai/api/exports/EXPORT_ID" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb get_export --export-id EXPORT_ID
Response
{
  "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

ParameterTypeDescription
exportId
path
uuid requiredThe export id.
Request
curl "https://app.groundbook.ai/api/exports/EXPORT_ID/file" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb download-export EXPORT_ID --out issues.pdf
Response
The 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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
Request
curl "https://app.groundbook.ai/api/checks/CHECK_ID/fieldwire" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb api GET /api/checks/CHECK_ID/fieldwire
Response
{
  "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

Request
curl "https://app.groundbook.ai/api/integrations/fieldwire/projects" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb api GET /api/integrations/fieldwire/projects
Response
{
  "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

ParameterTypeDescription
fieldwireProjectId
path
string requiredThe Fieldwire project id, from the projects list.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
fieldwireProjectId
body
string requiredThe Fieldwire project to send to.
teamId
body
string | nullA Fieldwire category to file the tasks under.
issueIds
body
uuid[] | nullOnly these issues. Otherwise every open issue.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
sendId
path
uuid requiredThe send id.
Request
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
Response
{
  "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

ParameterTypeDescription
checkId
path
uuid requiredThe check id.
Request
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
Response
{
  "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

Request
curl "https://app.groundbook.ai/api/tools/overlays" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb list_smart_overlays
Response
{
  "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

ParameterTypeDescription
overlayId
path
uuid requiredThe overlay id.
Request
curl "https://app.groundbook.ai/api/tools/overlays/OVERLAY_ID" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb get_smart_overlay --overlay-id OVERLAY_ID
Response
{
  "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

ParameterTypeDescription
title
body
string requiredUp to 300 characters.
sources
body
{ id, name, pages }[] requiredThe PDFs by document id, from a project's files or the saved files. pages: [] has the site read the sheets.
referenceColor
body
string requiredThe first drawing's color, as #rrggbb.
comparisonColor
body
string requiredThe second drawing's color, as #rrggbb.
sideA
body
string requiredThe document id of the reference file.
sideB
body
string requiredThe document id of the file laid over it; the same id compares sheets within one file.
pairs
body
{ id, referenceId, comparisonId }[] requiredSheet pairs by sheet id. [] before the files are read.
requestedPairs
body
{ reference, comparison }[]Sheets to pair once the files are read, by sheet number or page number.
viewers
body
object requiredEach pair's alignment and display. {} for a new overlay.
Request
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
Response
{
  "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

Request
curl "https://app.groundbook.ai/api/tools/overlay/usage" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb list_smart_overlays
Response
{
  "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

Request
curl "https://app.groundbook.ai/api/tools/overlay/files" \
  -H "Authorization: Bearer $GROUNDBOOK_API_KEY"
gb api GET /api/tools/overlay/files
Response
{
  "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

ParameterTypeDescription
projectId
path
uuid requiredThe project id.
question
body
stringUp to 8000 characters. Omit it to collect a pending answer.
conversationId
body
uuidContinue an earlier conversation.
waitSeconds
body
integer0 to 55. Default 45.
Request
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?"
Response
{
  "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.