API Overview
Authentication, error contracts, and architecture for GridWonk External API v1.
Public plugin and existing integrations
The public GridWonk plugin has a separate, curated user-OAuth catalog. When the rollout is enabled, it binds one exact sign-in session to a workspace after browser confirmation and rechecks current access for every operation. The organization-key and partner-token contracts below remain separate. The public plugin does not expose unrestricted chat, generic job execution, purchases, or human decision tools.
Trial and prepaid processing also requires the workspace's current processing allowance, including when an existing credential reaches a shared intake or review core. Public help access does not grant access to protected discovery or customer data.
API Overview
GridWonk External API v1 is exposed under /api/v1 and is designed for organization-scoped partner integrations.
How To Read Examples
An example explicitly labeled runnable can be executed after you set its named credentials and replace any angle-bracket placeholders. Response bodies, event transcripts, command synopses, and snippets not labeled runnable are illustrative: they explain the contract but are not complete programs.
Base URL
https://gridwonk.com/api/v1Direct HTTP examples use that canonical GridWonk origin. The CLI and TypeScript
SDK also default to https://gridwonk.com, so authenticated requests need no
base URL or trust override:
gridwonk utilities list --state CA --jsonimport { GridWonkClient } from '@gridwonk/sdk';
const client = new GridWonkClient({
apiKey: process.env.GRIDBOOST_API_KEY!,
});Use baseUrl or --base-url only for an approved alternate environment.
Arbitrary origins require the explicit untrusted-origin option before either
client sends credentials; PDF uploads to a custom SDK origin require the
separate file-upload override too.
Authentication
Most runtime routes use a GridWonk API key or OAuth bearer token. This request is runnable after setting GRIDBOOST_API_KEY:
curl -X GET https://gridwonk.com/api/v1/jobs \
-H "Authorization: Bearer $GRIDBOOST_API_KEY"Keys are organization-bound and cannot access data outside their tenant scope. Route-specific scoping still matters: for example, deficiency reports and application submission sync results may be visible to either the owner organization or the applicant organization. Document-bound async jobs also re-check the referenced document at enqueue time; private or individually shared applicant documents require a user-scoped path rather than an organization API key.
For legacy connector-owned Salesforce packets, ordinary organization access is not enough: packet, package, report, and document readers also require the effective human user's current Salesforce record and field permissions. Historical results retain that check. The connector itself remains planned and disabled; see Salesforce integration status.
The separate outbound-only installed application has a certificate-signed contract, not API-key or
OAuth access. Its Layer 1 endpoint always returns 503 {"error":"disabled"} before reading the
request body or database. This is not a customer-available packet operation.
Each API-key request also passes the credential's endpoint allowlist before the route handler runs; management keys do not gain access to an admin route unless that path is explicitly allowed.
Authentication and pre-auth callback throttles use shared Redis fixed-window state in production.
They do not trust caller-supplied X-Forwarded-For values; deployments that provide a client-IP
dimension must configure a header rewritten by a trusted edge.
The complete authenticated partner OpenAPI document declares those two Bearer alternatives separately: callers may send a raw organization API key or an issued OAuth JWT. The token endpoint overrides that default because it authenticates the client credentials used to obtain a JWT.
GridWonk also builds a curated OpenAPI 3.1 document for /openapi.json and
/.well-known/openapi.json on the app host. It advertises only active partner packet operations
that also have a hosted MCP binding, gives every operation a stable function-safe operationId,
and uses an OAuth 2.0 client-credentials scheme with exact partner.read or partner.write
requirements. It does not expose the human-only role-decision route, broad operator routes, admin
routes, or deprecated capabilities.
Both routes answer 404 today. Anonymous publication is off (isPublicOpenApiPublished in
lib/api/v1/public-openapi.ts). Public help and the curated plugin do not activate this separate
publication surface. Partners fetch the complete document from
/api/v1/openapi.json with a credential.
Packet REST routes require short-lived OAuth tokens carrying partner.read or partner.write.
For existing organization integrations, the hosted MCP route accepts either machine credential
lane but keeps their catalogs disjoint: broad keys
cannot see packet tools, and partner-scoped tokens can see only packet tools granted by their scopes.
OAuth clients may bind the issued JWT to the exact MCP endpoint with the resource token parameter;
the gateway pins the partner scope set, when present, to the MCP session. Resource-bound JWTs are
supported only by the public /api/v1/mcp gateway. The separate admin MCP endpoint accepts an
approved browser session or internal management key, plus its independently gated user-OAuth
lane with a separate approved client/audience and current administrator authority. Machine
client-credentials tokens do not authorize that lane; see MCP authentication.
A stateful MCP session delegated from an API-key owner to another member rechecks both people's current organization roles on each request. If the owner is demoted below the delegated member, or either membership is revoked, the session is refused before a tool runs. Reinitialize after the organization's permissions are corrected; the stored session does not preserve old authority.
A normal JSON GET /api/v1/mcp remains a discovery response. A standalone GET whose Accept
header includes text/event-stream in any letter case receives 405 Method Not Allowed, because
the hosted gateway does not offer a separate server-initiated event stream. Clients must not
reconnect that request.
The mixed-upload batch coordinator is available under
/api/v1/packets/{submissionId}/intake-batches, with reserve, status, heartbeat, pair, item cancel,
and abandon bindings in the SDK, CLI, and MCP. Pass both batch and item IDs into document intake
so automatic review and freeze wait for the whole selection. Native-CAD declarations and pairing
remain applicant-only. Standalone partner CAD creation still requires an exact current site-plan
version up front. ZIP create/status/finalize/abandon use the separate
/api/v1/packets/{submissionId}/archive-intake family. Individual document cancel, reauthorize,
and retry-processing live under /api/v1/packets/intake/{intakeId}. All seven operations have
SDK, CLI, and MCP bindings; see ZIP intake and recovery.
Packet document attachment and exact-document review also have REST, SDK, CLI, and MCP bindings.
Deletion has REST, SDK, and CLI bindings but is intentionally absent from MCP and therefore from the
anonymous public OpenAPI projection; it remains documented in the authenticated full contract.
Authorized utilities also use the shared packet-review start for screening. Manual freeze, finding adjudication, screening completion, and study requirements have REST, SDK, and CLI bindings but remain human decisions, excluded from MCP and its public OpenAPI projection. See Utility Applications for authority, exact-package inputs, review-budget reuse, and the next-submission-only study rule.
Package-bound notices now have implemented REST, SDK, and confirmed CLI bindings. Reads require
partner.read; writes require partner.write and current direct utility writer membership.
Only notice list/detail reads are exposed through MCP and the curated OpenAPI projection. A send
request may return 202 while delivery is pending or provider-accepted; that is neither canonical
sent status nor proof of inbox delivery. Schema activation, package publication, and production
release remain separate gates. See notice operations.
Exceptions:
POST /api/v1/oauth/tokenaccepts client credentials by HTTP Basic auth, form body, or JSON body; it does not require a bearer header.GET /api/v1/auth/bootstrap/statusandPOST /api/v1/auth/bootstrap-keyrequire an approved GridWonk user session.GET /api/v1/openapi.jsonaccepts a raw API key or scope-less OAuth JWT and returns the partner OpenAPI document directly. Partner-scoped tokens remain confined to partner endpoints.GET /openapi.jsonandGET /.well-known/openapi.jsonreturn 404. They are the routes the curated agent contract would be published on; anonymous publication is currently off.
For invite-only onboarding, the first management key is minted via:
GET /api/v1/auth/bootstrap/statusPOST /api/v1/auth/bootstrap-key
Key roles:
management: can manage API keys and call runtime endpointsruntime: can call runtime endpoints only
Management keys can create a runtime key for another organization, or update a runtime key already in that organization, only when the caller is a GridWonk platform organization key. The update operation does not move a key between organizations. Customer tenant management keys cannot perform cross-organization key operations.
Core Patterns
1. Tenant Isolation
Most v1 routes execute in API-key auth context and are scoped to the key's organizationId. The remediation working-draft and export routes are always on; their env feature gates were removed 2026-08-26. Organization API profile gates can also deny access before route logic runs: API access, key management, and MCP gateway access can each be disabled separately. Before those profile gates run, a platform-admin suspension of the organization's API and MCP access, or an account billing suspension, refuses every API-key and MCP request with 403 FORBIDDEN and reason: api_access_suspended or reason: billing_suspended (see Errors).
2. Async Job Handles
Long-running workflows return:
jobIdpollUrlstreamUrl
Cancelling a packet-review job settles its linked review and prevents late results. Read any
optional runtime and warning fields in the cancellation response: a stopped review status
does not prove an already-running provider request stopped. See Jobs API.
3. Streaming Endpoints
/api/v1/agents/chatreturns SSE token/events stream. Citations arrive assourceevents only when the request setsincludeSources: true./api/v1/jobs/{jobId}/streamreturns SSE status updates./api/v1/assistcan return one-shot JSON or SSE. When streaming, it emitscontent_block_deltaevents and finishes with adoneevent containingtext,model,provider,source, andusage.
The assist endpoint is environment-gated by GRIDBOOST_ENABLE_API_ASSIST. Its default model is
selected from the assist-api / default registry assignment when the REST request does not
supply an explicit model. Registry resolution failure returns 503 before generation; there is
no hardcoded fallback. Hosted MCP accepts no caller model override. In production, every resolved
assist model must be a Google model,
whether it came from the request body or the database config, unless
GRIDBOOST_ASSIST_ALLOW_NON_GOOGLE_MODELS=true is explicitly set.
4. Requirement Reads
GET /api/v1/published-requirements is the current requirement read. One server-side reader backs
it across REST, SDK, CLI, and MCP. It serves every published row except the ones a utility reviewer
explicitly rejected, and marks each returned row reviewStatus: "approved" or
reviewStatus: "pending" so you can tell a signed-off rule from one awaiting a current utility
decision. Unknown utilities and uncovered categories return an explicit honest state instead of a
near miss. The typed releaseStatus (released, partially_released, review_incomplete, or
not_published) reports utility-review progress only — it does not gate what is served.
GET /api/v1/requirements is the retired legacy lane. Since 2026-08-11, authenticated production
calls return typed 410 Gone / ENDPOINT_GONE and point to the published route. The frozen corpus
is not read and the old GET-webhook side effect does not run. There is no flag-based rollback to
the frozen corpus. See Retirement Stages.
5. Webhook Notifications
Signed delivery with retries covers job/document lifecycle events. The utility-event layer also implements human screening determinations, finding decisions, study-requirement changes, package freezes, and canonical notice transitions through the existing subscription API. Its schema activation and production release remain separately held. Only the application's receiving utility organization gets those events; applicant access does not grant subscription access. See Webhooks API for event names, ordering, and deduplication.
Common Error Envelope
Request and upload safety
API JSON and form parsers enforce bounded request bodies before parsing. The PDF upload route accepts
only strict base64 PDF data, caps the decoded file at 3 MiB, and derives the stored byte count from
the decoded payload rather than trusting a caller-provided sizeBytes. Invalid JSON or oversized
payloads receive a generic 400 or 413 response and are not processed.
Wrapped or URL-safe base64 is normalized before the PDF signature and decoded-size checks.
The partner packet review and role-decision routes, plus project PATCH updates, use a stricter
16 KiB JSON body cap because their mutation contracts are small. The larger general API limit does
not override those route-specific caps.
Native-CAD partner intake uses direct binary upload authorization instead of embedding file bytes in JSON. Its create request remains small, while the uploaded DWG has a separate 30 MB limit and is bound to an exact current site-plan version. See Partner Packets.
{
"error": {
"code": "INVALID_INPUT",
"message": "utility: Required"
},
"requestId": "req_xxx"
}Common Error Codes
| Code | Status | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing/invalid API key |
PAYMENT_REQUIRED | 402 | Org daily or monthly usage cap exceeded without active billing or override |
FORBIDDEN | 403 | Endpoint denied by policy or key restrictions |
RATE_LIMITED | 429 | Key request limit exceeded, or a paying org's daily or monthly usage cap reached (Retry-After to the next UTC window) |
INVALID_INPUT | 400 | Payload/query validation failure |
NOT_FOUND | 404 | Resource inaccessible or absent |
CONFLICT | 409 | Invalid state transition (for example cancel terminal job) or concurrent update — refresh and retry |
UNPROCESSABLE | 422 | Record state cannot accept the write; fix the state first (retrying will not help). Example: a role decision on a linked document with no accepted sanitized version |
ENDPOINT_GONE | 410 | Endpoint retired; body carries a replacement path |
INTERNAL_ERROR | 500 | Server-side failure |
Endpoint Families
- OAuth token exchange:
POST /api/v1/oauth/token(client credentials grant). - Bootstrap onboarding:
GET /api/v1/auth/bootstrap/status,POST /api/v1/auth/bootstrap-key. - Utility/document primitives: utility matching, classification, digitization, validation.
- Developer projects: tenant-scoped list, get, create, and editable-draft update operations using the organization key's authority; fine-grained project OAuth grants are not live. Reference -->
- Application queries: organization-scoped application sessions with incremental sync support.
- Async orchestration: jobs list/create/get/cancel/stream.
- Agent interfaces: async execute plus streaming chat.
- Assist generation: one-shot or streaming text assistance via
/assistwhen enabled for the environment. - Compliance data: published requirements (
/api/v1/published-requirements), the retired legacy path (/api/v1/requirements, typed 410 with replacement), and deficiency reports. Reference --> - Webhook control plane: subscription CRUD and attempt visibility.
- Key management: CRUD operations for API key lifecycle (create, list, update, revoke). Reference -->
- Usage analytics: per-org/per-key API consumption rollups.
- MCP gateway: credential-filtered JSON-RPC tool access over
/api/v1/mcp, including per-toolpartner.read/partner.writeenforcement and session cleanup withDELETE /api/v1/mcp. - OpenAPI metadata: complete authenticated metadata at
GET /api/v1/openapi.jsonfor raw API keys and scope-less OAuth JWTs. The curated anonymous projection atGET /openapi.jsonandGET /.well-known/openapi.jsonis built and tested but not published; both return 404. - Native CAD intake: cohort-gated partner routes under
/api/v1/packets/cad-intakereserve, finalize, inspect, restart, or cancel a private DWG upload against an exact site-plan version. This intake layer validates the file but does not attach it or invoke Autodesk processing.
See External API (v1) for route-level index and examples.
OpenAPI Coverage
The docs-host /.well-known/openapi.json document covers every /api/v1 operation available to
machine credentials. Fetching it requires native internal authorization; raw API-key and scope-less OAuth callers
retrieve the same complete document from /api/v1/openapi.json. Both copies are built by
lib/api/v1/full-openapi.ts, so the two URLs cannot drift. Four routes are deliberately
omitted: the two session-only bootstrap helpers and the authenticated /api/v1/openapi.json route
that serves the document itself, plus the hard-disabled installed-app endpoint described above.
A required contract compares every
exported route method with the OpenAPI document and this owned omission registry, so an undocumented
operation, stale omission, or nonexistent advertised operation fails CI.
The app-host /openapi.json and /.well-known/openapi.json routes are a separate curated
projection built by lib/api/v1/public-openapi.ts, currently unpublished (both return 404). Its contract rejects missing manifest
capabilities, REST or hosted-MCP bindings that are anything other than available, mismatched
scopes, duplicate or unsafe operationId values, missing descriptions, a declared status with no
named response schema, a success payload left as an open object, and any $ref that does not
resolve.
Because the anonymous document is readable by anyone, a second contract governs its wording. Every
summary, description, and response description is authored in public-openapi.ts rather than
inherited from the complete document, and the build fails if the serialized result contains an
environment or cohort gate name, a quota figure, billing language, a third-party processing vendor,
or the note explaining that a refusal is returned as a 404. Adding a status code upstream without
writing partner-facing text for it also fails, so operator prose cannot arrive unnoticed.
Salesforce connector status
Four authenticated connector operations are implemented for search, mapped-answer/file inspection, acknowledged import, and progress. They remain disabled pending acceptance and require current utility/connection/source authority. No anonymous discovery or browser-login exemption is added. See Salesforce interfaces.