Docs
API Reference

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/v1

Direct 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 --json
import { 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/token accepts client credentials by HTTP Basic auth, form body, or JSON body; it does not require a bearer header.
  • GET /api/v1/auth/bootstrap/status and POST /api/v1/auth/bootstrap-key require an approved GridWonk user session.
  • GET /api/v1/openapi.json accepts 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.json and GET /.well-known/openapi.json return 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/status
  • POST /api/v1/auth/bootstrap-key

Key roles:

  • management: can manage API keys and call runtime endpoints
  • runtime: 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:

  • jobId
  • pollUrl
  • streamUrl

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/chat returns SSE token/events stream. Citations arrive as source events only when the request sets includeSources: true.
  • /api/v1/jobs/{jobId}/stream returns SSE status updates.
  • /api/v1/assist can return one-shot JSON or SSE. When streaming, it emits content_block_delta events and finishes with a done event containing text, model, provider, source, and usage.

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

CodeStatusMeaning
UNAUTHORIZED401Missing/invalid API key
PAYMENT_REQUIRED402Org daily or monthly usage cap exceeded without active billing or override
FORBIDDEN403Endpoint denied by policy or key restrictions
RATE_LIMITED429Key request limit exceeded, or a paying org's daily or monthly usage cap reached (Retry-After to the next UTC window)
INVALID_INPUT400Payload/query validation failure
NOT_FOUND404Resource inaccessible or absent
CONFLICT409Invalid state transition (for example cancel terminal job) or concurrent update — refresh and retry
UNPROCESSABLE422Record 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_GONE410Endpoint retired; body carries a replacement path
INTERNAL_ERROR500Server-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 /assist when 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-tool partner.read / partner.write enforcement and session cleanup with DELETE /api/v1/mcp.
  • OpenAPI metadata: complete authenticated metadata at GET /api/v1/openapi.json for raw API keys and scope-less OAuth JWTs. The curated anonymous projection at GET /openapi.json and GET /.well-known/openapi.json is built and tested but not published; both return 404.
  • Native CAD intake: cohort-gated partner routes under /api/v1/packets/cad-intake reserve, 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.

On this page