Docs
API Reference

External API (v1)

Route index for GridWonk partner integrations over /api/v1.

External API (v1)

This page is the endpoint index for the GridWonk partner API.

Base URL

https://gridwonk.com/api/v1

Authentication

Most routes require a Bearer token — either an API key or a JWT obtained via OAuth 2.0:

Authorization: Bearer gw_live_...    (API key)
Authorization: Bearer eyJhbGci...    (JWT from /oauth/token)

Legacy gb_live_/gb_test_ keys are no longer accepted. Use a gw_live_... or gw_test_... key.

See Authentication & Rate Limiting for details on both methods.

Auth exceptions: /oauth/token accepts client credentials by body or HTTP Basic auth, bootstrap routes require an approved GridWonk user session, and /api/v1/openapi.json returns the complete discovery document directly to raw API-key and scope-less OAuth callers. The app-host /openapi.json and /.well-known/openapi.json routes would serve the curated partner packet projection, but anonymous publication is off and both return 404. The machine-token issuer advertises client credentials, and its optional resource parameter can bind a JWT to /api/v1/mcp. The separately gated public plugin uses user OAuth and exact-session browser confirmation; its curated tools do not grant general REST access. Machine tokens do not authorize admin MCP. Its separately gated administrator-OAuth lane requires an approved client, exact audience and current administrator authority; implementation does not establish activation. A platform-admin suspension of an 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 before endpoint and profile checks run. The project routes use the underlying organization key authority; projects:* scopes are not a live grant vocabulary.

Request bodies are bounded before route parsing. General JSON requests are limited to 1 MiB and the OAuth token body to 32 KiB. Oversized requests return 413 PAYLOAD_TOO_LARGE. Document bytes are never sent as JSON: packet intake issues a signed upload target (files up to 30 MB; formats per the packets page) and validates the stored object before it is accepted. The partner packet review and role-decision mutations and project PATCH updates use a stricter 16 KiB JSON cap because their request contracts are small.

The complete authenticated partner OpenAPI document covers every exported /api/v1 HTTP operation except four deliberate omissions: the two session-only bootstrap routes and the authenticated route that serves the OpenAPI document itself, plus the hard-disabled Salesforce installed-app endpoint. That separate certificate-signed contract is not callable using partner API keys or OAuth tokens; it returns 503 {"error":"disabled"} without accepting work. Each omission has an owner, documentation link, and rationale in the checked registry. CI rejects undocumented live operations, missing methods, stale omissions, and advertised operations with no route.

A smaller curated contract is built for https://gridwonk.com/openapi.json and https://gridwonk.com/.well-known/openapi.json, but it is not published — both routes return 404 while PUBLIC_OPENAPI_DISCOVERY is unset. It includes only active partner packet operations that also have hosted MCP bindings, plus the OAuth token exchange. Every operation has a unique function-safe operationId, exact partner.read or partner.write security, and a named schema for every declared status — success and error alike — with no payload left as an open object. Human role decisions and the broader operator surface remain outside that document.

The two documents differ in wording as well as in coverage. The complete document is written for operators and names internal rollout gates, quota figures, and processing vendors; the curated document's prose is authored separately, and a contract fails the build if any of that vocabulary reaches it. Ask for the complete document when you need those operational details.

Key management responses include role, endpoint restriction, cost limit, expiration, and usage fields. Create/update requests cap rateLimitPerMinute at 1000, and cross-organization key operations are restricted to GridWonk platform management keys.

OAuth token exchange is protected by a shared production rate limiter and does not accept a caller-supplied forwarded IP as its security identity. Use the client ID bucket for predictable automation behavior.

Endpoint Index

MethodPathPurpose
POST/oauth/tokenExchange API key for a short-lived JWT (OAuth 2.0 client credentials), optionally bound to an MCP resource
POST/utilities/matchMatch utility names to EIA-backed utility records
GET/utilities/listBrowse and search utilities with filters
POST/documents/classifyClassify document type from raw markdown
POST/documents/digitizeSynchronous document digitization
POST/documents/validateRetired tombstone; returns authenticated HTTP 410
GET/documents/{documentId}/working-draftFetch editable working-copy spans (always on — no feature gate)
PATCH/documents/{documentId}/working-draft/spans/{spanId}Update one working-copy span
GET/applications/queryQuery organization-scoped application sessions
GET, POST/projectsList developer projects or create a real customer draft
GET, PATCH/projects/{projectId}Read or update an organization-owned editable draft
POST/agents/chatStream chatbot responses (SSE). Opt in to citation events with includeSources: true
POST/agents/executeRun supported agents asynchronously
POST/assistRun enabled one-shot or streaming text assistance with resolved model/provider/usage metadata
GET/jobsList async jobs
POST/jobsCreate async job
GET/jobs/{jobId}Fetch one job
DELETE/jobs/{jobId}Cancel active job
GET/jobs/{jobId}/streamStream job progress/completion (SSE)
GET/published-requirementsQuery customer-released utility requirements
GET/requirementsRetired. Returns typed HTTP 410 with /published-requirements as the replacement
POST/packets/intakeStart partner-scoped packet intake; see Partner Packets for the full intake, document, role-decision, review, status, and screening surface
POST/packets/{submissionId}/intake-batchesReserve a declared upload selection; GET .../{batchId} reads it, and nested heartbeat, pair, items/{itemId}/cancel, and abandon routes coordinate its lifecycle
GET, POST/packets/{submissionId}/documentsList packet documents or attach an owner-organization File Library asset
DELETE/packets/{submissionId}/documents/{documentId}Delete a document only from an editable draft or resubmission working set; excluded from MCP and public OpenAPI
POST/packets/{submissionId}/documents/{documentId}/reviewStart or reuse one exact document review; budget exhaustion is 429 RATE_LIMITED with Retry-After
POST/packets/{submissionId}/reviewStart or reuse an applicant or eligible utility review through the shared review core; requires partner.write
POST/utility/applications/{submissionId}/freezeHuman-requested freeze of an eligible utility-owned draft
POST/utility/applications/{submissionId}/packages/{packageId}/adjudicationsRecord a human decision for the exact package, run, finding, and expected version
POST/utility/applications/{submissionId}/screening/completeComplete screening for the exact latest package; repeated completion is idempotent
POST/utility/applications/{submissionId}/study-requirementSet or replace a human study requirement for the next submission only
GET, POST/utility/applications/{submissionId}/noticesList application-bound notices or draft from an exact frozen package
GET, PATCH/utility/applications/{submissionId}/notices/{noticeId}Read safe notice detail or edit allowed draft content
POST/utility/applications/{submissionId}/notices/{noticeId}/{operation}Named submit, approve, return, revoke, or acknowledge transition; not an arbitrary status write
POST/utility/applications/{submissionId}/notices/{noticeId}/sendRequest durable delivery to an on-file applicant/member address; pending work returns 202
POST/packets/cad-intakeStart private DWG companion intake for an exact current site-plan version; finalize, status, reauthorization, and cancellation use nested intake-ID routes
GET/deficiency-reportsQuery scoped findings by findingState (open, resolved, superseded); remediationStatus separately tracks fix progress
POST/remediation/exportsCreate clean/redline/evidence remediation bundle
GET/remediation/exports/{exportId}Poll remediation export status
GET/webhooksList webhook subscriptions
POST/webhooksCreate webhook subscription
GET/webhooks/{id}Get one subscription and recent attempts
PATCH/webhooks/{id}Update subscription
DELETE/webhooks/{id}Delete subscription
GET/usageUsage and performance rollups
GET/mcpDiscover the credential-filtered MCP catalog: broad tools for raw/scope-less credentials, or exact-scope packet tools for partner OAuth tokens
POST/mcpExecute MCP JSON-RPC calls with the same per-tool discovery and authorization policy
DELETE/mcpClose a stateful MCP session
GET/openapi.jsonReturn OpenAPI metadata to raw API-key or scope-less OAuth callers

The MCP discovery GET and the optional event-stream GET are different contracts. A normal JSON GET returns discovery metadata; a GET advertising text/event-stream (matched case-insensitively) returns 405, so clients must not open a reconnect loop for a standalone stream.

The four utility human-decision writes require partner.write and current utility writer authority. They have SDK and CLI bindings but are excluded from MCP and the curated public OpenAPI document. See Utility Applications for strict request bodies and lifecycle restrictions.

The separate notice routes implement the package-bound notice workflow. Notice list/detail reads require partner.read and have REST, SDK, CLI, and read-only MCP bindings. All notice writes require partner.write and current direct utility writer membership; they are absent from MCP and the curated public OpenAPI document. JSON write bodies are strict and capped at 32 KiB. Creation returns 201; ordinary updates/transitions return 200. Send returns 202 for unfinished pending, retrying, or provider-accepted delivery and 200 for finalized, held, or canceled delivery; inspect its separate canonical status and delivery fields. Neither a 2xx response nor provider acceptance proves inbox delivery. These implemented contracts do not activate the held schema or production release.

The existing webhook subscription routes also accept the five utility.* event families for receiving-utility organizations. This is an event-contract extension, not another notice mutation route; schema activation and production release remain held. The signed Resend receipt endpoint is a provider callback outside /api/v1, not an API-key operation. See Webhooks API for the utility event contract.

Four Salesforce-specific REST/MCP/SDK operations are implemented but default-disabled; see the connector section below. Existing packet routes do not grant permission to import or overwrite Salesforce-owned evidence. Salesforce acceptance remains separate.

The OpenAPI document includes the complete native-CAD intake family, not only its create route. Those routes are utility-neutral: availability is controlled by the applicant organization's server-side cohort, while utility-specific drawing checks require a separately reviewed procedure profile. The server proves packet write access before revealing cohort or workflow state. The batch coordinator and applicant-only pairing also have REST, SDK, CLI, and MCP bindings. They can continue a console-created mixed selection and pair an inspected drawing once its PDF becomes a current site plan. Standalone partner CAD creation still requires that exact version up front; the batch bindings do not expose a target-free CAD upload. ZIP creation, status, finalization, and abandonment use the separate packet archive-intake routes, with document cancel, reauthorize, and retry-processing under the intake resource. See ZIP intake and recovery for all seven operations. Utility-owned batches accept ordinary document uploads, not native-CAD declarations or pairing.

Requirement Reads

GET /published-requirements, SDK queryPublishedRequirements(), CLI gridwonk requirements published, and MCP query_published_requirements share one server reader. It serves every published row except the ones a utility reviewer explicitly rejected; rejected rows are omitted server-side and never appear. Each returned row carries reviewStatus: approved (utility reviewers signed off) or pending (awaiting a current utility decision, including a verdict made stale by a later change). An unknown utility or uncovered category returns an explicit honest state rather than technical rows, legacy rows, or a fuzzy-matched neighbour. The typed releaseStatus (released, partially_released, review_incomplete, not_published) reports utility-review progress and is not a serving gate — a review_incomplete scope still returns its rows. category=fees is always empty. Utility resolution is exact.

GET /requirements is a permanent 410 Gone / ENDPOINT_GONE tombstone with /published-requirements as the replacement. The old SDK method, CLI aliases, and public MCP tool have been removed. The internal common-tools tool still uses the short name query_requirements, but it always reads the published Packet Intake store. See Retirement Stages.

Async Job Handle Contract

DELETE /api/v1/jobs/{jobId} also settles the linked review for an authorized packet-review job, preserving completed document findings. Its success response may include runtime and warning; do not interpret status settlement as an immediate stop of an external provider call. See Cancel Job for authority and retry boundaries.

Routes that queue long-running work return 202 with:

{
  "jobId": "uuid",
  "status": "pending",
  "pollUrl": "/api/v1/jobs/{jobId}",
  "streamUrl": "/api/v1/jobs/{jobId}/stream"
}

Quick Start

# Match a utility
curl -X POST https://gridwonk.com/api/v1/utilities/match \
  -H "Authorization: Bearer $GRIDBOOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Duke Energy","state":"NC"}'

# Poll a job returned by document upload or a supported job creation request
curl https://gridwonk.com/api/v1/jobs/<jobId> \
  -H "Authorization: Bearer $GRIDBOOST_API_KEY"

Next References

Salesforce connector operations

The authenticated specification includes four operations under /api/v1/integrations/salesforce/{connectionId}: application search, mapped-answer/file manifest, acknowledged idempotent import, and progress. They are implemented but default-disabled, and require partner scopes or connection-bound REST-audience tokens. Import returns 202; progress is not report access. See exact inputs and activation gates.

On this page