# GridWonk Documentation > AI-powered interconnection deficiency analysis platform. > Built for humans and AI agents. > 68 public pages included --- # Changelog Release history and notable changes to the GridWonk platform. URL: /docs-site/changelog This is a curated GridWonk platform-change ledger. The `v1.*` and earlier headings below are historical platform milestone labels. The aligned `v0.4.0` SDK, CLI, and MCP server packages were published to GitHub Packages on October 23, 2026 and passed the release workflow's clean-install check. This **breaking** package release removes legacy base64 uploads, AX optimization, and Queue Analytics methods, commands, and tools. Use matching package versions and review the [utility integration migration guide](/docs-site/api/utility-lane#package-versions-and-migration). **Unreleased** entries below have not been assigned to a numbered platform milestone; package publication and completion of an integration's live acceptance checks remain separate. ## One action on finding cards Finding cards now offer **Explain this finding**, which replaces **Ask the assistant**. It shows the same verified source quotations. ## Application packet review completion Completed packet reviews show **Review Finished**. Open Coverage to see which checks ran and what evidence an unfinished check needed. Platform administrators can inspect recorded costs, receipt gaps, evidence reuse and check coverage under **Monitoring → Packet reviews**. ## Per-check review outcomes New packet reviews may include a result for each declared check, with its outcome, findings and examined documents. The five meanings distinguish missing required information or a demonstrated problem, attempted but inconclusive checks, evidence-backed non-applicability, checks not evaluated with a reason, and no deficiency identified within completed checks. Partial evaluations keep valid findings and expose their unfinished scope. No outcome is utility approval; the separately planned full Checks table is not included in this contract change. ## Unreleased — October 2026 ### Review completeness and evidence Packet reports show **Review incomplete** while declared checks remain unresolved, preserving valid deficiencies and severity counts. Unknown equipment and unreadable evidence are not marked N/A. Coverage explains checks not evaluated and partial evidence, including mixed readable/unreadable sheets or one-line sources. Older reports without recorded coverage remain explicitly unknown; no result implies utility approval. ### Preview and save workspace appearance Direct Owners and Admins of developer and utility organizations can preview **Light**, **Brand color**, and **Dark brand** schemes, select roles from source colors, and explicitly **Save appearance** to enable full branding. Supplemental discovery reads public website and PNG/JPEG/WebP logo evidence; it does not spend a logo.dev Brand API credit or approve a discovered logo for display. Dark schemes require a readable dark source color. Already-enabled legacy themes use exact source fills on code release, with readable neutral text and surfaces. The prepared `20261027150000_organization_brand_appearance` migration does not backfill selections or automatically activate a customer. Production migration, deployment, and customer acceptance remain separate steps. See [Workspace appearance](/docs-site/help/organizations#workspace-appearance). ### Consistent utility screening status Utility screening started through REST, SDK, CLI or MCP now records a submitted application as screening before the review can finish. Completion moves it to screened; a startup failure restores its prior state. Draft package freezing and existing screening decisions are unchanged. ### CLI first-key bootstrap `auth bootstrap-key` accepts an explicit `--org` flag before or after the subcommand. Missing or blank flags are refused without choosing a target from stored or environment settings, and `--dry-run` makes no network request. Server authorization is unchanged. ### Confirmed Admin MCP actions Protected Admin MCP adds invitation creation/resend/revocation, team roles, access status, join-request approval, membership expiry/removal, ownership transfer, branding reads/updates and model-assignment preview/apply tools. Existing user update and bulk approval/rejection/deactivation pairs gain the same credential- and state-bound approval, single execution and safe retry receipt. The catalog declares 45 tools before lane and feature filtering. Legacy direct model updates stay deprecated and session-only. Public MCP and administrator OAuth gain no mutation authority. Internal management-key use defaults off behind `ADMIN_MCP_REMOTE_MUTATIONS_ENABLED`; the reviewed organization administration merge and all four database guards must be verified before a separately authorized activation. This implementation does not enable that flag, activate migrations or perform live mutations. Invitation/legal acceptance remains invitee-only, branding does not change sign-in domains, and model assignments retain catalog validation. ### Utility notice interfaces The dependent notice stack adds application-bound REST, SDK and CLI workflows for drafting, editing, review, approval, return, revocation, sending and acknowledgment. Programmatic sends are restricted to current addresses on file. MCP adds only scoped list/detail reads; every notice write stays excluded. Responses distinguish pending or held delivery, provider acceptance and canonical status without claiming inbox delivery. These bindings are included in the published `0.4.0` packages. Each integration must still verify its own live authorization, workflow and delivery behavior; package publication does not complete those acceptance checks. ### Embedded assistant loading The console and utility workspace load the assistant's chat engine when it is first opened or asked a question. A brief **Preparing assistant…** message can appear on first use; a question submitted during loading waits without needing to be sent again. Loading failures support retry and dismiss, and pending questions can be canceled. Closing or minimizing retains the conversation in its current context. Assistant permissions, model routing and supported operations are unchanged. ### Requirement metadata packaging Requirement metadata can read the names of supported checks and shared document-role labels without loading the equipment-evaluation code. Accepted check names, requirement validation, displayed labels and review behavior are unchanged. Equipment evaluation still uses the complete inverter, battery and PV certification catalogs; no catalog records or matching rules were removed. ### Code highlighting bundles Code blocks retain their existing light and dark themes, supported languages, embedded syntax, line numbers and copy behavior. Their lazy highlighter now declares only the two themes the component uses, so unrelated themes need not be included in its browser output. This does not narrow language support or preload the highlighter before a code block renders. ### Requirements runtime packaging Review-application, SLD analysis and site-plan analysis use their published database requirements without carrying local pipeline JSON. Local source readers remain available to pipeline commands, with unchanged identity, hash/storage and drift checks. A postbuild guard checks the runtime exclusion and retains the complete JSON inventory for the publish-drift cron. No requirement content, publication state or reconciliation behavior is changed. ### Chatbot settings display metadata The Gemini rollout card receives its canonical title and description from the server instead of importing the full capability registry into its browser code. Fallback text, rollout controls, status requests, and authorization are unchanged. No rollout stage, model assignment, or provider configuration is changed. ### Document browser fallback packaging Document fetching, link health checks, and SharePoint downloads now import the existing Playwright runtime library without its test runner. Browser resources are closed after partial setup or fetch errors, and response timers are canceled. The pinned version, URL and redirect guards, size limits, and accepted document types are unchanged. No provider configuration or customer data changes. ### Runtime artifact packaging Public MCP no longer packages a development-only compiled procedure projection through the procedure-discovery path registry. The file and development audit metadata remain available. Runtime utility data is unchanged and protected by a postbuild trace check; no customer capability or discovery behavior is removed. ### Native bundle diagnostics The application pins Next.js 16.4.0 and replaces the Webpack-only analyzer with native Turbopack capture and export commands. A tested server-file inventory and the official bundle-optimizer skill support measured optimization work. The one-time dependency release-age exception does not change the repository's seven-day policy. This tooling change removes no application capabilities; local bundle measurements do not establish hosted size or performance savings. ### Born-digital PDFs can be indexed from their own text (not yet switched on) When document intake starts keeping original PDFs instead of flattened copies, text recognition will first read the text a born-digital PDF already carries, inside the same isolated sandbox that renders pages, and use it when every page passes a quality gate (enough readable text, no invisible text layer, the extracted text matching what the page paints, and page geometry matching the rendered page). Such a document costs nothing to index and is never sent to the recognition provider. A scanned page, a page with an invisible text layer or a page the extractor cannot read fully sends the whole document to the existing recognition path. This engine is built and tested but no uploads use it until the intake switch lands. ### Legacy 3 MB document upload removed The original single-file upload — a base64 PDF of at most 3 MB sent as JSON — is gone: the `POST /api/v1/documents/upload` route now returns 404, the console no longer falls back to it, and the SDK `uploadDocument` method, CLI `docs upload` command and local MCP `upload_document` helper are removed (a breaking change in the `v0.4.0` packages published October 23, 2026). Nobody had used the API path in 120 days. Upload through packet intake (files up to 30 MB). Documents stored through the old path stay readable. ### Text recognition keeps a dense page when one line cannot be located (v5, activation pending) A new text-recognition profile, v5, no longer discards a whole page because one line came back with a box that has no width or height. That line is dropped, the count is recorded in the audit (`empty_text_boxes_dropped`), and every other line on the page is kept. A page where every line is empty, or more than 5% of its lines (beyond one) are, is still rejected. The request sent to the provider and all size, usage and budget checks are the same as v4, and v1–v4 behave as before. v5 takes effect only after its reviewed configuration change is applied. ### Text recognition accepts imperfect line numbering (v4, active since October 1) The not-yet-activated v4 OCR profile no longer rejects a page because the provider numbered its text lines imperfectly (one-based, with a gap, or with a duplicate). Line order was always derived from box position, so those numbers never changed saved output; the strict check could only turn a usable page into a failure, and did so three times on one production sheet. Such a page is now accepted and the run's audit notes it. Empty-box, schema, size, usage and spend checks are unchanged; earlier profiles keep their behaviour. Deployment, configuration activation and a verified customer retry remain separate steps. ### Dense-page text recognition (activation pending) A separately versioned OCR profile accepts up to 1,000 validated text entries per page instead of 250. This addresses pages whose complete response was rejected by our internal line limit, even though the provider finished below its token allowance. Model, 65,536-token request, geometry checks, response-size ceiling and retry limits stay unchanged; no entries are trimmed. Existing jobs and historical results retain their settings. Deployment, configuration activation and a verified customer retry remain separate steps. ### Packet cancellation and visible document findings Authorized reviewers can use **Review Actions → Cancel Packet Review** to settle an active packet run without losing completed document findings. Cancellation prevents later results from that run; an already-running provider request may still finish, and an unconfirmed workflow stop produces a warning. Current document findings remain visible during running, failed or cancelled packet reviews and are labeled separately from whole-project results. Completed current packet results retain priority; stale versions and older successful document checks do not hide a newer failed document review. Deployment and customer recovery still require separate verification. ### Time for large text-recognition responses to finish (activation pending) A separately versioned OCR profile keeps the 65,536-token response allowance and gives each page call up to eight minutes instead of two, so a full-size response is not cut off by the client timeout. The overall ten-minute limit per document run is unchanged, as are the model, text/location validation, retry limits and fallback policy. Existing jobs and historical results keep their original settings. It takes effect only after the reviewed production configuration is activated and does not automatically rerun failed documents. ### More room for text-recognition responses New Gemini OCR jobs use a separately versioned 65,536-token response allowance (activated 2026-09-29). Existing jobs and historical results keep their original settings. The model, text/location validation, retry limits and fallback policy are unchanged. This change does not automatically rerun failed documents or mark them complete. ### Classifier usage accounting (release pending) Chatbot accounting separately records intent-classifier calls, retries and cache hits instead of mixing them into answer-model token totals. Missing measurements or prices remain unknown; estimated costs are not provider bills. This changes no model assignment, customer permissions or Max workflow and does not establish completed Claude Agent SDK retirement. ### Eve usage and synthetic reporting Completed chatbot turns can recover late token measurements without repeating the answer or starting another model call. Missing or partial usage is explicitly marked unknown for total-cost estimation. Console synthetic accounts receive server-derived labels so their tests stay out of customer reports; this grants no additional permissions and does not backfill historical sessions. ### Protected document recovery (activation and execution pending) Human platform operators can preview exact failed document targets, approve a bounded OCR or document-review recovery, and read sanitized status through protected Admin MCP/API operations. The approval binds the current organization, version, artifacts and model settings, a numeric incremental ceiling and an absolute deadline. Durable receipts preserve history and stop uncertain spending; an automatic whole-project-review hold prevents downstream work without new customer intent. Both OCR and review require qualified conservative pricing before provider dispatch. Public MCP, customer SDK/CLI, chatbot mutations and source-managed projects are excluded. Migration activation, pricing configuration, GitHub-sourced deployment, each paid diagnostic/recovery and communications remain separately approved. This implementation is not evidence of customer recovery or a repaired historical root cause. See [Document troubleshooting](/docs-site/help/document-troubleshooting). ### Private packet review by default and controlled utility submission Developers can prepare projects and run private packet reviews by default for released, full state/program utility packet setups; no rollout setting is required. Private review stays available after a utility accepts submissions, and review alone never sends the packet. This includes Delmarva's Maryland packet lane. Sending a packet through GridWonk requires both GridWonk and an authorized utility representative to accept the exact state and program, plus an active utility reviewer. Revocation stops new submissions while earlier frozen packages remain available, and developers already answering a deficiency notice can still resubmit to the same utility. Real-utility acceptance remains a separate gate for each state and program. ### Salesforce installed-app packet submission (disabled) Layer 2 source adds private submission receipts, exact-version PDF checks, bounded direct uploads and finalization. The installed-app entry and model-processing gates remain closed. Native check-only validation passed 21 tests on September 26; no application was installed or activated. Results/history, retention and managed-package lifecycle remain later work requiring approval. ### Split PDF after document assignment (application release pending) Eligible accepted 2–250-page PDFs can be split from **More actions → Split PDF**, including after document-type assignment or review and without a classifier hint. People confirm editable page ranges and document types. Originals and review history remain available; new documents require review. Confirmed pending or failed splits pause new reviews and submission, with **Retry** and **Keep original** recovery. Existing enablement and public APIs are unchanged. The database foundation is already activated in production; this entry does not establish application release or protected-demo activation. ### Authentication cookie response handling Cookie domain, path, expiry and cache headers survive the final refresh, redirect, rewrite and denial responses. Explicit same-origin logout clears known session cookies at both host and parent-domain scopes, including old chunks. Session rotation and expiry policy are unchanged. Trusted refresh writes also remove legacy host-only copies of the active session's chunks while preserving unchanged chunks at the configured domain. Read-only requests do not infer cookie scopes. This entry records source changes, not a production release. ### Session inbox reliability The notification bell uses cancellable session-only reads and pauses in hidden or offline tabs. Sign-in expiry offers recovery without closing the workspace; account or organization changes pause notifications until the page context is restored. Failed updates no longer look successful, and valid administrator impersonation uses the existing organization resolver. Expected access refusals remain distinct from genuine service outages. All six workspace groups are included. This does not enable notification rollout flags or add public API-key access to the session inbox. ### Server-error alert reliability Server-error alerts now coordinate duplicate suppression across servers using existing Redis. Successful delivery starts the fifteen-minute suppression window; failed delivery allows a retry on a later error after one minute. Every genuine error remains logged, and Redis outages retain bounded local alert delivery. Vercel links now target the current project. This source change does not itself change production configuration or establish deployment. ### Console upload refresh recovery Reserved console uploads can recover after a refresh in the same browser tab and account. Reselecting unchanged original files resumes the original document, CAD or ZIP identities and any pinned site-plan target; accepted files are not uploaded again. The local record stores identifiers and fingerprints, not file contents, filenames or upload credentials. Recovery checks fresh server bindings and reconciles uncertain completion before transferring bytes again. Dismissing the record does not cancel server work or clear an unfinished upload gate. No database migration, public API, SDK, CLI or MCP operation is added. Deployment and live Layer 2 retesting remain separate acceptance gates; this entry does not unlock Layer 3. ### Utility-owned packet repair (production activation pending) Review manifests, human confirmations, and native-CAD companions now use the existing packet-owner rule: the applicant organization when present, otherwise the utility. Direct write-capable utility staff can confirm their own editable packet evidence without creating a developer or granting developer access. Applicant isolation, exact version/hash checks, Salesforce ownership restrictions, and utility review billing are preserved. The four confirmation types remain human-authored and console-only; no public integration gains confirmation authority. Production migration approval, matching deployment, and the complete Layer 2 live acceptance gate remain pending. Layer 3 is not unlocked by this source change. ### Eve remediation cutover The dedicated remediation page now uses Eve behind the default-off `REMEDIATION_EVE_ENABLED` flag. Exact stored proposals, separate apply/document-replacement/Packet Review approvals, durable cursor replay, duplicate suppression, refresh restoration, and real cancellation replace the former Claude Agent SDK stream. The legacy remediation config, MCP bundle, prompt entries, and unused context endpoint are removed; the historical `remediation-agent` model/session key and Claude Max workflow remain. ### New client-access notifications (disabled by default) New usable consultant grants can capture individual email work and persistent in-app alerts atomically. Eligible existing direct members are notified; current access is rechecked before display and dispatch. Console and Utility headers include the bell on desktop and mobile. Production migration, reviewed native-template publication, and rollout flags require separate approval. No historical grants are backfilled. ### Finding answer validation Finding-card **Ask the assistant** answers now quote individually verified passages from the saved source edition. A restricted model can select passages, but the server validates the selection and renders the quotations; model-written interpretations are not displayed or saved. The answer does not guess governing section scope, equipment applicability, or whether a drawing passes. Clearing a finding starts a fresh conversational context so old answers are not reused as evidence. This console-only change retains current access checks, model assignments, and Eve rollout controls. It adds no API, MCP, CLI, Slack, or Teams capability. Local regressions and this unreleased entry are not evidence of deployment or successful live acceptance. ### Assistant replay hardening Temporary reasoning summaries no longer display a serialized provider object or opaque signature. Empty, malformed, and redacted summaries are omitted. Saved-finding answers are instructed to cite verified document/page labels instead of constructing subsection numbers. These corrections do not change model settings or selected-finding evidence. ### Saved-finding assistant explanations **Ask the assistant** now identifies the saved review finding instead of relying on its question text. The server checks access and loads the original requirement and cited source edition before answering. The visible selection survives follow-ups and retries until cleared. Missing or incomplete evidence stops the explanation rather than prompting a guess. Explanations distinguish utility text from common checks and do not decide whether the applicant's drawing passes. This is a console-session change; it does not switch models, enable Eve, or grant other channels browser-session access. This unreleased entry is not evidence of deployment or live answer testing. ### Salesforce recovery isolation The disabled Salesforce connector now preserves existing imports and result deliveries when an unrelated reviewer, mapping, or grant changes. Relevant revocations still invalidate saved work. During a source permission-check outage, mixed application lists retain ordinary and currently authorized applications, with explicit partial counts and retry guidance in the UI, API, SDK, MCP, and CLI. Sandbox acceptance and separate activation approval remain required. Result delivery retries a temporary authorization-check outage within its existing ten-attempt limit. It checks current access before any Salesforce call; a revoked permission cancels delivery. ### AX optimizer source removed AX execution and the optimization/canary interfaces are removed: the `optimize` CLI group, the SDK optimization methods, the `optimization.*` admin MCP tools, the optimization REST routes and the Prompt Ops Optimization/Canaries tabs. Prompt history, effective-instruction inspection, evaluation tools and historical database records remain. Cloud resources, delayed queue messages, sleeping workflows and historical tables are cleaned up under separate authorization; merging the source removal does not touch them. ### Added - **Partner upload-batch lifecycle** — Partner REST, SDK, CLI, hosted MCP, and local MCP clients can reserve, inspect, heartbeat, pair, cancel, and abandon ordered packet upload batches. Batch-bound single-file intake carries both batch identifiers, verifies the exact packet, owner, actor, declaration, state, and expiry under the packet lock, and keeps retries idempotent. Unfinished batches continue to block review and freeze. Creation provenance is stored immutably by an additive migration; the migration is not applied by this code change. - **Utility workspace v2 (feature-flagged)** — With the `utility-workspace-v2` feature enabled for a utility organization, `/utility` renders on the shared console shell: a rail of **Applications**, **Notices**, **Rules & Sources** (Packet Requirements, Procedures), and **Analytics**; a header that hosts the application's **Overview · Documents · Review · Communications · History** navigation and the **Freeze package** action for utility-owned applications still in intake; the jobs tray; and a Cmd/Ctrl+K destination palette. Addresses are `?view=…` with `&app=…&pkg=…&appview=…` for an application; legacy `?tab=` links upgrade in place. The feature is off by default, and the legacy six-tab shell renders unchanged when it is off. - **AX retirement evidence preparation** — Local operator commands now export bounded, redacted log evidence and prepare an equivalent empty-overlay prompt reference. Neither command changes active prompts, uploads archives, or establishes the observation clock; completeness and production changes remain separately gated. ### Removed - **Interconnection queue retrieval** — Every surface that could retrieve interconnection queue data has been removed: the `/api/queue/*` REST endpoints, the `search_queue` and `get_queue_stats` MCP tools (hosted gateway and in-app assistant alike), the `gridwonk queue` CLI command group, and the SDK's `searchQueueProjects`, `getQueueStats`, `getQueueProject`, and `listQueueDataCenters` methods with their exported types. The `search-queue` and `get-queue-stats` capabilities are retired. **This ships as the breaking `v0.4.0` package release, and there is no replacement** — ISO/RTO queue data is public, so use `gridstatus` directly. Unaffected despite the shared names: `queue_statistics` and the console utility selector that reads it, the utility application-queue statistics, and the Vercel Queues topics. - **Queue Analytics destination** — The developer console's Analytics destination and both panels it hosted, Queue Analytics and Developer Portfolio Analytics, have been removed. `?view=analytics`, the legacy `?tab=analytics` and `?tab=queue-analytics` links, and `/console/queue-analytics` now land on Projects. What is gone in that step is the console UI over the data, plus the developer portfolio rollups (utility-level application counts, average readiness, deficiency totals) and the portfolio CSV export. ### Changed - **Projects API program declaration** — `POST /api/v1/projects`, the `create_project` MCP tool, SDK `createProject`, and CLI `projects create --declared-tier-slug` now enforce the console's program rule: when the utility publishes two or more interconnection programs for the chosen track, `declaredTierSlug` must name one of them; when it publishes zero or one, the field is refused. Refusals return `400 INVALID_INPUT` with the valid programs listed in `error.details.programs` as `{ slug, label }` objects, so a client can discover the programs from the refusal and retry. An unreadable or misconfigured program publication returns `503 SERVICE_UNAVAILABLE` (`reason` `program_lookup_failed` or `program_publication_invalid`) and creates nothing. The accepted program is stored on the project, returned as `declaredTierSlug` on every project read, and selects the rulebook the review runs against; it cannot be changed through `PATCH`, and a track change that would orphan a declaration (`409`) or land an undeclared project on a track that requires one (`400`) is refused. The v1 error envelope gained the optional `error.details` object, and retryable `503`s carry `retryAfter`; the SDK exposes `details` and `reason` on every `GridWonkError`, and the CLI includes them in `--json` error output. ## Unreleased — August 2026 ### Changed - **`gridwonk` is the CLI command** — The package installs two commands: `gridwonk`, the canonical one, and `gridboost`, the pre-rebrand name kept installed so existing scripts and aliases keep running. Both are the same launcher and behave identically; usage, help, examples, error hints, and the bash/zsh/fish completions all speak `gridwonk`, and completions register for that name. The local MCP server likewise installs as `gridwonk-mcp` alongside `gridboost-mcp`, and now reads `GRIDWONK_*` environment variables with a `GRIDBOOST_*` fallback, matching the CLI: an empty canonical value means "cleared" and does not fall back, and a conflict between the two warns once rather than silently picking one. Release binaries are named `gridwonk-`. - **MCP authentication retry containment** — The aligned private packages move to 0.3.2. The local MCP connector treats modern bridge HTTP 401 and 403 responses as terminal authentication failures instead of retrying the same rejected credential through the legacy proxy. This removes the doubled public authentication traffic seen during the August 28 admin render incident; it does not replace correcting stale credentials or duplicate host registrations. - **Platform organization type is `gridwonk`** — The `organization_type` database enum value `gridboost` was renamed to `gridwonk`, and the application code that accepted both labels during the rename has been removed. The visible effect is on the organization-type filter of the admin MCP `organizations.list` tool and the organization-create schemas: `gridboost` is no longer an accepted value and is rejected rather than silently ignored. Organization ids, memberships, grants, API keys, and every other org-scoped identifier are unchanged — only the type label moved, and the platform organization's own row moved with it. - **Workflow status responsible party renamed `gridboost` -> `gridwonk`** — the `responsibleParty` field of the packet workflow status now reports `gridwonk` instead of `gridboost` for the automated pre-screen state; `developer`, `utility`, and `null` are unchanged. This completes the rebrand for a value that was missed because it is derived presentation state rather than a stored column, and is unrelated to the `organization_type` database enum. Renamed outright rather than dual-emitted because the field is emit-only — nothing accepts it as input — and no stored row, webhook subscription, or typed SDK field carried the old string. Consumers that string-compare `responsibleParty` against `"gridboost"` should compare against `"gridwonk"`. - **GridWonk-named SDK classes and MCP server identifiers** — The SDK's exported classes are now `GridWonkClient`, `GridWonkSessionClient`, and `GridWonkError` (and `GridWonkTransport` / `GridWonkTransportError` in the local MCP package). The former `GridWonk`-prefixed names remain exported as deprecated aliases of the *same* classes, so existing class-name imports keep compiling and `instanceof` keeps matching across both names; only the display string `error.name` changed, from `GridBoostError` to `GridWonkError`. Catch by class, never by name. Package specifiers now use the `@gridwonk/*` namespace. On the MCP side the local stdio fallback server now advertises itself as `gridwonk` (matching the modern bridge, which already did), the admin endpoint reports `serverInfo.name` `gridwonk-admin-mcp` and `auth` `session-admin-or-gridwonk-management-key`, and eleven tool descriptions say GridWonk instead of GridWonk. Tool names, input schemas, endpoints, and authentication are unchanged. The repo-local Codex plugin dropped its duplicate `gridboost` / `gridboost-admin` server entries, which registered the same two servers a second time under legacy keys. - **GitHub package namespace repair** — Moved the SDK, CLI, and local MCP connector to `@gridwonk/*`, rewired the CLI to the canonical SDK dependency, and made publish failures and version drift fail closed. The immutable `0.3.0` CLI exposed a cross-package export mismatch during a clean registry install, so the corrected release is aligned at `0.3.1` and now installs the packed CLI against the published SDK before publication. The `gridboost` CLI executable remains available during its separate binary-name transition. - **Model catalog cron notifications** — Removed the obsolete global-token Slack summary. Supported catalog changes continue to create deduplicated GitHub issues, and every lifecycle change remains recorded in `model_sync_events`. ## Unreleased — July 2026 ### Removed - **Legacy pre-rebrand webhook delivery header aliases** — webhook deliveries now send only the canonical `X-GridWonk-Event`, `X-GridWonk-Event-Id`, `X-GridWonk-Timestamp`, and `X-GridWonk-Signature` headers. The `X-GridBoost-Event`, `X-GridBoost-Event-Id`, `X-GridBoost-Timestamp`, and `X-GridBoost-Signature` aliases, which had carried identical values during the rebrand transition, are no longer sent. Verified safe to remove: no webhook subscription has ever been created on the platform, so no delivery consumer could depend on them. The MCP `X-GridBoost-Client-User-Id` and `X-GridBoost-Delegation-Token` request headers and the legacy `gridboost://` resource-URI scheme are unaffected and still accepted. ### Added - **Hosted MCP partner packet tools** — Nine hosted MCP tools now bind the existing packet intake, safe status, applicant document/text, review, workflow, and utility screening cores. `partner.read` and `partner.write` are enforced per tool in both discovery and dispatch; scoped sessions pin their exact scope set, broad keys cannot see packet tools, scoped tokens cannot see broad tools/resources/prompts, delegated-user membership and document visibility are re-proved, and unexpected internal errors stay server-side. Human Confirm/Correct role decisions remain off the model-facing MCP surface. No migration, rollout flag, or new processing system. - **Partner packet SDK, CLI, and docs surfaces** — Ten `@gridboost/sdk` methods (`createPacketIntake` … `getPacketScreeningStatus`) and the `gridboost packets` CLI group (intake create/finalize/status, documents list/text/set-role, review start/get, status, screening) bind the partner packet REST lane, with `getOAuthToken(expiresIn, scope)` minting the required partner-scoped tokens. The initial July release deliberately withheld hosted MCP packet tools until the gateway gained per-tool scope enforcement; the newer hosted-MCP entry above records that follow-up. New public docs page `api/packets` plus CLI/MCP integration docs. - **Partner packet write API** — Four partner-scoped write endpoints under `/api/v1/packets/*` (partner.write tokens only): Storage-native intake create (server-selected signed/TUS upload authorization, idempotencyKey deduplication, server-derived applicant org, cohort + editable-stage + write-authorization re-proof in the service transaction), intake finalize (object-existence proof, CAS idempotent, durable pipeline start), confirm/correct document content role (the console's exact locked write core: PR3.0a lock protocol, transaction-current write-access proof, artifact-pinned classification with stale-suggestion 409, append-only accept-vs-correct decision lineage), and packet review start (supported-utility check, fail-closed duplicate-spend guard with automatic-run reuse, 50-per-hour cap per user+organization). Writes are confined to the key organization (an org-A key cannot upload into org-B packets through a shared key creator); the review start is applicant-lane only and re-applies the console's per-document visibility policy so colleagues' private documents never enter a partner-started review; internal failure detail never crosses the boundary (generic 502). The console actions and partner routes execute one shared write core; consultant keys act with the granting organization's context, mirroring console granted sessions. - **Partner packet read API** — Six partner-scoped read endpoints under `/api/v1/packets/*` (partner.read tokens only): intake status projection (confined to the key organization's own reachable submissions), sanitized OCR text + coordinates, the applicant-lane packet document list with classifier suggestions (applicant org and applicant-issued grantees only, with the console's exact per-document visibility policy applied), review-run detail with the cited deficiency report (access re-proved before any report bytes are read), canonical workflow status + immutable package list, and the utility-only package-bound screening status (UTILITY_APPLICATIONS_V2 cohort respected; read-only — adjudication stays in the console). Every endpoint reuses the exact console service cores and authorization predicates (org ownership, organization-access grants incl. applicant-org parity, resolver-verified version/package context), re-proves the key creator's membership per request, and collapses every refusal — including denials — to one anti-enumeration 404. No raw originals, signed storage references, service descriptors, or request-selectable resolver contexts are exposed. - **Partner access-token scopes** — `POST /api/v1/oauth/token` now honors an explicitly requested `scope` parameter (`partner.read`, `partner.write`), embedding it as a signed claim; unknown scopes fail with `invalid_scope` instead of being silently dropped (the historically advertised `api:read`/`api:write` values stay accepted as no-ops). Confinement is two-way: partner routes refuse raw API keys and scope-less tokens, and ordinary non-partner routes refuse partner-scoped tokens — so a scoped token is strictly narrower than its key. Partner routes re-verify the key creator's active organization membership on every request by default, partner-scoped tokens are capped at 1 hour, and partner-route denials consume the per-key rate limit. The initial capability declaration kept hosted MCP excluded pending per-tool enforcement; that prerequisite is now satisfied by the hosted-MCP entry above. Legacy scope-less token exchange is byte-compatible. - **Applicant-packet mutation protocol** — Submit, resubmit, link, attach, delete, role assignment, exact-content hydration, and remediation export writers now use one transaction and a canonical submission → link → document → version → package lock order with deterministic two-connection race proof. - **Applicant-document database write floor** — Added actor-bound RLS policies, restricted direct authenticated update columns, database-stamped role audit fields, and `ON DELETE RESTRICT` for linked applicant documents. Production activation requires the separately applied `20260714150000_packet_document_write_access_floor.sql` migration. - **Expanded utility-published procedure index** — As of July 14, GridWonk had indexed 2,913 unique utility-published documents across 686 utilities. Indexed means found and stored; that indexed corpus had not been human-reviewed. ### Changed - **Legacy validation creation surfaces retired** — New site-control requirements, compliance, deficiency-location, and report-generation jobs can no longer be created through REST, agent execution, CLI, SDK, or the local MCP connector. Historical jobs remain readable, and packet intake Review is the supported deterministic replacement. - **Existing-document replacement safety** — Exact-content hydration remains available, while byte-changing replacement returns HTTP 409 until centralized generation safety covers all asynchronous writers and current-result readers. - **Remediation source identity** — Export creation pins document ID, content hash, and version; stale completion or promotion now fails atomically instead of using newer source identity or attaching an old artifact. - **Applicant-packet vocabulary and access boundary** — Canonical packet roles and eight interconnection phases now fail closed across packet shapes and requirements, and applicant-packet reads and mutations are exposed through the `domains/applicant-packets` boundary. This is contract and access-layer work; it does not claim the later storage, UI, or model cutovers are complete. ## Unreleased — June 2026 ### Added - **NES interconnection deficiency detectors** — Prototype detectors with an end-to-end Nashville Electric Service demo, including single-line-diagram graph extraction promoted to a vote-reconciled electrical-detector graph and canonical IEEE/NEC vocabulary. - **Packet prescreening (UI-first prototype)** — New "Packet prescreen" tab in the utility workspace that previews missing-document and cross-document inconsistency checks before engineering review (illustrative, synthetic data). Added as a planned `pipeline` capability, bringing the manifest to 50 capabilities. - **Site-plan completeness analyzer** — Promoted the NES site-plan prototype into the ADR-078 analyzer platform with an operator admin upload route, per-user rate limiting, and the planned `analyze-site-plan` capability. - **Milestone invoicing toolkit** — `/invoice` skill plus the invoicing runbook and milestone-tracker guidance for milestone draws. - **React Doctor zero-warning operations** — Added the post-zero internal runbook, report-only weekly full scan, changed-file regression guidance, ledger hygiene workflow, and attribution expectations for future React/Next/code-quality cleanups. - **Admin Operations surface** — Added a platform-admin-only `Admin > Operations` tab for code quality, CI health, workflow checks, docs freshness, surface QA, and human-gated maintenance links. ### Fixed - **Admin org access grants** — Allow regranting previously revoked organization access and updating existing grants from the grant form. ### Changed - **GridWonk brand + domain migration** — Public app, docs, and marketing copy moved to gridwonk.com; legacy hosts now 301-redirect to it. Webhook deliveries send the `X-GridWonk-Event`, `X-GridWonk-Event-Id`, `X-GridWonk-Timestamp`, and `X-GridWonk-Signature` headers, with the prior `X-GridBoost-Event`, `X-GridBoost-Event-Id`, `X-GridBoost-Timestamp`, and `X-GridBoost-Signature` names kept as deprecated transition aliases; MCP accepts `X-GridWonk-Client-User-Id` and `X-GridWonk-Delegation-Token`, with `X-GridBoost-Client-User-Id` and `X-GridBoost-Delegation-Token` still accepted. Package scopes, `GRIDBOOST_API_KEY`, and legacy `gridboost://` resource URIs remain compatibility identifiers, but legacy `gb_live_` and `gb_test_` API keys are no longer accepted; use `gw_live_` or `gw_test_` keys. - **Post-zero source of truth** — Clarified that fresh React Doctor scan summaries after active ledger matching are the current source of truth; historical triage JSONL rows remain worklist evidence and may lag current scanner output. - **Capability manifest count refreshed** — Parity checks now report 52 capabilities, 13 chatbot tools, 22 local stdio package tools, 22 admin MCP tools, 19 hosted public gateway tools, 3 resources, 1 resource template, 2 prompts, and 177 REST API routes. ## Unreleased — May 2026 ### Added - **Shared submission access model** — Clarified and documented the current multi-org lifecycle model: one `organizations` table with four org types, shared `application_submissions` rows using utility ownership plus developer applicant linkage, and consultant participation through `organization_access_grants` - **Project-first submit/resubmit lifecycle proof** — Added the canonical architecture/docs story for current project state, immutable submission packages, utility screening, notices, revise/resubmit flow, and the browser-backed lifecycle proof/CI workflow that validates it - **PowerClerk status boundary docs** — Documented the coexistence rule that PowerClerk status remains external provider state while GridWonk keeps canonical internal submission and review workflow semantics - **Project-first console workflow** — Validation/results now require a selected project, while procedure documents, requirements, analytics, and draft uploads can remain projectless research. - **Procedure pipeline assess/update split** — `assess.ts` now produces proposed artifacts for human review before `update.ts --approve` applies changes. - **Docs freshness contract runner hardening** — The contract and skills layout validation now use a local TSX launcher that preserves Node 20.0+ compatibility while avoiding `npx` package resolution and `tsx` CLI IPC issues on newer Node runtimes. - **Canonical Capability Manifest contract enforcement** — `CAPABILITY_MANIFEST` now tracks 49 capabilities across chatbot, public MCP, admin MCP, CLI, REST API, and SDK bindings, with derived surface identifiers for `.well-known`, admin API, UI, and docs-facing projections. - **Shared MCP tool definitions** — Public MCP gateway, local `@gridboost/mcp-server`, and `/.well-known/mcp.json` now derive tool metadata from shared definitions instead of hand-maintained copies. - **Capability contract gate** — `npm run capabilities:contracts` validates manifest uniqueness, public/admin MCP parity, `.well-known` discovery parity, REST route coverage, schema/description drift, CLI command bindings, SDK method bindings, UI/admin metadata, docs guardrails, and workflow guardrails. - **Admin chatbot settings metadata** — The admin tool-settings API now reads capability-backed metadata so risk labels and permission groups stay aligned with tool contracts. - **Capability surface delta report** — `npm run capabilities:surface-report` writes JSON and Markdown reports for CLI, SDK, UI/admin, docs, and derived surface deltas. ### Changed - **Capability manifest count refreshed** — Parity checks now report 49 capabilities, 13 chatbot tools, 22 local stdio package tools, 22 admin MCP tools, 19 hosted public gateway tools, 3 resources, 1 resource template, 2 prompts, and 171 REST API routes. - **Hosted MCP semantics clarified** — The manifest `mcpServer` surface now means the hosted `/api/v1/mcp` gateway. Local stdio connector helpers such as `assist`, `upload_document`, and `validate_document` stay documented as `@gridboost/mcp-server` REST wrappers instead of public remote MCP tools. - **Discovery method sync** — Procedure data sync now tracks `discoveryMethod` / `discovery_method` consistently between compiled artifacts and DB-facing update keys. - **Legacy console cron path retired** — Console orchestration remains on Vercel Workflow/Queues; legacy cron processors for document notification, optimization dispatch, and webhook retry draining are no longer the active execution path. - MCP remains a consumer surface, not the canonical owner. The manifest in `lib/capabilities/manifest.ts` owns capability identity and surface availability, while MCP adapters project that contract into protocol-specific tool catalogs. - Documentation drift detection now tracks the capability manifest, shared MCP definitions, local MCP package tools, parity checker, surface report, repo instructions, and capability-alignment skill so capability docs are flagged when contract code changes. ## v1.2.1 — March–April 2026 ### Added - **Capability Manifest** — Canonical registry (`lib/capabilities/manifest.ts`) tracking customer-facing capabilities across chatbot, MCP, CLI, API, SDK, admin, UI, metadata, and docs surfaces with CI parity check script - **Expanded chatbot tools** — Added `list_utilities`, `match_utility`, `search_queue`, `get_queue_stats` to both web console and Slack chatbot via shared common-tools server - **MCP discovery catalog fix** — `.well-known/mcp.json` expanded from 9 to 13 tools (added `assist`, `chat`, `upload_document`, `validate_document`); TOOLS metadata array synchronized - **Document Upload REST API** — `POST /api/v1/documents/upload` with utility resolution and org-scoped storage; SDK upload client and CLI command - **AX Optimization Workflow Migration** — Durable Vercel Workflow execution for prompt optimization with three-tier dispatch (Workflow / Queue / Inline) - **CLI Session-Backed Mutation Parity** — Full write mutation coverage: admin users, orgs, chatbot settings, change subscriptions, monitoring - **CLI MCP/Chatbot Connectivity** — Admin MCP route integration and expanded chatbot admin commands - **Workflow-backed console pipeline orchestration** — Producer-safe migration for document digitization/compliance pipeline entry points with rollback-safe execution ownership - **Queue-backed eval dispatch** — Durable `eval-runs` topic dispatch with idempotent send, terminal guards, and retry-exhaustion failure handling - **5 new MCP gateway tools** — `query_deficiency_reports`, `get_job_status`, `search_queue`, `list_utilities`, `get_queue_stats` - **Utilities List endpoint** — `GET /api/v1/utilities/list` with state, type, query filters and pagination - **Multi-layer bot detection** — Browser fingerprinting, behavioral signals, and IP reputation scoring at auth callback with suspicious signup detection cron - **Muni/coop distribution IX discovery** — Claude-dispatch pipeline for municipal and cooperative utility interconnection procedures; the release-time snapshot stored 1,057 documents from 464 utilities. See the current Unreleased entry for the later indexed-corpus total. - **Platform threat model** — Comprehensive security threat model documentation - **React View Transitions** — Polished tab switching and navigation animations in the console using React's View Transition API - **Feedback-to-eval sync pipeline** — Expert review feedback automatically converted to benchmark test cases; cron-triggered with auto-enqueue of eval runs - **Standalone CLI binary** — Single-file `gridboost` binary via `bun compile` with automated GitHub Actions release workflow - **Slack bot OAuth + real-user linking** — Complete OAuth install flow, workspace-to-org mapping, Slack user-to-GridBoost account linking - **Short-form expansion phase 2** — Playbook execution, shared jurisdiction module, validator completion (5/5), research gaps pipeline - **Security gating** — Auth-gated partner discovery surfaces; package publish lifecycle workflow ### Changed - Cron-to-Vercel-Queues migration complete for all async dispatch (evals, optimization, webhooks, notifications, feedback) - Chatbot core extracted to shared pipeline (`lib/chat/chatbot-core.ts`) with thin route adapters - Async job ownership uses explicit execution metadata to prevent cron/workflow contention - Drizzle schema synced with live database; rebaselined snapshot v4 - Optimization pipeline execution inlined for clarity; queue test rewritten - 26 code quality findings resolved across auth, eval, AX, CLI, and pipeline modules - API validation and CLI auth wrappers unified across v1 endpoints - `ix_procedure_documents.region` migrated to `state` (NOT NULL) - React best practices applied to console validation, documents, and utility views ### Fixed - API hardening: jobs reads, upload utility resolution, compiled utility catalog bundling - SDK upload client hardened with retry logic - Jobs.mdx duplicate content block removed - Corrected compliance metadata key mismatch (`capacityMw` -> `projectCapacityMw`) - **Security hardening sweep** (12 PRs) — Admin RLS, document archive access, SSRF protection, org membership RLS, credential cleanup, admin auth enforcement, chat admin flag derivation, Slack installer fallback blocking - **Pipeline fixes** — CAISO/ERCOT data corruption, Southern Company OASIS override URL, artifact merge bug - SEO: unblocked `_next/static/` in `robots.txt` for Google rendering - Auth mismatch on v1/openapi redirect path - Slack callback jsdom import crash; admin Add to Slack error handling; DM reply identity and thread session fixes - Chatbot requirementText display and requirements query spec field - CLI structured JSON error preservation for SDK fallbacks - CI: publish OOM fix, MCP server build heap increase ## v1.1.0 — February 2026 ### Added - **External API v1** — Full REST API for programmatic access, including agent execution, document validation, async job management with SSE streaming, requirements listing, and webhook CRUD with retry logic - **API key authentication** — HMAC-SHA256 key-based auth with per-key rate limiting and organization scoping - **Access grants** — Cross-organization grant model for consultant access with project-level scoping, expiration dates, and soft-delete revocation - **Consultant access hub** — UI for managing grants and switching between client organizations - **Change monitoring pipeline** — Automated detection of utility requirement changes with webhook notifications, email alerts, and dashboard integration - **Document visibility controls** — Per-document access settings with org-level defaults and document-level overrides - **Email notifications** — Branded templates for change alerts, organization invitations, weekly digests, and welcome emails - **Claude 4.6 model support** — Opus 4.6 and Sonnet 4.6 with adaptive thinking and effort parameter control - **Chatbot memory resume** — Conversation continuity across sessions with org-type-aware content ### Changed - Nine new database migrations for grants, webhooks, audit logging, change monitoring, and document visibility - Security hardening with SSRF prevention, path traversal protection, and RLS gap closures - Enhanced procedures discovery agent with municipal web search support - Org-aware tool allowlists for the chatbot agent ### Fixed - E2E test stabilization for console discovery, PDF upload, and integration tests - Multiple rounds of review remediation across gates 1 through 5 --- ## v1.0.6 — February 2026 ### Added - **Utility workflow management** — Complete end-to-end utility workflow with multi-organization architecture supporting four org types (utility, developer, consultant, gridboost) - **Application intake** — Batch upload and automated screening pipeline for interconnection applications - **Deficiency notice system** — Email delivery with remediation workflow and developer acknowledgment - **Realtime updates** — Live application status synchronization via Supabase realtime subscriptions ### Changed - Foreign key cascade prevention (6 keys changed from CASCADE to RESTRICT) - Enhanced RLS policies with applicant visibility for cross-org access - Updated multi-org architecture documentation ### Fixed - All 31 security review findings resolved (3 high, 8 medium, 11 low, 9 info) - SQL injection prevention, rate limiting, TOCTOU race condition prevention, and email header injection protection - 992 tests passing with expanded utility workflow coverage --- ## v1.0.4 — February 2026 ### Added - **Admin organization management** — Organization listing with filtering, search, detail views, and member management - **User impersonation** — Admin support workflow for debugging user-specific issues with full audit trail ### Changed - Strengthened multi-entity access controls and organization scoping - Standardized admin table components and UI patterns --- ## v1.0.3 — February 2026 ### Added - **Skills infrastructure** — Community skill integration with security-focused review tools - **Evaluation bridge** — Automated benchmark result import to admin performance dashboard - **Slack export automation** — Direct API access with rate limiting, pagination, and incremental export ### Changed - Database schema split from monolithic file into 9 domain-specific modules - Dropped 34 unused indexes and added 3 FK covering indexes (34% reduction) - Resolved 14 RLS multiple permissive policy warnings --- ## v1.0.1 — January 2026 ### Added - **Chatbot settings dashboard** — Admin controls for MCP server management, tool permissions, and configuration presets - **Gemini model support** — Google Gemini integration with task-based model routing - **Dynamic MCP server loading** — Intelligent server selection based on query classification ### Changed - Digitization review tabs load 97% faster with lazy loading - Improved chatbot query classification for better tool routing --- ## v0.20.0 — December 2025 ### Added - **EIA-861 canonical data source** — Authoritative utility database with 1,329 utilities and data quality scoring - **Municipal utility discovery** — Extended procedures discovery to city-owned and district-owned utilities - **Realtime resilience** — Auto-reconnection with exponential backoff, subscription gap bridging, and network recovery - **Utility state resolution** — Centralized helper resolving 92% of utilities to their correct regulatory jurisdiction ### Changed - Enhanced procedures discovery agent for both IOU and municipal utilities - Restructured utility data model with EIA-861 as the canonical source ### Fixed - Resolved "No state specified for compliance job" errors for single-state utilities - Fixed race conditions in realtime subscriptions where early events were missed --- ## v0.19.0 — December 2025 ### Added - **Remediation agent** — Interactive deficiency remediation with amendment suggestions, form auto-fill, and real-time chat guidance - **Deficiency location agent** — Vision-powered PDF analysis with bounding box detection for precise deficiency positioning - **Report generation agent** — Automated compliance scorecards and annotated PDFs using Python and PyMuPDF - **Console workspace** — Professional "Command Center" interface with tab-based navigation, URL state management, and cross-device preference sync - **E2E testing infrastructure** — Playwright-based testing for console workflows, PDF upload, and realtime subscriptions - **User approval system** — Email-based access control for the initial rollout with admin approval dashboard - **GridWonk branding** — Updated all auth pages and reports with GridWonk identity --- # Glossary Key terms and definitions used across the GridWonk platform. URL: /docs-site/glossary A reference to terms you may encounter while using GridWonk or working with grid interconnection processes. --- ### API Key A secret credential used to authenticate programmatic requests to the GridWonk API. API keys are scoped to a specific organization and support configurable rate limits and endpoint restrictions. ### Capacity (MW) The maximum electrical output of a generation or storage resource, measured in megawatts. Capacity can affect interconnection fees, study requirements, and applicable technical standards. Fast-track eligibility depends on the governing tariff, voltage, technology, and screening results; capacity alone does not determine it. ### Capability Manifest GridWonk's canonical contract for product actions and the surfaces that expose them. A capability is the stable action, while an MCP tool, CLI command, REST route, SDK method, UI label, or docs entry is that action's surface-specific binding. The surface report classifies gaps as fill, reduce, document, or defer candidates. ### Compliance Validation The process of checking an interconnection application against utility-published requirements and applicable technical or regulatory standards. Current packet intake performs this work through packet Review, using published packet requirements and source-linked evidence. When a utility's cited requirement states a different threshold from a general external standard, the utility's governing text controls the finding. A separate transitional single-document workflow can still run from existing upload and screening surfaces until PR11 removes it. ### Cooperative A member-owned electric utility governed by its customers rather than shareholders. Cooperatives typically serve rural areas and may have their own interconnection procedures separate from state PUC tariffs. ### Deficiency An error, omission, or non-compliance issue identified in an interconnection application. A deficiency may require correction, clarification, or reviewer disposition before approval. Common categories include site control, missing or incomplete forms, technical requirements, fees, and formatting. ### Digitization The process of converting documents such as PDFs into structured, machine-readable content. GridWonk digitizes both utility procedure documents and applicant documents; reviewed procedure sources support requirement extraction, while applicant documents support packet review and validation. ### Discovery The automated process of finding and indexing a utility's interconnection procedures, application forms, and requirements documents from utility sites and other authoritative sources. An indexed document has been found and stored; indexing does not mean a human has reviewed or approved it. ### Extraction The step after discovery where specific requirements, rules, and form fields are extracted from raw procedure documents. Extracted requirements can become validation inputs after the required source-review, validation, and currentness gates pass. ### FERC The Federal Energy Regulatory Commission. FERC regulates interstate electricity transmission and issues orders that affect generator interconnection. [Order No. 2023](https://www.ferc.gov/news-events/news/fact-sheet-improvements-generator-interconnection-procedures-and-agreements) reformed transmission-provider generator interconnection procedures and agreements, including cluster studies, project-readiness requirements, and study-process accountability; it is not simply a small-generator standard. ### Interconnection The process of connecting a generation, storage, or other eligible facility to the electric grid. It requires approval from the relevant grid operator and compliance with the governing technical, regulatory, and administrative requirements. ### IOU Investor-Owned Utility. A shareholder-owned electric utility, which may be part of a publicly traded or privately owned company. Examples include Duke Energy, Southern Company, and Pacific Gas & Electric. IOUs are generally regulated by state public utility commissions and follow the tariffs approved for their jurisdictions. ### Interconnection Level Whether a project connects to the **transmission** system or a **distribution** system. The point of interconnection, facilities involved, governing tariff, and jurisdiction determine the level; voltage is an important signal but not a universal boundary. Interconnection level and generator-size procedure (LGIP or SGIP) are related inputs, not interchangeable labels. ### ISO/RTO Independent System Operator / Regional Transmission Organization. An entity that coordinates regional electricity markets and manages the bulk power transmission grid. Examples include PJM, MISO, CAISO, SPP, and ERCOT. ### LGIP (Large Generator Interconnection Procedure) Large Generator Interconnection Procedures. [FERC's pro forma LGIP](https://www.ferc.gov/electric-transmission/generator-interconnection) applies to generating facilities larger than 20 MW that interconnect under a jurisdictional transmission provider's tariff. The governing tariff defines the actual study process; LGIP is not determined by a universal voltage threshold. See also: SGIP. ### MCP (Model Context Protocol) An open protocol that allows AI agents to discover and use tools dynamically. GridWonk exposes MCP as a projection of the Capability Manifest, so MCP tool names stay tied to the same product-level capabilities used by CLI, REST, SDK, chatbot, and admin surfaces. ### Current Usable Procedure Document A utility procedure document that reviewers have approved or manually overridden, has completed digitization, and can support customer-facing requirement lookup and validation. ### Muni/Coop Discovery The process of finding interconnection procedures specifically for municipal utilities and electric cooperatives, which often have their own rules separate from state PUC tariffs. GridWonk uses the procedures discovery agent plus manager-owned probes, including landing-page discovery, hub-scrape, crawl, and search-playbook paths, to index these sources across self-governing, state PUC-regulated, and state-statute jurisdictions. Indexed sources still require human review before they become current usable procedure documents. ### Municipal Utility A publicly-owned electric utility operated by a city, county, or district government. Municipal utilities often have their own interconnection procedures that differ from state PUC tariffs. Examples include Austin Energy and Sacramento Municipal Utility District. ### OASIS Open Access Same-Time Information System. A FERC-mandated electronic platform where transmission providers post tariffs, transmission availability, and interconnection queue data. GridWonk references OASIS data for transmission-level interconnection procedures and queue status. ### OATT (Open Access Transmission Tariff) A FERC-mandated tariff that governs non-discriminatory access to the transmission grid. OATTs define transmission interconnection procedures, study processes, and site control requirements for LGIP and SGIP workflows. GridWonk discovers and stores OATTs as procedure source documents when they are the authoritative requirement source. ### PUC Public Utility Commission (also called Public Service Commission in some states). The state regulatory body that oversees electric utilities, approves tariffs, and sets interconnection rules for investor-owned utilities within its jurisdiction. ### Published Packet Store The reviewed, versioned packet requirements stored in `ix_packet_requirements`. Packet Review selects the applicable requirements by utility, phase, interconnection track, and document role. This is the centralized requirement source for new packet-intake review. ### Packet Review The submission-scoped workflow that consumes previously accepted document roles, verifies those roles against trusted current rows, extracts evidence, loads effective requirements from the published packet store, runs role-specific checks, and saves the result used for readiness. Classification and an accepted automatic or human role decision happen before Review; Review does not infer or override roles. It is a purpose-built workflow, not a raw agent that an operator starts directly. ### Packet Readiness A measure of how complete and compliant an interconnection application is before submission. Packet-intake readiness derives from persisted packet Review evidence and the current published requirements. The retained classic single-document validator can still produce transitional compliance results until its Packet Review replacement and historical-data gates are complete. ### Requirement Currentness The rule that customer-facing answers and Packet Review use only reviewed, published requirements tied to the correct utility, packet variant, and document role. The old REST, SDK, CLI, public MCP, console, and admin review surfaces are retired. A separate classic single-document validator and historical remediation links still read `ix_requirements`; they remain isolated from Packet Review until their replacement and retention gates are complete. ### Remediation Assistant The dedicated deficiency page and chat panel where Eve prepares exact, server-verified changes. The session and event cursor survive refreshes, and the browser approves only a stored request ID plus an approve/deny choice. Applying fixes, replacing the active document, and rerunning Packet Review are separate decisions. The assistant is off by default pending release approval. ### Screening The automated review process that checks incoming interconnection applications against utility requirements. Screening identifies deficiencies, generates compliance reports, and provides remediation guidance before or during the utility review cycle. ### SGIP (Small Generator Interconnection Procedure) Small Generator Interconnection Procedures. [FERC's pro forma SGIP](https://www.ferc.gov/electric-transmission/generator-interconnection) applies to generating facilities no larger than 20 MW when they interconnect under a jurisdictional transmission provider's tariff. A state or utility tariff may define a different distribution process, and small-generator status does not by itself mean a project is distribution-level or fast-track eligible. See also: LGIP. ### Site Control Legal documentation showing the applicant's right to develop or operate a generation resource at the proposed site. Accepted evidence can include deeds, leases, options to lease, and easements. The governing utility procedure or tariff determines the required footprint, term, signatures, and evidence; there is no single universal threshold. ### SSE (Server-Sent Events) A web technology that allows the server to push real-time updates to the client over a single HTTP connection. GridWonk uses SSE for job progress, assistant output, tool events, and live status updates. ### Vercel Queues A durable queue service with topic-based routing, retry policies, and dead-letter handling. GridWonk uses Vercel Queues for async dispatch paths such as evals, optimization runs, webhook deliveries, document notifications, and feedback analytics. ### Tariff A filed schedule of rates, terms, and conditions accepted or approved by the relevant regulator, such as a state PUC or FERC. Interconnection tariffs can define application fees, technical requirements, study procedures, and timelines for connecting resources to the grid. ### Webhook An HTTP callback that GridWonk sends to a URL you configure when supported events occur, such as job completion or failure, document digitization, or requirements extraction. Webhooks enable event-driven integration without repeatedly polling the API. --- # GridWonk Documentation AI-powered interconnection deficiency analysis platform built for humans and AI agents. URL: /docs-site last-updated: "2026-10-27" --- Current-result contracts distinguish document self-checks from completed packet reviews and utility approval. Partial findings never prove submission eligibility; mandatory CAD follows the published utility/process policy. Welcome to the GridWonk documentation. This site covers everything you need to use the platform, integrate via API, or connect your own AI agents. For public-plugin access, start with [account and workspace setup](/docs-site/help/self-service), then [connect with MCP](/docs-site/api/mcp). Registration, prepaid purchases, and client availability depend on their rollout settings. The public plugin uses a fixed customer tool catalog and the workspace confirmed in [Connected apps](/docs-site/help/connected-apps). Purchases and human approval workflows remain on the website. The console's **Create Project** utility picker requires a released full state/program packet setup, not a receiving utility organization. Private review is the default; authorized synthetic choices retain pairing checks. **Utility Research** keeps the full catalog. Availability does not guarantee exhaustive coverage or utility approval. Review coverage is specific to the utility's supported state and program. See [Utility Selector](/docs-site/help/utility-selector). Projects show current document findings and partial reports before whole-packet review completes. The completed packet shows **Review Finished**. Its Coverage section explains which inputs were missing and what the reviewer can do next. Individual document results remain visible during a failed, cancelled or running packet review and are labeled as individual-document results. Authorized reviewers can cancel an active packet run from **Review Actions** without deleting completed document findings. Those partial results are neither utility approval nor proof of submission eligibility. See [Application Packet Review](/docs-site/help/packets) for current-result selection, outstanding checks, and exact-version DWG attachment. GridWonk supports utility teams, project developers, and engineering consultants in one shared platform. Utilities own the review queue, developers can follow their own submission lifecycle, and consultants participate through scoped cross-org access when granted by a client organization. ## Salesforce connector status A separate outbound-only installed application now has its Layer 1 certificate-authentication foundation and Layer 2 packet-submission workflow in source. It can preview the selected packet, save a durable Salesforce receipt, pin exact field and file versions, authorize scoped uploads, finalize an immutable packet and read submission progress. It remains hard-disabled: no customer installation, review processing, result retrieval, MCP tool or CLI command is active. The [Salesforce utility connector](/docs-site/integrations/salesforce) is implemented but disabled, not an activated customer integration. Its guide covers the four scoped REST/MCP/SDK operations, current access across captured history, automatic immutable packages, and the real utility sandbox acceptance still required before activation. Direct Owners and Admins of developer and utility organizations can [preview and save workspace appearance](/docs-site/help/organizations#workspace-appearance) from **Team and logo**, using colors found in the organization's source palette. ## For Developers When enabled for the packet owner, **Projects → Review → Report** includes source-linked point of interconnection coordinates and an optional map. This capability starts disabled. Its geographic evidence and human confirmations do not create deficiencies, certify surveyed locations, or approve a packet. See [Point of interconnection](/docs-site/help/packets#point-of-interconnection). Project developers preparing interconnection applications can start with the [For Developers](/docs-site/getting-started/for-developers) guide to create a project, upload and validate working files, submit to the utility, receive notices, and revise/resubmit. The console's Utility Research view also provides read-only access to active procedure documents and published requirements for the selected utility — everything except requirements a utility reviewer has explicitly rejected. Requirements still awaiting a utility decision are shown and labelled as pending rather than hidden or replaced by legacy or neighbouring-utility rows; integrations expose the same per-row review status. For enabled projects, GridWonk automatically accepts positive packet-role classifications and starts the applicable document analysis. It also rechecks whether the complete packet is ready for automatic review. A person can correct a wrong role at any time before the package is frozen; that correction becomes authoritative, keeps the automatic assignment in audit history, and starts analysis again for the corrected role. Unknown and possible-combined results remain manual. The internal admin measurement separately reports later human changes, explicit retention, and assignments not yet revisited, without exposing tenant or document identifiers. Packet reruns normally reuse exact current document extractions and re-read only changed or unmatched documents. Platform administrators can force every reviewable PDF through the current models only on demo packets for synthetic quality assurance; this internal control is not exposed through partner APIs, MCP, or the CLI. For every applicant organization, projects can attach an immutable private DWG companion to the exact current site-plan PDF version regardless of utility, even when that utility does not require CAD. Native intake accepts DWG files, not DXF. Upload and attachment prove delivery and package identity. Native CAD visualization and evidence extraction run when the operational APS switches are healthy; utility-specific checks require a reviewed procedure profile. NES is the first profile, not a hardcoded platform limit. The original DWG remains private; the browser receives an exact-model authorization, not native bytes. An optional Combined-PDF workflow — on by default for every account, and set per organization by GridWonk — lets an applicant developer review sanitized page thumbnails and human-confirm complete page ranges and document roles. It never auto-applies the split; derived children replace the retained source only in current packet projections. An optional packet ZIP lane — on by default for every account, set the same per-organization way, and subject to the same platform rollout controls — lets an applicant use one bounded archive as a temporary shipping container for PDF, PNG, JPEG, or batch-linked DWG files. GridWonk validates the whole archive before any file enters its ordinary document or CAD processor; the ZIP itself never becomes a packet document or enters review. The capability contract also records an active mixed-upload batch coordinator. One Documents selection reports combined progress and safe CAD pairing while each PDF, image, DWG, or ZIP continues through its own authoritative processing lane. After a refresh in the same browser tab and account, reserved console uploads can recover their original identities. Reselect unchanged original files when prompted; accepted files are not uploaded again. See [Upload](/docs-site/help/upload) for recovery and local-record dismissal. This adds no API, SDK, CLI or MCP operation. Whole-packet review, including a manual start, waits for any active, unexpired upload batch to settle. Cancellation, abandonment, or expiry preserves accepted documents and releases only that upload gate; the packet must still meet its other readiness requirements. The capability contract records native-CAD intake, visualization, and deterministic preflight as separate operations. The shared partner REST intake and console attachment lanes can be enabled for an applicant-organization cohort without enabling Autodesk processing. SDK, CLI, and MCP expose batch coordination and applicant-owned CAD pairing, but not standalone native-CAD creation. The batch routes do not enable native-CAD intake for utility-owned packets. The capability contract also records active organization feature controls for an audited, signed-in human UI. These controls are intentionally absent from MCP and public REST mutation surfaces, so an integration cannot silently enable an organization's feature. ## For Utilities Utilities looking to integrate AI-powered deficiency detection into their review workflows can use [For Utilities](/docs-site/getting-started/for-utilities) for queue ownership, screening, notices, resubmission review, and source-review workflows. When a submitted package includes native CAD, authorized reviewers can switch between its sanitized site-plan PDF and package-pinned drawing derivative and open exact CAD findings in that same viewer. Utility organizations also have API and MCP access on by default: owners and admins mint keys at `/utility/api-keys`, then use the documented scopes and utility-specific routes. The [Utility Applications API](/docs-site/api/utility-lane) now describes screening and the REST/SDK/CLI bindings for manual freeze, adjudication, screening completion, and study requirements. MCP can start screening but cannot record those human decisions. Package-bound notice workflows also have implemented REST/SDK/CLI bindings, with current utility writer authority and on-file send recipients. MCP exposes notice list/detail reads only. Pending or provider-accepted delivery is not canonical `sent` status or proof of inbox delivery; schema activation, package publication, and production release remain separate gates. The dependent [utility-event contract](/docs-site/integrations/webhooks#utility-events) adds five ordered event families to existing receiving-utility webhook subscriptions. Events describe saved changes, not new decision authority; verified email-provider receipts remain separate from notice status and human acknowledgment. Schema activation, provider configuration, and production release are still separate approval gates. Utility-created packets remain utility-owned and private to authorized utility staff by default. Recording a developer name or contact neither creates an account nor shares the packet. The [utility-owned packet guide](/docs-site/help/applications#utility-owned-packets-and-developer-details) explains direct-staff confirmations and the separately required repair deployment and database activation. Human confirmations remain console-only; no new CLI, MCP, SDK, or REST write is added. ## For Consultants Engineering consultants and IX advisors managing workflows across multiple clients — see [For Consultants](/docs-site/getting-started/for-consultants) for multi-client setup, team coordination, and reporting. ## API & Integrations The [API Reference](/docs-site/api/overview) covers the External API v1 surface under `/api/v1`, including [developer project management](/docs-site/api/projects) under organization-key authority, async jobs, webhooks, usage analytics, and MCP access. See [Integrations](/docs-site/integrations/overview) for discovery and integration workflows, including the complete [Slack setup and usage guide](/docs-site/integrations/slack), the [Slack and Microsoft Teams channel comparison](/docs-site/integrations/chatbot-channels), and how GridWonk works alongside systems such as PowerClerk while preserving its own lifecycle model. For an accepted document with failed processing, follow [Document troubleshooting](/docs-site/help/document-troubleshooting). Support may investigate a scoped recovery without another upload; protected operator tooling does not add customer API, CLI, SDK or chatbot repair authority, or change these integration entry points. Files that were never accepted may still require their originals. ## For AI Agents - **[Product llms.txt](/llms.txt)** — Public product and marketing discovery. - **[Docs llms.txt](/docs-site/llms.txt)** — Anonymous plain-text bundle of explicitly public guides. - **[Public plugin and MCP guide](/docs-site/api/mcp)** — Customer research, intake, review, and result workflows. - **[Connected apps](/docs-site/help/connected-apps)** — Confirm one workspace for an exact sign-in session and revoke access. - **[Help Center](/docs-site/help)** — Account setup, utility claims, processing allowances, and packet guidance. Public documentation, search, navigation, metadata, and Markdown exports are readable without sign-in. Internal content and the complete docs-host discovery documents require native GridWonk platform-administrator authority. An administrator using a customer or support context sees the public audience. Search at `/docs-site/api/search` follows the same visibility policy. The public plugin catalog is stable before and after connection setup; ordinary calls require an active workspace connection and current permissions. Existing partner API keys and scoped tokens retain their separate credential-specific catalogs. Use the [MCP integration guide](/docs-site/integrations/mcp-servers) and [API authentication](/docs-site/api/authentication) for those connections. Public help does not provide access to another organization's files, an operator tool, or a human decision. The current requirements endpoint serves published Packet Intake requirements. The old requirements REST address returns `410 Gone` and names its replacement. See [Requirements API](/docs-site/api/requirements). --- # Agents API Agent execution routes for async and streaming use cases. URL: /docs-site/api/agents ## Async Agent Execution `POST /api/v1/agents/execute` Creates an async job for supported non-chat agents. The HTTP request has a 60-second duration limit for validating and enqueueing the job; the Workflow-backed job continues asynchronously after the `202` response. Monitor it through the returned polling or stream URL. Supported async agent IDs: | Agent ID | Job Type | Extra Requirement | |----------|----------|-------------------| | `procedures-discovery-agent` | `discovery` | Optional `metadata.discoveryMode: "pda-only"` for the PDA-only workflow; requires the deployment flag `USE_WORKFLOW_PDA_DISCOVERY=true` | Legacy requirements, compliance, deficiency-location, report-generation, and remediation agent IDs are retired. Requests return HTTP `410`; historical jobs remain readable through the Jobs API. New packet reviews use reviewed deterministic requirements rather than starting those agents. ### Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `agentId` | string | Yes | Supported async agent identifier | | `utility` | string | Yes | Utility name (1-500 chars) | | `state` | string | No | Two-letter state code | | `userQuery` | string | Yes | Query text (1-10,000 chars) | | `source` | string | No | Request origin. One of: `console`, `playground`, `api`, `cli`, `mcp`, `script`, `test`, `dev` | | `metadata` | object | No | Key-value metadata for the discovery job. If supplied and non-null, `metadata.submissionId` must be a valid UUID | | `webhookUrl` | string | No | URL for async completion webhook | ### Example ```json { "agentId": "procedures-discovery-agent", "utility": "duke-energy", "state": "NC", "userQuery": "refresh current interconnection procedure documents", "source": "api", "metadata": { "discoveryMode": "pda-only" }, "webhookUrl": "https://partner.example/hooks/gridwonk" } ``` Returns `202` with `jobId`, `pollUrl`, and `streamUrl`. ## Streaming Chat Agent `POST /api/v1/agents/chat` Set `includeSources: true` on the body to receive `source` events carrying the answer's citations. It defaults to `false`, so an existing integration's stream is unchanged — see [Chat Streaming API](/docs-site/api/chat#citations). SSE streaming chatbot endpoint for interactive assistant workflows. Routes through `executeChatbot()` for the full orchestration pipeline (classification, canonical FAQ, requirements preflight, routing). The streaming HTTP request has a 300-second duration limit. Chat requirement lookup follows the same current-procedure behavior as the API, SDK, CLI, and MCP tools. In shadow mode (`ENFORCE_CURRENT_PROCEDURE_REQUIREMENTS=false`), existing displayable requirements may still be returned and logged with diagnostics. In enforcement mode (`true`), customer-facing chat and compliance paths only use validated requirements linked to current usable procedure documents. Deprecated, pending-review, missing-source, and hash-mismatched requirements remain review data, not customer-usable agent truth. ### Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `message` | string | Yes | User message (1-10,000 chars) | | `utility` | string | Conditional | Utility name (1-500 chars). Required unless `sessionId`, `workContextId`, or `submissionId` is provided | | `state` | string | No | Two-letter state code | | `sessionId` | string | No | UUID for conversation continuity | | `workContextId` | string | No | UUID for shared cross-surface work context | | `submissionId` | string | No | UUID for submission-scoped assistant context | | `source` | string | No | Request origin. Same enum as execute endpoint | | `environment` | string | No | Telemetry environment (`production`, `preview`, `development`, `test`). Trusted only outside production | | `includeSources` | boolean | No | Emit citation-bearing `source` events; defaults to `false` | | `metadata` | object | No | Arbitrary key-value metadata | `queueProjectId` is not an accepted chat-context field. Supply `utility`, `sessionId`, `workContextId`, or `submissionId` instead; requests without one of those values return `INVALID_INPUT`. ### Example ```json { "message": "What site control items are required?", "utility": "duke-energy", "state": "NC", "source": "cli" } ``` ### Response Type `text/event-stream` — Server-Sent Events with streaming chat tokens. The final `complete` event includes route diagnostics under `chatbot` when available. ## Notes - `agents/execute` rejects unsupported agent IDs with a `400` error. - `procedures-discovery-agent` maps to an async discovery job. It is not the same raw Agent SDK execution path as `/api/agents/execute`. - Workflows requiring document access validate document ownership against API key org scope. - `/agents/chat` trusts synthetic telemetry labels only in local and preview runtimes. Production derives environment/source labels server-side, and test API keys are persisted as test traffic. - Both endpoints use `withApiKeyAuth` — an organization API key or OAuth bearer JWT is required. ## Lightweight hosted assistance `POST /api/v1/assist` needs the API and CLI assistant on for your organization, and returns `403` when it's off. Hosted MCP `assist` needs the MCP assistant. The endpoint provides one-shot text or optional streaming separately from the orchestrated chat agent. Hosted MCP `assist` uses the same generation service with a string prompt and optional string context; it adds no caller model or streaming control. The deployment switch, registry model resolution, organization admission and request cancellation still apply. When the default model must be resolved, a missing registry assignment fails before generation without a hardcoded fallback. See [API Overview](/docs-site/api/overview). --- # Applications API Query interconnection applications scoped to your organization. URL: /docs-site/api/applications # Applications API ## Query Applications `GET /api/v1/applications/query` Returns interconnection applications scoped to the calling API key's organization. The primary `applications` array still comes from `agentSessions`, ordered by creation date, newest first. When you provide a non-empty external-sync filter (`changed_since`, `external_source`, `external_id`, or `intake_method`), the response also includes a supplemental `submissions` payload from `application_submissions`. Archived synthetic demo submissions remain audit history and are not returned as active sync data. ### Authentication Bearer token required. See [Authentication](/docs-site/api/authentication). ```bash curl https://gridwonk.com/api/v1/applications/query \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ### Query Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `utility` | string | No | — | Filter `applications` by utility name. Supports `*` wildcards (for example `duke*`). Does not filter `submissions`. | | `status` | string | No | — | Filter `applications` by session status: `active`, `completed`, `error`, `timeout`. | | `limit` | integer | No | `50` | Results per list (1–1,000), applied independently to `applications` and `submissions`. | | `offset` | integer | No | `0` | Non-negative pagination offset, applied independently to each list. | | `includeReports` | string | No | `false` | Set to `"true"` to include deficiency reports for returned applications. | | `changed_since` | string | No | — | ISO 8601 timestamp. Filters the supplemental `submissions` payload for incremental sync. | | `external_source` | string | No | — | Filters the supplemental `submissions` payload by external platform, such as `powerclerk`. | | `external_id` | string | No | — | Filters the supplemental `submissions` payload by external platform record ID. | | `intake_method` | string | No | — | Filters the supplemental `submissions` payload by intake method: `batch_upload`, `platform`, `api`, or `powerclerk_sync`. | Invalid parameter values return HTTP `400` with error code `INVALID_INPUT`. ### Response Shape ```json { "applications": [ { "id": "uuid", "utility": "duke-energy", "status": "completed", "source": "api", "createdAt": "2026-02-15T12:00:00.000Z", "updatedAt": "2026-02-15T12:05:00.000Z", "completedAt": "2026-02-15T12:05:00.000Z" } ], "reports": [ { "id": "uuid", "sessionId": "uuid", "createdAt": "2026-02-15T12:05:00.000Z" } ], "total": 1, "limit": 50, "offset": 0 } ``` The `reports` field is only present when `includeReports=true` and at least one application is returned. Each report references its parent application through `sessionId`. ### Wildcard Filtering The `utility` parameter supports `*` as a wildcard character. Internally, `*` is converted to a SQL `ILIKE` pattern (`%`), so matching is case-insensitive. | Pattern | Matches | |---------|---------| | `duke*` | `duke-energy`, `duke-energy-carolinas`, `duke-energy-indiana` | | `*electric*` | `pacific-gas-electric`, `nashville-electric-service` | | `con-ed` | Exact match only (case-insensitive) | ### Example: Paginated Query with Filters ```bash curl "https://gridwonk.com/api/v1/applications/query?utility=duke*&status=completed&limit=10&offset=0&includeReports=true" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ## Supplemental Submissions Payload When any non-empty external-sync filter is provided (`changed_since`, `external_source`, `external_id`, or `intake_method`), the response includes additional fields alongside the standard `applications` array, even when no submissions match: ```json { "applications": [], "submissions": [ { "id": "uuid", "applicationNumber": "APP-2026-001", "projectName": "Sunrise Solar", "screeningStatus": "screened", "externalSource": "powerclerk", "externalId": "pc-12345", "intakeMethod": "powerclerk_sync", "createdAt": "2026-02-15T12:00:00.000Z", "updatedAt": "2026-02-15T12:05:00.000Z" } ], "submissionsTotal": 1, "total": 0, "limit": 50, "offset": 0 } ``` | Field | Type | Description | |-------|------|-------------| | `submissions` | array | Submission records that match the external-sync filters. | | `submissionsTotal` | integer | Total count of matching submission rows. | The two lists are independent. `utility` and `status` filter only `applications`; the external-sync filters affect only `submissions`. `total` counts matching applications, while `submissionsTotal` counts matching submissions. The same `limit` and `offset` apply separately to both lists, so `limit=50` can return up to 50 rows in each. Submissions are ordered by `updatedAt`, newest first. Submission `projectName` values have internal demo identity markers removed. The field is `null` if no displayable name remains; stored names are unchanged. ## Incremental Sync Pattern Use the `changed_since` parameter for delta syncs of the supplemental `submissions` payload. The current route uses inclusive timestamp filtering and offset pagination; it does not expose a snapshot cursor or upper-bound filter. Do not advance a checkpoint when a sync window is larger than one response page, because concurrent writes can shift offsets and make a multi-page pass incomplete. The following illustrative pattern advances only to the newest server-returned `updatedAt` value returned by a complete one-page window. It uses idempotent upserts (inserts or updates that are safe to repeat) and stops without advancing the checkpoint when the window exceeds one page: ```typescript async function incrementalSync(apiKey: string, lastSyncedAt?: string) { if (lastSyncedAt && Number.isNaN(Date.parse(lastSyncedAt))) { throw new Error('Stored sync checkpoint is not a valid ISO 8601 timestamp'); } const url = new URL('https://gridwonk.com/api/v1/applications/query'); url.searchParams.set('external_source', 'powerclerk'); url.searchParams.set('limit', '1000'); if (lastSyncedAt) { url.searchParams.set('changed_since', lastSyncedAt); } const res = await fetch(url.toString(), { headers: { Authorization: `Bearer ${apiKey}` }, }); if (!res.ok) throw new Error(`Sync failed: ${res.status}`); const data = await res.json(); const submissions = data.submissions ?? []; if ((data.submissionsTotal ?? 0) > submissions.length) { throw new Error( 'Sync window exceeds one page; checkpoint was not advanced. ' + 'Run more frequently or request a cursor-capable export path.' ); } let nextCheckpoint = lastSyncedAt; for (const submission of submissions) { const updatedAtMs = Date.parse(submission.updatedAt); if (Number.isNaN(updatedAtMs)) { throw new Error('Response contains an invalid submission.updatedAt value'); } await upsertSubmission(submission); if (!nextCheckpoint || updatedAtMs > Date.parse(nextCheckpoint)) { nextCheckpoint = submission.updatedAt; } } if (nextCheckpoint) { await saveSyncCheckpoint(nextCheckpoint); } return { synced: submissions.length, checkpoint: nextCheckpoint ?? null }; } ``` **Recommended pattern:** 1. On first sync, provide an external-sync filter such as `external_source=powerclerk`; omit `changed_since` only if you want all matching supplemental submissions. 2. Compare `submissionsTotal` with the returned row count. If the window exceeds the page limit, do not advance the checkpoint; the current offset contract is not snapshot-safe under concurrent writes. 3. Commit every returned row with an idempotent upsert. Advance only to the maximum server-returned `updatedAt`; when the response is empty, retain the previous checkpoint. 4. On subsequent syncs, keep the external-sync filter and pass the stored timestamp as `changed_since`. Because the filter is inclusive, deduplicate by submission ID plus `updatedAt`. 5. Do not build a lossless multi-page integration on this offset route. That requires a server-generated snapshot upper bound and a stable `(updatedAt, id)` cursor, which this endpoint does not currently expose. ## Access Scope The `applications` array is tenant-scoped to the calling API key's organization. Applications belonging to other organizations are never returned. The supplemental `submissions` payload is visible to both the owning organization and the applicant organization: a submission is returned when the calling API key's organization matches either the submission's owning org or its `applicantOrgId`. This lets a developer (applicant) org sync submissions it filed even when another organization owns the record. This endpoint is still hybrid today: - `applications` reflects the legacy agent-session view - `submissions` exposes submission rows only when external-sync filters are used The shared submission architecture is real in the database, but the public route has not fully switched to a submission-first response contract yet. --- # Authentication & Rate Limiting API key management, authentication flow, rate limiting tiers, and security best practices for GridWonk API v1. URL: /docs-site/api/authentication ## Public plugin authentication When enabled, the [public GridWonk plugin](/docs-site/api/mcp) uses user OAuth followed by an exact-session workspace confirmation in the website. Its stable customer catalog and current membership checks are separate from the organization credentials documented below. A public-plugin bearer token cannot act as a first-party browser session for setup, legal acceptance, purchases, or human decisions. API keys and machine tokens cannot substitute for that browser confirmation. Reviewed public help is readable without sign-in. Internal documentation and complete docs-host discovery require native internal authorization; merely having an approved customer session does not grant access. # Authentication & Rate Limiting Existing organization API integrations use the following authentication lanes. Check the endpoint reference before choosing credentials; there is no single credential accepted by every route. Each active request re-evaluates the organization's current API/MCP policy, billing state, and the credential's scope. API access, MCP access, and self-service key creation are separate controls; creating a key or connecting an MCP client does not preserve access after an administrator changes the applicable policy. | Lane | Credential | Used for | |------|------------|----------| | User session | Approved first-party GridWonk browser session | Approved bootstrap and session-only routes | | Client credentials | API key supplied to `POST /api/v1/oauth/token` | Exchange for a short-lived OAuth JSON Web Token (JWT) | | Runtime Bearer | Organization API key or OAuth JWT | Most organization-scoped API v1 runtime routes | Request parsing is bounded in every authentication lane. The OAuth token exchange accepts a body of at most 32 KiB, general API JSON defaults to a 1 MiB limit, and oversized or malformed input is rejected before route work begins. Request-provided size metadata is never used as the upload byte count. ## API Key Format ```text gw_{environment}_{32-random-bytes-hex} ``` - **Live keys** (`gw_live_...`): Production environment, real data. - **Test keys** (`gw_test_...`): Test-labeled API traffic. They do not, by themselves, create a separate data sandbox. Total length: 72 characters. Legacy `gb_live_`/`gb_test_` keys are no longer accepted. Use a `gw_live_...` or `gw_test_...` key. ## Using Your API Key Include the key in the `Authorization` header on runtime requests that support API-key authentication: ```bash curl -X GET https://gridwonk.com/api/v1/jobs \ -H "Authorization: Bearer gw_live_..." ``` ## OAuth 2.0 Client Credentials For integrations that prefer standard OAuth 2.0 flows, GridWonk supports the `client_credentials` grant type. This exchanges your API key for a short-lived JWT bearer token. The machine-token issuer advertises the `client_credentials` grant. The separately gated public plugin uses the configured user-OAuth issuer and browser sign-in. MCP clients must follow the exact protected-resource metadata for their connection; the machine issuer is not a user sign-in endpoint. ### Token Exchange `POST /api/v1/oauth/token` No authentication header required — credentials are sent in the request body. **Request (form-urlencoded):** ```bash curl -X POST https://gridwonk.com/api/v1/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=gw_live_..." \ -d "client_secret=$GRIDBOOST_API_KEY" ``` **Runnable request (JSON):** ```bash curl -X POST https://gridwonk.com/api/v1/oauth/token \ -H "Content-Type: application/json" \ -d "{\"grant_type\":\"client_credentials\",\"client_secret\":\"$GRIDBOOST_API_KEY\"}" ``` **Request (HTTP Basic Auth):** ```bash curl -X POST https://gridwonk.com/api/v1/oauth/token \ -u "gw_live_...:$GRIDBOOST_API_KEY" \ -d "grant_type=client_credentials" ``` Token exchange is rate-limited separately: 30 requests per minute per client/network bucket and 10 requests per minute per client ID. Production counters use shared Redis state; forwarded headers are not accepted as a security identity unless a trusted edge header is configured. Do not treat an untrusted forwarded address as a credential or tenant identity. OAuth failures always use the token endpoint's `error` and `error_description` fields. An unexpected server fault returns `500 server_error` with an `X-Request-ID` header for support; it does not expose database, signing, or credential details. **Response (200):** ```json { "access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "Bearer", "expires_in": 3600, "scope": "api:read api:write" } ``` ### Using the JWT Token ```bash curl -X GET https://gridwonk.com/api/v1/jobs \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." ``` The JWT token is accepted like an API key on most runtime endpoints protected by the API authentication layer. It does not replace an approved user session on the session-only bootstrap routes. A scope-less token can fetch `/api/v1/openapi.json`; partner-scoped tokens remain confined to partner endpoints. The token-exchange route receives client credentials in its request rather than an access token. ### Token Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | `grant_type` | string | Yes | — | Must be `client_credentials` | | `client_id` | string | No | — | API key prefix (for verification) | | `client_secret` | string | Yes | — | Full GridWonk API key | | `scope` | string | No | — | Space-delimited partner scopes to embed in the token (see below) | | `resource` | absolute URL | No | Legacy API audience | Bind the token to `https://gridwonk.com/api/v1/mcp`; admin MCP continues to require a browser admin session or raw internal management key, and other targets are rejected | | `expires_in` | integer | No | 3600 | Token lifetime in seconds (60–86,400) | ### Partner Scopes Partner packet REST endpoints (`/api/v1/packets/*`) and the packet tools on the hosted MCP gateway (`/api/v1/mcp`) require an access token minted with an explicit partner scope. Raw API keys and scope-less JWTs are refused on packet REST endpoints with `reason: "insufficient_scope"`; on MCP they can discover and call only the historical broad-key tools, never packet tools. | Scope | Grants | |-------|--------| | `partner.read` | Packet read endpoints (intake status, documents, sanitized text, review runs, workflow status, utility screening status) | | `partner.write` | Packet mutation endpoints (intake create/finalize, role confirm/correct, review start) | Scopes are independent — `partner.write` does not imply `partner.read`; request both if you need both: ```bash curl -X POST https://gridwonk.com/api/v1/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_secret=$GRIDBOOST_API_KEY" \ --data-urlencode "scope=partner.read partner.write" ``` Utility application and notice list/detail reads use `partner.read`; utility screening starts, manual freeze, adjudication, completion, study-requirement, and notice lifecycle writes use `partner.write`. Current utility identity, membership, and application-state checks still apply. Manual decisions and notice writes are not MCP tools even when a token has write scope. See the [utility lane guide](/docs-site/api/utility-lane). Webhook subscriptions continue to use the management-key lane, not a partner token. **A partner-scoped token is strictly narrower than its key.** Confinement is two-way: packet REST endpoints refuse credentials without the required scopes, and ordinary non-partner endpoints refuse partner-scoped tokens with `reason: "partner_token_confined"`. The hosted MCP gateway is the one multiplexed exception: it accepts either credential lane, then filters both `tools/list` and `tools/call` from the same per-tool policy. A `partner.read` token sees only read-scoped packet tools; it cannot see broad tools, resources, templates, prompts, or write-scoped packet tools. A broad key cannot see any packet tool. The API key creator's active organization membership is re-verified on every partner request. When an MCP session acts for a delegated client user, that user's membership and document visibility govern the packet call, and the membership is re-proved on every scoped session request. Stateless MCP calls re-verify the delegated identity on each call. Partner-scoped tokens are capped at **1 hour** regardless of the requested `expires_in` (the scope lives only in the signed claim, so a short lifetime bounds exposure; revoking the underlying API key invalidates outstanding tokens immediately). Requesting any scope outside this vocabulary fails the whole exchange with `invalid_scope` — unknown scopes are never silently dropped. Two legacy exceptions exist for backward compatibility: `api:read` and `api:write` (the values this endpoint has always advertised in its response) are accepted as no-ops and grant no partner scope. Fine-grained customer scopes such as `projects:read` and all `admin:*` scopes are not live token grants. They are neither advertised nor accepted until an interactive grant and consent flow can issue and enforce them end to end. When no partner scope is requested, the response advertises the legacy `"api:read api:write"` value, which means "full authority of the underlying API key" and is **not** a partner scope. ### Token Properties - **Algorithm**: HS256 - **Default lifetime**: 1 hour (3,600 seconds) - **Maximum lifetime**: 24 hours (86,400 seconds) - **Minimum lifetime**: 1 minute (60 seconds) - **Issuer**: `gridboost-api` - **Audience**: `gridboost-api-v1` ### When to Use OAuth vs API Keys | Use Case | Recommended Auth | |----------|-----------------| | Server-to-server with long-running process | API key (simpler) | | Short-lived automated tasks | JWT token (auto-expires) | | Standard OAuth 2.0 compliance required | JWT token | | PowerClerk or external platform integration | JWT token | ### TypeScript Example ```typescript async function getGridWonkToken(apiKey: string): Promise { const res = await fetch('https://gridwonk.com/api/v1/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'client_credentials', client_secret: apiKey, }), }); if (!res.ok) throw new Error(`OAuth error: ${res.status}`); const { access_token } = await res.json(); return access_token; } ``` ### Python Example ```python import requests def get_gridwonk_token(api_key: str) -> str: resp = requests.post( "https://gridwonk.com/api/v1/oauth/token", data={ "grant_type": "client_credentials", "client_secret": api_key, }, ) resp.raise_for_status() return resp.json()["access_token"] ``` ## Key Properties | Property | Description | |----------|-------------| | `organizationId` | All queries are scoped to this org (tenant isolation) | | `environment` | `live` or `test` | | `keyRole` | `management` or `runtime` | | `status` | `active`, `suspended`, or `revoked` | | `rateLimitPerMinute` | Default 60 requests/minute | | `allowedEndpoints` | Default `['/api/v1/*']` — can be restricted to specific routes | | `monthlyCostLimitUsd` | Optional spending ceiling | | `expiresAt` | Optional expiration timestamp | Endpoint permissions are part of the API-key credential, not just a UI hint. Every API-key lane, including internal management routes, checks the request path against `allowedEndpoints` before the handler runs. Keep management keys narrowly scoped and mint a new key when an integration needs a different route family. ## Bootstrap Flow (Invite-Only Pilot) For invite-only onboarding, the first management key is minted through session-auth endpoints: - `GET /api/v1/auth/bootstrap/status` - `POST /api/v1/auth/bootstrap-key` Eligibility states: - `eligible` - `needs_admin_membership` - `not_allowlisted` - `payment_required` The status response also carries `nextStep`: `create_bootstrap_key`, `request_org_admin_access`, `add_payment_method`, or `contact_support`. A `not_allowlisted` result caused by a platform API access suspension or a billing suspension returns `contact_support` (the `reason` text names the brake); every other `not_allowlisted` result returns `request_org_admin_access`. Notes: 1. Bootstrap requires direct active `owner/admin` membership in the target org. 2. Grant-derived access does not allow bootstrap. 3. Bootstrap creates the first `management` key. ## Rate Limiting Authentication throttles use shared Redis fixed-window state in production so instance scaling does not split the budget. A deployment may add a client-IP dimension only through the explicitly configured `TRUSTED_CLIENT_IP_HEADER`; caller-supplied `X-Forwarded-For` and `X-Real-IP` values are not trusted. Rate limits are enforced at two tiers: | Tier | Window | Default Limit | Reset | |------|--------|---------------|-------| | Per-minute | Fixed current-minute window | 60 requests | End of current minute | | Daily | Midnight UTC | 86,400 requests (60 × 1,440) | Next midnight UTC | ### Rate Limit Headers API-key-authenticated handler responses that pass auth, organization-profile, rate-limit, and organization-usage gates include: ```text X-RateLimit-Limit: 86400 X-RateLimit-Remaining: 85950 X-RateLimit-Reset: 1740009600 X-Request-Id: req_a1b2c3d4e5f67890 ``` | Header | Description | |--------|-------------| | `X-RateLimit-Limit` | Daily request cap | | `X-RateLimit-Remaining` | Requests remaining in current day | | `X-RateLimit-Reset` | Unix timestamp when daily counter resets (midnight UTC) | | `X-Request-Id` | Unique correlation ID for support and debugging | ### Handling 429 Responses When a rate limit is exceeded, the API returns: ```json { "error": { "code": "RATE_LIMITED", "message": "Per-minute request limit exceeded", "retryAfter": 42 }, "requestId": "req_a1b2c3d4e5f67890" } ``` Use the `retryAfter` field (seconds) to schedule your next request. Organization API profile gates can deny otherwise-valid keys before route logic runs: | Reason | Meaning | |--------|---------| | `api_access_suspended` | API and MCP access is suspended for the organization (a platform kill switch, checked before every other gate) | | `billing_suspended` | The organization's account is suspended | | `not_allowlisted` | API access is disabled for the organization | | `key_management_disabled` | `/api/v1/keys*` is disabled for the organization | | `mcp_disabled` | `/api/v1/mcp` is disabled for the organization | ### Organization Usage Caps After the per-key limits, every request is counted on an organization ledger for the current UTC day and then for the current month, on every billing status. The organization's API profile carries the caps: `limits.hardDailyRequests` and `limits.hardDailyEstimatedCostUsd` for the day, `limits.hardMonthlyRequests` and `limits.hardMonthlyEstimatedCostUsd` for the month. For an organization with active billing (or an active manual override) a cap of 0 means no explicit cap (the request is still counted); for an organization without active billing a cap of 0 admits nothing. Request-count caps are always enforced; cost caps are recorded without refusing unless the deployment enables hard cost enforcement. At a cap, an organization with active billing receives `429 RATE_LIMITED` with `retryAfter` (seconds to the next UTC day or month, also in the `Retry-After` header); an organization without active billing receives `402 PAYMENT_REQUIRED` with a billing URL. Both carry a machine-readable `reason`: `hard_daily_request_cap_exceeded`, `hard_daily_cost_cap_exceeded`, `hard_monthly_request_cap_exceeded`, or `hard_monthly_cost_cap_exceeded`. Raising a limit is a support request; there is no bypass. Separately from request caps, each new screening run started through the API (`POST /api/v1/packets/{submissionId}/review` and the MCP `start_packet_review` tool) is reserved against the reviewing organization's review-spending budget (`reviewBudget` on the same profile: daily runs, daily and monthly estimated cost). These limits are enforced before new work is queued: a refusal returns `429 RATE_LIMITED` with `retryAfter`. Reusing an already-active run does not reserve a second run. The recorded charges are estimates, not a ceiling on actual provider bills. See [Errors & Retries](/docs-site/api/errors) for the response shapes. **Recommended retry strategy:** ```typescript async function callWithRetry(url: string, options: RequestInit, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { const res = await fetch(url, options); if (res.status === 429) { const body = await res.json(); const waitSeconds = body.error?.retryAfter ?? 60; await new Promise(r => setTimeout(r, waitSeconds * 1000)); continue; } return res; } throw new Error('Rate limit exceeded after retries'); } ``` ## Request Correlation When `X-Request-Id` is present, include it when contacting support — it maps directly to audit log entries for rapid investigation. Most API-key-authenticated handler responses include it after authentication, organization-profile, rate-limit, and monthly-usage gates pass. An early failure at one of those gates can omit the header. ## Key Security Best Practices 1. **Never expose keys in client-side code.** API keys should only be used from server-side applications. 2. **Use environment separation.** Use `gw_test_` keys for development and `gw_live_` keys for production. 3. **Restrict allowed endpoints.** Scope keys to only the endpoints your integration needs (e.g., `['/api/v1/jobs*', '/api/v1/documents/*']`). 4. **Set cost limits.** Use `monthlyCostLimitUsd` to prevent unexpected charges from runaway integrations. 5. **Rotate keys periodically.** Create a new key, update your integration, then revoke the old key. 6. **Set expiration dates.** For time-limited integrations (POCs, contractor access), set `expiresAt`. ## Self-Service Key Management Org owners and admins can manage API keys programmatically via the Keys API, the CLI, or the customer dashboard — no admin intervention required. ```typescript import { GridWonkClient } from '@gridwonk/sdk'; const client = new GridWonkClient({ apiKey: process.env.GRIDBOOST_API_KEY!, }); // Create a new key for your organization const { key } = await client.createKey({ name: 'Production Key' }); console.log(key.plaintext); // Store securely — shown only once ``` See the full [Key Management API reference](/docs-site/api/keys) for all endpoints, CLI commands, and security considerations. ## Next Steps - [External API endpoint index](/docs-site/api/external) - [API Quickstart walkthrough](/docs-site/api/quickstart) - [Webhooks setup](/docs-site/integrations/webhooks) --- # Chat Streaming API SSE chat endpoint for Bearer-authenticated conversational workflows with intelligent routing. URL: /docs-site/api/chat ## Availability for trial and prepaid workspaces Unrestricted assistant chat is unavailable for workspaces enrolled in trial or prepaid processing. Enabling a chat channel or purchasing a pack does not remove that restriction. Use the supported [public plugin tools](/docs-site/api/mcp), packet intake and review, and public help instead. The channel behavior below applies where ordinary chat is authorized. See [processing allowances](/docs-site/help/processing). # Chat Streaming API ## Endpoint `POST /api/v1/agents/chat` Authenticated with an organization API key or short-lived OAuth bearer JWT. Streams responses as Server-Sent Events (SSE). ## Self-service availability Self-service processing remains unlaunched. A workspace enrolled for metered packet processing cannot use this generic chat endpoint: packet-processing credit does not enable chat. The server refuses the turn before FAQ routing, classification, or model execution. Supplying a different channel label or omitting workspace context does not override the server's ownership checks. Existing eligible workspaces retain the authentication and transport gates described below. GridWonk also releases this endpoint per organization. The API and CLI assistant is off by default during the staged release. While it's off, a turn ends with an error before any model runs. ## Request Body | Field | Type | Required | Description | |-------|------|----------|-------------| | `message` | string | Yes | User message (1–10,000 chars) | | `utility` | string | Conditional | Utility name, or `"all"` for general search. Required unless `sessionId`, `workContextId`, or `submissionId` supplies context. | | `state` | string | No | Two-letter state code (e.g., `"NC"`) | | `sessionId` | uuid | No | Continue an existing conversation. The session is accepted only when it belongs to the authenticated API principal and organization; request metadata cannot change that scope. | | `workContextId` | uuid | No | Shared cross-surface work context | | `submissionId` | uuid | No | Submission-scoped assistant context | | `source` | string | No | Source surface (`console`, `playground`, `api`, `cli`, `mcp`, `script`, `test`, `dev`). Defaults to `api`. | | `environment` | string | No | Telemetry environment (`production`, `preview`, `development`, `test`). Trusted only outside production. | | `includeSources` | boolean | No | Opt in to `source` events carrying the answer's citations. **Defaults to `false`** — see [Citations](#citations). | | `metadata` | object | No | Additional context for analytics | ## Response Format Content-Type: `text/event-stream` Each SSE message is a JSON object with a `type` field: | Type | Description | |------|-------------| | `content` | Text chunk from the assistant response | | `tool_use` | Tool invocation (tool name + input) | | `tool_result` | Tool execution result | | `usage` | Token usage update | | `complete` | Stream finished - includes `sessionId`, `duration`, `tokenUsage`, and optional chatbot diagnostics | | `error` | Error occurred during execution | | `source` | One docs page the answer is grounded in. **Only sent when the request set `includeSources: true`** | ### Illustrative SSE Messages ```text data: {"type":"content","content":"Based on Duke Energy NC requirements...","timestamp":"..."} data: {"type":"tool_use","tool":"published_requirements","input":{...},"timestamp":"..."} data: {"type":"complete","status":"success","sessionId":"abc-123","duration":2450,"tokenUsage":{"input":1200,"output":350,"total":1550},"timestamp":"..."} ``` `complete.chatbot` includes route diagnostics such as `executionMode`, `queryCategory`, `directToolName`, `stopReason`, `resultSubtype`, `source`, `environment`, `synthetic`, and `excludedFromReports` when available. Existing-session reads and writes are always scoped to the authenticated API principal and organization. Treat `sessionId` as an opaque identifier: do not use a session ID from another organization, and do not send an organization ID in `metadata` to select the session scope. For published-requirement lookups, rows whose customer wording is still under review are not returned as usable requirements. If every match is in that state, the streamed answer says the wording is under review instead of claiming the utility has no published requirements. Counts of available results exclude those hidden rows. A zero-row published lookup also keeps the release reader's distinction between a role awaiting review, a completed review in which every row was rejected, and a utility with no technical publication. Eve completions label `tokenUsage.measurementStatus` as `complete`, `partial`, or `unavailable`. Partial or unavailable measurements are not zero-cost results and do not receive a derived total-cost estimate. A bounded read of the existing session may recover late usage; it never sends another model turn or repeats the answer. ## Citations Set `includeSources: true` on the request to receive a `source` event for each docs page the answer is grounded in: ```text data: {"type":"source","sourceId":"src-1","url":"/docs-site/api/authentication","title":"API Authentication","visibility":"public","timestamp":"..."} ``` `url` is **site-relative**. Prefix it with the site origin to make it clickable; internal pages still resolve only through the authenticated docs site, so a caller who may not read internal documentation never receives one in the first place. **Why opt-in.** A client written against this stream has only ever seen six message types, and some switch exhaustively on `type`. Sending a seventh unannounced would hand every existing integration a frame it never agreed to receive. Omitting the field — or sending `false` — gives you byte-for-byte the stream you had before. `heading` is present when the citation points at a specific section rather than a whole page. ## Intelligent Routing The API runs the full chatbot orchestration pipeline: 1. **Canonical FAQ fast path** — Known questions return audience-authorized deterministic answers instantly (zero LLM cost) 2. **Uploaded-document inventory fast path** — Explicit file-list/count questions call `query_user_documents`. A selected packet uses access-checked current attachments; no selected packet uses personal upload counts. An unavailable packet read is not a zero count and never falls back to personal totals. 3. **Source-backed requirements fast path** — Narrow requirement questions can call `published_requirements` directly and return matched published rows with source context 4. **Query classification** — LLM-backed classification determines intent and tool requirements 5. **Requirements preflight** — A typed published lookup returns review-pending or reviewed-empty wording immediately; only a true `not_published` result uses generic no-coverage guidance 6. **Route planning:** - `direct_llm` — Fast conversational responses for simple queries - `eve` — Approved tool-backed retrieval and orchestration - `deterministic` — Typed clarification, refusal, or unavailable response when a model-backed turn cannot run safely 7. **Safe recovery** — A direct-model failure before output retries through Eve. An Eve denial, preparation failure, or streaming failure returns a recoverable terminal error and is never replayed through the Claude Agent SDK. Supported organization-scoped retrieval, requirements, and orchestration turns run on Eve. In non-production deployments the comparison harness selects Eve with `CHATBOT_RETRIEVAL_RUNTIME=eve`. In production, that variable is ignored: Eve requires an explicit deployment audience **and** a per-channel flag, with each channel enabled separately. If those gates or Eve preparation fail, the API returns a typed unavailable result; it does not invoke the Claude Agent SDK. Once Eve accepts a turn, no failure path replays it through another runtime. Whether your API requests may reach Eve is therefore an operator decision, not a request parameter, and it does not change the SSE contract. New customer turns record `deterministic`, `direct_llm`, or `eve` in `complete.chatbot.executionMode`; historical `agent_sdk` values remain readable. The administrator's **Database Access** control also applies to Eve product tools. The server signs that decision into the short-lived delegated token for the turn, and the tool refuses access unless the signed value explicitly allows it. If admin settings cannot be loaded, Eve treats database access as disabled, and a product-record turn that needs those tools ends with a recoverable terminal error rather than a refusal. A caller cannot turn database access back on with request data. An eligible, self-contained Eve documentation question starts with the required documentation search directly; it does not spend a separate model request deciding whether to call that required tool. A follow-up whose meaning depends on earlier conversation stays on the full context-aware model path. Both paths still emit the ordinary `tool_use`, `tool_result`, content, source, and completion events described above. This is the same pipeline used by the web chat assistant, the Slack bot, the MCP `chat` tool, and the CLI. Fast-path tool answers still set `directToolName` in completion metadata. Runtime evals and API clients can therefore distinguish a direct `query_user_documents` or `published_requirements` answer from a plain FAQ response even when no model-backed `tool_use` event was streamed. The requirements fast path and preflight use the same published reader as the REST/SDK/CLI/MCP lane: every published requirement except utility-rejected rows, each carrying `reviewStatus` (`approved` or `pending`). They report how much of an answer awaits a utility decision, and preserve a reviewed-empty message instead of collapsing every empty result into “no requirements.” The tool-backed agent loop uses that same published reader unconditionally. The temporary cutover flag and legacy fallback were removed after the production cutover proved stable. The authenticated work context still selects the exact utility and state; this cleanup does not change the SSE event contract. ## Telemetry Labels The console finding-card action sends an internal `explain_finding` intent and a structured saved finding reference. Before model execution, the server checks the signed-in user's current project access and loads the saved review requirement and original cited source edition. Typed follow-ups and retries reuse the server's selected finding until it is cleared, with access checked again. This console-only path bypasses generic shortcuts, documentation-only Eve, and the general tool-backed answer loop. A tool-free model may select only known source-passage identifiers; the server validates that selection and renders exact quotations with source-edition and page labels. Model-written explanations are neither displayed nor saved. The answer explicitly leaves governing section scope and project applicability unconfirmed rather than inferring them from nearby text. Missing or incomplete evidence returns an explicit limitation; the server does not substitute a current rule for the saved one. Clearing the finding starts a fresh conversational context so an old explanation cannot become evidence for later answers. This is a console-session capability, not a new request field on this public API. Supplying `source: "console"`, metadata, or a session identifier does not confer browser-session authority or enable the finding action through API, CLI, MCP, Slack, or Teams. Packet reads still require the active organization's current access and enabled Database Access; there is no service-role fallback when that authorization cannot be proved. See [Chatbot Channels](/docs-site/integrations/chatbot-channels) for the console workflow and its limits. Local and preview synthetic loops may send `source`, `environment`, and synthetic metadata such as `syntheticRunId` or `corpusCaseId`. Production does not trust caller-supplied synthetic labels: the runtime environment is server-derived, live-key requests cannot self-mark as `dev`, `script`, or `test`, and test API keys are persisted as `source: "test"` by the server. Synthetic production traffic stays human-gated and should not be used to satisfy the real runtime contract without approval. For the pre-live pilot quality gate, GridWonk operators use the protected local or preview question-corpus loop, not production API traffic. Platform admins can open that operating guide from their docs navigation. ## Session Continuity Pass the `sessionId` from a `complete` event to continue the conversation. This illustrative adapter omits a full SSE frame parser: ```typescript const response = await fetch('/api/v1/agents/chat', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ message: 'What are the site control requirements?', utility: 'Duke Energy Carolinas', state: 'NC', sessionId: previousSessionId, // from prior complete event }), }); const reader = response.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const text = decoder.decode(value); // Parse SSE lines: data: {...}\n\n } ``` ## Error Handling Errors are delivered as SSE `error` events, not HTTP status codes once streaming has started. An illustrative event is: ```text data: {"type":"error","error":{"type":"AgentExecutionError","message":"The answer took too long and was stopped.","code":"AGENT_ERROR"},"timestamp":"..."} ``` `error.message` is a **user-facing** string, safe to show a customer directly, and is never empty — a turn that fails without producing an explanation still returns a generic one rather than a blank. It deliberately does not carry internal detail — server-side failure text, workflow run ids, provider request ids. When you need to trace a specific failure, quote the `correlationId` present on every event; support can resolve it to the underlying cause. An `error` event does **not** mean the preceding `content` was invalid. A turn can stream a partial answer and then fail, and the text you already received still stands — it is simply incomplete. ### If the stream itself is cut off A turn can also end because the connection behind it dropped rather than because the pipeline reported a failure. That arrives as a terminal frame with `error.type` of `StreamingError` and `error.code` of `STREAMING_ERROR`: ```text data: {"type":"error","error":{"type":"StreamingError","message":"Something went wrong.","code":"STREAMING_ERROR"},"timestamp":"..."} ``` `message` on this frame is always the same generic sentence. An interrupted stream has no user-facing explanation to give, and the underlying reason is internal detail, so it is not disclosed — use the `correlationId` to trace it, exactly as with `AGENT_ERROR`. Whatever `content` arrived before the frame still stands. When the client cancels the response, the server forwards that cancellation to the chatbot stream so the turn can release its session and lease instead of waiting for the executor timeout. Release happens once the step already in flight finishes — a tool call or model request that had started still runs to its own end — so treat it as prompt rather than instantaneous. A cancelled turn is still billed for the work it had already done. ### Denials Pre-stream errors — authentication failure, validation, an organization not entitled to API access — return standard JSON error responses with appropriate HTTP status codes, and never begin an SSE stream. Every credential that fails authentication returns the same `401` with code `UNAUTHORIZED` and the message `Invalid or missing API key`, whether the key is unknown, revoked, expired, or suspended. The response deliberately does not say which, so the denial cannot be used to test keys. The `requestId` in the body is how support identifies the specific call. --- # Deficiency Reports API Query organization-scoped deficiency findings generated by validation workflows. URL: /docs-site/api/deficiency-reports ## Reading existing reports Reading an authorized saved report does not consume a trial or prepaid review credit and remains available after processing expiry. Saving a new usable packet report consumes one credit even when cached evidence avoids a provider call. Current organization access is still required. See [trial and prepaid processing](/docs-site/help/processing). # Deficiency Reports API ## List Deficiency Reports `GET /api/v1/deficiency-reports` ### Query Params - `utility` (optional) - `severity` (optional): `critical`, `high`, `medium`, `low` - `status` (optional alias): location statuses (`exact`, `approximate`, `unresolved`, `pending`), finding states (`open`, `resolved`, `superseded`) or remediation progress (`open`, `in_progress`, `pending_revalidation`, `resolved`, `wont_fix`) - `locationStatus` (optional): `exact`, `approximate`, `unresolved`, `pending` - `findingState` (optional): `open`, `resolved`, `superseded`. This is whether the deficiency is still open. Only a review closes a finding. - `remediationStatus` (optional): `open`, `in_progress`, `pending_revalidation`, `resolved`, `wont_fix`. This is the applicant's progress on a fix. `resolved` here means a fix was applied, not that the finding closed. - `applicationId` (optional uuid) - `documentId` (optional uuid) - `limit` (1-100, default 50) - `offset` (default 0) ### Response Shape ```json { "reports": [ { "id": "uuid", "sessionId": "uuid", "utility": "duke-energy", "state": "NC", "applicationId": "c8a43756-2e9f-4d10-a7c3-216bdd403e15", "documentId": "uuid", "deficiencyType": "site_control", "description": "Lease term does not meet minimum duration", "severity": "high", "requirementSource": "Duke Energy NC Tariff Section 3.2", "requirementId": "uuid", "pageReference": 4, "boundingBox": { "x": 120, "y": 210, "width": 180, "height": 50 }, "locationStatus": "exact", "locationMethod": "vision_verified", "locationConfidence": "high", "locationReason": null, "locationMatchedText": "Lease shall remain in effect for twenty years", "workingSpanId": "4f2e2b15-8b6d-4a31-8fdb-2a38f5e0b222", "workingPageHint": 4, "workingQuote": "Lease shall remain in effect for twenty years", "workingCharStart": 1421, "workingCharEnd": 1472, "workingAnchor": { "spanId": "4f2e2b15-8b6d-4a31-8fdb-2a38f5e0b222", "pageHint": 4, "charStart": 1421, "charEnd": 1472, "quote": "Lease shall remain in effect for twenty years" }, "sourceAnchor": { "pageReference": 4, "boundingBox": { "x": 120, "y": 210, "width": 180, "height": 50 }, "matchedText": "Lease shall remain in effect for twenty years", "method": "vision_verified", "confidence": "high", "reason": null }, "findingState": "open", "remediationStatus": "open", "createdAt": "2026-02-18T04:00:00.000Z" } ], "total": 1, "limit": 50, "offset": 0 } ``` ## Access Scope Results are scoped to the calling API key organization. A report can be returned when the caller organization is either the report owner organization or the applicant organization on the report. Implementation note: hybrid anchors are additive fields used by the split remediation UI and API/CLI workflows; existing deficiency consumers remain backward-compatible. `sessionId`, `applicationId`, `documentId`, `requirementSource`, and `requirementId` can be `null` for legacy or packet-level findings that do not carry that linkage. --- # Documents API Classification, digitization and validation entrypoints, and the retired upload route. URL: /docs-site/api/documents ## Trial and prepaid workspaces The legacy standalone digitization path is unavailable for trial and prepaid workspaces. Use supported [packet intake](/docs-site/api/packets), where upload, preprocessing, and review share the durable processing controls. Existing authorized document reads remain available; prepaid capacity does not enable an unsupported adapter. > **Deprecated compatibility adapters.** The generic classify and digitize endpoints on this > page are retained for pre-packet integrations, but new integrations should use the > [Packets API](/docs-site/api/packets): Storage-native intake is the upload path (the inline > base64 upload route was retired on 2026-09-30), the intake pipeline's sanitization/OCR > supersedes generic digitization, and packet role results with cohort-gated automatic > acceptance and human correction replace generic classification. The remaining adapters are > removed only after a consumer-migration review (the PR11 legacy retirement decision); their > access restrictions below continue to apply. ## Upload Document (retired) `POST /api/v1/documents/upload` was retired on 2026-09-30 (legacy register LEG-04) and now returns `404`. It accepted a base64-encoded PDF of at most 3 MiB and stored the bytes inline. Upload documents through [packet intake](/docs-site/api/packets) instead: create an intake, upload the file to the signed target (files up to 30 MB; accepted formats are listed there), then finalize it. Documents stored through the retired route stay readable. ## Classify Document Text `POST /api/v1/documents/classify` Classifies raw markdown into known document types. ### Body ```json { "text": "This Lease Agreement...", "model": "optional-model-override" } ``` ### Response ```json { "documentType": "lease", "confidence": 0.92, "metadata": { "inputTokens": 1250, "outputTokens": 45, "durationMs": 890, "estimatedCostUsd": 0.0012 } } ``` ## Digitize Document `POST /api/v1/documents/digitize` Runs synchronous digitization for an accessible document id. Applicant-document digitization now resolves its byte source through the storage-native document source lane when the organization is in that cohort; otherwise it keeps the legacy source path. Every applicant digitization write remains pinned to the captured document generation. ### Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `documentId` | string (UUID) | Yes | Document to digitize. Any 8-4-4-4-12 hexadecimal ID is accepted, so older procedure documents keep their original IDs. | | `tableName` | string | No | One of: `ix_applicant_documents`, `ix_procedure_documents`. Defaults to `ix_applicant_documents`. | | `fileFormat` | string | No | File format. Defaults to `pdf` when omitted. | | `utility` | string | Conditional | Required only when `tableName` is `ix_procedure_documents`; optional for applicant documents. | | `model` | string | No | Model override for digitization | ```json { "documentId": "550e8400-e29b-41d4-a716-446655440000", "tableName": "ix_applicant_documents", "fileFormat": "pdf" } ``` ## Retired Validation Endpoint `POST /api/v1/documents/validate` This compatibility route now returns authenticated HTTP `410 Gone` with `CAPABILITY_RETIRED`. It does not create a validation job. Use packet intake Review for deterministic document review. ## Access Rules For digitize operations, document access is verified against the API key organization scope before execution. For exact-content hydration, the locked document must belong to that same non-null organization. The API-key creator's uploader identity does not grant access to a personal or foreign-organization document. Salesforce-owned documents are read-only copies for ordinary processing. Generic digitization and document-bound job creation return `404 NOT_FOUND` for them, and ordinary upload replacement cannot change their packet membership. Source changes must be captured by the connector rather than written into the copy; the [Salesforce connector is implemented but disabled](/docs-site/integrations/salesforce). Packet document reads also check the viewer's current source permission before issuing access to a Salesforce-owned copy. Current document lists omit files removed from the current source revision; an authorized historical package can retain its original files without restoring them to the current packet. Direct reports and selected package artifacts require current permission for the fields in every committed source revision, including old-only fields. More than 200 revisions or malformed history is refused without truncating the proof. A revoked old field can also deny a current view. See the [connector acceptance gates](/docs-site/integrations/salesforce). Sanitized PDF reads use the logical version-row context when available. A selected project document therefore carries both the applicant document id and the current `application_document_versions.id` needed by the resolver-backed PDF route. --- # Errors & Retries Error response format, status codes, rate limit handling, and retry strategies. URL: /docs-site/api/errors ## Public plugin setup and processing refusals The curated [public plugin](/docs-site/api/mcp) returns tool results inside MCP JSON-RPC responses. Before activation, ordinary tools return `CONNECTION_REQUIRED` and the browser setup link. An active tool can return `PROCESSING_UNAVAILABLE` when the workspace cannot admit processing; read the returned reason, check the existing job's status, and review purchase receipts in Billing. See [processing help](/docs-site/help/processing). Read `isError` and structured content even when the HTTP request itself succeeds. An uncertain result is not proof of failure or permission to start another paid operation. Preserve the returned resource identity and check its status before retrying. # Errors & Retries Most GridWonk API v1 endpoints return errors in a consistent envelope format. This page covers the error contract, rate limiting, and recommended retry strategies. ## Error Response Envelope Bounded parsers reject an oversized request with `413 PAYLOAD_TOO_LARGE` before JSON, form, or PDF work starts. Malformed JSON uses the same safe error envelope with `400 INVALID_INPUT`; internal exception details are kept in server logs rather than returned to callers. Partner packet review, partner role decisions, and project `PATCH` updates are limited to 16 KiB before parsing. Callers should treat `413` as a request-shape error, not as a retryable server fault. A packet review POST with no body is valid when its optional review fields are omitted. Utility notice write bodies have their own 32 KiB cap and reject unknown fields. Named notice transitions require an empty JSON object; callers cannot assign a status or approval identity. Most JSON API errors follow this illustrative structure: ```json { "error": { "code": "PAYMENT_REQUIRED", "message": "Usage cap exceeded. Add a payment method to continue.", "paymentUrl": "https://gridwonk.com/console/billing", "reason": "hard_monthly_request_cap_exceeded" }, "requestId": "req_a1b2c3d4e5f6g7h8" } ``` | Field | Type | Description | |-------|------|-------------| | `error.code` | string | Machine-readable error code (see table below). | | `error.message` | string | Human-readable description of what went wrong. Safe to show a customer: it is the user-facing string, never internal server detail, and never empty — a failure with no specific explanation still returns a generic one. Quote `requestId`/`correlationId` when you need support to trace the underlying cause. | | `error.retryAfter` | number | Seconds to wait before retrying. Present on `429` responses and on retryable `503` responses (mirrored in the `Retry-After` header). The SDK surfaces it on every error class, not only rate limits. | | `error.paymentUrl` | string | Billing URL to resolve `402 PAYMENT_REQUIRED` responses. | | `error.reason` | string | Machine-readable denial reason (for rollout/billing gates, and for `503 SERVICE_UNAVAILABLE` causes). | | `error.details` | object | Endpoint-specific structured detail on some `400` responses. Project creation, for example, lists the utility's valid interconnection programs as `{ slug, label }` objects under `details.programs`. Absent when the endpoint has nothing structured to add. | | `requestId` | string (optional) | Correlation ID for this request when available. Include it in support tickets. | ZIP and document-processing recovery return `503 WORKFLOW_START_FAILED` with `Retry-After: 5` when the durable workflow cannot start. Retry the same archive finalize or intake retry-processing operation after that delay; do not create a replacement identity. Ineligible state or an exhausted three-cycle user processing-retry limit returns `409 CONFLICT`; foreign or unauthorized resources return the shared `404 NOT_FOUND`. Route-specific exceptions: - Utility notice routes return generic `404 NOT_FOUND` for missing, foreign, or inaccessible applications/notices. Invalid strict bodies or list filters return `400 INVALID_INPUT`; stale lifecycle state returns `409 CONFLICT`. Refresh the same notice before retrying a conflicted or uncertain send. `202` means unfinished delivery, not canonical `sent` status; a held delivery can return `200` and still require review. Do not change the recipient or create another request to bypass a hold. See [notice operations](/docs-site/api/utility-lane#package-bound-notices). - Utility manual-decision writes return the same `404 NOT_FOUND` for absent resources, foreign resources, and definite source-access denial. Stale package/version or concurrent study-evidence writes return `409 CONFLICT`; refresh before retrying. Invalid strict-body fields return `400 INVALID_INPUT`. An authorization-service outage remains a server failure, not a successful empty result or a permission denial. See [utility decisions](/docs-site/api/utility-lane#record-human-decisions). - `POST /api/v1/oauth/token` uses OAuth error shape: `{ "error": "invalid_client", "error_description": "..." }`. - That token route returns `invalid_target` when `resource` is not an exact GridWonk MCP endpoint; MCP authentication failures include a `WWW-Authenticate` challenge pointing to protected-resource metadata on the canonical GridWonk origin. - `/api/v1/mcp` JSON-RPC failures use `{ "jsonrpc": "2.0", "id": ..., "error": { "code": ..., "message": "...", "data": ... } }`. - Unexpected failures from partner-scoped MCP packet tools return a generic `Tool execution failed` result plus the request ID. Internal database, storage, and workflow details stay in server logs. - Partner native-CAD intake returns the same `404` for an inaccessible submission, an organization outside the enabled cohort, or an inaccessible intake. A stale site-plan target returns `409`; invalid extension, DWG header, or size uses the safe API error or status projection without exposing storage paths, source hashes, or internal parser details. - Reusing a native-CAD intake idempotency key with a different filename, byte count, or site-plan target returns `409`; generate a new key for a different upload. If finalization accepted the bytes but could not start its durable workflow, it returns `503 workflow_start_failed` with `Retry-After: 5`. Retry finalization with the same intake ID; atomic processing claims prevent the duplicate start from creating duplicate provider work. - Batch pairing can return HTTP `200` with `status: "needs_selection"` and authorized site-plan candidates. Choose one and repeat pairing with its exact version ID; a stale target returns `409`. Hosted MCP returns that selection-needed result with `isError: true`. Standalone `POST /api/v1/packets/cad-intake` still requires a target. Native-CAD declarations and pairing on utility-owned packets return the shared `404`. - Batch reservation replays return `200` and `deduped: true`; a changed manifest under the same key returns `409`. Both `batchId` and `batchItemId` must be valid UUIDs on document creation (`400` otherwise). Once an upload has advanced beyond its active upload attempt, poll its existing intake instead of creating another; a creation retry can return `409` at that stage. - Delegated-user resolution on `/api/v1/mcp` separates intentional delegation failures — a missing, invalid, or non-member delegation context, answered with HTTP `403`, JSON-RPC `-32600`, and a controlled message — from internal resolution faults, which return a generic `Unable to resolve effective user` (HTTP `500`, JSON-RPC `-32603`) and keep the underlying detail in server logs under the correlation ID. - On a later stateful MCP request, a key owner demoted below the delegated member, or a delegated member whose membership is revoked, makes the session unavailable before dispatch: HTTP `404`, JSON-RPC `-32001`, `MCP session not found`. If the key owner's own membership is revoked, API-key authentication refuses the request earlier. Reinitialize after permissions are corrected; retrying the same session ID does not restore its former authority. - Bootstrap status errors can omit `requestId`; use the response status and message when no correlation ID is present. - Generic digitization and document-bound job creation return `404 NOT_FOUND` for a Salesforce-owned document. Reading a source-owned copy does not authorize ordinary processing; retrying through the other generic endpoint does not bypass this restriction. - A utility Applications queue query matching more than 200 Salesforce-owned applications returns `400 INVALID_QUERY` and asks for narrower filters. This bound applies before pagination: lowering `limit` alone does not fix it. The equivalent MCP tool returns an `INVALID_QUERY` tool error. These safeguards do not activate the [default-disabled Salesforce connector](/docs-site/integrations/salesforce). When checking current source permissions, an authorization-service outage fails the read rather than returning a successful empty queue or an incomplete count. ## Error Code Reference Packet-job cancellation can succeed while returning a `warning` that the background runtime could not be stopped or a provider call may still finish. This is not a failed status write or permission to immediately retry the packet. Inspect current state and resolve the warning first. Already-terminal, out-of-scope or otherwise uncancellable jobs retain the existing `409 CONFLICT` response; authentication and the error envelope are unchanged. ### Packet upload recovery An optional intake `uploadState: "failed"` describes a reported transfer problem, not a rejection of the source file or a failed document review. Read the existing intake before starting recovery: server-verified completion takes precedence over a late browser failure report. If finalization returns `409 CONFLICT` because the upload attempt changed, refresh the intake and use its current recovery path. Reauthorization retains the intake ID but creates a new byte-zero attempt; quota reacquisition after expiry can return `429 RATE_LIMITED`. Respect `Retry-After` and do not create new identities to evade a quota. A batch that is abandoned or past its fixed lifetime stays closed history, but the file's own intake can still be retried. See [safe recovery](/docs-site/api/packets#upload-observations-and-safe-recovery). The remediation working-draft and export routes no longer emit a `FEATURE_DISABLED` code — their environment feature gates were removed on 2026-08-26 and the routes are always on. | Code | HTTP Status | When It Occurs | |------|-------------|----------------| | `UNAUTHORIZED` | 401 | Missing `Authorization` header, malformed Bearer token, expired key, or revoked key. | | `FORBIDDEN` | 403 | API key is valid but not authorized for the requested endpoint (endpoint allowlist), or the organization is refused before the endpoint check: `reason: api_access_suspended` (a platform-admin suspension of the organization's API and MCP access, also returned while the deployment-wide brake is on) or `reason: billing_suspended` (the account is suspended). Both apply to the hosted MCP endpoint as well. Contact support; retrying will not help. Credentials that act as one person (user OAuth on the hosted MCP endpoint and the CLI bootstrap routes) also return `reason: legal_acceptance_required` while that person has not accepted the current legal documents; `details.acceptUrl` opens the page where they accept, and the same credential works again right after. Organization API keys are not refused for their own acceptance, but an MCP request that delegates to a person who has not accepted gets HTTP 403 with JSON-RPC error `-32600` and a plain message instead of this body (see [MCP error semantics](/docs-site/api/mcp#error-semantics)). | | `PAYMENT_REQUIRED` | 402 | Org-level hard usage cap (daily or monthly) exceeded and billing is not active. `reason` names the cap (see below) and `paymentUrl` opens the billing portal. | | `RATE_LIMITED` | 429 | Per-minute or daily request limit exceeded for the API key, or an organization with active billing has reached its daily or monthly organization usage cap. Check `retryAfter` in the response body (also sent as the `Retry-After` header for organization caps). | | `INVALID_INPUT` | 400 | Request body or query parameter validation failed. The `message` field lists specific issues. | | `NOT_FOUND` | 404 | Resource does not exist or is not accessible within your organization scope. | | `CONFLICT` | 409 | Invalid state transition, such as canceling an already-terminal job, or a concurrent update changed the records — refresh and retry. | | `UNPROCESSABLE` | 422 | The record cannot accept the write in its current state (for example, assigning a content role to a linked document with no accepted sanitized version). Nothing changed concurrently, so retrying will not help — fix the underlying state first (for example, re-upload the document). The partner discovery spec declares this status on the affected endpoints. | | `LIMIT_EXCEEDED` | 400 | Resource quota reached (e.g. maximum webhook subscriptions per organization). | | `CAPABILITY_RETIRED` | 410 | A retired capability was called. Not retryable — the message names the supported replacement. | | `ENDPOINT_GONE` | 410 | A retired *endpoint* was called. Not retryable — the body adds a machine-readable `replacement` path. See below. | | `SERVICE_UNAVAILABLE` | 503 | A dependency the request needs could not be trusted, so nothing was written. Project writes use it when a utility's published interconnection programs could not be read (`reason: program_lookup_failed` — retry after `retryAfter` seconds) or are misconfigured (`reason: program_publication_invalid` — contact support; retrying will not help). | | `INTERNAL_ERROR` | 500 | Server-side failure. Safe to retry with backoff. | `GET /api/v1/openapi.json` uses the same machine-credential authentication and error envelope as other broad API routes: a missing or invalid raw API key or scope-less OAuth JWT returns `UNAUTHORIZED`, while endpoint restrictions can return `FORBIDDEN`. The docs-host copy requires native internal authorization. Anonymous app-host `/openapi.json` and `/.well-known/openapi.json` publication remains disabled and returns `404`; public help availability does not open those complete discovery documents. The anonymous document names a schema for every status each operation declares, not just the success case. Packet operations reference the envelope above; the token exchange references the OAuth 2.0 `{ error, error_description }` shape it actually returns. A generated client can therefore type its error branches without a second lookup. Project reads deliberately return the same `NOT_FOUND` result for an unknown project and a project owned by another organization. Project updates return `CONFLICT` when the project is no longer an editable draft; refresh the record rather than retrying the stale write. An unexpected create failure, including a database insert that returns no record, stays behind the generic `INTERNAL_ERROR` response. ## Retirement Responses (410) Two distinct codes return `410`. Both are permanent — retrying the same call will never succeed — but they differ in how the replacement is communicated. ### `CAPABILITY_RETIRED` Uses the standard error envelope, naming the replacement in prose: ```json { "error": { "code": "CAPABILITY_RETIRED", "message": "Legacy single-document validation is retired. Use packet intake Review." }, "requestId": "req_a1b2c3d4e5f6g7h8" } ``` Live today on: - `POST /api/v1/documents/validate` — the retired single-document validation tombstone. It stays authenticated and returns `410` rather than `404`, so an old caller gets a definite permanent-retirement signal instead of a path that looks like a typo. - `POST /api/v1/agents/execute` with `agentId: "remediation-agent"` — the retired legacy remediation agent. Other agent IDs are unaffected. ### `ENDPOINT_GONE` Adds a machine-readable `replacement` path next to the envelope, so a client can route without parsing prose: ```json { "error": { "code": "ENDPOINT_GONE", "message": "This endpoint has been retired. It served the frozen legacy requirements corpus; use GET /api/v1/published-requirements for published requirements." }, "replacement": "/api/v1/published-requirements", "requestId": "req_a1b2c3d4e5f6g7h8" } ``` Read `replacement` and call that path instead. `ENDPOINT_GONE` is live for the retired `GET /api/v1/requirements`. Authenticated calls receive HTTP 410 and the replacement path; the endpoint no longer reads the frozen corpus or emits its historical read webhook. See [Requirements API — Retirement Stages](/docs-site/api/requirements#retirement-stages). ### Handling both Treat `410` as a code path worth writing before an endpoint you depend on is retired. Neither code is retryable, so a generic 4xx backoff branch is the wrong home for either: ```typescript if (response.status === 410) { const body = await response.json(); // ENDPOINT_GONE carries a machine-readable path; CAPABILITY_RETIRED explains in `message`. const target = body.replacement ?? null; alertOperators({ code: body.error?.code, // 'ENDPOINT_GONE' | 'CAPABILITY_RETIRED' detail: body.error?.message, replacement: target, requestId: body.requestId, }); return; // Do not retry — 410 is permanent. } ``` ## Rate Limiting GridWonk enforces two rate limits per API key: - **Per-minute limit**: Configurable per key (default 60 requests/minute). Uses a fixed-window counter. - **Daily limit**: Derived as `rateLimitPerMinute * 1,440` (minutes per day). Resets at midnight UTC. Authentication and pre-auth alert throttles are separate from API-key usage limits and use shared Redis state in production. A forwarded client address is used only when the deployment explicitly configures a trusted edge header; ordinary caller-supplied forwarding headers do not choose the security bucket. ### Organization Usage Caps Every authenticated request is counted on a per-organization ledger, first for the current UTC day and then for the current month, on every billing status. When a cap refuses, `error.reason` is one of: | Reason | Window | Cap | |--------|--------|-----| | `hard_daily_request_cap_exceeded` | UTC day | Daily request count | | `hard_daily_cost_cap_exceeded` | UTC day | Daily estimated cost (USD) | | `hard_monthly_request_cap_exceeded` | Calendar month (UTC) | Monthly request count | | `hard_monthly_cost_cap_exceeded` | Calendar month (UTC) | Monthly estimated cost (USD) | The status depends on billing: an organization with active billing (or an active manual override) receives `429 RATE_LIMITED` with `retryAfter` (seconds to the next UTC day or month) mirrored in the `Retry-After` header; an organization without active billing receives `402 PAYMENT_REQUIRED` with the same `reason` and a `paymentUrl`. Cost caps are only enforced when the deployment runs cost enforcement in hard mode; by default they are recorded without refusing. The same split applies on the hosted MCP endpoint for both credential lanes. ### Rate Limit Headers API-key-authenticated handler responses that pass auth, organization-profile, rate-limit, and organization-usage gates include these headers: | Header | Description | |--------|-------------| | `X-RateLimit-Limit` | Daily request cap for this API key. | | `X-RateLimit-Remaining` | Requests remaining in the current daily window. | | `X-RateLimit-Reset` | Unix timestamp (seconds) when the daily counter resets (midnight UTC). | | `X-Request-Id` | Correlation ID matching the `requestId` in error response bodies. | ### Handling 429 Responses When you receive a `429`, the `retryAfter` field tells you how many seconds to wait. For per-minute limits, this is the time remaining in the current minute window. For daily limits, this is the time until midnight UTC. For an organization usage cap, it is the time until the refusing window (UTC day or month) rolls over. ```typescript async function fetchWithRetry( url: string, options: RequestInit, maxRetries = 3 ): Promise { for (let attempt = 0; attempt <= maxRetries; attempt++) { const response = await fetch(url, options); if (response.status !== 429) { return response; } if (attempt === maxRetries) { return response; } // Use server-provided retryAfter, or exponential backoff const body = await response.json(); const retryAfter = body.error?.retryAfter ?? Math.pow(2, attempt); const jitter = Math.random() * 1000; await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000 + jitter) ); } throw new Error("Unreachable"); } ``` ## SSE Stream Error Handling The `/api/v1/jobs/{jobId}/stream`, `/api/v1/agents/chat`, and enabled `/api/v1/assist` endpoints use Server-Sent Events. Errors during a stream are delivered as `error` events: ```text event: error data: {"code":"INTERNAL_ERROR","message":"Agent execution failed","requestId":"req_abc123"} ``` The job stream requires a Bearer credential. Native browser `EventSource` cannot set the `Authorization` header, so use authenticated `fetch`, an SSE-capable client that supports headers, the SDK, or the CLI. This runnable TypeScript helper parses authenticated job events: ```typescript async function consumeJobStream(streamUrl: string, accessToken: string) { const response = await fetch(streamUrl, { headers: { Authorization: `Bearer ${accessToken}`, Accept: 'text/event-stream', }, }); if (!response.ok || !response.body) { throw new Error(`Stream request failed: ${response.status}`); } const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }).replace(/\r\n/g, '\n'); const frames = buffer.split('\n\n'); buffer = frames.pop() ?? ''; for (const frame of frames) { const lines = frame.split('\n'); const event = lines.find((line) => line.startsWith('event:'))?.slice(6).trim(); const data = lines .filter((line) => line.startsWith('data:')) .map((line) => line.slice(5).trimStart()) .join('\n'); if (!event || !data) continue; const payload = JSON.parse(data); if (event === 'error') { throw new Error(`Stream error [${payload.code}]: ${payload.message}`); } if (event === 'job.complete') return payload; if (event === 'timeout') return { timedOut: true }; } } throw new Error('Stream closed before a terminal event'); } ``` The job stream emits a `timeout` event when that stream connection reaches its duration limit. It does not mean the underlying job failed; reconnect or poll `GET /api/v1/jobs/{jobId}` to continue watching. The assist stream emits `content_block_delta` events for text chunks. Its final `done` event includes the assembled text, resolved model identifier, provider, source, and normalized token usage. If generation fails after the stream starts, it emits `event: error`: unexpected provider failures use `ASSIST_STREAM_FAILED`, while a disconnected client uses `REQUEST_CANCELLED` and the bounded host deadline uses `ASSIST_TIMEOUT`. ## Idempotency ### Webhook Event Delivery Webhook payloads include an `X-GridWonk-Event-Id` header. Use this to deduplicate deliveries, since GridWonk retries failed webhook attempts. Store processed event IDs and skip duplicates: ```typescript app.post("/webhooks/gridwonk", (req, res) => { const eventId = req.headers["x-gridwonk-event-id"]; if (alreadyProcessed(eventId)) { return res.status(200).send("OK"); // Acknowledge duplicate } processEvent(req.body); markProcessed(eventId); res.status(200).send("OK"); }); ``` ### Job Deduplication Creating a job for a utility and job type that already has an active (non-terminal) run returns the existing job instead of creating a duplicate. This is safe for retry logic -- if a `POST /api/v1/jobs` request times out, retrying with the same parameters will return the in-progress job. ## Best Practices 1. **Always check `error.code`**, not HTTP status alone. Multiple error codes can share the same status (e.g. `RATE_LIMITED` and `LIMIT_EXCEEDED` are both client errors). 2. **Log `requestId` when present.** This is the fastest way to trace issues with GridWonk support, but early authentication and gate failures can omit it. 3. **Respect `retryAfter`**. Ignoring it and retrying immediately will extend your lockout. 4. **Use exponential backoff with jitter** for `500` errors. Start at 1 second, cap at 30 seconds. 5. **Set timeouts on SSE connections**. If no events arrive within 5 minutes, reconnect and poll the job status via `GET /api/v1/jobs/{jobId}`. 6. **Deduplicate webhook events** using `X-GridWonk-Event-Id` to ensure at-least-once delivery does not cause duplicate processing. Authorization failures are terminal for the presented credential. A `403` caused by an API-key endpoint policy is not a transient error; do not retry it with the same key or broaden a key's allowlist without an explicit operator decision. ## Salesforce connector retries The separate outbound-only installed-app route currently returns only `503 {"error":"disabled"}` with `Cache-Control: no-store`. This is an intentional code gate, not a transient failure to retry. Its small contract-specific envelope is not the partner API error envelope described above. The default-disabled connector uses `400` for invalid strict inputs, `403` for denied source access, `404` for an inaccessible import reference, `409` for known conflicting or not-ready operations, and `503` for an unknown dependency failure. Existing authentication, usage, and rate-limit refusals still apply. After an uncertain import response, explicitly retry with the same `idempotencyKey` and `acknowledge: true`; the SDK does not auto-retry that POST. Errors do not expose provider response bodies or credentials. ### Disabled hosted assistance When `GRIDBOOST_ENABLE_API_ASSIST` is off, REST `POST /api/v1/assist` returns `404 NOT_FOUND`. Authenticated MCP discovery omits `assist`, and a direct MCP call returns `400` with JSON-RPC code `-32602` before assistant execution. A catalog entry in public, unauthenticated documentation does not establish availability for the current deployment or credential. --- # External API (v1) Route index for GridWonk partner integrations over /api/v1. URL: /docs-site/api/external # External API (v1) This page is the endpoint index for the GridWonk partner API. ## Base URL ```text https://gridwonk.com/api/v1 ``` ## Authentication Most routes require a Bearer token — either an API key or a JWT obtained via OAuth 2.0: ```text 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](/docs-site/api/authentication) 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](/docs-site/api/mcp) 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 | Method | Path | Purpose | |-------|------|---------| | POST | `/oauth/token` | Exchange API key for a short-lived JWT (OAuth 2.0 client credentials), optionally bound to an MCP resource | | POST | `/utilities/match` | Match utility names to EIA-backed utility records | | GET | `/utilities/list` | Browse and search utilities with filters | | POST | `/documents/classify` | Classify document type from raw markdown | | POST | `/documents/digitize` | Synchronous document digitization | | POST | `/documents/validate` | Retired tombstone; returns authenticated HTTP 410 | | GET | `/documents/{documentId}/working-draft` | Fetch editable working-copy spans (always on — no feature gate) | | PATCH | `/documents/{documentId}/working-draft/spans/{spanId}` | Update one working-copy span | | GET | `/applications/query` | Query organization-scoped application sessions | | GET, POST | `/projects` | List developer projects or create a real customer draft | | GET, PATCH | `/projects/{projectId}` | Read or update an organization-owned editable draft | | POST | `/agents/chat` | Stream chatbot responses (SSE). Opt in to citation events with `includeSources: true` | | POST | `/agents/execute` | Run supported agents asynchronously | | POST | `/assist` | Run enabled one-shot or streaming text assistance with resolved model/provider/usage metadata | | GET | `/jobs` | List async jobs | | POST | `/jobs` | Create async job | | GET | `/jobs/{jobId}` | Fetch one job | | DELETE | `/jobs/{jobId}` | Cancel active job | | GET | `/jobs/{jobId}/stream` | Stream job progress/completion (SSE) | | GET | `/published-requirements` | Query customer-released utility requirements | | GET | `/requirements` | **Retired.** Returns typed HTTP 410 with `/published-requirements` as the replacement | | POST | `/packets/intake` | Start partner-scoped packet intake; see [Partner Packets](/docs-site/api/packets) for the full intake, document, role-decision, review, status, and screening surface | | POST | `/packets/{submissionId}/intake-batches` | Reserve 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}/documents` | List 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}/review` | Start or reuse one exact document review; budget exhaustion is `429 RATE_LIMITED` with `Retry-After` | | POST | `/packets/{submissionId}/review` | Start or reuse an applicant or eligible utility review through the shared review core; requires `partner.write` | | POST | `/utility/applications/{submissionId}/freeze` | Human-requested freeze of an eligible utility-owned draft | | POST | `/utility/applications/{submissionId}/packages/{packageId}/adjudications` | Record a human decision for the exact package, run, finding, and expected version | | POST | `/utility/applications/{submissionId}/screening/complete` | Complete screening for the exact latest package; repeated completion is idempotent | | POST | `/utility/applications/{submissionId}/study-requirement` | Set or replace a human study requirement for the next submission only | | GET, POST | `/utility/applications/{submissionId}/notices` | List 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}/send` | Request durable delivery to an on-file applicant/member address; pending work returns `202` | | POST | `/packets/cad-intake` | Start private DWG companion intake for an exact current site-plan version; finalize, status, reauthorization, and cancellation use nested intake-ID routes | | GET | `/deficiency-reports` | Query scoped findings by `findingState` (`open`, `resolved`, `superseded`); `remediationStatus` separately tracks fix progress | | POST | `/remediation/exports` | Create clean/redline/evidence remediation bundle | | GET | `/remediation/exports/{exportId}` | Poll remediation export status | | GET | `/webhooks` | List webhook subscriptions | | POST | `/webhooks` | Create webhook subscription | | GET | `/webhooks/{id}` | Get one subscription and recent attempts | | PATCH | `/webhooks/{id}` | Update subscription | | DELETE | `/webhooks/{id}` | Delete subscription | | GET | `/usage` | Usage and performance rollups | | GET | `/mcp` | Discover the credential-filtered MCP catalog: broad tools for raw/scope-less credentials, or exact-scope packet tools for partner OAuth tokens | | POST | `/mcp` | Execute MCP JSON-RPC calls with the same per-tool discovery and authorization policy | | DELETE | `/mcp` | Close a stateful MCP session | | GET | `/openapi.json` | Return 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](/docs-site/api/utility-lane) 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](/docs-site/api/webhooks) 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](/docs-site/integrations/salesforce) 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](/docs-site/api/packets#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](/docs-site/api/requirements#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](/docs-site/api/jobs#cancel-job) for authority and retry boundaries. Routes that queue long-running work return `202` with: ```json { "jobId": "uuid", "status": "pending", "pollUrl": "/api/v1/jobs/{jobId}", "streamUrl": "/api/v1/jobs/{jobId}/stream" } ``` ## Quick Start ```bash # 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/ \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ## Next References - [Jobs API](/docs-site/api/jobs) - [Documents API](/docs-site/api/documents) - [Requirements API](/docs-site/api/requirements) - [Webhooks API](/docs-site/api/webhooks) - [Remediation API](/docs-site/api/remediation) - [MCP API](/docs-site/api/mcp) - [Usage API](/docs-site/api/usage) ## 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](/docs-site/integrations/salesforce). --- # Jobs API Async job lifecycle for long-running GridWonk workflows. URL: /docs-site/api/jobs # Jobs API Async jobs support long-running procedure discovery and document digitization. Historical validation and report jobs remain readable. Queued or retryable rows with a retired or unknown historical job type fail with an explicit non-retryable error. Stored metadata cannot select or revive the removed generic agent runner. ## List Jobs `GET /api/v1/jobs` ### Query Params - `limit` (1-100, default 50) - `offset` (default 0) - `status` (`pending`, `discovering`, `parsing`, `extracting`, `fetching`, `analyzing`, `validating`, `complete`, `failed`) - `jobType` (`discovery`, `document-digitization`, or historical read-only types `site-control-requirements`, `site-control-compliance`, `deficiency-location`, and `report-generation`) - `onlyCurrentKey` (`true` to scope by current API key id) ## Create Job `POST /api/v1/jobs` Creatable job types are `discovery` and `document-digitization`. The legacy `site-control-requirements`, `site-control-compliance`, `deficiency-location`, and `report-generation` types return `410 JOB_TYPE_RETIRED` on creation, while existing jobs remain available through `GET`. ### Body ```json { "jobType": "discovery", "utilityName": "duke-energy", "state": "NC", "metadata": { "discoveryMode": "pda-only" }, "webhookUrl": "https://partner.example/webhooks/gridwonk" } ``` ### Document Digitization Metadata | Job type | Required metadata | Why it matters | |----------|-------------------|----------------| | `document-digitization` | `documentId`; `tableName: "ix_procedure_documents"` when digitizing a procedure document | Procedure-document digitization must point at the source document being prepared for extraction. | For applicant-document jobs, the organization API key must be authorized for the referenced document and the row must be organization-visible. Private or individually shared applicant documents are not eligible for organization-key job creation; use a user-scoped workflow instead. Procedure-document jobs must also provide the matching `utilityName`. Salesforce-owned documents cannot be processed through this generic job endpoint, even when the organization can read the copy; creation returns `404 NOT_FOUND`. There is no Salesforce job type to select here. Source capture and review belong to the separate [default-disabled Salesforce connector](/docs-site/integrations/salesforce), which remains disabled. For PDA (Procedures Discovery Agent) discovery-only runs, create a `discovery` job with `metadata.discoveryMode: "pda-only"`. The `USE_WORKFLOW_PDA_DISCOVERY` flag controls whether that mode is admitted. Once admitted, the job uses the PDA workflow and leaves requirements extraction out of the run; the flag does not select between cron and Workflow engines. Packet intake Review loads reviewed deterministic requirements from `ix_packet_requirements` and does not depend on the retired legacy job types. ## Get Job `GET /api/v1/jobs/{jobId}` Returns current status, progress, counters, metadata, and result payload (if terminal). Terminal status is compare-and-set from an active status. If another actor already completed, failed, cancelled, or generation-superseded the row, a stale runner cannot overwrite that result or send a terminal webhook it did not earn. Generation-superseded jobs intentionally emit no customer terminal webhook. ## Cancel Job `DELETE /api/v1/jobs/{jobId}` Cancels active jobs. Returns `409` if job is already terminal or cannot be canceled. For packet-review jobs, cancellation settles the linked active review and blocks further packet results without deleting completed document findings. The key must match the job organization and the packet's review-authority organization; a utility-executed applicant self-check does not become utility-cancellable merely because its job ran in that utility's workspace. Use the authorized project action when the key cannot reach the exact review lane. A successful response retains `success` and `jobId` and may add `runtime` and `warning`. Runtime outcomes distinguish a requested stop, an already-terminal runtime, unavailable identity, a failed stop or no stop attempted. Read the warning before retrying: an already-running provider request may finish even though its packet result can no longer publish. Cancellation is not a repair of the failure that caused a stuck run. ## Stream Job Updates `GET /api/v1/jobs/{jobId}/stream` Server-Sent Events stream. ### Event Types - `job.update` - `job.complete` - `error` - `timeout` ## Compatibility Note The Jobs API contract remains stable across Workflow-backed execution: - `POST /api/v1/jobs` and related endpoints still return the same `jobId` / polling flow - Job state remains in `discovery_jobs` and streams through the same SSE channel - Supported async job types route through Workflow-backed execution; external API behavior remains compatible For workflow-owned rows, `discovery_jobs.metadata` may include: - `execution_engine` - `workflow_run_id` - `workflow_entry_mode` - `workflow_stage` These fields are additive metadata and do not change response contracts. ## Example Create + Poll ```bash # Create curl -X POST https://gridwonk.com/api/v1/jobs \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jobType":"discovery","utilityName":"duke-energy"}' # Poll curl https://gridwonk.com/api/v1/jobs/ \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` --- # Key Management API Self-service API key lifecycle management — create, list, update, and revoke keys programmatically. URL: /docs-site/api/keys # Key Management API Org admins and owners can manage API keys programmatically via the Keys API, the CLI (`gridwonk keys`), SDK methods, or the customer dashboard. `/api/v1/keys*` endpoints require a **management key**. Runtime keys are denied key lifecycle operations. GridWonk platform management keys can create a runtime key for another organization, or update a runtime key already in a target organization, by passing `organizationId`. The platform organization uses the canonical `gridwonk` type after the Batch 8 rename; the legacy `gridboost` label is no longer accepted. An update uses the target organization only to scope the lookup; it does not move a key between organizations. Tenant management keys cannot perform cross-organization key operations, and cross-organization create requests cannot mint management keys. ## Endpoints - `GET /api/v1/keys` — List keys for the authenticated organization - `POST /api/v1/keys` — Create a new key - `GET /api/v1/keys/{id}` — Get key details - `PATCH /api/v1/keys/{id}` — Update key properties - `DELETE /api/v1/keys/{id}` — Permanently revoke a key ## ApiKeyInfo Response Schema | Field | Type | Description | |-------|------|-------------| | `id` | string (UUID) | Key identifier | | `keyPrefix` | string | Visible prefix (e.g. `gw_live_...`) | | `name` | string | Human-readable label | | `environment` | `"live"` \| `"test"` | Key environment | | `keyRole` | `"management"` \| `"runtime"` | Key privilege role | | `status` | `"active"` \| `"suspended"` \| `"revoked"` | Current lifecycle status | | `rateLimitPerMinute` | number | Requests per minute limit, max 1000 | | `allowedEndpoints` | string[] | Endpoint allowlist patterns enforced before route handling | | `requestsToday` | number | Requests made today | | `currentMonthCostUsd` | string \| null | Current month API costs | | `monthlyCostLimitUsd` | string \| null | Monthly cost ceiling | | `lastRequestAt` | string \| null | ISO 8601 timestamp of last request | | `expiresAt` | string \| null | ISO 8601 expiration date | | `createdAt` | string | ISO 8601 creation date | Legacy `gb_live_`/`gb_test_` keys are no longer accepted. Use a `gw_live_...` or `gw_test_...` key. ## List Keys ```bash curl https://gridwonk.com/api/v1/keys \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` Query parameters: `status` (active/suspended/revoked), `limit` (default 50, max 100), `offset`. Response: `{ keys: ApiKeyInfo[], total: number }` ## Create an API Key through REST Create a new API key with `POST /api/v1/keys`, authenticated by an existing management key. An organization owner or admin can create a runtime key for application requests or another management key for key lifecycle operations. A runtime key cannot create keys. If you do not yet have a management key, use the first-key setup in the [CLI guide](/docs-site/integrations/cli) before calling this endpoint. Your organization's API Keys page creates runtime keys only. ```bash curl -X POST https://gridwonk.com/api/v1/keys \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Partner Integration","environment":"live","keyRole":"runtime","rateLimitPerMinute":120,"monthlyCostLimitUsd":250}' ``` Response (201): ```json { "key": { "id": "...", "keyPrefix": "gw_live_...", "plaintext": "gw_live_...", "...": "..." }, "warning": "Store this key securely. It will not be shown again." } ``` The `plaintext` field is returned **only at creation time**. Store it securely. Optional create fields include `expiresAt`, `monthlyCostLimitUsd`, and, for GridWonk platform management keys only, `organizationId` to create a runtime key for another organization. Endpoint restrictions are applied by `PATCH`, not by create. **Limit:** Maximum 25 non-revoked keys per organization. Active and suspended keys both count toward the limit. ## Update Key ```bash curl -X PATCH https://gridwonk.com/api/v1/keys/{id} \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Renamed Key","status":"suspended","rateLimitPerMinute":30,"allowedEndpoints":["/api/v1/jobs*"],"monthlyCostLimitUsd":100}' ``` Updatable fields: `name`, `status` (`active`/`suspended`), `rateLimitPerMinute`, `allowedEndpoints`, and `monthlyCostLimitUsd`. A GridWonk platform management key can pass `organizationId` to update a runtime key already in that target organization; it cannot move the key to a different organization. Customer keys cannot target another organization. Cannot change `environment` or set status to `revoked` (use DELETE). ## Revoke Key ```bash curl -X DELETE https://gridwonk.com/api/v1/keys/{id} \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` Response: `{ id: "...", revoked: true }` Revocation is **permanent**. A key cannot revoke itself (self-revoke protection). ## SDK Usage ```typescript import { GridWonkClient } from '@gridwonk/sdk'; const client = new GridWonkClient({ apiKey: process.env.GRIDBOOST_API_KEY!, }); // List keys const { keys, total } = await client.listKeys({ status: 'active' }); // Create a key const { key, warning } = await client.createKey({ name: 'CI/CD Pipeline', environment: 'test', keyRole: 'runtime', rateLimitPerMinute: 120, }); console.log(key.plaintext); // Store securely! // Revoke a key await client.revokeKey(key.id); ``` ## CLI Usage The CLI defaults to the canonical GridWonk API origin: ```bash gridwonk keys list --status active gridwonk keys create --name "CI Key" --env test --role runtime --rpm 120 gridwonk keys create --name "Tenant Runtime" --target-org gridwonk keys get gridwonk keys update --name "Renamed" --status suspended \ --allowed-endpoints "/api/v1/jobs*,/api/v1/published-requirements" --cost-limit 250 gridwonk keys revoke ``` ## Security Considerations - **Key role separation:** Runtime keys cannot call `/api/v1/keys*`; only management keys can manage keys. - **Self-revoke protection:** A key cannot delete itself to prevent accidental lockouts. - **Organization scoping:** Keys can only see and manage other keys within the same organization. - **Platform-only cross-org operations:** Only GridWonk platform management keys can target another organization, and cross-org create is runtime-key-only. --- # Connect with MCP Connect the public GridWonk plugin and use authorized research, intake, and review tools. URL: /docs-site/api/mcp title: MCP API description: Public and admin Model Context Protocol endpoints for GridWonk tools, docs, jobs, and work-item continuity. last-updated: "2026-10-27" --- Model Context Protocol (MCP) lets an AI client use GridWonk tools. The hosted endpoint is `https://gridwonk.com/api/v1/mcp`. Authentication and current workspace permissions are required for customer operations. Interactive sign-in uses identity scopes; machine integrations use the partner scopes advertised by their separate authorization server. ## Organization access and setup Open **Integrations** in the selected organization workspace to inspect access and connection setup: `/console/integrations`, `/utility/integrations`, or `/consultant/integrations`. Platform administrators enable organization API/MCP access. Owners/admins can create organization runtime keys when self-service key creation is also enabled. Enabling access does not supply a credential or complete a client's sign-in flow. Active MCP connections, including curated customer OAuth connections, obey the organization's current API/MCP access choices and suspensions. Disabling MCP refuses subsequent MCP calls while permitted REST calls continue; disabling API blocks both. Revocation remains available on the website. Existing data scopes, membership checks and processing budgets still apply, and the curated customer's processing accounting remains separate from legacy API usage. Claude Desktop and Codex Desktop are the selected live connection acceptance targets. The setup UI and local tests do not establish live-client acceptance or public plugin publication. Pending organization-free setup remains separate from authorization to execute customer operations. ## Public GridWonk plugin The public package is **GridWonk**, with package ID `gridwonk-connect` and server name `gridwonk-customer`. Availability depends on the public rollout and your client's approved connection support. The `chat` tool also needs the MCP assistant turned on for your organization, which is off by default during the staged release. It does not require a private repository or a GridWonk administrator account. 1. Complete [account and workspace setup](/docs-site/help/self-service). 2. Install the public plugin when it is available and sign in with your own GridWonk account. 3. If `connection_status` reports `CONNECTION_REQUIRED`, open its setup link in the browser. 4. Confirm the workspace as the same signed-in user, then retry your request in the client. The connection binds that exact session to one workspace. A browser workspace switch cannot retarget it. [Connected apps](/docs-site/help/connected-apps) explains revocation, replacement, and recovery. Expired or revoked access cannot be repaired by guessing another workspace ID. ## Stable customer catalog The public plugin exposes a fixed catalog of 38 tools, including `connection_status`. It stays the same before and after connection setup. A pending session can inspect the available schemas and connection status; ordinary operations return a setup instruction until activation. Tool availability does not itself grant permission. | Workflow | Customer scope | | --- | --- | | Documentation and research | Public help and published utility requirements | | Developer preparation | Authorized draft projects and supported packet intake | | Processing | Eligible review starts, status, and cited results within current allowances | | Utility work | Authorized application, package, finding, history, and notice reads; eligible intake and reviews | | Recovery | Supported status and recovery operations, with current authority rechecked | The website handles document-role decisions, submission and resubmission, utility adjudication, notice writes and sending, team administration, and purchases. The customer catalog excludes unrestricted chat and generic job execution. A completed review is decision support, not utility approval. ## Safe client behavior Use returned identifiers and schemas; do not invent project, utility, job, or document IDs. Keep uploads within the current intake limits and follow the returned upload/status workflow. Do not use retired inline base64 document uploads. Poll with bounded retries and honor `Retry-After`. A pending or uncertain processing result is not permission to start a duplicate paid operation. Never place access tokens or signed upload URLs in chat transcripts or logs. The server checks the current signed session, connection, membership, role, legal acceptance, and processing eligibility on each use. Public documentation access does not grant data access. See [processing allowances](/docs-site/help/processing). If a request returns `legal_acceptance_required`, open the supplied acceptance link and accept the updated legal documents in your browser, then retry with the same connection. ## Existing partner integrations Existing organization credentials retain their own authorized catalog and scope rules. The public plugin's browser-bound connection does not replace an organization's integration key. Use [API authentication](/docs-site/api/authentication), the [API overview](/docs-site/api/overview), and the [utility lane guide](/docs-site/api/utility-lane) for those integrations. Full discovery documents and internal operator tools remain protected; they are not the public plugin contract. ## Workspace appearance Organization admins preview and save source-palette color schemes in the signed-in website. Appearance discovery and saving have no public or Admin MCP mutation tool. Finding logo colors does not approve a logo for display. See [organization settings](/docs-site/help/organizations). --- # API Overview Authentication, error contracts, and architecture for GridWonk External API v1. URL: /docs-site/api/overview ## Public plugin and existing integrations The [public GridWonk plugin](/docs-site/api/mcp) 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](/docs-site/help/processing), 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 ```text 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: ```bash gridwonk utilities list --state CA --json ``` ```typescript 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`: ```bash 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](/docs-site/integrations/salesforce). 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](/docs-site/api/mcp). 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](/docs-site/api/packets#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](/docs-site/api/utility-lane) 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](/docs-site/api/utility-lane#package-bound-notices). 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](/docs-site/api/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](/docs-site/api/jobs#cancel-job). ## 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](/docs-site/api/requirements#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](/docs-site/api/webhooks) 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](/docs-site/api/packets). ```json { "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 -->](/docs-site/api/projects) - 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 -->](/docs-site/api/requirements) - Webhook control plane: subscription CRUD and attempt visibility. - Key management: CRUD operations for API key lifecycle (create, list, update, revoke). [Reference -->](/docs-site/api/keys) - 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)](/docs-site/api/external) 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](/docs-site/integrations/salesforce). --- # Partner Packets Partner-scoped REST and hosted MCP access to active Storage-native packet intake, documents, review, status, and screening. URL: /docs-site/api/packets ## Restricted test credentials A temporary application-scoped test credential can further restrict the operations below. Its allowed application IDs and expiry are checked on every request, including requests using an existing bearer token or MCP session. A `partner.write` scope does not override those restrictions. Revocation blocks new token exchanges and subsequent API requests. An already issued storage upload link has its own expiry; it only writes its reserved object and cannot read or overwrite files. Ordinary partner credentials and endpoint contracts are unchanged. ## Trial and prepaid intake For trial and prepaid workspaces, supported uploads require a current processing allowance before an upload authorization or background processing starts. The trial source allowance includes the ZIP container and each expanded source entry; resuming that same entry does not count it twice. Native DWG processing is unavailable in this rollout, including DWG entries inside archives. A format listed for an existing integration does not override this workspace restriction. See [processing allowances and recovery](/docs-site/help/processing). Workspace format restrictions are enforced before upload authorization and File Library attachment. If a workspace is limited to PDF review, only standalone PDFs are supported; images, ZIP containers, and native CAD files are refused. Review starts recheck stored packet sources, so an earlier upload or a different client cannot widen eligibility. These restrictions do not waive utility evidence requirements or change the endpoints, credential scopes, or request schemas below. Partner review starts reserve against the reviewing organization's shared review budget. Utility screening charges the reviewing utility, including when it screens a developer-submitted packet. Console partial reports are read views over current document checks, not completed packet-run resources. The partner review endpoint still returns real run records; partial results do not satisfy submission eligibility. Required CAD is resolved from the published utility/process policy, not a global capacity threshold. The partner packet lane exposes the production packet-intake and review capabilities under `/api/v1/packets/*`. It is a **binding of the existing console services** — the same cores, cohorts, authorization predicates, and shared role-decision writer — never a second processing or authorization system. For resumable intake, use the server-returned `uploadAuth.endpoint` exactly: signed uploads use `/storage/v1/upload/resumable/sign` with the token in `x-signature`, not the ordinary bearer-authenticated resumable route. This shared transport also serves CAD and ZIP reservations; their authorization, size limits and finalize contracts remain distinct and unchanged. The outbound-only Salesforce installed application uses those same intake and acceptance cores through a separate certificate-signed API. Its durable receipt pins the exact field values, program mapping, file version IDs, sizes and checksums selected in Salesforce. That private API is not part of `/api/v1/packets/*`, partner OAuth, the SDK, CLI, or MCP, and its processing gate remains off until a later activation approval. For an applicant packet, create or locate the owning developer record through the [Projects API](/docs-site/api/projects) before starting intake. Utility-owned drafts use the utility creation routes below. Developer project submission and resubmission remain console-only safety transactions; packet intake does not bypass them. Packet JSON requests use the same bounded parsing and generic error contract as the other API v1 routes. The server rejects oversized or malformed input before packet state, document content, or review work is loaded. The review-start and human role-decision mutations use a 16 KiB JSON body cap. A body over that route-specific limit receives `413 PAYLOAD_TOO_LARGE` before authorization-dependent write work. A review-start request may omit its body when no optional review fields are supplied. ## Authentication: partner-scoped tokens only The console's **Cancel Packet Review** control is a session-authenticated action with exact review-lane authorization, not a new partner packet endpoint. Existing partner scopes, endpoint paths and start/read contracts below are unchanged. Ordinary job cancellation retains its own job-organization scope; it is not an alternative grant of partner packet access. Every packet REST endpoint and hosted MCP packet tool requires an access token minted with an explicit partner scope (see [Authentication → Partner Scopes](/docs-site/api/authentication)). Raw API keys and scope-less tokens receive `403 insufficient_scope` on packet REST routes and cannot discover or call packet MCP tools. Partner-scoped tokens are refused on ordinary non-packet endpoints (`partner_token_confined`) and capped at one hour. The MCP gateway accepts them only for the packet tools granted by the token's exact scope. A platform-admin suspension of the organization's API and MCP access, or an account billing suspension, refuses packet REST routes and MCP packet tools before the scope check with `403 FORBIDDEN` and `reason: api_access_suspended` or `reason: billing_suspended`. ```bash curl -X POST https://gridwonk.com/api/v1/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_secret=$GRIDWONK_API_KEY" \ --data-urlencode "resource=https://gridwonk.com/api/v1/mcp" \ --data-urlencode "scope=partner.read partner.write" ``` The `resource` parameter is required only when the caller wants an MCP-bound audience. Omit it for packet REST calls, which continue to use the legacy API audience. On every request the acting user's active organization membership is re-verified, and access is confined to the **key organization's own reach**: its applicant projects, its utility submissions, or submissions covered by an active organization-access grant. For a delegated MCP session, the delegated user—not the API-key owner—governs membership and private-document visibility. Every refusal — absence, denial, off-cohort — is the same `404`. ## Endpoints The mixed-upload batch coordinator is available to partner clients under a submission. It reserves one immutable ordered selection without replacing the document, CAD, or archive intake identities. The existing session-authenticated console route uses the same service. Utility credentials can read and mutate only utility-owned batch manifests, not applicant-owned manifests. Utility writes require the utility application's write-membership checks; applicant callers retain their own membership or applicant-issued grant checks. A grant from the reviewing utility is insufficient. An unfinished, unexpired upload batch blocks both automatic and manual full-packet review. Manual REST, SDK, CLI, and MCP starts return `409 CONFLICT` until the batch finishes, is canceled or abandoned, or naturally expires. Individual document reviews remain available. Canceling a batch does not remove accepted documents or waive any other packet-readiness requirement. The manual start checks before budget/job work and again under the packet lock before creating its review run; if a new batch wins that race, no review workflow starts and reserved spend is released. | Method + Path | Scope | Purpose | |---|---|---| | `POST /api/v1/packets/intake` | `partner.write` | Create a Storage-native intake; returns server-selected upload authorization (signed upload ≤6MB, resumable TUS above). Retries with the same `idempotencyKey` deduplicate. A batch item supplies both `batchId` and `batchItemId`; supplying only one is refused, and a batch-bound retry deduplicates on the item plus its declaration rather than on `idempotencyKey`. | | `POST /api/v1/packets/intake/{intakeId}/finalize` | `partner.write` | Prove the uploaded object, enter processing, start the durable pipeline. Idempotent. | | `GET /api/v1/packets/intake/{intakeId}` | `partner.read` | Safe acceptance / sanitization / OCR / searchable-PDF status projection, including nullable `batchId` and `batchItemId`. | | `POST /api/v1/packets/{submissionId}/intake-batches` | `partner.write` | Reserve one ordered manifest of 1–12 loose files, or one ZIP placeholder. An identical `idempotencyKey` replay returns the original batch with `200`; a new reservation returns `201`. | | `GET /api/v1/packets/{submissionId}/intake-batches/{batchId}` | `partner.read` | Read batch and item status after proving the exact packet and owner organization. | | `POST /api/v1/packets/{submissionId}/intake-batches/{batchId}/heartbeat` | `partner.write` | Extend an active batch's idle deadline without exceeding its fixed 24-hour lifetime. | | `POST /api/v1/packets/{submissionId}/intake-batches/{batchId}/pair` | `partner.write` | Applicant-only: pair one inspected DWG item to an exact current site-plan version, or request the server's unambiguous match. | | `POST /api/v1/packets/{submissionId}/intake-batches/{batchId}/items/{itemId}/cancel` | `partner.write` | Cancel one not-yet-uploading item (`reserved`, `registering`, or `rate_limited`). | | `POST /api/v1/packets/{submissionId}/intake-batches/{batchId}/abandon` | `partner.write` | Abandon unfinished items and settle the batch. | | `GET /api/v1/packets/{submissionId}/documents` | `partner.read` | Document list with current roles and pinned classifier lineage. Two lanes: the applicant organization (and applicant-issued grants) under per-document visibility; a utility organization runs the utility lane's ladder (cohort, utility identity, formally submitted or utility-owned draft — never a developer draft) and then sees every linked document. Utility-issued grants stay console-only. | | `POST /api/v1/packets/{submissionId}/documents` | `partner.write` | Attach an owner-organization File Library asset. Returns `201` when created or `200` when the exact attachment already exists; only PDF, PNG, and JPEG assets are accepted. | | `DELETE /api/v1/packets/{submissionId}/documents/{documentId}` | `partner.write` | Permanently delete a document only while every linked packet is a draft or resubmission under development. Submitted history, package pins, foreign ownership, and mismatched IDs are refused. This destructive operation is not available through MCP. | | `POST /api/v1/packets/{submissionId}/documents/{documentId}/review` | `partner.write` | Start or reuse review for the exact packet/document pair. Optional `{ "retryFailed": true }` is available on REST, SDK, and CLI. Returns `429` with `Retry-After` when the request limit or the paying organization's review budget is exhausted. | | `GET /api/v1/packets/documents/{documentId}/pdf` | `partner.read` | Preview or download the accepted sanitized rendition: a `302` to a signed URL valid for at most five minutes, never the original upload. Requires exact `submissionId` + `versionId` (+ `packageId` for utility package context); `202` with `Retry-After` while the rendition is preparing, `409` on a package pin integrity conflict. | | `GET /api/v1/packets/documents/{documentId}/text` | `partner.read` | Sanitized OCR text + `document-coordinates-v1` locations. Requires exact `submissionId` + `versionId` (+ `packageId` for utility package context). | | `POST /api/v1/packets/documents/{documentId}/role` | `partner.write` | Confirm or correct a document content role. This route always records a human decision; when it supersedes an automatic assignment, the human role remains authoritative and the analysis applicable to the corrected type runs again. A stale suggestion or concurrent update returns `409 CONFLICT` — refresh and retry. A linked document with no accepted sanitized version returns `422 UNPROCESSABLE` — re-upload the document first; retrying will not help. | | `POST /api/v1/packets/{submissionId}/review` | `partner.write` | Start an applicant or utility packet review (an active automatic review is reused, never double-billed; 50 starts/hour per user+organization). Utility calls also require the utility application lane and current write membership. | Each declared item keeps its own intake identity. For a document item, pass the returned `batchId` and `itemId` as `batchId` and `batchItemId` when creating the single-file intake, then upload and finalize normally. The server verifies the batch, item, submission, owner, actor, file declaration, state, and expiry under the packet lock. The pair cannot be used to move an existing intake to a different batch. Repeating the same batch or item request does not create a second intake or charge quota again. Creating a new document link through intake or File Library attachment recounts the packet's active documents in the same transaction. A failed transaction rolls back both the link and the count; replaying an existing intake or attachment does not add another link or increment the count. An exact attachment retry also reuses a document retained in that packet's version history. It returns that document's version identity with `reused: true` and `viewable: false` when the version is no longer current. The retry does not restore the old version, promote a replacement, or create another attachment or audit record. While the upload attempt is active, retrying creation returns the original intake with fresh upload authorization. Once processing has begun or the attempt is terminal, creation can return `409`; poll that intake instead of generating a new item. Batch declarations are immutable. Native-CAD declarations and pairing on utility-owned packets are excluded and return `404`. Pairing an applicant-owned item may return `200 needs_selection` with authorized candidates; retry with one exact version ID. A stale target returns `409`. These routes can continue an existing console mixed selection but do not add target-free CAD creation. ZIP creation uses the separate archive protocol below. Creation records preserve authenticated provenance — who acted and through which interface. Later human mutations add audit records in the same transaction as the state change; they do not overwrite the origin. No-change retries add no second mutation record. These records never accept actor or organization IDs from request bodies and are not part of public status payloads. When batch cancellation or abandonment starts an automatic packet review, the job retains that request's authenticated user, credential, interface and correlation ID. Background item completion and batch expiry use the batch's validated creation record instead. Automatic freeze adds the executing job ID to that record. Missing or invalid legacy records stay explicitly `unknown`; they are not reconstructed from a different caller. No request or response fields change. An unfinished batch blocks automatic packet review and package freeze. Completing every item, cancelling unfinished items, or abandoning the batch removes only that batch's block; all other readiness checks still apply. A heartbeat extends the two-hour idle deadline, capped at 24 hours from reservation. File limits remain 30 MiB per item, 120 MiB per batch, and 12 items. When the applicant packet-review readiness check refuses an incomplete packet, REST returns `400 INVALID_INPUT` with an instruction to complete the packet requirements. Hosted MCP returns the same `INVALID_INPUT` outcome. This expected refusal starts no review and is not a server error. The utility lane also returns `INVALID_INPUT` when an uploaded document has not finished processing or role classification; finish those steps before requesting review again. A human-confirmed PDF split also pauses new document/packet reviews and submission while it is pending or failed. Resolve it in the console with **Retry split** or **Keep original**; review starts return the existing `INVALID_INPUT` outcome. **More actions → Split PDF** is console-only, including for assigned or previously reviewed PDFs; no REST, SDK, CLI, or MCP split operation is introduced. Successful children need their own reviews; retained parent findings are historical. Attaching a document also fires an automatic packet-review check in the background. That check is best-effort by design and never affects the attach response — but it is no longer silent when its own infrastructure is broken: a failed review reservation (an unapplied migration, a dead connection) is logged at error level with its SQLSTATE rather than read as "nothing to do". The hourly reconciliation sweep remains the durable backstop either way. The check adds no work to a healthy attach: the reporting path is loaded only when there is an error to report. | `GET /api/v1/packets/{submissionId}/review/{runId}` | `partner.read` | Review run detail with the cited deficiency report. | | `GET /api/v1/packets/{submissionId}/status` | `partner.read` | Canonical workflow status (never implies utility approval) + immutable submitted-package list. | | `GET /api/v1/packets/{submissionId}/screening` | `partner.read` | Utility-organization-only package-bound screening status. This GET is read-only; adjudication uses the separate [utility decision endpoints](/docs-site/api/utility-lane#record-human-decisions), not MCP. | ### ZIP intake and recovery ZIP uploads use a separate reservation, not the single-file intake endpoint (which refuses ZIP). The packet owner is the applicant organization when present, otherwise the utility organization. Utility credentials cannot change a developer-owned packet, even when their creator also belongs to the developer. Every operation checks the current actor and owner; unavailable or foreign resources return the same `404`. | Operation | Route | Scope | |---|---|---| | Create | `POST /api/v1/packets/{submissionId}/archive-intake` | `partner.write` | | Status | `GET /api/v1/packets/{submissionId}/archive-intake/{archiveId}` | `partner.read` | | Finalize or resume processing | `POST /api/v1/packets/{submissionId}/archive-intake/{archiveId}/finalize` | `partner.write` | | Abandon an incomplete upload | `POST /api/v1/packets/{submissionId}/archive-intake/{archiveId}/abandon` | `partner.write` | | Cancel a document intake | `POST /api/v1/packets/intake/{intakeId}/cancel` | `partner.write` | | Restart a document upload from byte zero | `POST /api/v1/packets/intake/{intakeId}/reauthorize` | `partner.write` | | Retry failed document processing | `POST /api/v1/packets/intake/{intakeId}/retry-processing` | `partner.write` | Create accepts `declaredFileName` (ending in `.zip`) and integer `declaredSizeBytes`. Supply `idempotencyKey`, or both `batchId` and `batchItemId` from an archive batch reservation. The response contains `archiveId`, `uploadAuth`, and `deduped`; new reservations return `201`, identical retries while uploading return `200`. Changed declarations conflict. Upload bytes using the returned authorization, then finalize the archive. Never send a chosen storage path. The limits are 30 MiB compressed, 12 supported files, 30 MiB per file, 120 MiB expanded, and a maximum compression ratio of 100. Nested archives, unsafe paths, encrypted entries, and unsupported files are rejected. Utility ZIPs accept PDF, PNG and JPEG, not native CAD. Applicant-owned batch-linked ZIPs retain the existing DWG rules and pairing requirements. Status returns archive progress and safe entry states. If processing fails or finalize returns `503 WORKFLOW_START_FAILED`, retry finalize with the **same archive ID**. Accepted children retain their identities. A live run is not restarted; a processing row untouched for over 15 minutes can claim a restart. Concurrent child handoffs reconcile the same authorized child; an accepted document whose error-free initial processing was interrupted resumes without consuming a user recovery cycle. Completed processing is not repeated. Handoff retries quota pressure at most five times, one minute apart. Abandon applies only while uploading, returns `status: abandoned`, and stores `rejected` with `upload_abandoned`; cleanup waits for outstanding upload authorization to expire. Individual recovery is separate: cancel refuses accepted documents; reauthorize supersedes the old attempt and returns a new upload authorization for the same intake, starting from byte zero. Both remain creator-only and require current owner write access. Processing retry requires an accepted document with an internal processing failure, no valid current artifact, and owner write access. It permits three user recovery cycles. A startup failure restores the previous counter; replaying a fresh queued or running reservation does not start another workflow or consume another cycle. An inactive reservation may be reclaimed after 15 minutes in the same cycle, without another retry audit or upload quota reservation. Successful processing records completion and keeps the same accepted identities. State refusals, including retries after a valid current artifact exists, return `409`. Document recovery does not handle native CAD. ### Upload observations and safe recovery The document-list response separately adds optional `ocrState` for the authorized current document version: `not_enqueued`, `queued`, `running`, `using_fallback`, `ready`, `retryable`, or `terminally_failed`. It is independent of `reviewStatus`, legacy `digitizationStatus`, and `reviewArtifactReady`. Omission means OCR status is unavailable, not that OCR failed or completed. A failed text-recognition sidecar does not turn a completed review into a failed review. Document intake status may include optional `uploadState`: `pending`, `uploading`, `failed`, `expired`, or `complete`. Keep it separate from `acceptance`, sanitization, OCR, and review. A browser-reported transfer failure is an observation, not proof that the stored file is invalid. Server-verified bytes take precedence: a delayed failure report cannot downgrade an upload that has already advanced to processing or acceptance. Older responses may omit this field. For an interrupted transfer, use the existing reauthorize operation on the same intake. It creates a new attempt and storage path, starts from byte zero, and preserves previous attempts as history. It does not overwrite an accepted document. Current creator/owner authorization and editable-packet checks still apply. If expiry cleanup already released the previous attempt's reservation, a new attempt must reacquire quota and can return `429 RATE_LIMITED`; otherwise the live reservation remains in force. A reported failure alone never frees quota. The original creator can also cancel a pending intake after a reported transfer failure, with current owner write access. Cancellation schedules its pending object for cleanup and records one cancellation audit; repeating it is a no-op. A batch item already settled as `failed / upload_failed` retains that terminal history instead of being reopened or rewritten. Accepted source documents cannot be cancelled. Finalization verifies the exact uploaded object and declared byte length before changing state. The matching attempt and intake advance together with an eligible batch item in one transaction. A concurrent retry that replaces that attempt returns `409 CONFLICT`: refresh the intake status before deciding whether to retry. Successful or cancelled batch-item history is not reopened. A failed loose-file item reopens with its own upload or processing retry. Its batch reopens only within the batch's fixed lifetime; neither recovery extends that lifetime. An expired or abandoned batch stays closed history while its file finishes, so reporting a transfer failure never makes a file less retryable than an unreported interruption. Finalization also completes an older attempt already marked uploaded whose intake was never advanced, after the same verification. The browser's failure-report callback is session-only. There is no corresponding partner REST, SDK, CLI, or MCP report-failure operation; integrations use the existing status and recovery calls. Archive creation provenance is immutable and is carried to child intakes. Subsequent human archive and recovery changes record their own authenticated provenance in the same transaction. Feature enablement, upload quotas and all other readiness checks still apply. ### Utility lane reads A utility organization's partner key (org type `utility`, inside the `UTILITY_APPLICATIONS_V2` cohort) also reads its own Applications workspace under `/api/v1/utility/applications`. The organization and its utility identity come from the key's own organization row; no request value can select another organization, and every refusal is the same `404`. | Method + Path | Scope | Purpose | |---|---|---| | `GET /api/v1/utility/applications` | `partner.read` | The Applications queue: formally submitted applications pinned to the key organization (add `includeDrafts=true` for utility-owned drafts), each with its canonical workflow status. Filters `query`, `screeningStatus`, `generationType`, `minCapacityMw`, `maxCapacityMw`, `sortBy`, `sortOrder`, `limit` (max 200), `offset`; an unusable value returns `400`. | | `GET /api/v1/utility/applications/{submissionId}` | `partner.read` | One application: summary, workflow status, package list, and — bound to the latest package or `?packageId=` — the frozen document list, review summary, evidence, communications, and active study requirement. A utility-owned draft with no package yet returns `package: null`. | | `GET /api/v1/utility/applications/{submissionId}/packages` | `partner.read` | Every immutable submitted package, newest first, with `pinnedReview`. | | `GET /api/v1/utility/applications/{submissionId}/packages/{packageId}/findings` | `partner.read` | The pinned run, its report snapshot, the append-only adjudication ledger, the CAD-revision comparison, and the screening summary (latest-package flag, open notices, blocking-finding counts) for one exact package. Read-only; the console's decision controls are not part of the payload. | | `GET /api/v1/utility/applications/{submissionId}/history` | `partner.read` | The immutable application history, newest first, in a closed vocabulary (package, stage, screening, external, notice, adjudication, study requirement). | For mixed application lists, a temporary Salesforce permission-check outage can return `200` with `salesforceReadUnavailable: true`. Rows and `total` include ordinary applications and only Salesforce applications whose current access checks succeeded; the list and count are partial. The field is absent when no such outage occurred. Retry to recheck live source permissions. This does not relax direct application, package, finding, history, or artifact authorization. Screening completion in any of these payloads is a screening decision, never utility approval. Manual freeze, adjudication, screening completion, and study requirements are available through the human-decision routes below. Notice writes remain a later layer. #### Utility lane writes (`partner.write`) A utility organization's partner key with the `partner.write` scope creates its own draft applications and shapes them before documents arrive. The key creator must hold a write-capable seat (owner, admin, or member); a viewer's key reads but never writes. Every write records the key and the request surface in the row's change provenance. | Method + Path | Scope | Purpose | |---|---|---| | `POST /api/v1/utility/applications` | `partner.write` | Create one utility-owned draft. Nothing is required up front; a blank `applicationNumber` is generated. Send `requestKey` to make the call retry-safe: an identical replay returns the same draft with `200`, a changed replay is refused with `409`. | | `POST /api/v1/utility/applications/batch` | `partner.write` | Create a manifest of drafts in one retry-safe call. `applicationNumber` is required on every row (unique within the batch) and is never generated; the other fields are optional. | | `PATCH /api/v1/utility/applications/{submissionId}/shape` | `partner.write` | Set a utility-owned draft's `capacityMw`, `interconnectionLevel`, and `declaredTierSlug` (`null` clears it). Drafts only; the program follows the utility's published shapes. A developer's packet is never edited by the utility. A `409 CONFLICT` means another request changed the application at the same moment; retry. | | `POST /api/v1/utility/applications/{submissionId}/freeze` | `partner.write` | Manually freeze an eligible utility-owned draft through the console's shared core; body `{}`. | | `POST /api/v1/utility/applications/{submissionId}/packages/{packageId}/adjudications` | `partner.write` | Record a version-checked human decision for the exact latest package, pinned run, and finding. | | `POST /api/v1/utility/applications/{submissionId}/screening/complete` | `partner.write` | Complete the exact current `packageId`; repeating a completed decision is idempotent, but older or wrong packages still refuse. | | `POST /api/v1/utility/applications/{submissionId}/study-requirement` | `partner.write` | Record study evidence for the next submission while the screened round remains open; never rewrite the frozen package. | The four manual decisions have SDK and confirmed CLI bindings but are excluded from hosted and local MCP, including direct invocation. Bodies are strict and bounded to 32 KiB. See the [utility lane guide](/docs-site/api/utility-lane) for body fields, receipts, and lifecycle rules. When supplied, `capacityMw` must be between `0.000001` and `99999999.999999` MW in whole-watt increments (at most six decimal places). Creation and shape changes reject values that would round or overflow storage with `400`. An application number already used by the organization returns `409`. Request bodies are strict: an unknown field anywhere in the body is refused with `400` and the message names the field, so a misspelled field is never silently dropped. Uploading documents into a utility-owned draft uses the same single-file intake endpoints as the applicant lane. Upload batches, ZIP intake and recovery are also available. Draft document deletion, library attachment and explicit per-document review are available through the document operations on this page; deletion remains excluded from MCP. To screen a utility-owned draft or a formally submitted developer application, call `POST /api/v1/packets/{submissionId}/review` with `{ "reviewAuthority": "utility" }`, or use the existing `start_packet_review` MCP tool, SDK `startPacketReview`, or CLI `packets review start`. Utility callers may omit `reviewAuthority`; the server selects utility authority. The same utility cohort, organization identity, application-stage and current write-membership checks apply to REST and MCP. Developer drafts, foreign applications and utility-issued consultant grants do not enter this lane. The shared review core permits genuinely missing required documents for utility screening, but requires every uploaded document's processing and role classification to be settled. Completion may freeze a utility-owned draft into an immutable package; it does not approve the application or send an applicant notice. The review body accepts only the documented `reviewAuthority` field; unknown fields return `400 INVALID_INPUT` before review starts. Applicant and consultant credentials cannot select utility authority. A new review job reserves the reviewing organization's budget atomically with enqueueing. An exact active-job retry reuses that job without another charge, including when the organization has reached its review cap; the request-rate limit still applies. `GET /api/v1/packets/{submissionId}/documents` reports `readyForReview` and `missingRequiredRoles` from the packet's published lane roster (not a fixed role list). When the roster cannot be determined, `readyForReview` is `false` with an empty `missingRequiredRoles` — the gate is closed, not satisfied. `POST …/review` returns the readiness reason verbatim when the packet's lane cannot be resolved (for example, a utility that publishes several programs needs the submitted application form to select one). A partner review start records a change-provenance record in the job's metadata: the acting user, the credential (`api_key:` or `oauth_client:`), the surface, and the request correlation id. A REST start is recorded as surface `rest`; the GridWonk CLI sends the `x-gridwonk-client-surface: cli` header (SDK option `clientSurface: 'cli'`) so its starts are recorded as `cli`; the hosted `start_packet_review` tool records `mcp`. The record is built from the server's own authentication and cannot be supplied in the request body. When a review's terminal edge settles the screening status or freezes a utility package automatically, whether from the job's own completion or from the recovery sweep, the resulting status-history rows carry that job's provenance plus the job id. ### Salesforce-owned packets: disabled connector The retained credentialed [Salesforce connector](/docs-site/integrations/salesforce) is implemented but disabled. Its four scoped REST/MCP/SDK operations and automatic service-owned package freezing are implemented; the existing utility review binding does not activate that workflow or close sandbox acceptance. Source-owned copies have additional safeguards. Ordinary intake, replacement, role correction, shape changes, and review starts cannot change or recapture their source evidence. A new review requires a complete connector capture of the approved field mapping and exact file versions; pending, failed, expired, or changed captures do not open the review gate. Packet, package, report, history, and document reads require the effective human user's current Salesforce record and field permissions, including when reading an older package. A service credential does not stand in for that viewer. Queue filtering applies the same permission decision to rows and totals before pagination; queries matching more than 200 source-owned applications must use narrower filters. A permission-service outage fails the read instead of returning an incomplete successful result. Historical reads now require current permission for all committed captures, including old-only fields and previous-package comparisons. Foreign selected runs, malformed snapshots, and more than 200 revisions fail closed. A revoked older field can also deny a current view. The current document list contains only the committed source revision's files. Historical packages retain their captured files and findings. Structured application-field evidence is separate from PDF evidence: reports identify the captured snapshot and field citations identify the source record, field, and capture time. These citations do not invent a PDF, page number, or document count. The separate outbound-only installed application does not use the partner credentials or linked-human remote checks above. Its Layer 1 foundation preserves the installation and Salesforce reviewer through the existing packet pipeline; both its API and processing authorizer remain hard-disabled. Ordinary packet/document/result readers and direct authenticated database reads deny installed content, even for staff. The retained connector's result delivery and recovery sweeps skip installed imports entirely, and CAD companion replays reauthorize installed imports through their own installation lane rather than a saved service credential. No new packet submission or results operation is enabled by merging that foundation. ### Native CAD companion intake These utility-neutral endpoints attach one private DWG companion to an existing current site-plan PDF version. They use the ordinary signed direct-upload transport and the same organization authorization and packet-locking core as packet intake. For partner packets, the applicant organization owns the packet and controls upload availability, not the selected utility; utility-specific review requires a reviewed CAD procedure profile. Finalization and background acceptance, rejection, or failure updates recheck that same owner before changing packet state. The target-free `awaiting_target` state belongs only to a session-authenticated console batch. The console first tries an exact normalized filename match to a current site plan and otherwise pairs only when the submission has one unambiguous current site plan. An ambiguous drawing remains private and asks an authorized user to select a site plan. None of those console semantics widens this partner contract. | Method + Path | Scope | Purpose | |---|---|---| | `POST /api/v1/packets/cad-intake` | `partner.write` | Reserve a DWG-only intake for an exact current site-plan version and return signed standard or resumable TUS upload authorization. | | `POST /api/v1/packets/cad-intake/{intakeId}/finalize` | `partner.write` | Prove and inspect the upload, then attach the accepted immutable source to the selected current site-plan version. | | `GET /api/v1/packets/cad-intake/{intakeId}` | `partner.read` | Return separate upload, inspection, attachment, rejection, and internal-failure states without private storage metadata. | | `POST /api/v1/packets/cad-intake/{intakeId}/reauthorize` | `partner.write` | Supersede an expired attempt and issue fresh upload authorization from byte zero. | | `POST /api/v1/packets/cad-intake/{intakeId}/cancel` | `partner.write` | Cancel an incomplete intake and schedule its provisional object for cleanup. | An idempotency key may be retried only for the same declared filename, byte count, and site-plan target. Reusing it for a different upload returns `409`. If accepted finalization cannot start its durable workflow, the route returns `503 workflow_start_failed` with `Retry-After: 5`; retry the same finalization. Processing attempt numbers and atomic claims fence duplicate workflow starts. Only `.dwg` is accepted, with a separate 30 MB ceiling. The first source binds to the existing site-plan version. Replacing it with different bytes creates a new logical version, preserves the sanitized PDF artifacts, and invalidates stale readiness and review identity. Submitted packages pin the exact companion asset and SHA-256 hash. Upload and attachment do not require Autodesk. Separately gated APS processing can create a browser-safe derivative and structured evidence after acceptance; native bytes are never exposed through MCP or loaded into the browser. Operational telemetry records only the intake stage, safe outcome, elapsed time, and whether a new logical version was created. It never records native bytes, signed upload authorization, storage paths, or source hashes. Packet reruns prefer exact current stored extractions and read changed or unmatched documents again. The partner route cannot request the internal forced-fresh synthetic QA mode; that control is limited to authorized platform administrators reviewing eligible editable demo packets in the console. ## Hosted MCP tools Connect to `POST https://gridwonk.com/api/v1/mcp` with the same scoped OAuth token. MCP means Model Context Protocol: a standard way for an AI client to discover and call named tools. Discovery and execution use one policy, so a tool hidden from `tools/list` is also refused by `tools/call`. | MCP tool | Scope | REST-equivalent capability | |---|---|---| | `create_packet_intake` | `partner.write` | Create intake | | `finalize_packet_intake` | `partner.write` | Finalize intake | | `get_packet_intake_status` | `partner.read` | Intake status | | `reserve_packet_intake_batch` | `partner.write` | Reserve an ordered upload manifest | | `get_packet_intake_batch` | `partner.read` | Read batch and item status | | `heartbeat_packet_intake_batch` | `partner.write` | Extend the idle deadline | | `pair_packet_intake_batch_item` | `partner.write` | Pair a DWG item to a site plan | | `cancel_packet_intake_batch_item` | `partner.write` | Cancel one unfinished item | | `abandon_packet_intake_batch` | `partner.write` | Abandon an unfinished batch | | `list_packet_documents` | `partner.read` | Document list (applicant lane, or the pinned utility organization) | | `attach_packet_document_from_library` | `partner.write` | Attach an owner-organization File Library asset; exact retries are reused | | `start_packet_document_review` | `partner.write` | Start or reuse review for one exact packet document; MCP does not expose failed-run retry | | `get_packet_document_text` | `partner.read` | Sanitized text and coordinates | | `start_packet_review` | `partner.write` | Start or reuse review | | `get_packet_review_run` | `partner.read` | Review-run detail | | `get_packet_workflow_status` | `partner.read` | Canonical workflow status | | `get_packet_screening_status` | `partner.read` | Utility package screening status | | `get_packet_document_rendition` | `partner.read` | Signed URL for the sanitized rendition | | `list_utility_applications` | `partner.read` | Utility Applications queue | | `create_utility_application` | `partner.write` | Create one utility-owned draft | | `create_utility_application_batch` | `partner.write` | Create a manifest of drafts | | `update_utility_application_shape` | `partner.write` | Set a draft's capacity, level, and program | | `get_utility_application` | `partner.read` | One application with package-bound detail | | `list_utility_application_packages` | `partner.read` | Submitted packages of an application | | `list_utility_package_findings` | `partner.read` | Pinned review, ledger, and screening decision | | `get_utility_application_history` | `partner.read` | Application history | The Confirm/Correct role operation is deliberately not model-facing. Use the console, REST API, SDK, or CLI when a human must confirm or correct a role. ## What is never exposed Raw original files, signed storage references, service-only descriptors, provider errors, and internal identifiers never cross this surface. There is no request-selectable resolver context: version, package, and organization context are proved server-side on every call. ## Feature availability There is no packet-specific rollout flag on this surface. Each operation obeys the same authoritative server-side cohorts as the console (for example, Storage-native intake creation and the utility screening read are enabled per organization — the env dial merged with per-organization feature states, which platform admins manage from the organization's admin Features tab); outside a cohort the endpoint behaves as `404`. Native-CAD intake is available to every applicant organization by default. The server-only `NATIVE_CAD_INTAKE_COHORT` setting is an operational kill switch or temporary narrowing control, not an NES-only entitlement. A utility procedure profile controls which deterministic review rules may use accepted evidence; no profile means upload, visualization, and evidence summaries can still work while utility-specific automated CAD findings stay unavailable. The classifier's owner-approved automatic policy is a separate internal rollout under the server-only `CLASSIFIER_AUTO_APPLY` role/organization cohort. Positive v1 results in that cohort can become authoritative and start review without a partner call. The partner API cannot change the cohort; its role endpoint always records a human Confirm or Correct decision. Historical v1 suggestions remain valid without a score, while the optional confidence-v2 contract remains a separate internal identity. The optional Combined-PDF split is a session-authenticated console capability, on by default per applicant organization (the server-only `COMBINED_SPLIT` dial and per-org feature states can narrow or disable it). It is not a new endpoint on this partner REST surface. After a person confirms a split in the console, the derived children appear through the ordinary document and review endpoints; the immutable source container does not count as a reviewable packet document. The packet status endpoint's `documentCount` excludes the retained source, and assigning a content role to it through the role endpoint returns a clear conflict message ("assign roles on its derived documents instead") rather than a database error. The optional ZIP container intake is available through the archive protocol above. An expired idempotent upload retry must reacquire an organization slot under the same database lock as a new upload; it is refused when all three slots are live and does not charge the rolling file/byte quota twice. ## SDK and CLI Every endpoint has a first-class binding in `@gridwonk/sdk` (`createPacketIntake`, `finalizePacketIntake`, `getPacketIntakeStatus`, `reservePacketIntakeBatch`, `getPacketIntakeBatch`, `heartbeatPacketIntakeBatch`, `pairPacketIntakeBatchItem`, `cancelPacketIntakeBatchItem`, `abandonPacketIntakeBatch`, `createPacketArchiveIntake`, `getPacketArchiveIntake`, `finalizePacketArchiveIntake`, `abandonPacketArchiveIntake`, `cancelPacketIntake`, `reauthorizePacketIntake`, `retryPacketIntakeProcessing`, `attachPacketDocumentFromLibrary`, `deletePacketDocument`, `startPacketDocumentReview`, `listPacketDocuments`, `getPacketDocumentText`, `setPacketDocumentRole`, `startPacketReview`, `getPacketReviewRun`, `getPacketWorkflowStatus`, `getPacketScreeningStatus`, `getPacketDocumentRenditionUrl`, and for utility organizations `listUtilityApplications`, `getUtilityApplication`, `listUtilityApplicationPackages`, `listUtilityPackageFindings`, `getUtilityApplicationHistory`, `createUtilityApplication`, `createUtilityApplicationBatch`, `updateUtilityApplicationShape` — mint a scoped token with `getOAuthToken(expiresIn, scope)`) and the `gridwonk packets …` CLI group (`intake create/finalize/status/cancel/reauthorize/retry-processing`, `archive-intake create/status/finalize/abandon`, `intake-batches reserve/status/heartbeat/pair/cancel-item/abandon`, `documents list/attach/delete/review/text/pdf/set-role`, `review start/get`, `status`, `screening`) plus `gridwonk utility applications list/get/packages/findings/history/create/batch-create/shape`. The SDK methods hang off `GridWonkClient` (exported as `GridBoostClient` too, a deprecated alias of the same class). Both client surfaces default to the canonical `https://gridwonk.com` API origin. Legacy production hosts remain accepted for compatibility and are normalized to the canonical origin before authenticated packet requests are sent. ## Relationship to the legacy document endpoints The generic `classify` and `digitize` document endpoints are **deprecated compatibility adapters** for pre-packet integrations. Packet workflows use this lane instead: classification arrives as a pinned model result followed by an automatic or human authoritative role decision, and digitization/sanitization/OCR run inside Storage-native intake. The adapters remain unchanged until the scheduled legacy retirement. The separate legacy `GET /api/v1/requirements` read permanently returns typed `410 Gone` with the published replacement. Its SDK, CLI, and public MCP wrappers have also been removed. That does not affect any endpoint on this page. Packet review uses the separate effective-analysis requirement tier, so the state of a utility's requirement review does not gate an authorized packet review (the review's reject decisions and edits apply where analysis enforcement is activated). See [Requirements API — Retirement Stages](/docs-site/api/requirements#retirement-stages). ## Corrected submissions and intake reservation clocks Corrected applicant resubmission returns to **Pending** after its immutable package commits. The receiving utility starts the shared whole-packet review through the existing review endpoint or queue action. The core selects `utility_rescreen` after an earlier utility round; the applicant action does not invoke the legacy per-document screening lane. Partner scopes, request schemas, budget reservations and provenance checks remain those documented above. Intake batch creation records its creation, last-activity and expiry timestamps from the same application-clock instant. The configured idle and maximum lifetime windows remain unchanged, avoiding disagreement between database and application clocks at reservation. ## Interpreting review completeness A review-run response retains the existing verdict enum. `incomplete` means declared checks remain unresolved or coverage was not recorded; it does not convert missing evidence into a technical failure. Deficiency severity and blocking counts remain independently visible. `scope-inapplicable` requires an affirmative applicability decision and does not keep the review incomplete. `report.coverage.checksIncomplete` is optional and lists a `check`, a `reason` (`context-missing` or `not-built`) and a reviewer-facing `note` when the check ran on some evidence but could not finish its declared scope. The same check remains in `checksPerformed`; valid findings are retained. `checksNotPerformed` explains checks that did not run. When available, its optional `note` identifies the missing prerequisite and a next action. Older records may have only a reason code. Missing coverage on older reports means unknown, not all checks passed. No review result is utility approval. When `report.coverage.results` is present, it has one row per declared check. The stable machine values mean: | Machine outcome | Meaning | |---|---| | `deficiency` | Deficiency identified: required information is missing or a technical problem is demonstrated. Inspect the cited finding to distinguish them. | | `could-not-verify` | Unable to verify: the check was attempted but could not conclude, including partially evaluated evidence. A partial check may carry a reason and note without inventing a finding. | | `not-applicable` | Not applicable: evidence establishes that the rule does not apply. | | `not-performed` | Not evaluated: the check did not run; its reason explains why. | | `no-deficiency-found` | No deficiency identified in this completed check. This is not utility approval. | Partial checks retain any valid `findingIds` alongside their unfinished reason and note. Reports without `results` have no per-check record; their absence does not mean every check passed. This API contract does not assert delivery of the separately planned full Checks table. --- # Projects API List, read, create, and update developer projects. URL: /docs-site/api/projects `capacityMw` remains MW on the API. The approval-gated precision migration widens storage to six decimal places, preserving 11.4 kW as `0.0114` MW. Extraction reads the utility's registered field mapping and keeps AC and DC capacity separate; existing values are not silently corrected. # Projects API The Projects API manages the same developer project records shown in the GridWonk console. Every read and write is limited to the developer organization that owns the API key. Utility and platform organizations cannot use these customer endpoints. Authentication uses the authority of the organization API key or its short-lived legacy-audience JWT. Fine-grained `projects:*` OAuth grants are not advertised or enforced yet. Use [packet intake](/docs-site/api/packets) to add documents after creating a project. Submission and resubmission remain console workflows while their full package-integrity transaction is extracted for headless use; the API does not bypass that safety boundary. You can create a private project by default and review its packet for a utility with a released, complete packet setup, even if that utility has not joined the platform. Creating or reviewing a project does not send the packet to the utility. Formal submission is available only after GridWonk and the utility have accepted submissions for the selected state and program and an active utility reviewer is available. Private Review remains available after that activation; there is no automatic submission. Explicit Submit shares the frozen documents and the one packet report pinned to the package, not other unpinned private reviews or private document-review history. Project creation does not require a receiving utility organization or an environment flag. Project create JSON bodies use the general 1 MiB API cap. Project `PATCH` bodies use a stricter 16 KiB cap because updates contain only a few fields. A malformed or oversized update is rejected before any project lookup or write occurs. ## List projects `GET /api/v1/projects` Optional query parameters: `utilityName`, `state`, `limit` (1–100), and `offset`. ```bash curl "https://gridwonk.com/api/v1/projects?state=TN&limit=20" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ## Get a project `GET /api/v1/projects/{projectId}` An unknown project, a project in another organization, and an archived synthetic demo project all return `404`. ## Create a project `POST /api/v1/projects` ```json { "utilityName": "nashville-electric-service", "projectName": "River Solar", "capacityMw": 12.5, "state": "TN", "interconnectionLevel": "distribution" } ``` Creation requires the exact canonical utility record and an available packet-review lane for the requested state and connection type. It does not require a receiving utility organization. A missing utility returns `404`; demo project markers and synthetic applicant organizations return `403`. Missing state or an unavailable review lane returns `400 INVALID_INPUT`. Creation stores the utility's canonical EIA identifier so readiness and automatic-review workflows use the same utility identity as the console. Formal submission separately checks the receiving utility's acceptance and reviewer setup. ### Program declaration `capacityMw` remains megawatts on the API; no API unit selector is introduced. Console input may use kW and converts before calling the server. Database precision is six decimal places after the approved precision migration, preserving 11.4 kW as `0.0114` MW. AC and DC application ratings remain distinct; a mismatch is surfaced rather than silently overwriting the stored project capacity. Some utilities publish more than one interconnection program for the same track — for example Maryland Level 2, Level 3, and Level 4 for distribution. The console's project dialog asks for the program in that case, and the API enforces the same rule through the optional `declaredTierSlug` field: - The utility publishes **two or more** programs for `interconnectionLevel`: `declaredTierSlug` is required and must be the slug of one of them. - The utility publishes **zero or one** program: `declaredTierSlug` must be omitted. A missing, unpublished, or unexpected `declaredTierSlug` returns `400 INVALID_INPUT`. The message lists the valid programs as `slug (label)`, and `error.details.programs` carries the same list as `{ slug, label }` objects, so a client can discover the programs from the refusal and retry. There is no separate list-programs endpoint yet; this payload is the discovery mechanism. ```json { "error": { "code": "INVALID_INPUT", "message": "This utility publishes 3 interconnection programs for the distribution track; declaredTierSlug is required. Valid programs: maryland-level-2 (Maryland Level 2), maryland-level-3 (Maryland Level 3), maryland-level-4 (Maryland Level 4).", "details": { "programs": [ { "slug": "maryland-level-2", "label": "Maryland Level 2" }, { "slug": "maryland-level-3", "label": "Maryland Level 3" }, { "slug": "maryland-level-4", "label": "Maryland Level 4" } ] } }, "requestId": "req_a1b2c3d4e5f6g7h8" } ``` Resend with the chosen program: ```json { "utilityName": "delmarva-power", "projectName": "Asilomar II", "capacityMw": 0.25, "state": "MD", "interconnectionLevel": "distribution", "declaredTierSlug": "maryland-level-2" } ``` The accepted program is stored on the project, returned as `declaredTierSlug` on every project read (`null` for an undeclared project), and selects the rulebook the review runs against. A stored declaration that cannot be read returns `409` rather than reporting the project as undeclared. It cannot be changed through `PATCH`. If the utility's published programs cannot be read, or the publication is misconfigured, the API returns `503 SERVICE_UNAVAILABLE` and creates nothing — a project is never created without the declaration its utility requires. `error.reason` says which case it is: `program_lookup_failed` is transient and carries `retryAfter` plus a `Retry-After` header; `program_publication_invalid` means the utility's publication needs correction and retrying will not help. The SDK exposes both as `reason` and `retryAfter` on the thrown error, and the CLI includes them in `--json` output. ## Update a project `PATCH /api/v1/projects/{projectId}` You may change `projectName`, `capacityMw`, `state`, or `interconnectionLevel` while the project is an editable draft. After authorization, a project that is no longer an editable draft returns `409` before checking the proposed field changes. The utility and the declared program cannot be changed, and a track change has to leave the project in a state creation would have accepted: moving a project that declared a program to another track returns `409 INVALID_STATE`, and moving an undeclared project onto a track where the utility publishes two or more programs returns `400 INVALID_INPUT` with the valid programs in `error.details.programs` — create a new project with `declaredTierSlug` instead. A state or track change must also land on a released packet-review lane within the utility's service states, as creation requires; otherwise it returns `400 INVALID_INPUT`. A draft created before `state` was required can still change only its track under the original program rule; add `state` before submitting. The update and stage check happen in one database statement, so a concurrent submission cannot be overwritten by a stale edit. ## SDK and CLI ```typescript const created = await client.createProject({ utilityName: 'nashville-electric-service', projectName: 'River Solar', capacityMw: 12.5, state: 'TN', interconnectionLevel: 'distribution', // declaredTierSlug: 'maryland-level-2', // only when the utility publishes 2+ programs }); ``` When the API refuses an undeclared or mismatched program, the SDK throws a `ValidationError` whose `details` is a `ProjectProgramDeclarationDetails` — `programs` lists the valid `{ slug, label }` options. Every SDK error also exposes `reason` and `retryAfter`, so a `503` can be told apart as `program_lookup_failed` (wait `retryAfter` seconds, then retry) or `program_publication_invalid` (do not retry) without parsing the message. ```bash gridwonk projects list --state TN --json gridwonk projects create \ --utility nashville-electric-service \ --name "River Solar" \ --capacity-mw 12.5 \ --state TN \ --interconnection-level distribution \ --yes # Multi-program utilities: add --declared-tier-slug . A refusal lists the # valid slugs, and --json output includes them under error.details.programs. ``` --- # API Quickstart End-to-end walkthrough from API key setup through utility matching, document processing, and job monitoring. URL: /docs-site/api/quickstart # API Quickstart This guide walks through a complete integration — from your first API call to receiving webhook notifications. The current `@gridwonk/sdk` and `@gridwonk/cli` clients default to the canonical `https://gridwonk.com` API origin, so authenticated requests do not need a base URL override. For utility application screening and package-bound human decisions, follow the [utility lane guide](/docs-site/api/utility-lane). Those operations require the utility's own partner-scoped token; the management key used below is not a substitute for it. That guide also covers package-bound notices. The SDK implements `listUtilityNotices` and `getUtilityNotice` for reads, plus separate create, update, named-transition, and send methods. Notice writes require current direct utility writer membership and `partner.write`; MCP exposes only reads. A successful send request is not proof of `sent` status or inbox delivery. These source bindings do not establish package publication, schema activation, or production release. ## Prerequisites - A GridWonk organization account - A management API key (format: `gw_live_...` or `gw_test_...`). - An HTTPS endpoint for webhooks (optional) Document bytes never travel as JSON: packet intake issues a signed upload target and validates the stored object (files up to 30 MB; accepted formats and cohort-gated lanes are listed on the [Partner Packets](/docs-site/api/packets) page) before it is accepted. The former base64 upload route (3 MiB) was retired on 2026-09-30 and returns 404. ## Step 0: Bootstrap Your First Management Key (Invite-Only) For invite-only onboarding, bootstrap with a user session token: ```bash curl https://gridwonk.com/api/v1/auth/bootstrap/status \ -H "Authorization: Bearer $GRIDBOOST_SESSION_TOKEN" ``` If eligible (`nextStep: "create_bootstrap_key"`), create the first management key. A `not_allowlisted` status with `nextStep: "contact_support"` means the organization's API access or billing is suspended; no key can be minted until support restores access. ```bash curl -X POST https://gridwonk.com/api/v1/auth/bootstrap-key \ -H "Authorization: Bearer $GRIDBOOST_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{"organizationId":"","name":"Initial Management Key"}' ``` Use the returned key as `GRIDBOOST_API_KEY` for the remaining steps. ## Step 1: Match a Utility Find the canonical utility record for a given name: ```bash 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 Carolinas", "state": "NC"}' ``` Response: ```json { "match": { "eiaId": 5416, "name": "Duke Energy Carolinas", "confidence": 0.95 }, "utility": { "eiaId": 5416, "name": "Duke Energy Carolinas", "ownershipType": "Investor-Owned", "states": ["NC", "SC"], "rtoIso": "SERC" }, "fromCache": false } ``` ## Step 2: Upload Through Packet Intake Uploading a document to a packet is a three-call flow on the partner packet API, documented on the [Partner Packets](/docs-site/api/packets) page: create an intake for the packet (`POST /api/v1/packets/intake`), upload the file to the signed target the response selects (a signed upload for files up to 6 MB, resumable TUS above that), then finalize it (`POST /api/v1/packets/intake/{intakeId}/finalize`). Finalizing proves the uploaded object and starts the durable processing pipeline; `GET /api/v1/packets/intake/{intakeId}` reports acceptance, sanitization, text-recognition and searchable-PDF status. These calls need a partner-scoped token; a management key alone does not upload documents. `POST /api/v1/documents/digitize` is the synchronous manual digitization endpoint for a document that already exists and is eligible for the legacy unmetered path. Trial and prepaid customer workspaces cannot use generic or legacy digitization to bypass supported packet processing. Do not call it after a normal intake; follow the intake status and supported recovery controls. ### Asynchronous lifecycle ## Step 3: Monitor Job Progress ### Option A: Poll ```bash curl https://gridwonk.com/api/v1/jobs/a1b2c3d4-... \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ### Option B: Stream (SSE) ```bash curl -N https://gridwonk.com/api/v1/jobs/a1b2c3d4-.../stream \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` Illustrative SSE events arrive as the job progresses: ```text event: job.update data: {"id":"a1b2c3d4-...","status":"analyzing","progress":60,"step":"Digitizing document"} event: job.complete data: {"id":"a1b2c3d4-...","status":"complete","result":{...}} ``` The stream auto-closes after 55 seconds. Reconnect to continue watching. The former single-document validation endpoint is retired and returns authenticated HTTP `410 Gone`. Use packet intake Review instead. ## Step 4: Query Results Query customer-released requirements for the utility: ```bash curl "https://gridwonk.com/api/v1/published-requirements?utility=nashville-electric-service&state=TN" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` Coverage is everything published except utility-rejected rows, with honest gaps. Rows still awaiting a current utility decision come back marked `reviewStatus: "pending"` rather than being withheld — rows awaiting reviewed wording are separately withheld and counted in `filteredOutCount`. Read `message` and `summary` rather than inferring "no requirements" from an empty array. See [Requirements API](/docs-site/api/requirements). The older `GET /api/v1/requirements` read is a permanent tombstone. Authenticated calls return typed `410 Gone` / `ENDPOINT_GONE` with `/api/v1/published-requirements` as the replacement. Or query deficiency findings: ```bash curl "https://gridwonk.com/api/v1/deficiency-reports?utility=duke-energy&severity=critical&findingState=open" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ## Step 5: Set Up Persistent Webhooks For ongoing event notifications, create a webhook subscription: ```bash curl -X POST https://gridwonk.com/api/v1/webhooks \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-server.com/hooks/gridwonk", "events": ["job.completed", "job.failed", "document.digitized"] }' ``` Save the `secret` from the response — you'll need it to verify webhook signatures. See the [Webhook Integration Guide](/docs-site/integrations/webhooks) for full details. ## Step 6: Check Usage Monitor your API consumption: ```bash curl "https://gridwonk.com/api/v1/usage?days=7" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ## Next Steps - [Authentication & Rate Limiting](/docs-site/api/authentication) — key management, rate limits, security - [External API endpoint index](/docs-site/api/external) — full endpoint reference - [Webhook Integration Guide](/docs-site/integrations/webhooks) — event types, payloads, verification - [MCP API](/docs-site/api/mcp) — JSON-RPC tool access for AI agents ## Salesforce SDK scope `GridWonkClient` now implements `searchSalesforceApplications`, `getSalesforcePacketManifest`, `importSalesforcePacket`, and `getSalesforceImport` for an approved connector. The connector is still default-disabled and the updated SDK has not been published. Use the required scoped credential; `acknowledge: true` and a stable `idempotencyKey` are mandatory for import. The client does not automatically retry that POST. See [Salesforce setup](/docs-site/integrations/salesforce). --- # Remediation API Working-copy editing and remediation export bundle endpoints for hybrid deficiency anchoring. URL: /docs-site/api/remediation # Remediation API These endpoints are additive to existing API v1 contracts and are designed to mirror the same remediation workflow available in the console UI and CLI. ## Get Working Draft `GET /api/v1/documents/{documentId}/working-draft` Returns editable working-copy spans derived from digitized content. ### Response ```json { "documentId": "uuid", "fileName": "sample-lease.pdf", "utility": "duke-energy", "state": "NC", "spans": [ { "id": "uuid", "spanId": "span_4_12_abc123", "pageNumber": 4, "lineNumber": 12, "charStart": 1421, "charEnd": 1472, "originalText": "Lease shall remain in effect for twenty years", "currentText": "Lease shall remain in effect for twenty-five years", "normalizedText": "lease shall remain in effect for twenty five years", "lineHint": null, "isEdited": true, "editedAt": "2026-03-05T16:20:00.000Z" } ], "stats": { "total": 530, "edited": 4 } } ``` ## Patch Working Draft Span `PATCH /api/v1/documents/{documentId}/working-draft/spans/{spanId}` Updates a single working span and records remediation audit metadata. `spanId` accepts either: - the span row UUID (`spans[].id`), or - the stable span token (`spans[].spanId`, e.g. `span_4_12_abc123`) ### Body ```json { "text": "Lease shall remain in effect for twenty-five years", "deficiencyId": "optional-deficiency-uuid" } ``` ## Create Remediation Export Bundle `POST /api/v1/remediation/exports` Creates clean/redline/evidence artifacts and returns a poll handle. ### Body ```json { "documentId": "uuid", "format": "bundle", "sessionId": "optional-session-uuid" } ``` `sessionId` is optional and links the export to an application or validation session when available. At creation time, the export manifest records the source document ID, content hash, and version number. Those values are immutable for that export. ### Response ```json { "exportId": "uuid", "status": "processing", "pollUrl": "/api/v1/remediation/exports/uuid", "export": { "id": "uuid", "documentId": "uuid", "format": "bundle", "status": "processing", "cleanDocumentUrl": null, "redlineDocumentUrl": null, "evidencePacketUrl": null } } ``` ## Get Remediation Export `GET /api/v1/remediation/exports/{exportId}` Fetches status and generated artifact links. Possible `status` values: - `pending` - `processing` - `complete` - `failed` When complete, the payload includes: - `cleanDocumentUrl` - `redlineDocumentUrl` - `evidencePacketUrl` Completion and promotion use the stored source identity, not the document's later current identity. If the project link or source generation has changed, the operation returns the canonical stale-export failure and commits no artifact attachment, promoted document, link change, version, or manifest change. Exporting a working copy does not grant permission to replace source-owned packet evidence. Promotion refuses a Salesforce-owned packet before rendering and checks again under the packet lock before writing. Correct the record or files in Salesforce; the separate [connector capture workflow remains planned and disabled](/docs-site/integrations/salesforce). The remediation routes are always on: the environment feature gates that once returned `FEATURE_DISABLED` were removed on 2026-08-26 after being hardcoded enabled, so generated clients no longer need to handle that code on these routes. The routes are included in the complete authenticated partner OpenAPI document so generated clients match the live REST surface. That document is built by `lib/api/v1/full-openapi.ts` and shared by both authenticated copies. The remediation routes are intentionally absent from the curated agent specification, which lists only active partner packet operations whose REST and hosted-MCP bindings are both `available`. The shared OpenAPI document now also includes native-DWG intake routes under `/api/v1/packets`. Those routes do not alter remediation drafts or exports; CAD intake is documented in [Partner Packets](/docs-site/api/packets). ## Related Endpoints - `GET /api/v1/deficiency-reports` returns normalized `workingAnchor` and `sourceAnchor`, plus `findingState` (`open`, `resolved`, or `superseded`). Use `findingState=open` for findings that still need review resolution. - `locationStatus` filters anchor quality (`exact`, `approximate`, `unresolved`, or `pending`). `remediationStatus` filters the applicant's fix progress; setting it to `resolved` does not close a finding. Only a review closes a finding. - The legacy `status` alias accepts all three families. `open`, `resolved`, and `superseded` select finding state; use the explicit `remediationStatus` parameter to filter fix progress by `open` or `resolved`. ## CLI Equivalents The same operations are available in the CLI: - `gridwonk remediation draft get --document-id ` - `gridwonk remediation draft patch --document-id --span-id --text ""` - `gridwonk remediation export create --document-id --format bundle` - `gridwonk remediation export get --export-id ` --- # Requirements API Query published utility requirements and migrate from the retired legacy read. URL: /docs-site/api/requirements # Requirements API There are two requirement endpoints. Use the published one. | Endpoint | Status | Reads | |---|---|---| | `GET /api/v1/published-requirements` | **Current** | The published requirement tier, minus utility-rejected rows | | `GET /api/v1/requirements` | **Retired — returns 410** | No corpus read; use the published endpoint | ## Query Published Requirements `GET /api/v1/published-requirements` Returns the published packet requirements for one utility — every published row **except** the ones a utility reviewer has explicitly rejected. This is the replacement for the legacy requirements read. Each returned row carries a `reviewStatus` of `approved` (utility reviewers signed off) or `pending` (awaiting a current utility decision), so you can tell the two apart without guessing. This matches what a packet deficiency report can cite: reports draw from the same all-except-rejected set, so the requirements list shows what a report may raise. Pending rows are labelled honestly rather than hidden. ### Coverage Policy Everything published except rejected rows, with honest gaps. This surface never substitutes something adjacent for the thing you asked for: - **Utility resolution is exact.** The server matches on the utility name, then on its canonical slug (`"Nashville Electric Service"` → `nashville-electric-service`). There is no fuzzy match and no nearest-neighbour guess. - **An unknown utility returns an empty result**, not legacy rows and not a similar utility's rows. - **An uncovered category returns an empty result.** `category=fees` always returns an empty set — the published store has no fee role, and unrelated checks are never relabelled as fee requirements. - **Rejected rows are omitted server-side.** A row a utility reviewer rejected never appears in any response, in any count, on any surface. - **Everything else is served, with its review status attached.** An incomplete utility review no longer empties the response. Rows still awaiting a decision return with `reviewStatus: "pending"`; rows the utility signed off on return with `reviewStatus: "approved"`. - **A stale decision counts as pending re-review.** When decision-relevant content changes after a verdict, the row reverts to `reviewStatus: "pending"` until a reviewer records a current decision. It is never silently dropped or hidden. - **Rows whose published wording is still under review are withheld and counted.** They appear in `total` and in `filteredOutCount`, never in `requirements`. This is a separate mechanism from `reviewStatus`. Read `message` and `summary` before treating an empty page as "this utility has no requirements": they distinguish *nothing is technically published*, *nothing in scope survived rejection*, and *published wording is still in review*. ### Query Params - `utility` (required): utility name or canonical slug - `state` (optional, exactly 2 characters): echoed in the response for context. No published rule is state-conditional any more (the state condition was retired on 2026-11-04), so it does not narrow the result. `region` is accepted as a compatibility alias for callers migrating off the legacy endpoint. - `category` (optional): - `site_control` - `technical_specs` - `forms` - `fees` (always empty — see coverage policy) - `ixType` (optional): `T` for transmission or `D` for distribution - `limit` (optional): 1-200, defaults to 50 - `offset` (optional): defaults to 0 ### Example Request ```bash curl "https://gridwonk.com/api/v1/published-requirements?utility=nashville-electric-service&state=TN&category=forms" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ### Review-Incomplete Response This is the durable response shape when the requested role has published rows whose utility review is still in progress. The rows are served — `releaseStatus` reports review progress, not whether anything came back. Counts depend on that utility's current review state. ```json { "utility": "nashville-electric-service", "state": "TN", "category": "forms", "count": 13, "total": 13, "source": "dynamic_extraction", "releaseStatus": "review_incomplete", "message": "13 published packet requirements for nashville-electric-service in this scope; 13 are awaiting a current utility review decision.", "summary": "13 published requirements; 13 awaiting utility review.", "filteredOutCount": 0, "dedupedCount": 0, "requirements": [ { "id": "application-form:0:total_cost_missing", "requirementText": "Application Form — Distribution: Total system cost provided.", "validationStatus": "published", "extractedAt": "", "acceptedDocumentTypes": [], "timingRequirements": [], "citations": ["Total System Cost (Required)"], "reviewStatus": "pending", "sources": [ { "title": "Utility application instructions", "documentType": "procedure", "pageRef": "2" } ] } ], "sources": [], "limit": 50, "offset": 0 } ``` As utility reviewers work through the scope, those rows flip to `"reviewStatus": "approved"` and `releaseStatus` advances toward `released`. Rows the utility rejects disappear from `requirements` entirely. Pending wording is withheld separately and counted in `filteredOutCount`, as described above. ### Response Fields | Field | Type | Description | |-------|------|-------------| | `utility` | `string` | The utility name as provided in the query. | | `state` | `string \| null` | The two-character state code echoed from the query, or `null`. It no longer narrows rows. | | `category` | `string \| null` | Requirement category filter applied, or `null` if not filtered. | | `count` | `number` | Number of requirements returned on this page. | | `total` | `number` | Every served rule in scope, including rows beyond this page and rows withheld for pending wording. Rows awaiting a utility decision are included; only utility-rejected rows are excluded. | | `source` | `string` | `"dynamic_extraction"` for a live read of the published store. | | `releaseStatus` | `string` | Typed **utility-review progress**: `released`, `partially_released`, `review_incomplete`, or `not_published`. It is not a serving gate — `review_incomplete` still returns rows. Use it to describe review state, and per-row `reviewStatus` to judge an individual rule. | | `message` | `string` | Human-readable outcome — what was served, how much is awaiting a utility decision, wording still in review, or no technical publication. | | `summary` | `string` | One-line count and review-progress summary suitable for display. | | `filteredOutCount` | `number` | Served rows withheld because their published wording is still under review. Separate from `reviewStatus`, which marks rows that *are* served. | | `dedupedCount` | `number` | Always `0` today; the published reader performs no duplicate collapse. Present for contract compatibility. | | `requirements` | `array` | Requirement objects for this page (see below). | | `sources` | `array` | Deduplicated source list covering the returned page only. | | `limit` | `number` | Page size used for this response. | | `offset` | `number` | Offset used for this response. | ### Requirement Object Fields | Field | Type | Description | |-------|------|-------------| | `id` | `string` | Identifier of the rule within the current published set (`role:index:findingId`). Not guaranteed stable across republishes — do not key long-lived state on it. | | `requirementText` | `string` | Reviewed customer-facing wording, prefixed by its group heading (`" — : "`). | | `validationStatus` | `string` | Always `"published"` for wire compatibility. Read `reviewStatus` for the utility-review state of the row. | | `extractedAt` | `string` | Always `""`. This surface does not expose an extraction timestamp; read `reviewStatus` for utility approval. | | `acceptedDocumentTypes` | `string[]` | Always empty on this surface. | | `timingRequirements` | `string[]` | Always empty on this surface. | | `depositInLieuAllowed` | `boolean` | Optional; present only when the published rule records it. | | `citations` | `string[]` | Quoted citation text supporting the rule. | | `reviewStatus` | `string` | `"approved"` — utility reviewers signed off on this row; or `"pending"` — awaiting a current utility decision, including a decision made stale by a later change. Rejected rows are never returned, so there is no third value. Absent on the deprecated legacy read. | | `sources` | `array` | Source documents for this rule: `title`, `documentType: "procedure"`, and optional `url` / `pageRef`. | ### Rate Limits Standard API-key per-minute and daily limits apply, plus the daily unique-utility cap shared with utility matching. Exceeding the cap returns `RATE_LIMITED`; you can still re-query utilities you have already accessed that day. Unlike the legacy endpoint, this read emits **no webhook event** — a read is not an extraction. ### Other Bindings | Surface | Binding | |---------|---------| | SDK | `client.queryPublishedRequirements(options)` — strict `QueryPublishedRequirementsResult` type | | CLI | `gridwonk requirements published --utility ` | | MCP | `query_published_requirements` tool, and the `gridwonk://utilities/{utility}/requirements` resource | The SDK and CLI default to the canonical `https://gridwonk.com` API origin; use a base URL override only for an approved alternate environment. The SDK method calls this endpoint directly. The CLI wraps that SDK method and deliberately does **not** pre-resolve the utility name — resolution stays exact and server-side, so an unknown utility comes back as an honest empty answer rather than a guessed neighbour. The MCP tool takes the same arguments and, in stateful sessions, inherits `utility` and `state` from the active work item when they are omitted. See [MCP API](/docs-site/api/mcp). --- ## Query Requirements (legacy — retired) `GET /api/v1/requirements` > **Retired.** Production no longer reads the frozen legacy `ix_requirements` corpus through this > route. Use > [`GET /api/v1/published-requirements`](#query-published-requirements) instead. > > Authenticated calls now return typed `410 Gone` / `ENDPOINT_GONE` with the replacement path. ### Deprecation Signals (historical notice) Before retirement, handler-produced responses carried these migration signals. The current `410` keeps the two headers and the replacement body field: | Signal | Value | |---|---| | `Deprecation` header | `true` | | `Link` header | `; rel="successor-version"` | | `replacement` body field | `"/api/v1/published-requirements"` | The `replacement` field mirrors the headers for clients that only parse bodies. Authentication and per-minute rate-limit rejections can still occur in the API-key wrapper before the retired handler, so those wrapper responses do not carry the retirement headers. The RFC 8594 `Sunset` value was announced as `2026-08-11T19:00:00Z` and remains on the handler's `410` response. ### Retirement Stages | Stage | State today | What changes | |---|---|---| | 1. Deprecation signals | **Complete** | `Deprecation: true`, `Link rel="successor-version"`, and the `replacement` body field announced the replacement before retirement. | | 2. Sunset announcement | **Complete** | The retirement instant was `2026-08-11T19:00:00Z`. | | 3. `410 Gone` | **Live since 2026-08-11** | The endpoint no longer reads the legacy corpus and returns typed `410`. | The retirement stages are complete. The response is now: ```json { "error": { "code": "ENDPOINT_GONE", "message": "This endpoint has been retired. Use GET /api/v1/published-requirements for published Packet Intake requirements." }, "replacement": "/api/v1/published-requirements", "requestId": "req_xxx" } ``` The legacy corpus is never read on this route and the `requirements.extracted` webhook event stops firing for this endpoint. See [`ENDPOINT_GONE`](/docs-site/api/errors#endpoint_gone) for the error contract and a handling snippet. Migration notes: - `region` becomes `state` on the replacement (the replacement also accepts `region` as an alias). - `limit` rises from a maximum of 50 to a maximum of 200. - The replacement emits no `requirements.extracted` webhook event. - The response shape changes: see [Response Fields](#response-fields) above. ### Historical Current Procedure Enforcement This section records how the legacy endpoint behaved before retirement. No current route can restore this behavior. The published endpoint has no shadow/enforcement mode: it serves the Packet Intake store and exposes each row's utility-review state as `approved` or `pending`. The `ENFORCE_CURRENT_PROCEDURE_REQUIREMENTS` flag controls whether legacy customer-facing reads filter to only current usable requirements: | Mode | Behavior | |------|----------| | Shadow mode (`false`) | Returns the existing displayable extracted corpus so rollout does not hide utilities before review cleanup is complete. The `message` field may include shadow diagnostics, such as how many returned matches would remain customer-usable after enforcement. | | Enforcement mode (`true`) | Returns only requirements that pass the current-procedure usability check: `extractionOutcome: "requirements_found"`, `validationStatus: "validated"`, linked `documentId`, linked procedure document with approved/manual-override discovery and completed digitization, and matching source hash when both hashes exist. | Deprecated, rejected, pending-review, missing-source, and source-hash-mismatched requirements can still appear in admin review or migration tooling, but they are not customer-usable API results when enforcement is on. ### Historical Query Params These parameters describe the removed success handler. The permanent 410 tombstone does not parse them. - `utility` (required) - `region` (optional, 2-char) - `category` (optional): - `site_control` - `technical_specs` - `forms` - `fees` - `ixType` (optional): `T` for transmission or `D` for distribution - `limit` (optional): 1-50, defaults to 50 - `offset` (optional): defaults to 0 ### Example Request (retired path) ```bash curl "https://gridwonk.com/api/v1/requirements?utility=duke-energy®ion=NC&category=site_control" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` ### Historical Success Response ```json { "utility": "duke-energy", "state": "NC", "category": "site_control", "requirements": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "category": "site_control", "key": "lease_agreement", "value": { "description": "Executed lease or ownership documentation for the project site", "required": true, "stage": "application" }, "spec": { "site_control_requirements": { "interpreted_summary": "Executed lease or ownership documentation for the project site" } }, "requirementText": "Executed lease or ownership documentation for the project site", "ixType": "D", "extractedAt": "2026-02-15T08:30:00.000Z", "validationStatus": "validated" }, { "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "category": "site_control", "key": "proof_of_ownership", "value": { "description": "Deed or title documentation proving site ownership or control", "required": true, "stage": "application" }, "spec": null, "requirementText": "Deed or title documentation proving site ownership or control", "ixType": "D", "extractedAt": "2026-02-15T08:30:00.000Z", "validationStatus": "validated" } ], "count": 2, "total": 12, "limit": 2, "offset": 0, "source": "dynamic_extraction", "message": "Successfully loaded 2 of 12 requirement(s) from IX Requirements Agent database." } ``` ### Response Fields (legacy) | Field | Type | Description | |-------|------|-------------| | `utility` | `string` | The utility name as provided in the query. | | `state` | `string \| null` | Two-character state/region code, or `null` if not filtered. | | `category` | `string \| null` | Requirement category filter applied, or `null` if not filtered. | | `requirements` | `array` | Array of matching requirement objects (see below). | | `count` | `number` | Number of requirements returned in this page. | | `total` | `number` | Total matching rows before pagination. | | `limit` | `number` | Page size used for this response. | | `offset` | `number` | Offset used for this response. | | `source` | `string` | Data source: `"dynamic_extraction"` when requirements are found in the database, `"fallback_static"` when no results are available. | | `message` | `string` | Human-readable summary of the query result. | ### Requirement Object Fields (legacy) Each entry in the `requirements` array contains: | Field | Type | Description | |-------|------|-------------| | `id` | `string` | UUID of the requirement record. | | `category` | `string` | Requirement category (`site_control`, `technical_specs`, `forms`, `fees`). | | `key` | `string` | Machine-readable requirement identifier (e.g., `lease_agreement`). | | `value` | `object` | Structured data extracted from the source document. Contents vary by requirement type. | | `spec` | `object \| null` | Full rule-pack style requirement object when available, including site-control detail. | | `requirementText` | `string \| null` | Human-readable requirement text derived from `spec` or `value`. | | `ixType` | `"T" \| "D" \| null` | Transmission/distribution applicability when known. | | `extractedAt` | `string` | ISO 8601 timestamp of when the requirement was extracted. | | `validationStatus` | `string` | Current validation state, usually `"pending"`, `"validated"`, or `"disputed"`. Customer-facing enforcement requires `"validated"`. | ### SDK and CLI Retirement The TypeScript SDK `client.queryRequirements()` method and the CLI `requirements query` / `requirements list` aliases have been removed. Use `queryPublishedRequirements()` and `gridwonk requirements published`. ### Notes (legacy) - The retired route emits no `requirements.extracted` [webhook event](/docs-site/integrations/webhooks#event-types). The published endpoint also has no read-side webhook. - The former success handler shared the daily unique-utility cap used by utility matching. The 410 guard runs before that check. - Results reflect the frozen extracted requirement corpus. The utility name is normalized to slug format (e.g., "Duke Energy" becomes `duke-energy`) with fuzzy matching as a fallback. The published endpoint removes that fuzzy fallback deliberately. - When no requirements are found, the response returns `count: 0`, `source: "fallback_static"`, and an empty `requirements` array. - In shadow mode, `source: "dynamic_extraction"` can include pending, deprecated-source, or missing-source rows from the existing corpus. Treat the shadow diagnostic as the customer-usable count forecast, not as the returned count. --- # Usage API API usage rollups and performance metrics for the calling organization and key. URL: /docs-site/api/usage # Usage API ## Get Usage Summary `GET /api/v1/usage` ### Query Params - `days` (1-90, default 30) ### Response ```json { "windowDays": 30, "since": "2026-01-19T00:00:00.000Z", "summary": { "requests": 120, "errors": 4, "estimatedCostUsd": "3.420000", "avgResponseMs": 182 }, "currentKey": { "id": "uuid", "name": "production", "requestsToday": 32, "rateLimitPerMinute": 60, "currentMonthCostUsd": "3.42", "monthlyCostLimitUsd": "100.00", "status": "active", "lastRequestAt": "2026-08-04T18:25:00.000Z", "environment": "live" }, "byEndpoint": [ { "path": "/api/v1/jobs", "requests": 60, "errors": 2, "avgResponseMs": 140, "estimatedCostUsd": "1.250000" } ] } ``` ## Use Cases - partner rate/cost visibility - endpoint-level performance monitoring - operational capacity planning Usage is scoped to the calling organization. `currentKey` describes only the API key used for the request, and `byEndpoint` is capped to the top 50 paths in the selected window. `currentKey` is `null` only when the authenticated key row is no longer available during the request. `lastRequestAt` can also be `null` for an unused key. --- # Utilities API Match utility names and browse the utility catalog via the EIA-backed API. URL: /docs-site/api/utilities ## List Utilities `GET /api/v1/utilities/list` Browse and search available utilities with filters and pagination. ### Authentication Bearer token required. See [Authentication](/docs-site/api/authentication). ### Query Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `state` | string | No | Two-letter state code filter | | `type` | string | No | Ownership type. One of: `iou`, `cooperative`, `municipal`, `political_subdivision`, `state`, `federal` | | `query` | string | No | Free-text search (max 200 chars) | | `limit` | number | No | Results per page (1-200, default 50) | | `offset` | number | No | Pagination offset (default 0) | ### Example ```bash curl "https://gridwonk.com/api/v1/utilities/list?state=CA&type=iou&limit=10" \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" ``` --- ## Match Utility `POST /api/v1/utilities/match` Match a user-provided utility name to an official EIA (Energy Information Administration) utility record. Matching is deterministic: the route uses database-backed slugs, display names, search aliases, state narrowing, and normalized text comparison. It does not call an LLM. - **Deterministic**: The same stored utility input returns the same official record. - **Fast**: Common names, aliases, and normalized matches resolve from stored catalog data. - **Capped**: Each organization has a daily unique-utility lookup cap for match requests. ### Authentication Bearer token required. See [Authentication](/docs-site/api/authentication). ### Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `name` | string | Yes | Utility name to match (1–500 characters). Supports common abbreviations (e.g. `PG&E`, `NES`, `Con Ed`). | | `state` | string | No | Two-letter state code (e.g. `NC`, `CA`). Narrows candidates for multi-state utilities. | ### Response Shape ```json { "match": { "eiaId": 5416, "name": "Duke Energy Carolinas, LLC", "confidence": 0.95 }, "utility": { "eiaId": 5416, "name": "Duke Energy Carolinas, LLC", "ownershipType": "Investor-Owned", "states": ["NC", "SC"], "rtoIso": "SERC" }, "fromCache": false } ``` ### Response Fields | Field | Type | Description | |-------|------|-------------| | `match.eiaId` | number \| null | EIA utility ID, or `null` if no match found. | | `match.name` | string \| null | Matched utility name, or `null` if no match. | | `match.confidence` | number | Numeric confidence score: `0.95`, `0.7`, `0.3`, or `0`. | | `utility` | object \| null | Full utility details when a match is found. `null` otherwise. | | `utility.eiaId` | number | EIA utility ID. | | `utility.name` | string | Official utility name from EIA records. | | `utility.ownershipType` | string | Ownership classification (e.g. `Investor-Owned`, `Municipal`, `Cooperative`). | | `utility.states` | string[] | All states where this utility operates. | | `utility.rtoIso` | string \| null | Regional transmission organization or ISO, or `null` when none is stored. | | `fromCache` | boolean | Whether the response was served from a stored prior match. | ### Confidence Levels | Score | Meaning | |-------|---------| | `0.95` | Exact, alias, or high-confidence stored match. | | `0.7` | Likely correct, usually from partial or narrowed candidate matching. | | `0.3` | Best-effort low-confidence match. Verify before using in workflows. | | `0` | No reasonable match found in the EIA dataset. | ### Multi-State Utilities Many utilities operate across multiple states. Providing the `state` parameter helps disambiguate: ```bash # Without state — could match any Duke Energy entity 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"}' # With state — narrows to Duke Energy Indiana 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": "IN"}' ``` ### Example ```bash curl -X POST https://gridwonk.com/api/v1/utilities/match \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "PG&E", "state": "CA"}' ``` --- # Utility Applications Screen utility applications, record package-bound decisions, and manage reviewed notices through REST, the SDK, and CLI. URL: /docs-site/api/utility-lane last-updated: "2026-10-27" --- ## Public plugin scope and processing The public plugin exposes only the utility tools in its [curated customer catalog](/docs-site/api/mcp) after exact-session workspace confirmation and current direct-member authorization. Its presence does not expose the human decision or notice-write operations documented for existing integrations below; public-plugin users perform those actions in the website. Trial and prepaid screening uses the reviewing utility's processing allowance and the exact submitted package. Applicant private results do not replace that review or fund it. See [processing allowances](/docs-site/help/processing). The utility lane uses the same application, package, review, and decision services as the utility console. Your credential selects the organization; requests cannot select another utility or supply an actor, organization, or provenance record. Screening starts are available to authorized automation, including MCP. Manual freeze, finding adjudication, screening completion, and study requirements remain human decisions. They are available through REST, the SDK, and CLI, but excluded from both hosted and local MCP. ## Package versions and migration The examples on this page target the published, aligned `0.4.0` release of `@gridwonk/sdk`, `@gridwonk/cli`, and `@gridwonk/mcp-server`. Install the components your integration uses from GitHub Packages with an account that has package access. Local installs require a classic personal access token with `read:packages`; see [GitHub's registry authentication guidance](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#authenticating-to-github-packages). See the [CLI installation instructions](/docs-site/integrations/cli#quick-start) for registry setup. Check the installed CLI with `gridwonk --version`; a website deployment does not update local packages. When moving from `0.3.x`, replace legacy base64 uploads (`uploadDocument`, `docs upload`, and `upload_document`) with [storage-native packet intake](/docs-site/api/packets). The `0.4.0` release also removes AX optimization and Queue Analytics methods, commands, and tools. Those removals have no replacement GridWonk operation. Review existing automation before upgrading; MCP still excludes the human decisions described below. ## Access 1. An owner or administrator creates a **runtime** organization key at `/utility/api-keys` after ordinary invite-and-login onboarding. Organization suspension and billing restrictions still apply. 2. Exchange the key at `POST /api/v1/oauth/token` for a short-lived token with `partner.read`, `partner.write`, or both. The scopes are independent: write does not imply read. See [authentication](/docs-site/api/authentication#partner-scopes). 3. Reads require current authorized membership. Writes also require a current writer role, the matching utility identity, and an eligible application state. An expired membership, viewer seat, or consultant grant does not confer utility decision authority. For first-key setup through the CLI, sign in with `gridwonk auth login --browser`, identify the organization with `gridwonk orgs list`, and use `auth bootstrap-status --org ` followed by `auth bootstrap-key --org --name "Initial Management Key"`. The bootstrap command requires an explicit `--org`; switching the stored active organization is insufficient. Bootstrap creates a **management** key for [key lifecycle operations](/docs-site/api/keys); use it to provision the runtime key for application traffic. Key role, partner scopes, and the creator's current organization role are separate checks. Keep keys and bearer tokens private. Ordinary packet operations do not create webhook subscriptions; use the management-key lane described in [webhooks](/docs-site/api/webhooks). Notice REST/SDK/CLI operations and read-only MCP bindings are implemented in the released utility-notice stack. Schema and provider setup were separately activated for this release; each new integration should still verify its own live behavior. The five utility event families use existing webhook subscriptions; see [Webhooks API](/docs-site/api/webhooks). Notice writes remain human decisions and are excluded from MCP. ## Read before deciding Use `GET /api/v1/utility/applications` to find applications, then `GET /api/v1/utility/applications/{submissionId}` for the selected application. Its `/packages`, `/packages/{packageId}/findings`, and `/history` reads expose the immutable package, pinned review and findings, current adjudication versions, and application history. The application, package, run, and finding identifiers are related identities, not interchangeable strings. Take them from the same current package read. When point-of-interconnection review is enabled for the packet owner, the existing authorized packet report may also contain geographic evidence. Coordinate observations and their coverage do not create deficiency findings or approve the package. Human POI decisions use authenticated review actions; this addition does not introduce a REST, SDK, CLI, or MCP mutation endpoint. ## Start screening Use the existing `POST /api/v1/packets/{submissionId}/review` endpoint with an empty JSON object for the default start. A direct utility credential selects utility authority. The equivalent CLI command is `gridwonk packets review start --submission `; MCP uses `start_packet_review`. See [packet review](/docs-site/api/packets) for the complete start contract. Eligible utility-owned packets and developer-submitted packets can be screened. An unsubmitted developer draft cannot. Active, unexpired upload batches block screening until they settle, are abandoned, or expire. For a formal application in `pending`, `queued`, or `resubmitted`, the queued review and its move to `screening` commit together before work is dispatched. This applies to console, REST, SDK, CLI, and MCP starts. A completed run moves it to `screened`; a failed start or run restores the prior status once no other utility review is active. An exact retry reuses the active run. Re-screening does not reset an existing `screened`, notice, or `complete` state. Utility-owned drafts keep their separate package-freeze transition, and completed automated screening still requires the human decisions below. The reviewing utility pays through the shared review budget, including when the applicant owns the documents. Concurrent or repeated starts of the same eligible work reuse the existing run and job instead of charging again. Reuse does not require another budget reservation even when the daily cap has been reached. New work remains subject to the current organization limits; `429` responses include `Retry-After`. Do not change a budget to make a retry succeed. Automatic package freeze continues to follow the utility screening policy. A manual freeze is a separate human operation and cannot request the automatic path. ## Record human decisions Every route below uses `POST`, requires `partner.write`, and accepts a strict JSON object. Unknown fields are refused. All paths start with `/api/v1/utility/applications/{submissionId}`. | Operation | Path | Body | |---|---|---| | Manual freeze | `/freeze` | `{}` | | Adjudicate one finding | `/packages/{packageId}/adjudications` | `runId`, `findingId`, `decision`, `expectedVersion`; optional `rationale` and `editAfter` | | Complete screening | `/screening/complete` | `packageId` | | Set or replace a study requirement | `/study-requirement` | `scopeDescription`, `requirementText`; optional `caseReference` | ### Manual freeze Only a utility-owned draft can be manually frozen. The shared core checks current ownership, visibility, membership, upload completion, and packet readiness under the application lock. An applicant-owned draft or already-submitted application cannot use this operation. The response identifies the frozen package; use that package's reads before making a finding decision. ### Adjudication The package must be the latest package, and its pinned run and finding must match the request. The decision is `accept`, `dismiss`, `defer`, or `edit`. Dismiss, defer, and edit require a written reason. An edit supplies `editAfter`; the server derives the original values. `expectedVersion` is the version you read, or `0` if the finding has no decision. A competing decision returns a conflict; refresh the package findings before trying again. The original review is not overwritten. Decisions are recorded in a versioned ledger, including the authenticated actor and the originating surface. ### Completion Completion checks the exact latest package and the current decision state. Repeating a successful completion for that package is idempotent: the response reports that it was already complete, without another transition. A wrong or older package is still refused after completion. Completed screening is not approval to interconnect. ### Study requirement Record a study requirement after automated screening while the human decision round is still open (`screened` or `notice_draft`). Closed screening is refused. The requirement applies to the **next submission only**. Setting or replacing it does not alter the existing frozen package, its evidence pins, or its saved report. A later submission must satisfy the then-current requirement. The evidence version and its history entry are committed together. ## Package-bound notices Every notice belongs to the application named in its URL. A notice ID from another application is refused even when both applications belong to the same utility. All paths below begin with `/api/v1/utility/applications/{submissionId}/notices`. | Method | Path | Scope | Strict request body | |---|---|---|---| | `GET` | Collection | `partner.read` | None; optional status, round, query, sort and paging filters | | `GET` | `/{noticeId}` | `partner.read` | None | | `POST` | Collection | `partner.write` | `packageId` from the current immutable package | | `PATCH` | `/{noticeId}` | `partner.write` | One or more of `subject`, `body`, `deficiencyItems`, `responseDueAt` | | `POST` | `/{noticeId}/submit` | `partner.write` | `{}`; draft to review | | `POST` | `/{noticeId}/approve` | `partner.write` | `{}`; review to approved, bound to the exact content revision | | `POST` | `/{noticeId}/return` | `partner.write` | `{}`; review to draft | | `POST` | `/{noticeId}/revoke` | `partner.write` | `{}`; approved to review when safe to cancel | | `POST` | `/{noticeId}/send` | `partner.write` | `recipientEmail` | | `POST` | `/{noticeId}/acknowledge` | `partner.write` | `{}`; sent to acknowledged | The optional notice `round` list filter accepts integers from 1 through 2,147,483,647. Larger values fail request validation before a database query. The programmatic lane requires direct, current utility membership. A write scope does not replace a write-capable role, application access, or current state checks. Console consultant grants and applicant acknowledgment remain separate existing permissions; they do not create an applicant or consultant notice API. Source-managed applications do not gain notice-write authority from this interface. Draft creation derives findings and their provenance from the package. Edits cannot supply a new actor, organization, approval, or adjudication identity. Notice reads include content, revision and package identity, canonical status, and a bounded delivery summary; they do not return contact addresses, internal edit history, actor identities, or provider payloads. ### Send and retry behavior `recipientEmail` must match the recorded applicant address or an active, unexpired owner/admin/member address in the applicant organization. The server proves eligibility at the mutation boundary; it does not publish a contact directory. This restriction applies to REST, SDK, and CLI. Existing authorized console free-text recipients remain supported. Send commits an immutable recipient, approved revision, payload and delivery key before any provider attempt. A pending request returns `202`; the canonical notice can still be `approved`. Repeating it reuses the same intent. A finalized send returns `200` with `changed: false`; an existing held result can also return `200` with its explicit delivery state, not a sent claim. Held or uncertain delivery is not a new-send invitation. There are at most eight automatic attempts within 23 hours; a failed queue hint does not erase the committed request. Provider acceptance, canonical `sent`, and inbox delivery are different facts. A successful acknowledgment returns `acknowledged`; repeating it returns `changed: false` without a second history entry or event. Refresh state after a conflict instead of substituting another notice or resetting a delivery key. ## SDK, CLI, and provenance The SDK methods are `freezeUtilityPackage`, `adjudicateUtilityFinding`, `completeUtilityScreening`, and `setUtilityStudyRequirement`. The matching commands are `utility applications freeze`, `utility adjudicate`, `utility screening complete`, and `utility study-requirement set`. See the [CLI reference](/docs-site/integrations/cli#gridwonk-utility-utility-partner-lane) for flags and examples. Notice methods are `listUtilityNotices`, `getUtilityNotice`, `createUtilityNotice`, `updateUtilityNotice`, `transitionUtilityNotice`, and `sendUtilityNotice`. `transitionUtilityNotice` selects the named `submit`, `approve`, `return`, `revoke`, or `acknowledge` action; it cannot assign an arbitrary status. CLI commands are `utility notices list/get/create/edit/submit/approve/return/revoke/send/acknowledge`. CLI mutations require confirmation or `--yes`. `--dry-run` prints the intended operation without an HTTP request; it is not proof of authorization or readiness. The normal SDK identifies a REST origin; the CLI identifies a CLI origin. The server derives actor and credential identity, and console actions retain their console origin. A client cannot submit its own provenance object. ## Refusals and MCP boundary An unresolved notice delivery also blocks conflicting freeze, finding, screening-completion and study-requirement decisions. Resolve pending, held or accepted-but-unfinalized delivery through the authorized notice workflow; do not reset its key or retry with another notice. The notice interfaces retain this guard and do not grant MCP write permission. Malformed request bodies return `400`; malformed path identifiers and missing or unauthorized application/package/run/finding identities return `404`; stale versions, incompatible states, and unfinished upload batches return `409`. Authentication, scope, request-rate, and shared-budget checks also apply. No refusal should be worked around by changing production membership, flags, or budget settings. MCP catalogs omit all four earlier human-decision operations and every notice write. `list_utility_notices` and `get_utility_notice` require `partner.read` and use the same scoped, slim notice reads as REST. A direct call to an excluded operation is refused before its mutation core executes, regardless of partner scope or supported protocol revision. MCP may start screening and read the resulting package and findings; it cannot make the utility's decision. These REST-only decisions appear in the authenticated full OpenAPI document, not the public agent-facing OpenAPI projection. ## Corrected applicant packages An applicant resubmission creates its corrected immutable package and returns the application to **Pending** for the same receiving utility. It does not start legacy per-document screening or assume utility authority. A current authorized utility writer starts the shared packet review through the endpoint above or **Screen Selected** in the queue; the shared core selects `utility_rescreen` after the earlier utility round. Package-bound decisions and historical package reads retain their existing authorization and version checks. --- # Webhooks API Subscription management and delivery behavior for GridWonk event notifications. URL: /docs-site/api/webhooks # Webhooks API ## Endpoints - `GET /api/v1/webhooks` - `POST /api/v1/webhooks` - `GET /api/v1/webhooks/{id}` - `PATCH /api/v1/webhooks/{id}` - `DELETE /api/v1/webhooks/{id}` ## Supported Events - `job.completed` - `job.failed` - `document.classified` - `document.digitized` - `document.validated` - `deficiency.found` - `screening.complete` - `requirements.extracted` - `utility.screening.determined` - `utility.finding.adjudicated` - `utility.study_requirement.set` - `utility.package.frozen` - `utility.notice.status_changed` `deficiency.found` and `screening.complete` are reserved event types unless a specific workflow emits them through its job completion payload. The five `utility.*` families are implemented in the reviewed utility-notice stack and require its separately approved schema activation and release. This documentation does not establish production availability. They describe actual human screening decisions, finding decisions, study-requirement changes, package freezes, and canonical notice status changes. A send request, provider receipt, replay or rolled-back transaction does not create another status event. A `utility.package.frozen` event can include an optional `data.syntheticFeeExemption` audit record for an explicitly approved synthetic test application. It identifies the exact application, form version, finding and approval, and states `paymentRecorded: false`. The fee finding remains in the immutable report; this record is not a payment receipt or a general fee waiver. Only subscriptions in the application's receiving utility organization receive these events. An applicant or consultant subscription does not inherit them through its actor's application access. Registering a subscription does not backfill historical changes. Existing management-key authentication and organization scoping are unchanged. ## Create Subscription ```bash curl -X POST https://gridwonk.com/api/v1/webhooks \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://partner.example/hooks/gridwonk","events":["job.completed","job.failed"]}' ``` If `secret` is omitted, GridWonk generates one and returns it only at creation time. Response shape: ```json { "subscription": { "id": "uuid", "url": "https://partner.example/hooks/gridwonk", "events": ["job.completed", "job.failed"], "isActive": true, "createdAt": "2026-05-08T12:00:00.000Z", "secret": "whsec_..." } } ``` Each organization can have up to 25 webhook subscriptions. ## Update and Delete `PATCH /api/v1/webhooks/{id}` accepts `url`, `events`, and `isActive`. Setting `isActive` to `false` records `disabledAt`; setting it back to `true` clears `disabledAt` and resets consecutive failure counters. `GET /api/v1/webhooks/{id}` returns the subscription and its 50 most recent delivery attempts. `DELETE /api/v1/webhooks/{id}` returns `{ "success": true, "id": "..." }`. For utility events, an event-list change affects future changes, not already committed deliveries. Disabling pauses new claims; an already in-flight request can finish. Re-enabling permits pending work to resume but does not reset exhausted holds. Deleting the subscription removes its delivery rows while retaining immutable source events. ## Delivery Headers Each delivery includes: - `X-GridWonk-Event` - `X-GridWonk-Event-Id` - `X-GridWonk-Timestamp` - `X-GridWonk-Signature` > **Removed aliases:** deliveries previously also carried `X-GridBoost-Event`, `X-GridBoost-Event-Id`, `X-GridBoost-Timestamp`, and `X-GridBoost-Signature` with identical values. Those aliases have been removed — use the `X-GridWonk-*` headers above. ## Signature Verification Signature input format: ```text . ``` Algorithm: `HMAC-SHA256(secret, payload)` with header value `sha256=`. ## Retry and Reliability - Delivery attempts are persisted in `webhook_delivery_log`. - Failures are retried with increasing delay. - Legacy job/document subscriptions auto-disable after repeated consecutive failures. - Invalid internal or private webhook targets are rejected at configuration time. URLs must use HTTPS, cannot include credentials, and cannot resolve to localhost, private, reserved, `.local`, `.internal`, or metadata host addresses. ### Ordered utility events The business change, immutable event and subscribed deliveries commit in one transaction. The payload includes `eventId`, `eventType`, `payloadVersion: 1`, `organizationId`, `submissionId`, `sequence` (a decimal string), `occurredAt`, originating `provenance`, and event-specific `data`. Notice events contain notice/revision/package/run IDs and previous/new status, not recipients or email content. See the [integration guide](/docs-site/integrations/webhooks#utility-events). Delivery is at least once: verify the signature and durably deduplicate by event ID before acknowledging. Retries retain the stored payload and ID with a fresh signature timestamp. Each subscription/application pair is ordered independently; unsubscribed events may leave sequence gaps. Up to eight attempts use delays of 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 12 hours and 24 hours. Recovery queues due stream heads every five minutes, so these are minimum delays, not a delivery-time guarantee. Exhaustion holds that pair and its later events without disabling the subscription or blocking other applications/subscribers. Operator review is required for held work; changing the subscription does not reset its budget. --- # For Consultants Manage interconnection workflows across multiple clients with GridWonk. URL: /docs-site/getting-started/for-consultants ## Client processing and account scope Self-service developer registration and verified utility claims do not enroll a consulting firm or create a client access grant. Continue to use the consultant approval and grant workflow below. Within an authorized client context, new packet processing must also satisfy that client's [processing allowance](/docs-site/help/processing) and supported workflow. A grant does not enable native DWG processing or unrestricted chat for a trial or prepaid client workspace. In an authorized developer-client context, current document checks can produce a partial report before the packet review completes. Treat that report as incomplete coverage, not approval or a submission-ready packet. Client grant scope and utility review authority remain unchanged. After a permitted, human-confirmed PDF split, the original and its earlier reviews stay in history. Current findings cover the resulting documents and their exact packet set. A read-only grant cannot confirm or recover a split; existing client permissions remain in force. ## Client workspace appearance A client workspace may use its organization's saved colors. Consultant workspaces do not support the appearance schemes, and grant-derived admin access does not let a consultant change a client's appearance. A direct Owner/Admin of the developer or utility client uses **Team and logo > Workspace appearance** to preview and save it. Colors never change data access or grant scope. ## Salesforce pilot access Consultant grants and platform impersonation do not authorize Salesforce connection administration or substitute for a direct utility employee's linked account. The implemented connector remains disabled, and its captured results also require current Salesforce source access. Ordinary client-grant workflows on this page remain separate. ## Who Is This For? Engineering consultants, interconnection advisors, and firms that serve both utilities and project developers as intermediaries. If you manage interconnection applications on behalf of clients — like [DRG Technologies](https://drgtechnologies.com) — this guide is for you. ## Getting Started When you work in a developer client's granted project, a released full packet setup can support private review by default, including before the utility joins GridWonk. Private review remains available when Submit is available. That does not authorize formal submission: GridWonk and a real utility representative must accept the exact state and program, and the utility must have an active reviewer. Your existing grant and role limits still apply. 1. **Contact us for consultant-tier access** — Email [contact@gridwonk.com](mailto:contact@gridwonk.com) to request a consultant account 2. **Account approval** — A GridWonk admin will review and approve your account before you can access any data or features; accept any current legal documents when GridWonk asks you to do so 3. **Set up your organization** — Create your consulting firm as an organization in GridWonk 4. **Request or receive client access grants** — Client organization admins and owners can grant consultant access; GridWonk admins can assist when support access is needed 5. **Work within each grant boundary** — Use available agents and workflows only for the active organization, grant level, and project scope 6. **Export branded reports** — Deliver professional PDF reports to your clients Utility organizations are provisioned by GridWonk after affiliation review; a consultant cannot self-claim a `utilityId`. ## Multi-Client Workflow Notice mutations and dispatch recheck current membership and the exact client grant, including project scope. Pending or held notice delivery blocks conflicting application changes. Use the correct client context and resolve delivery; a cached grant or new send request cannot override the hold. GridWonk supports consultants who work across multiple clients and utility territories. The important model detail is that consultants are their own organization type in GridWonk — one of four, alongside utility, developer, and the internal GridWonk platform type. They do not replace the utility or developer on a shared submission row. Instead, they participate through scoped access grants from their client organizations. ### Organization Switching - Each client engagement maps to an organization in GridWonk - Use **Organization and role** to switch directly into an available client context without logging out. Find it in the shared header, or near the bottom of the expanded Console or Utility sidebar. - All validation runs, uploads, and results are scoped to the active organization - Project and demo deep links are checked against that active context and fail closed rather than switching organizations automatically - Work for utilities and developers from the same consultant account - Access is controlled via **grants** — utility and developer clients can grant your consultant org specific access levels (`read`, `write`, or `admin`) with optional project-level scoping and expiration dates ### Working for Different Client Types | Client Type | Your Workflow | |-------------|--------------| | **Project Developers** | Upload their IX applications, run validation agents, deliver deficiency reports before submission | | **Utilities** | Review incoming applications against utility-specific requirements, flag deficiencies for the utility review team | ## Team Coordination ### Roles & Permissions GridWonk uses role-based access control to keep your team organized: | Role | Capabilities | |------|-------------| | **Owner** | Full access, billing, org management | | **Admin** | Manage members, run all agents, export reports | | **Member** | Upload documents, run agents, view results | | **Viewer** | Read-only access to results and reports | Assign roles based on responsibility — give junior analysts Viewer access for QA review, and senior engineers Member or Admin access for active validation work. Grant-derived access is not the same as direct organization membership. Creating console projects through developer workflows requires direct membership in the active organization; granted access is rejected for that specific mutation. Use write/admin grants for workflows that explicitly support granted mutations, and switch into a directly joined client org before creating a new project. A write or admin grant does not override your role in the receiving consultant organization. Grant-aware mutations require both an active **Member**, **Admin**, or **Owner** receiving-org role and a **write** or **admin** grant. A Viewer remains read-only even when the organization has a higher-level grant. That means: - the client org still owns its own workflow rows - your consultant org works inside the granted scope - audit and grant rules stay attached to your consultant participation The optional Combined-PDF split has a stricter applicant-authority boundary than ordinary granted reads. Optional intake features (combined-PDF split, ZIP upload) are on by default and managed per applicant organization by that organization's own admins (platform rollout controls can still narrow availability, and platform-set rows appear read-only on that organization's Features page), so their controls appear only where that organization has them on. A consultant context may see authorized document and split status, but it cannot analyze, confirm, or discard a split—even with a write/admin grant. The applicant developer organization (or a platform administrator) must make the human page-range and role decision. Responding to a deficiency notice is developer-client scoped. Your consultant home organization does not receive the **Start response** action. After you switch into a granted developer-client context, the action can run only when your receiving consultant organization still has an active Member, Admin, or Owner user plus an in-scope write/admin grant for that project. Attaching the first corrected document also starts the response automatically, so the response stage is recorded even when nobody presses the button first. After an authorized resubmission, the corrected immutable package returns to the receiving utility as **Pending**. The utility starts its whole-packet review with **Screen Selected** or an authorized integration. The application moves to **Screening** before work starts and **Screened** when complete; a failed start or run restores the earlier status once no other utility review is active. The applicant-side action does not act with utility review authority, and client grants do not gain new permissions. ### Audit Trails Every action in GridWonk is logged: - Who uploaded which documents - Which agents were run, when, and by whom - Validation results and any changes over time This makes it straightforward to demonstrate diligence to your clients. ## Reporting & Deliverables ### PDF Reports Export professional, branded validation reports for client delivery. Reports include: - Compliance scorecards with pass/fail status per requirement - Identified deficiencies with remediation guidance - Document classification and extraction results Before delivering a report or notice, confirm that no document re-review is pending. GridWonk hides findings tied to replaced bytes and prevents packet-wide notice drafting until the current document versions have been reviewed. > **Coming Soon:** Custom branding (your firm's logo and colors on exported reports) is planned for a future release. ### JSON API For consultants who build their own tools or dashboards, the [API Reference](/docs-site/api/overview) documents the org-scoped results currently available through the public API, including deficiency-report and application query/sync surfaces. It does not expose every internal validation result or workflow. Integrate only the documented surfaces that your organization key can access. API access and usage limits are provisioned by GridWonk per organization — they are not configurable from organization settings. Repeated organization-setting updates may return HTTP 429; wait before retrying. The browser organization-management routes use the same fail-closed input boundary: grant and organization mutations reject bodies over 32 KiB, member changes over 16 KiB, and switch requests over 8 KiB before database work. Project-scoped grant lists are capped at 500 identifiers. ## Bulk Processing Utility workspaces already support batch intake, queue filtering, multi-select screening, and CSV export. Consultants can use those workflows when the active organization and grant level allow utility workspace access. Consultant-specific reporting across multiple client organizations is still constrained by organization switching and grant scope. Switch to the correct client context before uploading, screening, exporting, or running agents. ## Next Steps - [API Reference](/docs-site/api/overview) — Programmatic access for custom integrations - [Access Grants](/docs-site/help/access-grants#how-grant-based-access-is-decided) — How membership, grant level, scope, and action rules combine - [Help Center](/docs-site/help/documents) — Detailed feature documentation - [For Developers](/docs-site/getting-started/for-developers) — Understand the developer workflow you'll be supporting - [For Utilities](/docs-site/getting-started/for-utilities) — Understand the utility workflow you'll be supporting ## Discover new client access When enabled, a new client grant creates a persistent bell alert for eligible existing direct members of your consulting organization. Email can be enabled separately; no invitation acceptance is needed. Alerts remain visible in other organization contexts, and **View client access** opens Consultant Access without silently switching organizations. Existing grants and later member joins are not backfilled. See [Access Grants](/docs-site/help/access-grants) for the full workflow. --- # For Developers Validate your active interconnection application packets before submission. URL: /docs-site/getting-started/for-developers Project creation defaults capacity to kW with an explicit MW option. Overview, Documents, Findings, and Report share current results: completed document checks provide a partial report immediately, while a current completed packet review replaces overlapping results. This is not utility approval or submission eligibility. Site-plan cards offer Attach DWG; the published utility/process policy determines whether it is required. If cards or Overview show **Findings unavailable**, refresh before relying on their counts. A background read failure is not a clean review and cannot silently replace current applicant results with an older utility report. ## Background updates The permission-aware live-update rollout is gated. Once enabled, organization-wide access uses one private channel, while project-scoped access receives only permitted project topics. Document and project readers also refresh periodically. Temporary failures retain displayed information; confirmed loss of access clears it. **Retry updates** refreshes data without restarting processing. See [live-update status](/docs-site/help/jobs). ## Salesforce pilot boundary The implemented [Salesforce utility connector](/docs-site/integrations/salesforce) is disabled and does not replace a developer's submission channel. Its captured utility-internal results do not become available through applicant access, and source-managed evidence cannot be edited through ordinary project controls. ## Who Is This For? Project developers preparing interconnection applications for submission to utilities. For supported document and application roles, GridWonk reviews the submission against source-backed utility requirements so teams can identify and correct gaps before utility review. You can select optional files in **Create Project**. The compact drop area closes after selection; **Add files** reopens it, and removal controls stay beside the filenames. Choose up to 12 PDF, PNG, JPEG, or DWG files (30 MB each, 120 MB total), or one ZIP alone. Invalid additions leave accepted files in place. Upload starts after the project is created, with permissions and ZIP availability checked in Documents. Capacity means the AC (alternating current) nameplate rating; **Capacity help** expands the unit definitions. ## What You Get - **Deficiency detection** — For supported utilities, Packet Review checks accepted document roles and evidence from the current documents against the effective-analysis requirement tier and flags gaps - **Compliance scorecards** — Pass/fail status for each requirement category (site control, technical specs, insurance, fees) - **Role-specific checks** — Deterministic evaluators check supported application fields, evidence, and cross-document rules - **Requirement provenance** — Each finding card shows the requirement, source document, page, and cited text. **Explain this finding** explains that saved finding using its original requirement and source evidence after checking your access. It distinguishes utility text from common practice; publication alone is not human approval. The older remediation route remains transitional and its revalidation action still uses the legacy compliance pipeline - **Developer-first packet check** — Work from a named project, review the exact current packet, correct detected deficiencies, and rerun before using the utility's required submission channel - **Source-backed utility research** — Read active procedure documents with a plain-language Role (what the document covers) and Source (who issued it) When you ask about a finding, the assistant keeps it selected for follow-up questions and retries. Use **Clear finding** to change topics, or choose another finding. Changing user, organization, or project clears that selection. If the exact saved source cannot be verified, the assistant states the limitation instead of guessing or substituting today's requirements. It explains the rule and its applicability; it does not re-read your drawing or decide whether your application passes. ## Getting Started 1. **Create or join a developer workspace** — [Verify your email and complete onboarding](/docs-site/help/self-service), or accept your team invitation. If registration is unavailable, use the access contact shown in the app. 2. **Navigate to the Interconnection Console** — Select your target utility from the dropdown. Authorized synthetic test utilities carry a **Synthetic** badge and identify their canonical requirements source. 3. **Research requirements** — Browse procedure documents and customer-released requirements without creating a project 4. **Upload draft files when useful** — Drag and drop documents for digitization while you are still organizing the application 5. **Create or select a project when you are ready to validate** — Enter a project name, capacity, and distribution/transmission track. If the utility publishes more than one interconnection program for that track, a **Program** dropdown appears and a choice is required — the review then runs against that program's rules. GridWonk handles the internal reference; you do not need a utility application number. For a synthetic selection, GridWonk keeps research on the canonical utility and re-checks the active applicant's reciprocal pairing before routing the test project. 6. **Review the packet where available** — Attach working files and confirm their document roles. For supported utility, state, and program combinations, the developer console automatically starts the applicant packet check once required evidence is ready; utility screening is performed from the utility organization context. Use **Review Actions** for a deliberate manual run or rerun. Existing projects outside supported coverage explain that automated review is not yet available. Customer-release approval of the reference requirements is a separate state and does not itself block Packet Review. 7. **Correct and rerun** — Fix cited issues, replace affected files, and let the automatic checks advance again, or use **Review Actions** → **Run Review Again** when a deliberate rerun is needed. Returning to Review after changing roles or confirmations refreshes its readiness row. 8. **Prepare the GridWonk package** — A completed review is decision support, not utility approval or proof of delivery 9. **Submit only when ready** — If the utility accepts packets in GridWonk, **Submit Project** explicitly shares a frozen package and its pinned packet report. Private review remains available before submission. Otherwise use the utility's required external portal, email, or other channel 10. **Prepare a revised package when needed** — If the utility sends a notice, select **Start Response** in the shared toolbar above any project view, replace the affected files, run another applicant self-check, and select **Resubmit Project** when the revision is ready. The new immutable package returns to **Pending**; the receiving utility starts its review with **Screen Selected** or an authorized integration. The application then shows **Screening** before work starts and **Screened** when complete. A failed start or run restores the prior status once no other utility review is active; your applicant self-check cannot perform this utility transition If a packet review appears stuck, use **Review Actions → Cancel Packet Review** when your review permissions allow it. Completed current document findings stay available and remain separate from whole-project results. A provider request already running may finish in the background; the interface warns if its workflow stop cannot be confirmed. Follow [Document troubleshooting](/docs-site/help/document-troubleshooting#a-packet-review-appears-stuck) before retrying rather than repeatedly starting another run. The **Create Project** utility picker requires a released, full packet setup for the selected state and program. A normal utility choice defaults to private review without a receiving organization or a rollout environment variable. Authorized synthetic choices use a separately validated test pairing backed by a released utility. A utility inherited from Research must qualify too. The support check starts as soon as the dialog opens; choose another utility if yours is unsupported, or use **Retry** to run the check again when it could not be completed. Research keeps the full utility catalog; being listed there does not prove review support for a utility, state, or interconnection program. Contact support when utility setup is incomplete. An available choice does not guarantee exhaustive requirement coverage or utility approval. GridWonk submission remains unavailable until the utility accepts that state and program and has an active reviewer; private review does not send the packet. That check applies to the first Submit only: **Resubmit Project** after a deficiency notice is never blocked by it. See [Private Reviews and Utility Submissions](/docs-site/help/private-reviews-and-submissions). If one accepted PDF contains several document types, choose **Documents → More actions → Split PDF**. Eligible PDFs have 2–250 pages, and can already have a type or completed review. Check the previews, confirm complete non-overlapping ranges, and assign each resulting document a type. Only confirmation starts a split. On success, the original and its reviews remain historical while the new documents go through processing and review. Reopen the action for progress; after failure choose **Retry split** or **Keep original**. New reviews and submission stay paused until resolved. Existing organization feature controls and editable-project permissions apply; no new setting or re-upload is required. Use the project's **Upload Project Files** control for one loose selection of PDFs, PNGs, JPEGs, and AutoCAD DWGs, or for one ZIP containing 1–12 supported files. A matching site-plan PDF and DWG can be selected together; GridWonk pairs them automatically only when the match is unambiguous and asks you to choose the site plan otherwise. GridWonk validates an entire ZIP before any file enters its normal document or CAD processor, so one unsafe entry rejects the whole ZIP. The ZIP never becomes a packet document. Do not select a ZIP together with loose files. Finish or cancel unfinished uploads before submitting or resubmitting a project. An active, unexpired batch blocks package creation while its files are uploading, processing, or awaiting pairing. The refusal preserves your current documents and any earlier submitted packages. The console offers a `Cmd+K` / `Ctrl+K` command palette for jumping between destinations; it stays available while a Review toolbar disclosure is open and steps aside only for a full dialog. Eligible developer organizations in the packet-review-checks cohort also receive **Checks**, which lists projects with completed checks; select a project there, use `[` and `]` to move through the queue, or choose **Open project** for its full workspace. The project views (Overview · Documents · Review · Activity) and the back-to-projects control sit in the top header, the review work area carries a collapsible findings panel plus a full-screen document mode, and opening Review temporarily collapses the sidebar (the automatic collapse is never saved as a preference; a manual toggle wins and persists). Leaving a project with the back-to-projects control clears the entire project address, including the project subview and the Review tab, so a copied link never points at a project view with no project; re-opening a project starts on Overview. Utility Research keeps the same developer-safe document and requirement visibility rules. The console also reports anonymized performance measurements (page speed and navigation timing) so slow screens can be found and fixed; project and document identifiers are stripped before anything leaves the browser. The console stays quiet while background updates are healthy, including successful periodic refreshes. After eight seconds, the header distinguishes **Connecting live updates…** from **Live updates interrupted — reconnecting…**. **Some live updates are unavailable.** offers **Retry updates** for incomplete refresh coverage. Offline and expired-session warnings remain visible; see [live-update status](/docs-site/help/jobs). Saved links remain subject to the active organization and current project visibility. If a project has been archived or is no longer available, GridWonk shows **Project unavailable** and **Return to projects** instead of mounting its Overview, Documents, Review, or Activity content. A failed availability check — for example a temporary connection problem — shows **Couldn't load this project** with **Try again** instead, so a transient error is never presented as a removed project. Research access starts with the developer-safe view while GridWonk resolves your active organization. Developer organizations remain limited to active customer-usable records; authorized reviewer organizations then receive their historical review controls. Developer Utility Research does not show deprecated or rejected procedure documents. Use the Role description to understand a document's purpose and the separate Source label to confirm who issued it. ## How Developer Visibility Works GridWonk keeps the developer's applicant self-check separate from a utility-authority review. When a verified utility workflow record exists, your organization can see its own submission lifecycle because GridWonk links the applicant organization to the shared submission record. In plain English: - the utility owns the review row - your developer org is linked as the applicant on that same row - notices and resubmission history stay shared without making you the owner of the utility queue itself ## Workflow Capabilities A queued or held utility notice is not yet a sent notice. Conflicting response or submission changes wait for delivery resolution and the application's final notice-sent update; contact the utility if progress remains held. Earlier immutable packages remain unchanged. GridWonk combines one active assistant persona with purpose-built workflows and deterministic pipeline stages. A pipeline stage can run as part of screening without being a separate agent that users configure or call directly. When a project document is selected, GridWonk resolves the current logical version row for sanitized PDF viewing. That keeps Results and packet review tied to the current safe rendition instead of a caller-controlled raw file path. | Capability | Current implementation | |------------|------------------------| | **Procedures Discovery** | Active workflow/job identifier backed by purpose-built discovery pipelines; not an Agent SDK persona | | **Packet Requirements** | Deterministic, role-specific producers technically publish requirements to the packet store; utilities then approve or reject each current row, and a rejected row is the only one removed from developer surfaces | | **Packet Review** | For supported utility, state, and program combinations, consumes accepted document roles and checks current document evidence against the effective-analysis tier. This tier has its own activation policy and does not wait for customer-release review. The default path reads the current documents; an enabled extraction-read cohort may reuse an exact matching stored extraction. | | **Legacy Site Control Compliance** | Compatibility-only single-document workflow called directly by older upload paths; not used by packet review | | **Role-Specific Validation** | Deterministic packet evaluators replace the retired broad form-validation persona | | **Interactive Assistant** | Active agent persona for coordination and questions | | **Remediation** | Transitional dedicated customer route whose revalidation tool still starts the legacy compliance pipeline; migration or retirement is owned by PR11 | | **Deficiency Location** | Packet-review stage that locates findings in PDFs; not a separate active persona | | **Report Generation** | Packet-review stage that creates annotated reports; not a separate active persona | ## What Requirements You See, And Their Review Status The requirements you can browse are every published requirement for the utility **except** the ones a utility reviewer has explicitly rejected. Rejected requirements are removed on the server and never reach you. Each requirement you see carries its own review status: **approved** means the utility's reviewers signed off on it; **pending** means it is still awaiting a current utility decision — including a requirement whose logic changed after a decision, which returns to pending re-review rather than disappearing. Nothing is hidden merely because a utility's review is unfinished; the surface reports that review progress separately (`review_incomplete`, `partially_released`) while still listing the requirements. This is deliberate: a Packet Review deficiency report cites requirements from the same all-except-rejected set, so the list shows you what a report can raise, with pending items labelled honestly. Packet Review uses the separate effective-analysis tier. Where Packet Review is supported and your project resolves to a real utility organization, an unfinished utility review does not by itself block a deficiency review. Serving requirements does not depend on a contract or subscription flag, although account access and normal project authorization still apply. The effective-analysis tier also applies current-source safeguards. When current-procedure enforcement is enabled, analysis uses requirements that are: - Validated by a reviewer - Linked to a current usable procedure document - Still tied to the same document text GridWonk read during extraction, when that check is available If a utility is still under cleanup, you may see fewer analysis requirements or a message that no approved site-control requirements are available yet. That means GridWonk has not confirmed enough source-backed rules for that analysis mode. It does not mean the utility has no requirements. ## Using the API For programmatic access, see the [API Reference](/docs-site/api/overview). The streaming agent API accepts JSON requests and returns Server-Sent Events (SSE) for real-time results. ## Next Steps For an interrupted upload, a corrected PDF, a failed review or a combined drawing set, use [Document troubleshooting](/docs-site/help/document-troubleshooting). It explains when to Retry upload, Replace, Retry review or Split, and why completed document results are separate from a whole-project review and utility approval. - [Quick Start](/docs-site/getting-started) — Console workflow overview and keyboard shortcuts - [Help Center](/docs-site/help/documents) — Detailed feature documentation - [Applications](/docs-site/help/applications#application-and-review-lifecycle) — Submission stage vs review workflow status - [Notices](/docs-site/help/notices) — What happens after a utility sends a deficiency notice - [For Utilities](/docs-site/getting-started/for-utilities) — How utilities use GridWonk (useful context for developers) ## Client-access notifications The Console header includes a notification bell on desktop and mobile. If you also belong to a consulting organization, enabled new-grant alerts remain visible while another organization is selected. The alert's **View client access** link opens Consultant Access without switching your organization. See [Access Grants](/docs-site/help/access-grants). --- # Get started with GridWonk Set up your account, choose a workspace, and prepare an interconnection packet. URL: /docs-site/getting-started/for-external-users GridWonk helps you research utility requirements, prepare application packets, and review cited findings. Public help is available without an account. Your organization's files and reviews require sign-in and current access. ## Choose your path | You are | Start here | | --- | --- | | A developer preparing a packet | [Create a developer workspace](/docs-site/help/self-service), then use the [developer guide](/docs-site/getting-started/for-developers) | | A utility representative | [Submit an affiliation claim](/docs-site/help/self-service#utility-affiliation), then use the [utility guide](/docs-site/getting-started/for-utilities) after verification | | Joining an existing team | Accept your own invitation, verify your email, and complete legal acceptance | | Using an AI client | Complete workspace setup, then [connect the public plugin](/docs-site/help/connected-apps) when available | | Maintaining an approved integration | Use the [API authentication guide](/docs-site/api/authentication) and your organization's assigned credentials | ## Your first review 1. Select the utility, state, and program relevant to your project. 2. Read the published requirements and check that automated packet review is supported. 3. Create a private project and upload supported files through packet intake. 4. Make any document-role or other human confirmations in the website. 5. Start an eligible review and follow its status. Read findings with their source citations. 6. Correct your packet. Submit only when you are ready and the utility accepts that workflow. Private review does not send a package to the utility. Formal submission is a separate human action. Review findings do not establish utility approval or a guarantee of interconnection. Eligible new workspaces have a bounded [trial](/docs-site/help/processing). Preprocessing uses processing allowance, and an unavailable provider or exhausted limit may block a new run. Existing authorized results remain readable. ## Files and connections Use the current packet upload flow. It accepts supported files up to 30 MiB each, with up to 12 files and 120 MiB per batch; additional file-type and page limits apply. The retired inline base64 upload endpoint is not a supported alternative. See [upload help](/docs-site/help/upload). The public plugin signs you in and asks you to confirm one workspace. When **App connected** appears, return to the plugin; the confirmation link cannot be reused. Do not share API keys, passwords, or tokens in a conversation. [Connected apps](/docs-site/help/connected-apps) shows how to review and revoke its access. Purchases and human decisions stay on the website. If signup or the public plugin is not yet available, use the access contact shown by the app. Existing partners can continue their authorized integration workflow. See the [Help Center](/docs-site/help) for account, packet, and support guides. ## Bot Detection on OAuth GridWonk can block OAuth browser login from cloud provider IP ranges (AWS, GCP, Azure) when the request also has a programmatic User-Agent or other bot signals. Approved server-to-server integrations should use API key authentication instead of browser-based OAuth. Public plugin users should complete sign-in in their own browser; never paste an integration key into a chat. If a normal browser is blocked, contact support. Forwarded IP headers cannot bypass these checks. --- # For Utilities Screen interconnection applications, detect deficiencies, and send notices — all from one workspace. URL: /docs-site/getting-started/for-utilities ## Establish utility access When self-service setup is available, verify your account, accept the current terms and privacy policy, then [submit a utility affiliation claim](/docs-site/help/self-service#utility-affiliation). Staff review evidence independently. Approval creates a utility workspace with the claimant as Owner or grants Member access to the existing workspace selected by staff. It does not activate formal intake: the exact state/program acceptance and an active qualified reviewer are still required. Existing invitations remain a separate way to join an approved utility team. Trial or prepaid screening uses the utility workspace's [processing allowance](/docs-site/help/processing) and the exact submitted package. A developer's private review credit does not pay for utility screening. Applicant partial reports show current document self-checks, not utility approval. Utility screening remains a separate authority over submitted packages. The developer capacity selector does not change the MW units in utility batch CSVs. ## Salesforce pilot preparation Utility account settings link to **Manage Salesforce**. Its four authenticated integration operations and automatic service package creation are implemented but disabled by default. Setup requires an exact utility sandbox, approved mapping and review profile, individual reviewer links, and separately granted automation authority. Follow the [pilot preparation guide](/docs-site/integrations/salesforce); source implementation does not establish a live integration. ## Who Is This For? Utility interconnection engineers and queue managers responsible for reviewing grid connection applications. GridWonk automates the most time-consuming parts of your review process — document screening, deficiency detection, and applicant communications — so your team can focus on engineering judgment. ## What You Get When an applicant completes a confirmed PDF split, current reviews cover the resulting documents. The original and its earlier findings remain historical; they do not inflate current findings or packet counts. This does not change utility review authority or an already frozen package. - **Automated application screening** — AI agents analyze selected submissions for completeness, compliance, and site control issues - **Deficiency notice generation** — AI drafts structured notices with requirement citations, ready for your review and approval - **Email delivery** — Send branded deficiency notices directly to applicants with one click - **Cross-org visibility** — Developers on the platform can view notices for their own applications - **Project-first resubmission flow** — Review the current application state while preserving prior submitted package history - **Discovery feedback** — Rate and correct the AI's understanding of your interconnection procedures ## The Utility Workspace Every utility organization uses the utility workspace on the same shell as the developer console: a left rail of global destinations, a header that hosts the selected application's views, a jobs tray, and a `Cmd+K` destination palette. | Rail destination | Purpose | |------------------|---------| | **Applications** | The application queue. Upload batches, filter by status, trigger screening, and open an application. | | **Notices** | Draft, review, approve, and send deficiency notices. Track notice rounds and applicant responses. | | **Rules & Sources** | **Packet Requirements** (approve or reject each published role-based requirement) and **Procedures** (confirm which source documents are current). | | **Analytics** | Queue health metrics and compliance trend reporting as those features are enabled. | A selected application shows **Overview**, **Documents**, **Review**, **Communications**, and **History** in the header. An application the utility originated itself starts as a draft in intake; **Freeze package** in the header turns its current documents into the immutable package that review, adjudication, and notices work from. Every destination has a shareable address (`/utility?view=applications&app=…`), and older `?tab=` links open the matching destination. On **Review**, each finding of the submitted package's review also shows the applicant's own response when they gave one: **Applicant confirmed** or **Applicant declined**, with the date and any reason. It is read-only context that helps you focus on findings the applicant agrees with; it does not change your adjudication, and you never see responses on the applicant's unsubmitted self-checks. The previous six-tab shell and base64 batch uploader are retired. The Applications V2 control still governs package reads and packet creation; disabling it hides both upload entry points and refuses package reads without restoring the old screen. ## Getting Started 1. **Verify your utility affiliation** — [Create your account and submit a claim](/docs-site/help/self-service#utility-affiliation). Staff verifies your authority before granting native utility access. Claim approval does not activate formal intake; state/program acceptance and reviewer eligibility remain separate. 2. **Navigate to the Utility Workspace** — Your org type determines which workspace you see after login 3. **Intake applications** — Applications is the default destination for daily work 4. **Review packet requirements** — In Rules & Sources, approve or reject each published role-based requirement and check its procedure citations 5. **Review procedures** — Confirm the source documents supporting those requirements are current and usable. In **Rules & Sources → Procedures**, pick a document from the list to preview the stored copy GridWonk indexed, the text extracted from it, and the utility's published link side by side, then confirm it or report a problem. The address includes `procDoc=`, so you can share a link to one document. A confirmation applies to the copy you viewed; if the stored copy is re-captured later, the document asks to be confirmed again. 6. **Screen and review** — Trigger screening, review findings, and generate deficiency notices 7. **Track notice and resubmission rounds** — Review the next resubmission against the same shared submission record without losing earlier submission history ## Current Procedure Review Procedure documents are the rulebooks GridWonk reads before it extracts requirements. The review status tells GridWonk whether a document can safely support customer-facing outputs. | Status | Reviewer meaning | |--------|------------------| | **Current usable** | Approved source document with completed text extraction. Requirements from this source can become customer-usable after requirement validation. | | **Pending review** | Found by GridWonk, but not approved as an authoritative source yet. | | **Deprecated** | Kept for history, but not used for new customer answers or validation. | | **Rejected** | Not the right source and not used for customer outputs. | Requirements also need source linkage. A validated requirement without a linked current usable procedure document is still a cleanup item, not a customer-facing rule. ## Reviewer Filters and Links The `/console` reviewer workflow includes temporary filters while current-procedure cleanup is underway. Documents filters: **Current usable**, **Pending review**, **Deprecated**, and **All reviewable**. Requirements filters: **Current usable**, **Pending source document**, **Deprecated source document**, **Missing source document**, and **All reviewable**. These filters are saved in the URL. Share the browser URL when you want another reviewer to open the same utility, state, view, interconnection level, and cleanup filter — inside Utility Research the URL also carries the `research` subview, as in `?view=utility-research&research=documents`. Older `?tab=` links still redirect to the matching current destination. Customer-facing users do not get the full cleanup view after enforcement. They see only the current usable source-backed set. ## Application Intake Developers may privately review packets by default for your utility's released full packet setups, both before and after your organization has accepted submissions. Those drafts and correction reviews are not in your queue. Formal GridWonk intake for each state and program requires GridWonk approval, acceptance by an active utility owner or admin, and an active qualified reviewer. Once accepted, reviewers receive an in-app receipt for each frozen package; revocation stops new submissions without removing earlier packages. Revocation does not stop developers already answering one of your deficiency notices from resubmitting their corrections. Manage acceptance under Settings → Integrations → Application packet submissions; see [Private Reviews and Utility Submissions](/docs-site/help/private-reviews-and-submissions). GridWonk supports three intake methods: | Method | Description | Status | |--------|-------------|--------| | **Batch upload** | Upload a CSV manifest with application metadata and select multiple PDF documents directly. PDFs are matched by filename prefix. | Available | | **Platform submission** | Developers explicitly submit a frozen package and its pinned report through the GridWonk developer console | Available only after the utility's state/program acceptance checks pass | | **Public API creation** | Programmatically create a utility-owned draft through the GridWonk API | Utility organizations have API and MCP access on by default, with self-service keys at `/utility/api-keys`. The utility lane provides draft creation, packet intake, screening, authorized human decisions, and notice reads and lifecycle operations through REST, SDK, and CLI. MCP provides permitted reads and reversible intake operations, but not formal decisions or notice writes. See [Utility Applications](/docs-site/api/utility-lane) for scope and authorization boundaries. | Applications the utility originates itself are owned by the utility organization (ADR-093): they can enter the same Storage-native intake and start utility screening through the same code developers use, and while their documents are still arriving they show the workflow state **Intake in progress**. That intake surface for utilities lands with the utility workspace; the batch upload below is the current utility path. Organization owners and admins reach the key page from the account settings sheet (**Integrations** tab, **Manage API keys**) or directly at `/utility/api-keys`. Keys can carry an optional expiry of 1 to 365 days. A platform admin can suspend one organization's API and MCP access, and every organization has request and screening budgets that refuse a call or run once they are reached. For batch uploads, prepare a CSV with columns for application number, project name, applicant name, email, capacity (MW), and generation type. Then select the corresponding PDF documents in the upload dialog. The utility batch-upload dialog does not accept ZIP bundles. A separate applicant-project ZIP control is implemented behind the storage-native intake and `ZIP_INGESTION` organization cohorts; it is not a utility batch-import format. ### Combined PDF status GridWonk can preserve a combined PDF as an immutable source container and record proposed page ranges and derived-document lineage. The human-confirmation workflow is enabled by default per applicant organization (the `COMBINED_SPLIT` env dial or a per-organization feature toggle can narrow or disable it). An applicant developer must confirm every page range and document role before separate packet documents are created; GridWonk never auto-applies the split. Utility and consultant org contexts are read-only for this action (a consultant acts only through a granted developer context with write access). After completion, queue counts, readiness, review, and submitted-package projections use the derived children and exclude the retained combined source. Existing uploads are unchanged unless a permitted applicant confirms a split. ### Native drawing status Native-CAD intake accepts one private DWG as an immutable companion to the current site-plan PDF for applicant organizations, regardless of utility. The PDF remains the packet's `site-plan`; the native drawing does not create a second document role. Replacing the DWG creates a new logical site-plan version, so a utility reviewer never sees an old drawing presented as evidence for a newer submission. When an exact package-pinned Autodesk derivative is ready, an authorized reviewer can open the site plan from **Documents**, switch between the sanitized PDF and native drawing, inspect layouts and layers, select entities, view properties, and measure geometry. A CAD finding includes an **Open native drawing** action that opens the same package-bound viewer at the implicated entity only when the source hash and every derivative identity still match. Package review never silently substitutes the developer's newer draft. Approximate and unresolved findings stay labeled and are not converted into PDF page boxes. Automated checks remain utility-specific through reviewed procedure profiles. NES is the first profile; adding another utility supplies its accepted procedure evidence and rules without changing the shared upload, derivative, evidence, or viewer pipelines. ## Interpreting the automated report **Review incomplete** means declared checks remain unresolved or coverage was not recorded. Valid deficiencies remain visible with their severity and evidence. An absent required document can be a deficiency while its content checks are not evaluated. Unknown evidence is not N/A; N/A requires evidence that the rule does not apply. No deficiency identified applies only to completed checks, never utility approval. See [Application Packet Review](/docs-site/help/packets) for the outcome meanings and coverage reasons. ## Automated Screening Pipeline When you trigger screening for selected applications, each application starts one whole-packet review run in the utility lane, the same engine that reviews a developer's packet before submission: 1. **Digitize** — Converts each current document version to extractable text 2. **Review** — Checks the whole packet against your utility's published packet requirements 3. **Findings** — Records each deficiency with severity, citation, and page reference 4. **Package** — For a packet your utility originated, the immutable package is frozen pinned to the completed run (automatically when the `utility-packet-screening` feature is on for your organization, otherwise with **Freeze package**) Automated review is switched on per utility. If your utility has not yet been onboarded for automated review, **Screen Selected** reports **Automated review is not yet available for this utility** for each row; the rows stay unchanged and notices stay manual. For formal applications in **Pending**, **Queued**, or **Resubmitted**, starting a review moves the application to **Screening** before work starts, then **Screened** when it completes. A failed start or run restores its prior status once no other utility review is active. Console, REST, SDK, CLI, and MCP starts follow the same workflow. Re-screening preserves existing human decisions and notice states; utility-owned drafts still use the package-freeze step above. **Screened** does not mean approval to interconnect. After current-procedure enforcement is on, site-control compliance uses only usable site-control requirements. If a utility has pending, deprecated, or unlinked site-control rows but no usable rows yet, screening may wait for cleanup instead of judging the application against unapproved rules. Packet review records findings and their severities. It does not produce a single score or grade. ## Deficiency Notice Lifecycle Notices follow a controlled workflow with human review and approval: 1. **Draft** — Begin a notice from the current package's accepted and edited findings, preserving their citations 2. **Review** — Edit the subject, body and existing findings in the split-pane composer; excluded findings require justification 3. **Approve** — An authorized member, admin or owner approves that exact saved content revision 4. **Send** — Save a delivery request and follow its queued, retrying, held or provider-accepted progress; Sent does not prove inbox delivery 5. **Acknowledge** — The developer views the notice and can acknowledge receipt Follow-up notices track the **round number** so you can see the full history of communications per application. Unresolved delivery blocks conflicting application decisions. Revoke Approval is available only before any delivery attempt; afterward resolve the delivery instead of resending. See [Notices](/docs-site/help/notices) for recovery and current-access rules. The dependent utility-event release records actual package, study, decision, and notice changes for your organization's webhook subscriptions. It does not make a decision on your behalf or turn automated review completion into human approval. Verified provider receipts are separate delivery evidence, not applicant acknowledgment. Schema activation, provider setup, and production release require separate approval; see [Webhooks](/docs-site/integrations/webhooks#utility-events). After a sent notice, a developer organization can select **Start response** from its project Overview or Review view. Utility and GridWonk reviewer organizations do not receive that developer-only control. Starting the response moves the project into `resubmission_under_development` and records the stage change in application history, so the next working-document round is traceable without changing the earlier submitted package. When the developer resubmits, the corrected immutable package returns to **Pending**. Select **Screen Selected** to run the whole-packet utility review; completed screening enables the decision on that current package. ## Cross-Org Visibility When an applicant's organization is on the GridWonk platform, they can view notices sent to them through their own developer console. This creates a shared record of communications without email-only tracking. The important ownership rule is: - the utility organization still owns the queue and review workflow - the developer organization is linked as the applicant on the same submission - consultants join only through grants when that access is explicitly configured ## Nashville Electric Service Pilot Cleanup Nashville Electric Service (NES) is the first pilot cleanup for this model. Cleanup means reviewers decide which NES procedure documents are authoritative, approve and digitize those documents, re-extract and validate site-control requirements from them, and retire or migrate older unlinked or deprecated-derived rows. During that cleanup, NES may show fewer customer-facing site-control results than reviewers can see in the cleanup filters. That is expected until the approved source-backed NES requirement set is ready. ## Energy Source Support | Availability | Sources | |-------------|---------| | **Supported intake values** | Solar, wind, storage, gas, hybrid, nuclear, hydro, coal, load, other | | **Reviewed during screening** | Any supported value when the uploaded application and utility procedure sources provide enough evidence | | **Not separate intake values today** | Fuel cell and geothermal; use `other` until dedicated intake metadata is added | ## Programmatic utility work Owners and administrators can create an organization key at `/utility/api-keys` after ordinary onboarding, then exchange it for a token with `partner.read`, `partner.write`, or both. The token selects the utility organization; an application ID never grants access to another utility. Use the [utility lane guide](/docs-site/api/utility-lane) for application reads, screening starts, and the REST, SDK, and CLI decision workflow. Screening automation uses the shared review budget and may be started through MCP. Manual freeze, adjudication, screening completion, and study requirements remain human decisions and are excluded from MCP. These interfaces use the same cores as the console; they do not add notice sending or make completed screening an approval to interconnect. ## Next Steps - [Utility Applications API](/docs-site/api/utility-lane) — Screen applications and record package-bound human decisions through REST, SDK, or CLI; MCP can start screening but cannot make these decisions - [Application Queue](/docs-site/help/applications#application-and-review-lifecycle) — Managing the application queue - [Screening Pipeline](/docs-site/help/screening#the-screening-pipeline) — How packet review works and how to interpret historical scores - [Deficiency Notices](/docs-site/help/notices) — The full notice workflow - [Help Center](/docs-site/help/documents) — All feature documentation --- # Quick Start Get up and running with GridWonk in minutes. URL: /docs-site/getting-started ## Account and processing availability When registration is enabled, [create or join a workspace](/docs-site/help/self-service), complete email verification, and accept the current terms and privacy policy. Utility affiliation is reviewed separately. The [public plugin](/docs-site/help/connected-apps) binds your own sign-in to one workspace when its rollout is available. Trial and prepaid workspaces use supported project packet intake and review within their [processing allowances](/docs-site/help/processing). Standalone legacy digitization, unrestricted assistant chat, and native DWG processing are unavailable for those workspaces. ## Background updates During the gated permission-aware rollout, brief interruptions and successful periodic refreshes stay quiet. The header distinguishes connecting, actual reconnect attempts, offline status, and unavailable updates. **Retry updates** does not reload the page or start a new processing job; expired sessions offer **Sign in**. Existing tabs need a refresh after activation. See [the exact messages](/docs-site/help/jobs). ## Choose Your Path - **[For External Users](/docs-site/getting-started/for-external-users)** — Customers, partners, and coding agents connecting through the UI, CLI, API, or MCP - **[For Developers](/docs-site/getting-started/for-developers)** — Validating interconnection applications before submission - **[For Utilities](/docs-site/getting-started/for-utilities)** — Integrating GridWonk into review workflows - **[For Consultants](/docs-site/getting-started/for-consultants)** — Managing workflows across multiple clients Start with the external guide for API, CLI, MCP, or partner setup. GridWonk platform admins also see a protected internal-operator guide in their docs navigation. If you need workflow-specific product context, use the developer, utility, or consultant guides. ## Console Workflow Overview The GridWonk console supports both research and project work: 1. **Select Utility and Program** — Choose your utility from the dropdown in the header; a program chip or the skippable program step lands you on the interconnection program you care about, and the header then reads **Utility › Program**. Authorized synthetic test utilities are labeled **Synthetic** and name the canonical utility whose requirements they use. 2. **View Documents** — See the program’s reviewed source documents in order, each with its Role (what it covers), which programs it feeds, and how many published requirements cite it; **All programs** shows every document grouped by role. 3. **Confirm Current Sources** — Developer organizations see customer-usable active records; authorized reviewer organizations also receive historical review controls. 4. **Review Published Requirements** — Read the selected utility's versioned Packet Intake requirements, review status, and source links without creating a project. 5. **Prepare Draft Files** — Collect the supported files for your packet. Trial and prepaid workspaces upload through the project intake flow after project creation. 6. **Create or Select a Project** — Before validation, choose a project or create one with a project name, capacity, and distribution/transmission track. You do not enter a utility application number here. A synthetic selection is re-authorized on the server and routes only to its reciprocally paired test utility. 7. **Review the packet where available** — For supported utility, state, and program combinations, eligible projects automatically advance from document checks to packet review after their required evidence is ready. Use the compact **Review Actions** menu for a deliberate manual run or rerun and to open review history. The developer console defaults to the applicant self-check; utility teams screen from their utility organization context. Existing projects outside supported coverage explain that automated review is not yet available. Research can stay projectless. Durable outputs such as validation results, deficiencies, scorecards, reports, and remediation status are project-scoped. The **Create Project** utility picker requires a released, full packet setup for the chosen state and program. By default, a normal utility choice does not require a receiving organization for private review. Authorized synthetic choices use a validated test pairing backed by a released utility instead. A Research selection must also qualify before you can create a project. The support check starts as soon as the dialog opens; choose another utility if yours is unsupported, or use **Retry** to run the check again if it fails. **Utility Research** keeps the full catalog; packet review coverage depends on the utility's supported state and interconnection program. Contact support for incomplete utility setup. Availability does not guarantee exhaustive coverage, utility approval, or permission to submit a packet; formal submission requires the utility's accepted intake lane and active reviewer. **Create Project** can include optional documents. Valid selections collapse to a file count and removable list; use **Add files** to add more. Invalid additions leave accepted files in place. **Create and upload** starts upload on Documents only after the project exists. On a short screen, scroll the form; its title and action buttons remain visible. Project capacity defaults to kW, with an explicit MW selector. Current document checks immediately populate findings and a partial report while the full packet review is outstanding. A partial report is neither utility approval nor proof that the packet is ready to submit. Existing site-plan cards offer **Attach DWG**; utility/process policy determines whether that companion is required. Completed current document findings stay visible during running, failed or cancelled packet reviews, labeled as individual-document results. Authorized reviewers can use **Review Actions → Cancel Packet Review** without deleting those findings. Read any cancellation warning: a provider request already running may finish in the background. See [Document troubleshooting](/docs-site/help/document-troubleshooting#a-packet-review-appears-stuck) before retrying a stuck review. In a developer organization, the star on each Utility Selector row watches that utility for requirement changes. The project header does not carry a separate watch control because the subscription belongs to the utility, not the currently open project. Inside a project, the Overview, Documents, Review, and Activity views switch the workspace. Those view controls and the back-to-projects control sit in the top header. The review work area carries a collapsible findings panel and a full-screen document mode, and opening Review temporarily collapses the sidebar to its icon rail — the automatic collapse is never saved as your preference; only your own toggle persists. `Cmd+K` (`Ctrl+K` on Windows/Linux) opens a command palette that jumps to any destination — including the Utility Research views — plus the project views and review tabs. It stays available while a Review toolbar disclosure such as readiness or the document switcher is open, and steps aside only for a full dialog. The console does not spend permanent header space on healthy connections or successful periodic refreshes. Sustained interruptions show the connection or recovery message described above. **Retry updates** refreshes data when coverage is incomplete; it does not restart processing. Research access starts in the developer-safe mode while GridWonk resolves the active organization, so a reviewer workspace does not briefly expose broader history before its permissions are known. Developer Utility Research shows active distribution documents only; the status filter, level toggle and refresh control are reviewer tools. Deprecated and rejected sources never appear for developers. ## Source-Backed Outputs Customer-facing answers and validation depend on source-backed material. A procedure document is the utility rulebook. A published Packet Intake requirement is the structured rule GridWonk serves from its controlled, versioned catalog. Published requirement views return every technically published row except one with a current utility rejection. Each returned row is marked `approved` or `pending`, so unfinished review stays visible without being mistaken for approval. Packet evaluation uses its pinned published set rather than mixing in the frozen legacy table. On a finding, **Explain this finding** shows exact quotations from the saved review's original source edition after checking your current access. It can show nearby source wording, but it does not guess which section governs the requirement or whether that wording applies to your equipment. Follow-ups retain the selected finding until you choose **Clear finding**; clearing starts a fresh conversational context, and changing user, organization, or project clears the selection. Missing or incomplete evidence produces an explicit limitation. This is not a new drawing inspection or a pass/fail decision. See [the assistant guide](/docs-site/help/assistant#explain-a-review-finding). ## Navigation Basics - **Left sidebar icons** — Navigate between main views - **Project views** — Inside a project, switch between Overview, Documents, Review, and Activity from the app header - **Help button** — Open the help sheet from the left sidebar's Help & Support action - **AI Assistant** — Chat button opens conversational help - **Reviewer URLs** — Reviewer filters in `/console` are saved in the URL, so utility teams can share links to a specific utility, state, view, and cleanup filter The global rail contains **Projects**, **File Library**, and **Utility Research**. Eligible developer organizations in the packet-review-checks cohort also receive **Checks**, a queue of projects with completed checks; open a project from the queue or use its previous/next controls to move through that queue. A selected project contains **Overview**, **Documents**, **Review**, and **Activity**. One shared toolbar stays above all four project views and shows the current developer action: **Submit Project**, **Start Response**, or **Resubmit Project**. It shows no action while the utility owns the next step. Returning to Review after changing document roles or confirmations refreshes its readiness row. Utility Research has its own shareable destinations: `?view=utility-research&research=documents` and `?view=utility-research&research=requirements`. Older `?tab=` links still redirect to the matching current destination. The Analytics destination has been removed: `?view=analytics`, the legacy `?tab=analytics` links, and `/console/queue-analytics` all land on Projects. Interconnection queue retrieval has been retired across every surface. When you change or clear the selected project, GridWonk also clears any packet-review selection so it cannot carry into a different project or projectless research. Leaving a project with the back-to-projects control clears the whole project address — the project, its packet run, the open document, and the project subview and Review tab — so a shared link never describes a project view with no project. Switching to another rail destination instead keeps that subview and tab, so returning to Projects restores the workspace you left. Re-opening a project always starts on Overview. If a saved project link points to an archived project or one that is unavailable to the active organization, the console blocks all project subviews and provides **Return to projects**. An old link cannot open that project's Documents, Review, or Activity content. When the availability check itself fails — for example during a temporary connection problem — the console instead shows **Couldn't load this project** with **Try again**, because the project may still exist. For a developer organization with a sent deficiency notice, the project-view toolbar shows **Start Response**. The action records the response-stage transition, unlocks the working set, and then changes to **Resubmit Project**; reviewer organizations do not see this developer-only control. If another teammate already started the response, refreshing shows the new stage without creating a duplicate history entry. ## Keyboard Shortcuts - `Cmd+B` / `Ctrl+B` — Toggle sidebar expanded/collapsed - `Enter` — Send message in chat - `Shift+Enter` — New line in chat input ## Find notifications Use the notification bell in the shared header or the Console and Utility workspace header, including on mobile. When enabled, new client-access alerts appear there independently of email. Opening the inbox does not mark alerts read; use **Mark read** or **Dismiss** explicitly. --- # Access Grants Control cross-organization access with grants for consultants and partners. URL: /docs-site/help/access-grants ## What Are Access Grants? Access grants are the mechanism that allows consultant organizations to access data belonging to utility or developer organizations. When a utility grants access to a consulting firm, that firm's members can view and work with the utility's data — scoped to specific access levels and, optionally, specific submissions or projects. Grants are the foundation of GridWonk's multi-organization collaboration model. They enable consultants to work across multiple clients from a single account without sharing credentials or duplicating data. They do **not** change who owns a shared submission row. In the project-first lifecycle: - the utility still owns the review workflow row - the developer still appears as the applicant side of that row - the consultant joins through the grant, with scope and audit rules layered on top An access grant never creates a utility affiliation. Utility-review authority comes from a platform-provisioned utility organization and its active membership; grants only add the scoped client access described below. An admin-level client grant does not permit changing the client's **Workspace appearance**. That setting requires direct Owner/Admin membership in the developer or utility organization, or authorized platform support. Previewing or saving colors never widens a grant or changes the sign-in domain. See [Workspace appearance](/docs-site/help/organizations#workspace-appearance). ### How grant-based access is decided ## Access Levels Each grant specifies an access level that controls what the receiving organization can do. | Access Level | View Data | Mutate Scoped Workflows | Admin-Level Grant Operations | |--------------|-----------|-------------------------|------------------------------| | **Read** | Yes | No | No | | **Write** | Yes | Yes | No | | **Admin** | Yes | Yes | Yes, where the target workflow supports grant-based admin access | The grant level and the receiving user's membership role are both enforced. A write or admin grant does not make a Viewer a writer: grant-aware mutations require an active **Member**, **Admin**, or **Owner** role in the receiving consultant organization. A grant also does not make that user a member or owner of the client organization. - **Read** — View documents, deficiency reports, validation results, and dashboard statistics for the granting organization. - **Write** — Everything in Read, plus grant-aware mutations supported by the target workflow when the receiving user is Member-or-higher. - Some workflows still require direct membership even when you have a write grant; project creation is the main example today. - **Admin** — Everything in Write, plus admin-level access for grant-aware workflows that explicitly support it. This is not the same as organization ownership or GridWonk platform-admin access, and it does not include the workspace Features page — feature toggles require direct admin or owner membership in the organization, and settings made by the GridWonk platform team appear read-only there (support can change them). ## How Grants Are Created Only **admin** or **owner** members of the granting organization can create access grants. The process works as follows: 1. A utility (or developer) org admin uses the consultant access hub or organization grant management UI 2. They select the consultant organization to grant access to 3. They choose an access level (read, write, or admin) 4. Optionally, they scope the grant to specific submission or project records 5. Optionally, they set an expiration date Grants can only be issued to organizations with the **consultant** organization type. You cannot grant access to another utility or developer organization, or to the internal GridWonk platform organization. The API also blocks self-grants, duplicate active grants for the same organization pair, and grants to non-consultant receiving organizations. Grant create and update requests are bounded to 32 KiB before JSON parsing. Project-scoped grants accept at most 500 project identifiers, and each identifier is length-limited before it reaches the database. Invalid or oversized request bodies fail before grant state is read or written. ## Submission And Project Scoping By default, a grant provides access to all grant-aware work within the granting organization. For tighter control, grants can be scoped to specific submission or project records. The consultant access hub labels this field as scoped submission IDs. When a grant includes project scoping: - The consultant can only view and interact with the specified submission or project scope - Other out-of-scope work in the organization remains invisible - API requests outside the allowed scope return an authorization error Shared-submission access resolves the submission, application-document, deficiency, and applicant document context before checking the caller's organization or owner-user scope. That keeps legacy applicant documents, project-linked documents, and deficiency findings on one read decision path. Organization API keys can use that path only for organization-visible applicant documents; private and individually shared rows remain user-scoped even when a project grant exists. Grant scoping controls what an API key can reach — whether an organization has API access at all is provisioned by GridWonk and is not something a grant or an organization admin can change. Organization-setting updates are rate-limited separately from grant access and may need to be retried after HTTP 429. This is useful when a consultant is engaged for a specific interconnection application rather than managing an entire portfolio. ## Grant Expiration Grants can include an optional expiration date. When set: - The grant remains active until the expiration date passes - After expiration, all access is automatically revoked — no manual intervention required - Expired grants still appear in the grant history for audit purposes - Users attempting to access data through an expired grant receive an authorization error If no expiration date is set, the grant remains active indefinitely until manually revoked. ## Viewing Active Grants Both granting and receiving organizations can view their grants: - **Granting organizations** see a list of all grants they have issued, including the receiving organization name, access level, project scope, and expiration status. - **Receiving organizations** (consultants) see a list of all grants they have received, showing which clients have given them access and at what level. The grant listing supports filtering by direction (granted vs. received) and can optionally include expired grants for audit review. When a consultant is working through a grant, the workspace shows a grant banner with the access level, granting organization, project scope count, and expiration date when present. ## Revoking a Grant When access needs to be removed, grants use a **soft-delete model**: - Revocation sets a `revokedAt` timestamp on the grant record - The grant is not physically deleted from the database - Revoked grants no longer authorize any data access - The full grant history remains available for compliance auditing Only admin or owner members of the **granting** organization can revoke grants. ## Audit Trail Grant records and consultant actions preserve compliance evidence: - **Creation** — The grant records who created it, when, and with what parameters - **Access** — Consultant actions performed under a grant are recorded in the consultant audit log - **Revocation** — Revoked grants preserve their history and record the revocation timestamp The consultant audit log captures the actor, the consultant organization, the client organization, the grant ID, the action performed, the resource type and ID, and a timestamp for grant-scoped workflow actions. ## Who Can Manage Grants | Action | Viewer | Member | Admin | Owner | |--------|--------|--------|-------|-------| | View grants | Yes | Yes | Yes | Yes | | Create grants | No | No | Yes | Yes | | Revoke grants | No | No | Yes | Yes | Platform administrators (GridWonk staff) can also manage grants across all organizations for support purposes. ## Organization Switcher Consultants use the **Organization and role** selector to choose a client directly from their accessible organizations. You do not need to select your consulting organization first or visit Consultant Access. The selector shows the active organization and persona so the authorization context is visible before a user opens or changes project data. When a consultant switches to a client organization: - The dashboard updates to show that client's data - All actions are performed within the scope of the active grant - Project-level scoping is automatically enforced - The grant's access level determines what actions are available This allows consultants to work across their full client portfolio without logging in and out of separate accounts. On desktop dashboard and Consultant Access pages, the selector is in the header. In Console and Utility workspaces, expand the sidebar and find it above your account button. Choosing an organization saves it as your default. On production, switching reloads the current page; open **Console** for a developer client or the **Utility** workspace for a utility client afterward. Select the client before opening a project link: links do not silently change organization context. Alternatively, select your consulting organization and open [Consultant Access](https://gridwonk.com/consultant). Under **Client Organization Access**, inspect the client's level and scope, then choose **Switch**. This changes the active organization without changing your saved default. The lower **Incoming grants** list loads with **Refresh Grants**; an initially empty lower list does not mean you have no access. ### Email and bell alerts (when enabled) New-grant notifications are disabled by default pending approved rollout. When enabled, a new usable grant creates an unread bell alert for each eligible active member. Email is independently controlled. Existing grants and later membership joins do not generate historical alerts. The alert remains discoverable after login, including with another organization selected. **View client access** opens `/consultant`; it does not switch organizations or accept an invitation. Select the receiving consulting organization if needed and choose the client there. Marking read, dismissing, and navigating are separate controls. Read/dismiss choices are saved across devices. If an alert becomes inaccessible, the inbox explains that it is no longer available instead of reporting a successful update. Repeating an already accepted read or dismissal remains safe. After an account or organization changes in another tab, save your open work before choosing **Reload workspace**; notifications never silently switch the page to the new context. If a client is missing, check your signed-in email and active, unexpired consulting membership; then ask the client administrator to confirm the receiving organization, scope, expiration, and revocation state. Reload after a new grant. Email is not an access credential, and stale grants disappear from the actionable inbox. **No scheduled expiration** means no date was set, not guaranteed permanent access. If GridWonk asks you to accept updated legal terms, do that before retrying an action or using a client-data API. A valid grant does not bypass that requirement. ## Tips - Start with **read** access and upgrade to write or admin as the engagement deepens - Use project-level scoping for short-term or narrowly focused engagements - Set expiration dates that align with your contract terms - Review active grants periodically — revoke any that are no longer needed - Check the consultant audit log if you need to verify what actions a consultant has taken --- # Applications Application queue management, batch upload, and screening for utility interconnection reviewers. URL: /docs-site/help/applications ## Trial and prepaid screening An eligible utility review uses the utility workspace's [processing allowance](/docs-site/help/processing) and the exact submitted package. The applicant's private review remains separate. A saved usable packet report consumes one review credit; reading existing authorized reports does not. Completed screening is decision support and does not automatically approve the application or send a notice. The public plugin can perform eligible intake and review operations and read the resulting application history within its confirmed workspace. Package submission, adjudication, and notice writes remain website workflows. Switching the website's active workspace does not retarget the plugin connection. Applicant self-check findings and partial reports remain distinct from utility screening and approval. This change does not grant applicants utility review authority or alter package-pinned utility review. After an applicant-confirmed PDF split completes, current findings and packet counts use the resulting documents, not the retained original. Earlier findings remain available in history. New review starts and submission pause while a confirmed split is pending or failed; the applicant can inspect progress, retry, or keep the original from **More actions → Split PDF**. ## Salesforce packet pilot [Salesforce-sourced reviews](/docs-site/integrations/salesforce) are implemented but disabled pending acceptance. A source application keeps one application identity through captured revisions. Queue filtering checks the linked reviewer's current Salesforce access before pagination and counts. More than 200 source candidates require narrower filters. Automatic human- and service-owned package creation is implemented; the real utility sandbox pilot remains unverified. If Salesforce permission checks are temporarily unavailable, ordinary applications and successfully authorized Salesforce applications remain usable. The list warning and partial count labels explain that unverified Salesforce applications are hidden and excluded from totals. Use **Refresh** to retry live permission checks. An empty partial list does not mean there are no applications. Application-list database query failures still report an error. ## Application Queue Overview Pending, held or provider-accepted-but-unfinalized notice delivery blocks conflicting review, package and response-stage changes. Check the request in **Notices** and resolve its status before retrying the application change. Provider acceptance alone is not inbox delivery. An exact retry of an active screening job reuses it without another review-budget charge, even when the reviewing utility has reached its review cap. Request-rate limits still apply. Manual freeze remains limited to the utility's own draft. A study requirement saved after screening applies to the next submission, leaving the frozen package and its report unchanged. Saving the same normalized study requirement again preserves its existing version. The dependent utility-event release records actual package and decision changes for receiving-utility webhook subscriptions; retries do not create another change. These integration events do not alter queue counts, screening authority, or the distinction between an automated review and a human decision. Schema activation and production release remain separate approval gates. The Applications tab is your central view for managing incoming interconnection applications. It shows all submissions for your utility organization with filtering, sorting, and batch operations. The server resolves your organization's feature settings before it selects the queue layout and workflow-status data. A setting for one organization cannot expose or change another organization's applications. Archived synthetic demo submissions remain available as audit history but do not appear as active queue work. An approved synthetic developer may test several utilities. Each utility's queue remains scoped to its own organization; adding another destination does not combine utility reviewer queues. Test-account status comes from protected organization settings, not an organization name or a browser-supplied label. Synthetic packet routing requires the developer and utility organizations to name each other and agree on the real utility whose requirements apply. An invalid pairing is rejected instead of sending the test project to a real utility's queue. A test label never grants review or cancellation authority. Utility-side applications still use the utility application number as the formal queue identifier. Developer console projects use a project name first, and GridWonk keeps any temporary internal reference hidden until an official utility application number exists. The customer API, SDK, CLI, and MCP surfaces reuse that same generated-reference rule, so creating or reading a draft outside the console does not produce a second project identity. ### Workspace v2 Every utility organization sees the queue as the **Applications** rail destination. Opening a row selects the application (`?view=applications&app=…`): its views — Overview, Documents, Review, Communications, History — move into the header, and the back control returns to the queue. An application the utility originated itself opens on the draft workspace (the same Documents and Review views developers use) until **Freeze package** turns its documents into the immutable package the reviewer flows below work from. `Cmd+K` opens the destination palette. Old six-tab bookmarks redirect to the matching destination. The Applications V2 feature still controls package reads and both upload entry points; disabling it does not restore the removed shell or base64 uploader. ### Utility-owned packets and developer details A packet created by your utility stays owned by your utility and private to its authorized staff by default. Entering a developer's name or contact information records who the project concerns; it does not create an account, invite anyone, transfer ownership, or give that developer access. An unknown developer does not prevent intake or internal review. Developer invitations are not part of this release. For your own editable packet, open **Overview** → **Human confirmations** to complete any required placard, native CAD delivery, or study-documentation confirmation. You must be a direct, active member of the utility with write access; a viewer role, a grant from another organization, or an impersonated session cannot supply that authority. Confirm facts yourself, including placard placement, materials, mounting, and contacts—not just what a drawing appears to show. The saved record is labeled **Confirmed by utility staff** and retains the staff member, organization, time, and exact document versions. It does not sign a customer's declaration. Replacing a linked document requires a new confirmation. See [Human confirmations](/docs-site/help/packets#human-confirmations). These controls do not let utility staff change confirmations on an applicant-owned packet. Your own packet's review remains utility screening, with the utility as payer; recording a developer does not turn it into an applicant self-check. Existing budgets and readiness requirements still apply. The utility-owned confirmation and review repair requires the reviewed database migration and matching application deployment. Until both are active, a blocked review is not a passed review; do not create a dummy developer or change ownership to work around it. ## Two Status Families GridWonk tracks two related but different kinds of status: 1. **Submission stage** — where the applicant is in the formal submit/resubmit lifecycle 2. **Review workflow status** — where the utility is in screening and notice handling ### Submission stage | Stage | Description | |--------|-------------| | **Draft** | Project exists, but no formal submission has been sent yet | | **Submitted** | A formal submission package has been sent to the utility | | **Resubmission Under Development** | The applicant is revising the live project state after a notice | | **Resubmitted** | A new formal resubmission package has been sent | | **Withdrawn / Closed** | The submission is no longer active | ### Review workflow status Each utility-side review row also progresses through a review workflow: | Status | Description | |--------|-------------| | **Pending** | Received but not yet queued for screening | | **Queued** | History only: the retired per-document screening's waiting state | | **Screening** | A whole-packet review run is in progress | | **Screened** | Screening complete, results available for review | | **Notice Draft** | A deficiency notice has been drafted | | **Notice Sent** | Provider acceptance and the canonical notice/application update are finalized; inbox delivery is not confirmed | | **Resubmitted** | Applicant has resubmitted after addressing deficiencies | | **Complete** | Application review is complete | The key idea is that a submission can remain the same project while moving through multiple review states and notice rounds. Applications the utility originated itself (batch intake or a utility-created project) are owned by the utility organization (ADR-093). While their documents are still arriving they show the display state **Intake in progress** with the utility as the responsible party. That state comes from the shared workflow-status service, not from a new `screening_status` value; developer-submitted applications keep every state above. Each formal submit or resubmit creates an immutable package snapshot of the document versions sent in that round. Submit and resubmit both re-check the current actor, active organization, grant scope, linked documents, and project stage inside the locked packet mutation before committing the package. The applicant can continue changing the live project working set only in an allowed draft or resubmission-development stage; earlier packages remain frozen for review history. A developer's first project and packet review are private to the developer organization. The private review path is the default and remains available when Submit is enabled. Explicit Submit shares the frozen documents and the package-pinned packet report, not other private review history. The utility receives the application only after formal Submit, which checks that both GridWonk and the utility have accepted submissions for that state and program and that an active utility reviewer is available. A utility that has not completed this acceptance cannot receive a formal packet; the developer can continue preparing and reviewing the private project. A successful submission gives the utility's eligible reviewers an application link in their session inbox. An authorized utility owner or admin can manage acceptance under Settings → Integrations → Application packet submissions. GridWonk approves the same state and program separately; either party can stop future submissions without changing packages already received. Acceptance gates only the first formal Submit. A resubmission after a deficiency notice goes to the utility that already accepted the original package, so it is not blocked if that utility later stops accepting new submissions. If no qualified reviewer is available at that moment, the resubmission is still delivered and stored, but no reviewer receives an in-app notice. See [Private Reviews and Utility Submissions](/docs-site/help/private-reviews-and-submissions). When a packaged site-plan version has a native DWG companion, the snapshot also pins that exact companion asset and its SHA-256 file fingerprint. Replacing the DWG later creates a new live logical version and does not rewrite the package the utility already received. Authorized utility readers see the safe attachment name, size, and drawing-version label on the submitted package. From **Documents**, they can open the site plan and switch between its sanitized PDF and authorized native-drawing derivative. From **Review**, an exact CAD finding opens that same package-bound drawing at the matching entity; an identity mismatch is refused instead of showing a stale location. Utility readers cannot upload or replace the applicant's DWG, and the browser never receives the private native file bytes through these views. ### Developer response stage Applicant submit and resubmit refuse an unfinished, unexpired upload batch before freezing a package. Finish or cancel that batch first; already accepted documents and earlier packages remain. After a deficiency notice is sent, a developer organization can select **Start response** from project Overview or Review. The action moves the live project into **Resubmission Under Development** and records the transition in application history. Utility and GridWonk reviewer organizations do not receive that developer-only control; they continue to track the shared stage and later resubmission from the queue. Repeating the action after a teammate already started the response is safe and does not create a duplicate history row. Review history remains available, but the active Screening view and notice workflow use findings for the current document generations only. When a linked document is replaced, earlier findings are hidden until the replacement is reviewed. Consultants working from their own consultant organization do not receive developer-only lifecycle controls. When a consultant switches into a granted developer-client context, submit, start response, and resubmit still re-check the consultant's receiving-org membership, write-capable grant, grant scope, and project state inside the locked mutation. Read-only grants and out-of-scope project grants can still view allowed records, but they cannot change the application lifecycle. ### Application and review lifecycle ## Viewing the Queue The queue table supports: - **Sorting** — Click any column header to sort (application number, project name, status, date) - **Filtering** — Filter by status or generation type - **Search** — Search by application number, project name, or applicant name - **Pagination** — Navigate large queues in pages of 50 rows ## Batch Upload Workflow To upload multiple applications at once: Use the secure intake paths below. The former PDF-only base64 dialog is retired. ### Upload packet (workspace v2) **Upload packet** starts one application without a CSV. Nothing is required up front: project name, application number, capacity, and connection level are all optional, and a blank application number gets a generated reference. The new draft opens on its Documents view so the files can be added immediately through the same secure intake. If the connection level or the program (for utilities that publish two or more) is still missing, the application's Overview asks for just that item; automated review cannot start until it is answered. Clicking Create twice, or retrying after a network error, returns the same draft instead of a second one. ### Batch intake (workspace v2) After a refresh, open the application's **Documents** in the same browser tab and account to recover an already reserved upload. Reselect the original unchanged files if prompted; the same batch and child identities are reused, including a pinned CAD target. Accepted files are not uploaded again. Recovery does not retain file contents or signed credentials. Dismissing its local record does not cancel server work; use the individual cancellation controls where available. A rejected new file selection shows an upload error without recovery controls. Correct the selection and try again. **Retry Recovery** is for account or saved-upload verification failures. When `utility-applications-v2` is enabled, **Upload Batch** uses secure document intake: the CSV manifest (required `application_number`; optional `project_name`, `applicant_name`, `applicant_email`, `capacity_mw`, `generation_type`, `state`, `interconnection_level`, `program`) creates one draft application per row, owned by the utility. Loose PDF, image, and DWG files are then matched to applications by filename prefix (`Q-2025-001_deed.pdf` → `Q-2025-001`; the remainder is shown as a hint only) and uploaded through the same secure intake developers use, one session per application. Document roles are assigned automatically and confirmed in the application's Documents view; **Freeze package** turns the documents into the immutable package that screening and notices work from. Utilities that publish two or more programs for a track must fill the `program` column with the program slug. ## Triggering Screening To screen applications: 1. Select one or more applications using the checkboxes 2. Click **Screen Selected** in the toolbar 3. Each application starts one whole-packet review run in the utility lane (`utility_screening`), the same engine that reviews a developer's packet before submission 4. Status updates appear in real time as the run progresses Formal-stage applications and the utility's own intake drafts (batch intake in progress) are eligible; developer drafts are not. A formal application in **Pending**, **Queued**, or **Resubmitted** moves to **Screening** when its review is queued, before work starts. It moves to **Screened** when the run completes. A failed start or run restores its previous status once no other utility review is active. These transitions also apply to authorized REST, SDK, CLI, and MCP screening starts, so the queue reflects reviews started outside the console. A pending notice-delivery hold keeps the application status unchanged even when the run ends; resolve delivery through **Notices**. Salesforce imports use their connector-specific status path. Re-screening preserves existing **Screened**, notice, and **Complete** states and their human decisions. An intake draft keeps its separate package-freeze transition, including automatic freezing where enabled. Each start counts against the same 50-reviews-per-hour limit as a single review. The result is reported per application: started rows leave the selection, and refused rows stay selected with the reason shown above the table. A utility that has not yet been onboarded for automated review sees **Automated review is not yet available for this utility**; its rows stay unchanged and notices stay manual. There is no fallback to the retired per-document screening pipeline. For platform-submitted applications, screening happens against the same shared submission record the developer sees from their side. The utility owns the queue row, but the linked applicant can still see the lifecycle that belongs to that submission. Document processing and AI review remain separate states. A failed or still-running current document artifact is not shown as reviewed merely because an older review completed. Resolve the current processing problem before relying on its findings or clean-review result. ## Queue Statistics The utility workspace context bar shows: - **Total applications** in your queue - **Pending screening** count - **Pending notices** count These values and the **Notices** navigation badge load when the Utility workspace opens, including when you follow a direct link to Screening, Notices, or Analytics. You do not need to open Applications first to refresh them. For an applicant packet whose combined PDF has been human-confirmed and split, document counts use the derived child documents and exclude the retained source container. This keeps queue totals, readiness, review, and immutable package contents aligned. ## CSV Export Click **Export CSV** in the toolbar to download the current filtered view as a spreadsheet for offline analysis or regulatory reporting. ## Related - [Screening Pipeline](/docs-site/help/screening) — How the AI screening works - [Deficiency Notices](/docs-site/help/notices) — Creating and sending notices - [For Utilities](/docs-site/getting-started/for-utilities) — Utility workspace overview ## Personal notifications The utility workspace header includes a notification bell on desktop and mobile. When client-access notifications are enabled, eligible consultants can discover new grants there without reading email. The bell does not change the selected organization, application ownership, or review authority. See [Access Grants](/docs-site/help/access-grants). --- # AI Assistant Using the GridWonk chatbot for interconnection guidance. URL: /docs-site/help/assistant ## Availability for trial and prepaid workspaces Unrestricted assistant chat is unavailable for workspaces enrolled in trial or prepaid processing. Enabling a chat channel or purchasing a pack does not remove that restriction. Use the supported [public plugin tools](/docs-site/api/mcp), packet intake and review, and public help instead. The channel behavior below applies where ordinary chat is authorized. See [processing allowances](/docs-site/help/processing). ## Self-service availability Self-service processing remains unlaunched. Packet-processing credit does not include the general Assistant: metered workspaces cannot start ordinary chat or finding-explanation turns. Connecting Slack or Teams does not enable those turns. The existing assistant controls below apply when your workspace is eligible for chat. ## Opening the Assistant Click the chat button to open the Assistant as a slide-out panel. The header shows the current utility context and includes controls to change width, minimize, or close the panel. The embedded assistant loads its chat engine when you first open it or choose **Explain this finding**. You may briefly see **Preparing assistant…**. A question submitted during loading waits for the engine; you do not need to submit it again. Closing or minimizing the panel keeps the conversation in the current context and does not cancel a pending question. ## Panel Controls The assistant header provides three controls: - **Width toggle** — Cycle between default, medium, and fullscreen widths - **Minimize** — Collapse the panel to a floating action button - **Close** — Dismiss the panel entirely ## Utility Context The assistant automatically syncs with your console utility selection. The current utility is displayed in the header bar. If no utility is selected, it shows "All Utilities" and can provide general interconnection guidance. When a project is selected, document questions use that application's current attachments, including teammate uploads you can access. These are different from your personal File Library: reviewing a packet does not require copying its files into your personal library or relinking them. If access cannot be verified, the assistant says so instead of claiming the packet has no documents. ## Explain a Review Finding Click **Explain this finding** on a finding to inspect that exact saved review result. The server checks your current project access and loads the source edition saved with that review. It verifies each quotation against that edition before showing it, with its document title and digitized page. This is a quotation-first explanation. The model can select relevant passages, but cannot write new quotations, section numbers, equipment definitions, or interpretations. Nearby text is labeled separately: being nearby does not prove that it governs the finding. The assistant explicitly leaves the governing section and project applicability unconfirmed. Ask the utility to confirm these before changing your drawing. It does not re-read the drawing or decide pass or fail. Common-practice and form-model findings are identified as such when a utility quotation cannot be verified. Indexed sources and published requirements are not necessarily human-approved. ### Follow Up or Change Topics The selected finding appears above the conversation. Typed follow-ups and retries keep that selection, so asking about its source does not turn into a general requirements list. Use **Clear finding** before changing topics, or select another finding to replace it. Changing the signed-in user, organization, or project clears the selection. Access is checked again on every turn; a saved conversation does not preserve revoked access. Finding follow-ups use freshly checked source passages, not earlier assistant claims. Clearing a finding starts a clean model conversation; earlier messages remain stored as history but are not reused as evidence or carried into that new conversation. ### When Evidence Is Unavailable The assistant stops the explanation and states the limitation if it cannot verify the exact saved evidence. This can happen with a document review saved before it recorded a per-finding source pin, a review that lacks a requirement snapshot, a rule derived from a form model whose printed field has not been verified, or a missing or changed source edition. Ambiguous quotations and reading limits can leave only partial evidence. In that case the assistant labels the limit and shows only quotations it could verify. If passage selection fails, it falls back to the saved quotations without adding an interpretation. The assistant does not substitute today's requirement or guess from the finding title. Reopen the finding from its review report or ask your reviewer to confirm its applicability. ## Supported Utilities The AI Assistant can use general utility context for **1,329+ EIA-backed utilities** across the United States. Select a utility and state for scoped guidance. Specialized extracted requirement coverage depends on the utility procedure documents that have been processed for that utility, state, and interconnection track. ## File Upload in Chat The web chat composer accepts attachments in its interface: - **Formats**: PDF or JSON files - **Limit**: Up to 5 files per message - **Size**: 10MB maximum per file The current web assistant submit path does not forward the selected file bytes for analysis. Upload the file in a project's **Documents** view for document processing and compliance validation; do not rely on a chat attachment as evidence that the assistant read the file. The web chat request itself is bounded before parsing. A serialized chat request over 256 KiB is rejected, and the downstream turn composer applies its own query and history limits. This keeps large client-supplied transcripts from becoming model input or process memory without changing the normal conversation flow. ## Suggested Queries When starting a new conversation, the assistant may show suggested queries based on your organization type. Utility users see queue-related prompts; developers see compliance and validation prompts. ## Quick Answers vs Tool Answers The assistant uses quick answers for stable GridWonk platform facts. It should use tools or extracted data for user-specific and utility-specific questions such as uploaded documents, validation results, and requirement lookups. Quick answers and documentation sources follow the active organization being viewed. A platform administrator impersonating a customer receives the same public-only assistant content as that customer; ending impersonation restores native administrator access. Conversation sessions and their persisted history are scoped to the signed-in user and active organization. Switching organizations cannot expose another organization's session, and session metadata is not an authorization input. Published requirement answers do not repeat a document-role label as though it were approved customer wording. When matching rows are still awaiting wording review, the assistant says so; its available-result count includes only requirements it can actually show in chat. If a requirements lookup returns no rows, the assistant keeps the reason supplied by the published reader. It distinguishes a scope in which every matching row was rejected by the utility from a utility with no technical publication. An unfinished utility review is not a reason for an empty answer — those rows are returned and reported as awaiting a utility decision. Explicit document-list or count questions can use the `query_user_documents` fast path. With a selected project, answers report its accessible current attachments. Packet questions about status or recency use tool-backed answers with recorded processing statuses and upload dates; a partial file list is not evidence of a whole-packet status count or review verdict. Explicit File Library or vault questions use your personal library even while a project is selected. Without a project, or when asking without a utility scope, personal inventory behavior is unchanged. None of these results means the assistant has read chat attachment bytes. An administrator can disable the assistant's **Database Access** capability. When it is disabled, database-backed utility lookups are unavailable and the assistant should say it cannot perform that lookup instead of returning unscoped or guessed data. The same control applies on every channel. ## Slack Assistant Skill Sets An organization administrator can enable **Assistant skill sets** from **Features** and assign versioned instruction bundles for interconnection research, project coordination, or deficiency review. These bundles guide how the Slack assistant structures an answer. They do not add tools, widen access to organization data, or bypass confirmation rules. Each assignment is organization scoped and audited; disabling the feature removes the bundles from later Slack turns. ## Set Up the Slack Assistant An organization administrator opens **Features**, enables **Slack assistant**, and chooses **Connect Slack** under **Chat platform connections**. After approving the correct workspace in Slack, return to Features and confirm that the connection is **Active**. Each member then opens the GridWonk app in Slack and sends a direct message. If prompted, follow the secure account-linking URL while signed in to the organization connected to that workspace. In a channel, invite the app if required, mention **@GridWonk**, and keep follow-ups in the same thread. Use `/gk context ` to set channel defaults. `/gk status` opens the GridWonk console for validation job monitoring; it does not display jobs inside Slack. For the complete setup, privacy, command, and troubleshooting guide, see [GridWonk for Slack](/docs-site/integrations/slack). ## Slack Agent View When the organization uses the current Slack product-bot manifest, GridWonk conversations open in Agent View. Slack's native stop control cancels the active turn, status updates show progress, and the adapter assigns an automatic session title. Follow-up context comes from the Agent View transcript; ordinary Slack direct-message history exposes only the user's side in this mode. Changing an existing Slack app to Agent View cannot be reversed. GridWonk schedules that manifest change in a maintenance window and verifies encrypted installation storage, OAuth scopes, event subscriptions, and stop behavior before enabling an organization. ## Deep Research in Slack When GridWonk enables **Deep Research** for an approved operator organization, start a run with: `/gk research [--sources=web,gridwonk,organization]` The default selects only current, approved procedure documents that back published packet-review requirements for a supported utility. Set utility and state context first. Paid web search is GridWonk-only, disabled by default, and selected only with `--sources=web`. Private organization documents are never selected by default; add `organization` explicitly and run the command only in a one-to-one direct message with the app. Public channels, private channels, group direct messages, and Slack Connect cannot use the private lane. A requested source lane must return usable evidence or the run fails instead of silently omitting that lane. GridWonk records provider usage for cost auditing even when a paid web search returns no usable sources and the run fails. Use `/gk research status [run-id]` to inspect progress and open the organization-scoped report. Private-run status and stop controls remain in the one-to-one direct message, and only the requester can open a report that used private sources. Use `/gk research stop [run-id]` to request cancellation before the next durable workflow step. Pilot limits are one active run per person, five per organization, three starts per person per hour, and 20 sources per report. ## Validation Activity When tool details are enabled, adjacent assistant steps appear together as expandable lines. Each tool line reads **Running**, **Ran**, or **Failed to run**, followed by the tool name. A completed call appears once, with its input parameters and results together when those details are enabled. Click to expand the tool details that the interface exposes. Tool input and output are useful audit context, but they are not a complete record of the model's internal analysis. ## Sources and Docs Visuals For docs-backed answers, expand **Used N sources** below the response to see the numbered source list. The numbers match inline citations in the answer. Linked sources open in a new tab; historical evidence without a document URL stays plain text. Docs sources use the page titles and links returned by the documentation tools. Repeated references to the same URL appear once. Explicit docs citations are limited to paths authorized for the active organization. Customer and impersonated sessions cannot retrieve or cite internal pages. The same list may also include older extracted source links when the response or tool output includes them. Some docs-backed answers may also include a compact docs visual card, such as a flow, lane, layer diagram, or approved docs image. The answer text carries the same meaning, so the visual is a reading aid rather than a separate source of truth. ## Reasoning Display When reasoning display is enabled, the line reads **Thinking…** while streaming, then **Thought** with the measured duration when available. Older turns without a measured duration simply read **Thought**. Expand the line to read the visible explanation; automatic closing follows the display settings, and you can reopen it. Treat it as a visible explanation or progress artifact, not as a complete transcript of hidden internal reasoning. ## Message Feedback After receiving a response, hover over the message to copy it or mark it as helpful or unhelpful. ## Timeout and Error Handling If a response takes longer than expected, the assistant shows progress and then a clear error with retry/dismiss controls when available. Use **Cancel request** to stop a pending question, including one waiting for the chat engine to load. If the engine itself cannot load, **Try Again** retries loading even when the conversation is empty. **Dismiss** clears that loading error without sending a question. If loading keeps failing, reload the page. ## Conversation Context The assistant carries the selected utility and state, messages in the current chat partition, and an active project or work context when available. For selected-project model answers, a bounded attachment summary is included only after current access and Database Access settings are checked. This summary contains filenames, roles, recorded processing statuses, and upload dates—not document contents. A selected finding additionally loads its authorized saved requirement and source evidence before an explanation; this does not read the applicant's drawing again. Other document and deficiency data still require authorized tool lookups. Changing the utility, state, or selected project can move you to a different chat partition. Check the context shown in the header and repeat any detail that is missing rather than assuming every prior conversation follows you. ## Source-Backed Requirement Answers For utility requirement questions, the assistant should prefer extracted requirement rows over generic platform guidance. Include the utility and state when you ask about site control, application fees, forms, or technical requirements. If the assistant does not have enough context, it may ask you to narrow the utility, state, or interconnection track. To check an uploaded document's processing or review status, open the project's **Documents** view. To reuse an eligible File Library file, choose **Attach from library** there instead of uploading a duplicate. Uploaded applicant documents and utility procedure documents are different sources. Uploaded documents are evidence you provide; procedure documents define the requirements used for validation. Requirement answers should keep the requested source in view. If extracted rows do not list a detail such as an easement, right-of-way, minimum lease term, exclusivity rule, shared site agreement, milestone, or timing rule, the assistant should say the detail is not listed rather than answer from general interconnection knowledge. ## Channel Availability GridWonk releases each channel per organization. The web console is on by default. The API, CLI and MCP assistant are off by default during the staged release, and Slack and Teams have their own workspace switches. If a channel is off for your organization, the assistant says so and answers nothing. Every channel — web chat, Slack, Microsoft Teams, the public API, MCP, and the CLI — uses the shared chatbot orchestration core for routing and canonical answers. The surrounding channel adapter, authentication, enabled tools, context supplied, and presentation can differ: - Same query classification and intelligent routing - Same canonical FAQ responses (instant, deterministic) - Utility/state-aware context when the channel supplies it - Tool-backed requirements and validation routing subject to that channel's authentication and enabled tools - Same requirements preflight guidance This shared core improves consistency, but it does not guarantee identical features or output on every channel. The saved-finding selection described above is a web-console feature. It does not give Slack, Teams, public API, MCP, or CLI callers access through your browser session. | Capability | Web console | Slack | Microsoft Teams | |---|---|---|---| | Shared assistant answers | Yes | Yes | Yes | | Agent View progress, stop, titles, and transcript | No | Yes, after activation | No | | Organization assistant skill sets | Configure only | Yes, when enabled | No | | Start, check, or stop Deep Research | No; completed reports open here | Managed pilot | No | Approved tool-backed assistant turns use Eve. Operators open Eve one channel at a time; a channel that is not enabled returns a temporary unavailable response instead of replaying the request through the Claude Agent SDK. Deterministic quick answers and direct conversational responses keep their existing lanes, and every enabled channel uses the same answer, citation, and terminal-error contract. For integration details, see [Chatbot Channels](/docs-site/integrations/chatbot-channels). For API access, see [Chat Streaming API](/docs-site/api/chat). ## Getting the Best Results 1. **Be specific** — "What are Duke Energy NC lease term requirements?" beats "What do I need?" 2. **Provide context** — Mention your project type and size when relevant 3. **Ask follow-ups** — Build on previous answers for deeper detail 4. **Upload documents in a project's Documents view** — The current web chat attachment control does not send file bytes for analysis 5. **Name the source you need** — Ask "what does the utility require?" for requirements, or "what have I uploaded?" for your own evidence --- # Connected apps Set up organization API, MCP and service connections, and manage your connected apps. URL: /docs-site/help/connected-apps ## Open organization Integrations Select your organization, then open **Integrations** in its workspace. Developers use `/console/integrations`, utilities use `/utility/integrations`, and consultants use `/consultant/integrations`. The page shows saved access separately from whether you can use it now: an enabled service can still need a connection or be unavailable because access is suspended. Reached-limit notices show a snapshot of API usage and screening budgets. They do not reserve capacity; the service checks the applicable budget again when you make a request. Organization owners and admins can create API keys when the platform has enabled API access and self-service key creation. Save each new secret when it is shown; it cannot be displayed again. Existing API-key pages remain available. Members retain their existing personal connection permissions and cannot manage organization keys or installations. Use the MCP setup instructions for the supported client and complete its credentials or sign-in flow. Enabling MCP does not connect a client automatically. Claude Desktop and Codex Desktop are the selected connection-testing targets; a setup screen alone does not prove live availability in either client. The public plugin's release and client approval requirements still apply. Slack and Teams connections use your organization's existing feature permissions. Salesforce setup is utility-only and retains its separate release restrictions. If an action is unavailable, read its explanation before asking your organization administrator or support to enable it. ## Connect the GridWonk plugin When the public GridWonk plugin is available in your client, install it and follow its sign-in flow. Use your own verified GridWonk account. The plugin may show **Connection required** after sign-in: open its secure setup link in your browser, sign in as the same person, and confirm the workspace you want it to use. Finish any required legal acceptance first. After you confirm, the page shows **App connected**. Confirmation links work once; reopening a used link does not reconnect the app. Manage or revoke the saved connection from **Connected apps**. Return to the plugin and repeat your request. Completing setup enables that connection without requiring a different tool list. You do not need to paste an API key, token, or private repository path into a chat. The connection is bound to the exact sign-in session and selected workspace. Switching the web app's workspace does not redirect an existing plugin connection. Each account has one active connection for this app. To select a different workspace, revoke the current connection, finish provider cleanup, then sign in through the plugin again and confirm a fresh connection. A second connection cannot replace an active one automatically. ## What the plugin can do The plugin can research published requirements, prepare authorized developer drafts, attach supported packet files, start eligible reviews, and read status and cited results. Verified utility members can use the utility workflows their current role permits. Review availability also depends on supported utility coverage and processing allowances. Document-role decisions, formal submission or resubmission, utility decisions, notice approval and sending, membership changes, and purchases require the website. The plugin cannot approve an application or change those permissions for you. ## Review or revoke access Open your connected applications from organization **Integrations**, or use **Connected apps** at `/settings/connected-apps`. Check the selected workspace and revoke a connection you no longer need. Local access stops immediately. If provider cleanup needs another attempt, follow the retry action before making a fresh connection. A revoked session cannot be reactivated. If your membership expires, your role changes, or your account loses approval, the next plugin request uses that current access state. Reconnecting does not restore removed permissions. For an expired setup link, return to the plugin and request a new link. For a wrong-account message, use the account that signed in to the plugin. If API or MCP access is disabled for the bound organization, subsequent MCP requests are refused, including requests from an already connected app. Disabling MCP alone does not disable permitted REST API calls. Enabling access again does not restore a revoked connection or expand your data permissions. You can still revoke your connection from the website while access is disabled. --- # Developer Notices View and acknowledge deficiency notices sent to your organization by utilities. URL: /docs-site/help/developer-notices A project's partial document report is not a utility deficiency notice or an approval. It can show applicant self-check findings before any utility screening; notice authority and the response workflow below remain separate. ## Salesforce connector boundary The default-disabled Salesforce connector returns utility-internal decision support; it does not send applicant notices or change the Salesforce regulatory queue status. Automatic package freezing also makes no notice or queue/status changes. Source-managed revisions stop for staff review once adjudication or notice work begins. This does not change the developer response workflow for ordinary submitted applications. ## What Are Deficiency Notices? When a utility reviews your interconnection application and identifies issues, they send a deficiency notice listing the findings that need to be resolved. Each notice includes the specific deficiencies, their severity, and a deadline for your response. Deficiency notices are part of the standard interconnection review process. Receiving a notice does not mean your application is rejected — it means the utility needs corrections or additional documentation before they can proceed. If a document has been replaced, GridWonk excludes findings tied to the older bytes. The utility must finish reviewing the current document versions before it can draft the next packet-wide notice, so a notice cannot silently omit a document that is waiting for re-review. ## Where to Find Notices Notices appear on your **Dashboard** in the **Deficiency Notices** card. This card is visible to all members of developer organizations. The card header shows a count of notices awaiting your acknowledgment. ## Notice Table Each notice displays the following columns: | Column | Description | |--------|-------------| | **Application** | The project name and official utility application number, when one has been assigned | | **Notice** | The notice subject line, round number, and count of outstanding deficiency items | | **Status** | Whether the notice is awaiting acknowledgment or already acknowledged | | **Due** | The response deadline set by the utility, or "Not set" if no deadline was provided | | **Action** | An **Acknowledge** button for pending notices, or "Completed" for acknowledged ones | ## Acknowledging a Notice When you receive a notice with status **Awaiting Acknowledgment**, click the **Acknowledge** button to confirm you have received and reviewed the notice. Viewing and acknowledging are separate permissions. Viewers and read-only grant users can review notices but cannot acknowledge them. Acknowledgment requires an active **Member**, **Admin**, or **Owner** role; grant-derived access also requires a **write** or **admin** grant within the submission scope. Acknowledging a notice: The action rechecks current membership and the exact scoped grant under the application lock. Acknowledging an already acknowledged notice succeeds without writing another history entry. Pending or held delivery is not a sent notice; application changes wait for its resolution. Verified email-provider receipts, when separately activated, are delivery evidence only. They cannot acknowledge a notice for you or confirm that you read it. The dependent utility-event layer records an actual acknowledgment once; its subscriptions belong to the receiving utility, not automatically to the applicant or a consultant with project access. 1. Records a timestamp of your acknowledgment 2. Updates the notice status to **Acknowledged** for both you and the utility 3. Signals to the utility that you are aware of the findings Acknowledgment does not mean you agree with the findings or have resolved them — it confirms receipt. ## Notice Statuses From the developer perspective, notices have two statuses: | Status | Meaning | |--------|---------| | **Awaiting Acknowledgment** | The utility has sent the notice and it requires your acknowledgment | | **Acknowledged** | You have acknowledged receipt of the notice | ## Starting Your Response When a notice has been sent for one of your projects, the project **Overview** and **Review** views show a **Start response** action. This control is developer-client scoped: utility and GridWonk reviewer organizations do not receive it, and a consultant's own home organization does not receive it. A consultant may see it after switching into a granted developer-client context, but the server succeeds only when that context still has write-capable, in-scope access. Selecting it moves the project into **Resubmission Under Development**, records the stage change in application history, and unlocks the working document set for correction. Start response is idempotent: if a teammate already started the response, the action simply reports that and writes nothing — no duplicate history entry is created. Attaching the first corrected document to the project performs the same stage transition automatically, so the response stage is recorded even when nobody presses the button first. ## After Acknowledgment Once you acknowledge a notice, review the deficiency items and prepare your response. Common next steps include: - Correcting the identified issues in your application documents - Gathering additional documentation requested by the utility - Uploading corrected documents through the platform. A document that is linked to a project — a link row, logical version, or submitted package — still rejects different-byte replacement, so follow the [Upload safety states](/docs-site/help/upload#applicant-document-safety-states) and use a new filename when instructed. Only unlinked documents accept replacement bytes. Documents frozen in a submitted package cannot be changed or removed. - If one accepted PDF contains multiple document types, use **More actions → Split PDF** while the project is editable. Assigned or previously reviewed 2–250-page PDFs are eligible too. Confirm page ranges and types; the children need fresh review. The original and earlier findings remain historical after success. A pending or failed split pauses new review and submission until it succeeds or you choose **Keep original**; **Retry split** safely retries a failed attempt. - Contacting the utility's interconnection team if you have questions about specific findings Acknowledgment does not resubmit your application. It only records receipt. When you are ready to respond, use **Start response** (or attach the first corrected document) to open the resubmission working set, then link the corrected documents requested by the utility and follow the utility's instructions for the next screening round. Finish or cancel any unfinished upload batch before resubmitting. The server refuses to freeze the new package while an unexpired batch remains open, processing, or awaiting CAD pairing; that refusal does not change your documents, submission stage, or earlier packages. Resubmission is not blocked by the utility's submission acceptance: your correction goes to the utility that already accepted your original package, even if that utility has since stopped accepting new submissions or has no qualified reviewer at that moment. In that last case no reviewer receives an in-app notice, but the resubmitted package is still delivered and stored. See [Private Reviews and Utility Submissions](/docs-site/help/private-reviews-and-submissions). The corrected immutable package returns to the utility queue as **Pending**. The utility starts its whole-packet review with **Screen Selected** or an authorized integration. The review moves the application to **Screening** before work starts and **Screened** when complete. A failed start or run restores its earlier status once no other utility review is active. Resubmitting does not start another legacy document-processing pass. Earlier packages and notice rounds remain in history, and completed automated screening is not utility approval. If the utility re-screens your resubmitted application and finds remaining issues, they may send a follow-up notice (Round 2, Round 3, etc.). Each round links back to the previous notice so you can track the full history. ## Cross-Organization Visibility As a developer, you see notices for all applications submitted by your organization, regardless of which utility sent them. If your organization has applications with multiple utilities, all notices appear in the same Deficiency Notices card. This works because the notice is linked to a shared submission record: - the utility still owns the review workflow - your developer org is linked as the applicant on that same submission - you can see the notice history without becoming the owner of the utility queue row ## Related - [Notices](/docs-site/help/notices) — How utilities create, review, and send deficiency notices - [Results](/docs-site/help/results) — Understanding validation results and deficiency details - [Organizations](/docs-site/help/organizations) — Managing your organization and roles --- # Document troubleshooting Choose the right recovery action for an upload, text-recognition issue, review failure, or combined PDF. URL: /docs-site/help/document-troubleshooting ## Processing allowance or uncertain provider result For trial and prepaid workspaces, expiry, exhausted limits, a purchase hold, or an uncertain provider outcome can stop new work. Check [processing and purchase status](/docs-site/help/processing) before retrying. Re-uploading, creating another key, or restarting the same file does not clear an uncertainty hold. Contact support when reconciliation is required. A platform failure without a usable packet report releases the reserved review credit after the related work settles; processing already performed remains counted. Platform retries for the same review share its operation. A new review or changed source snapshot can use another credit. Previously saved, authorized files and results remain readable. import { DocsDiagram } from '@/components/docs/docs-diagram'; Start in the project's **Documents** view. Check the affected file and its current version before choosing an action. A failed background step does not mean every step failed, and a completed individual-document review does not mean the whole project is ready or approved by a utility. ## When an application form is refused The current failed form review can show a wrong-form, different-revision or could-not-verify explanation in its Documents row, with the recorded reason and observed differences. Check that the PDF belongs to the project's selected program and use the correct utility form before retrying. Both normal and compact document rows show the same explanation. A successful retry or replacement clears the old refusal; a refusal is not an upload-transfer failure. ## When progress stops updating A live-update connection warning describes how the browser receives fresh information, not whether the upload or review failed. Do not replace an accepted file or restart a completed review just to clear that warning. Check the affected document's separate processing outcomes below. With permission-aware live updates enabled, successful periodic refreshes stay quiet. **Some live updates are unavailable.** means at least one required source or connection remains unavailable; use its refresh/retry action. While offline, displayed information may be out of date. If the session cannot recover, use **Sign in**. Previously displayed data stays visible during temporary connection failures, but is removed when a fresh authorization check confirms lost access. This recovery behavior is a gated rollout. A tab opened before the upgrade needs a refresh to use the new behavior; reconnecting alone does not upgrade it. ## Self-service processing limits Self-service processing remains unlaunched. Its guarded recovery path keeps the original review, funding, and source versions together. A retry does not create a new trial or erase processing costs. Retrying an unchanged upload does not count the same source twice, but deleting a source does not restore its lifetime upload allowance. Archive containers, expanded entries, and linked file versions also count toward that allowance. A platform failure can return an unused packet-credit hold only after the related work settles. A usable report already delivered remains consumed, and incurred or uncertain provider costs are retained. An eligible retry must be recorded by the server, have available credit, and pass the original source and funding checks again. An expired trial or unresolved provider outcome cannot be bypassed by repeated retries. Ask support to resolve the underlying issue before trying again; these restrictions do not authorize a new paid run or make self-service available. ## Unsupported source format If your workspace is limited to PDF review, use standalone PDFs. The server refuses images, ZIP archives, and native CAD files in that scope, including saved File Library attachments and sources already attached to a packet. Repeated retries, another client, or an earlier upload cannot override the restriction. Supply supported source files without treating a PDF-only review as a waiver of the utility's required evidence. A format refusal does not establish a completed upload or review. If an assistant or integration returned upload, job, or review-run identifiers before an interruption, check those same operations before starting another attempt. Preserve the report's document and page citations when sharing findings so the result stays connected to its source evidence. ## Read the three outcomes separately The safe viewing copy is prepared separately from text recognition. If preview is still preparing, wait for that step; do not assume an OCR failure means the original PDF was lost. If no status is available, the outcome is unknown—not proof of failure or success. ## Choose the action that matches the problem ### Retry upload 1. Read the failure message and its suggested next action. 2. Check the limit shown by the project upload control. Project sources are limited to 30 MB each. 3. For a paused transfer, use **Resume** when available. For an expired authorization or an interrupted attempt that cannot resume, use **Retry** to obtain a new authorization and path. 4. If the server rejected the upload protocol, stop repeated retries and contact support. Repeating the same request does not correct a platform configuration error. 5. If finishing reports that the upload changed, another retry replaced this attempt. The card refreshes; use **Retry** if it is still offered. This is not a locked submission. 6. Wait for server acceptance and the document's safe viewing copy. Do not rely only on 100% progress. Retry preserves prior attempt history. Refreshing a page does not turn a reported failure into a successful upload, but bytes the server already verified count even if the browser reported a failure. Reporting a failure never makes a file less retryable. If its upload batch expired or was abandoned, the batch stays closed history; use the file's own **Retry** instead of reselecting it. ### Replace a corrected PDF In an editable project's Documents view, choose **More → Replace** on the intended document. Select the corrected PDF and wait for the new current version. If someone replaced the document while your upload was in progress, refresh and select the intended version again. ### Retry a document review Open the affected document's review controls and use **Retry review** when offered. If support has asked you to wait for a fix, wait for confirmation that this specific review can be retried. Do not replace an unchanged PDF just to restart a review. Keep individual-document results separate from a [whole-project review](/docs-site/help/packets#run-the-review). If the utility's published requirements changed since the failed review, support recovery may create a new review under the current rules while preserving the earlier failure in history. ### A packet review appears stuck Open **Review Actions → Cancel Packet Review** and confirm the active run. The action is available only if you have permission to run reviews in that same applicant or utility review lane. If the action is missing, contact support with the project and approximate start time. Cancellation stops that run from saving further packet results and preserves completed document findings. An external provider request already in progress may finish in the background. If the workflow's stop cannot be confirmed, the interface shows a warning; contact support before starting another packet review. Cancellation does not fix the cause of a crash or restart OCR. Use **Findings** or the **Partial report — document checks** to read completed current document results while the packet review is running, failed or cancelled. The **Individual-document review results** label means these are not whole-project results or utility approval. Current completed packet results take priority; old file versions or earlier successful checks are not used to hide a newer failed document review. ### Split a combined PDF Use **More actions → Split PDF** for an eligible accepted PDF in an editable project. An assigned role, earlier review, or missing possible-combined hint does not prevent splitting. The supported range is **2–250 pages**. Review the parent/child preview, cover every page exactly once, and assign a role to each retained range. Discard only genuine blank or separator pages. Analysis and preview preserve the parent's type and historical reviews. Confirming pauses new reviews and submission while the split runs; only success retires the active parent and creates children needing fresh review. If the version changed after preview, analyze it again. A failed attempt offers **Retry split** or **Keep original**; keeping it preserves the original and history. See [Split a combined PDF](/docs-site/help/packets#split-a-combined-pdf) for permissions and details. ## When text recognition fails Text recognition powers search and text-location features. It is not the same as document review. Check the safe preview and any completed review results independently. There is no general customer OCR-retry control described here: contact support for a scoped reprocessing decision. Replacing an unchanged file or repeatedly retrying review is not an OCR repair. If recognition output is cut off by a processing limit, support must address that limit or its cause before repeating the same recovery. A green status must reflect usable text, not a cleared error. Support may be able to recover processing from an accepted file without asking you to upload it again. Provide the project, filename and affected outcome, and wait for confirmation before repeated retries. OCR recovery does not require rerunning a successful document review. Support will verify the resulting text or review findings; a completed background job alone is not the same as confirming the result is usable. If the original bytes were never accepted, you may still need the original file for **Retry upload**. If the document or project review inputs change while support prepares recovery, tell support: the earlier approval no longer applies. This includes changing only the project's state. Support must check the current inputs again; an older recovery must not update a newer file or use outdated project details. ## What to send support Include the project, affected document/version, approximate time and time zone, the visible status, and the action you tried. Include packet, upload, job, and review-run identifiers when returned by your assistant or integration. A screenshot of the message can help. Do not send passwords, API keys, signed download links or unrelated confidential documents. Follow the [support guidance](/docs-site/help/support). ## Related guidance - [Upload and replacement](/docs-site/help/upload) - [Read review results](/docs-site/help/packets#read-the-report) - [Results and findings](/docs-site/help/results) - [Developer onboarding](/docs-site/getting-started/for-developers) --- # Documents Document discovery, requirements, and management for interconnection procedures. URL: /docs-site/help/documents ## Customer processing availability Trial and prepaid workspaces use supported project intake and reviews. Public procedure-document reads do not start customer processing. New uploads, text recognition, and review work require a current [processing allowance](/docs-site/help/processing); native DWG processing and legacy standalone digitization are unavailable in this rollout. Reading an authorized existing result does not spend a review credit. ## Background updates The gated permission-aware rollout keeps displayed documents during temporary refresh failures. Confirmed removal or lost access clears them. Periodic refresh coverage also includes procedure document changes that do not emit an organization job event. Successful refreshes stay quiet; failures still show recovery actions. **Retry updates** refreshes data, not discovery or processing work. See [live-update status](/docs-site/help/jobs). ## Salesforce evidence The Salesforce connector is still disabled pending pilot acceptance. Its source-managed packet files are separate from discovered procedure documents. Reading a captured file, CAD preview, text, or report requires an approved linked reviewer with current Salesforce source access; ordinary role changes and file edits are refused. See [Salesforce preparation](/docs-site/integrations/salesforce). Current access checks cover fields from all captured revisions, including fields no longer mapped. Losing access to an older field can therefore also block a current file or report. Ask the connection administrator to resolve the source permission; do not substitute an ordinary download. ## What is Document Discovery? Packet-review cancellation belongs to the project's **Review Actions** and does not delete completed document findings. It is separate from procedure discovery and its controls below. See [Jobs](/docs-site/help/jobs#cancel-a-packet-review) for cancellation warnings and limits. GridWonk automatically discovers interconnection procedure documents from utility websites. This includes: - Tariffs - Guidelines - Technical specifications These documents define the requirements for your project's grid connection approval. Procedure documents are the rulebooks GridWonk reads before it extracts requirements. Uploaded applicant files are different: they are the evidence you provide to show that your project meets those rules. Optional upload conveniences such as Combined-PDF split and packet ZIP upload are per-organization features, on by default, that your organization admin manages from the workspace Features page (see [Upload](/docs-site/help/upload)). ### From utility source to cited finding ## Document Roles and Sources GridWonk uses **Role** for what a procedure document covers. This avoids the ambiguity of “document type,” which can mean its file format, author, legal authority, or purpose. Examples include **Interconnection Procedures**, **Application Form**, **Technical Requirements**, **Site Control**, **Rates and Fees**, and **Interconnection Agreement**. The console turns the internal `content_role` value into the readable group heading above the cards, so users do not need to learn it. **Source** is separate. It identifies who published or owns the material, such as the selected utility, a state commission, an RTO/ISO, or a federal entity. Keeping Role and Source separate makes questions easier to answer: - “What does this document cover?” → Role - “Who issued this document?” → Source An unclassified role means GridWonk has not assigned a reliable role yet. It does not mean the document is invalid. When synchronization discovers a reliable title for a previously untitled document, GridWonk can fill that missing title without replacing a title that a reviewer has already accepted. ## Applicant Project Documents Inside a developer project, document selectors lead with the assigned packet role, such as **Single-Line Diagram** or **Site Plan**. A short filename is added only when two files share the same role. Uploaded documents show processing, failure, or another actionable state; a redundant success badge is not shown after processing completes. A site-plan PDF can carry an immutable native AutoCAD DWG companion. The PDF remains the packet document, while the DWG supplies the original drawing structure for layouts, layers, entity properties, measurement, and utility-specific checks. Replacing the DWG creates a new site-plan version so reviewers can compare revisions without changing the earlier evidence. Saved project and curated demo links are resolved inside the active organization. GridWonk refuses the link when the project is missing, duplicated, belongs to another organization, or the active user is not authorized; it does not switch organization context automatically. ## Review Status Explained GridWonk labels procedure documents by whether they are ready to support customer-facing answers and validation. | Status | What it means | What customers see | |--------|---------------|--------------------| | **Current usable** | A reviewer approved the document and GridWonk finished reading the document text. | Can be used for requirements, validation, and customer-facing outputs. | | **Pending review** | GridWonk found the document, but a reviewer has not approved it yet, or reading the text is not complete. | Hidden from customer-facing outputs after current-procedure enforcement is on. | | **Deprecated** | Kept for history because it may be old, replaced, or no longer authoritative. | Not used for new customer-facing answers or validation. | | **Rejected** | A reviewer decided the file is not the right source. | Not used for customer-facing outputs. | Current-procedure enforcement means GridWonk only uses approved, readable rulebooks for customer-visible work. This can make a utility look temporarily sparse while review cleanup is in progress, but it prevents old or unapproved rulebooks from driving deficiency results. ## Starting the Discovery Process Starting discovery is a mutation available in utility and GridWonk organization contexts. Developer and consultant users can browse Utility Research as read-only reference material but do not receive discovery or extraction controls there. For an authorized utility or GridWonk user: 1. Select your utility with the picker in **Utility Research** 2. Click **Start Discovery** to scan the utility's website 3. Follow the job status while scanning runs 4. Review discovered documents ## Extracting Requirements Extraction is also limited to utility and GridWonk organization contexts. After discovery completes, an authorized user can choose: - **Extract All** — Process all documents in the current eligible set - **Extract Selected** — Process only specific eligible documents you choose Extraction pulls structured requirements from the documents for validation against your submissions. When a reviewer status filter is active, extraction uses the filtered document set. Extraction is limited to **Current usable** documents so new requirements come from approved source material. ## Reliable Background Processing Discovery and applicant-document review run as durable background jobs. If the workflow platform retries a step after losing an acknowledgement, GridWonk reuses the job's stored terminal result instead of changing a completed job to failed or running the review again. Completion and failure notifications also use stable event identities so a safe replay does not create a contradictory result. ## Transmission and Distribution Filtering Utility and GridWonk reviewers use the transmission/distribution toggle in the **Procedure Docs** header to narrow discovered procedure documents (developer research is pinned to distribution): - **Both** shows all discovered procedure documents. - **Transmission** shows transmission-applicable documents and uncategorized documents. - **Distribution** shows distribution-applicable documents and uncategorized documents. Procedure Docs shows the filtered count when a specific interconnection level is active. ## Reviewer Filters and Shareable Links Utility reviewers and GridWonk admins may see a document status filter in `/console`. The temporary filter options are: - **Current usable** - **Pending review** - **Deprecated** - **All reviewable** These filters are URL-backed, which means the address bar carries the review state. A reviewer link can include `view=utility-research&research=documents&procedureStatus=all_reviewable` so another reviewer opens the same utility, state, destination, and filter. Older `tab=documents` links still redirect to that destination and keep the filter, and the `Cmd+K` palette jumps straight to the Procedure Docs or Requirements destination from anywhere in the console. Developer Utility Research shows active distribution documents only and has no status filter; deprecated and rejected documents never appear for developers. Reviewer and admin surfaces retain the **Current usable**, **Pending review**, **Deprecated** and **All reviewable** filters, and the console lists distribution documents for every audience. ## Understanding Document Cards GridWonk does not show unreviewed discovery-script notes on document cards. Any future document summary should be source-backed and reviewed before customer display. Every console audience sees the same slim card built for assembling an application packet; the group heading names the role: - **Title** and **Region/State** - **Feeds** — The published programs (for example Simplified, Expedited, Standard) whose reviewed source set includes the document; each chip opens the Requirements tab on that program - **Cited by** — How many published requirements cite the document, or "Not yet cited by published requirements" - **View** — Opens the stored copy GridWonk indexed for this record in a new tab, with its file type, or says the stored copy is unavailable - **Original source** — Where GridWonk got the document: the utility's own link, kept for provenance; for monitored utilities a warning appears only when the public version may have changed since capture Utility and GridWonk reviewers see the same card. Their only extra control is the review-status filter above the list; cards do not show a review-status chip. Review status, source owner, level and discovery date are not shown on console cards. ## Programs and the Packet Map The console header shows the lineage **Utility › Program**. The utility segment is the picker; the program segment lists the utility's published programs plus **All programs**. With a program selected, Procedure Docs shows the **packet map**: the program's reviewed source set, numbered in the order the packet is usually assembled, each document with its role label and how many published requirements cite it, and the utility's other documents in a collapsed section. With **All programs**, every document is grouped by role in packet order. The Requirements tab follows the same program. Every audience sees distribution documents only, with no level toggle or refresh button; reviewers keep the status filter. While a remembered program's data is still loading, the list shows a placeholder instead of flashing the grouped cards first. Older captured procedure documents keep their original record identifiers. The stored-copy link and review workspace can read those records without replacing the captured file or resetting its review history. A preview error alone does not mean the stored copy is unavailable. ## Asking the Assistant About Documents Useful document questions include: - "What procedure documents has GridWonk found for Duke Energy NC?" - "Have requirements been extracted from these documents?" - "Which documents have I uploaded for this utility?" --- # Email Notifications Automated emails GridWonk sends and when you receive them. URL: /docs-site/help/email-notifications ## Salesforce setup and email The utility Integrations tab also links to the default-disabled Salesforce setup page. That link does not change email preferences or enable applicant notices. Salesforce result delivery is utility-internal and separate from the notice-email workflow. ## Overview Notification recovery does not alter email delivery or preferences. The bell's read/dismiss updates confirm an authorized notification was matched; a removed or inaccessible item is explained and the list is refreshed, while already-read items and an empty mark-all-read remain valid successes. GridWonk sends automated emails to keep you informed about account activity, organization changes, and requirement updates. Emails are sent from `notices@gridwonk.com`; the visible product name follows the active brand configuration, so local legacy-branded environments may still show the legacy name during the transition. ## Email Types | Email | When Sent | Recipients | |-------|-----------|------------| | **Account Setup Invitation** | When a GridWonk administrator creates or reinvites an approved account that has not signed in | New or reinvited user | | **Welcome** | When your account is activated for an organization | New users | | **Organization Invitation** | When an admin invites you to join an organization | Invited user | | **Change Alert** | When a monitored utility's interconnection requirements change | Subscribed organization members | | **Weekly Digest** | Weekly summary of platform activity | Active organization members | ## Welcome Email Sent when your account is created and associated with an organization. **Contains:** - A greeting with your name - The name of the organization you have been added to - A link to open your dashboard - Contact information for getting access changes **Subject line:** `Welcome to GridWonk - [Organization Name]` ## Account Setup Invitation Sent when a GridWonk administrator creates an approved account or reinvites an approved user who has not signed in yet. The single-use GridWonk application invitation lasts 30 days. When you accept it, GridWonk creates a separate short-lived authentication handoff to confirm identity and complete account setup. Reinviting revokes the earlier unused setup invitation. **Subject line:** `Complete your GridWonk account setup` ## Organization Invitation Sent when an organization admin invites you to join their team. **Contains:** - The name of the person who invited you - The organization you are being invited to join - Your assigned role (Viewer, Member, Admin, or Owner) - An **Accept invitation** button with a unique link - A 30-day expiration date for the single-use organization invitation Organization invitation links are managed by GridWonk separately from Supabase authentication links. After you choose **Accept invitation**, GridWonk creates a short-lived authentication link to confirm your identity and then consumes the organization invitation. Password-reset, magic-link, and email-verification links keep their shorter security expiration. **Subject line:** `Invitation to join [Organization Name] on GridWonk` ## Change Alert Sent when GridWonk's change monitoring system detects that a utility has updated its interconnection requirements or procedures. **Contains:** - The utility name and state - When the change was detected (date and time in UTC) - A summary of what changed - An impact assessment describing how the change may affect your applications - A link to review the full change details in the platform **Subject line:** `Requirements change detected: [Utility Name]` ## Weekly Digest A periodic summary of activity relevant to your organization, sent once per week. **Contains:** - A greeting with your name - A week label identifying the reporting period - A summary paragraph of the week's highlights - Individual activity items, each with a title, description, and optional link to the relevant page - A link to open your dashboard **Subject line:** `GridWonk weekly digest - [Week Label]` ## Delivery Details For deficiency notices, **Sent** means the email provider accepted the message, not that it reached the recipient's inbox. Requesting a send first saves a frozen delivery request; queued, retrying, held and provider-accepted-but-finalizing progress are shown separately. Retries keep the same email and delivery key. Do not resend a held or uncertain request. The dependent safe-send release requires separate foundation activation and does not change notification preferences. The dependent receipt layer stores verified provider email events separately. A delivered receipt is provider delivery evidence, not proof that a person read the message; bounce or complaint evidence does not undo the notice's saved status or trigger another send. Unknown message IDs remain unlinked until they can be matched to a unique accepted request. This adds no receipt viewer or new email preference. Provider configuration and production activation remain held for separate approval. Automated emails are sent from `notices@gridwonk.com`. Replies go to `support@gridwonk.com`. If you are not receiving emails, check your spam or junk folder and add `notices@gridwonk.com` to your contacts or allowlist. Deficiency notice emails sent by utilities to applicants are also delivered from this address. Those emails contain the full deficiency list, response deadline, and the active product branding. ## Customization Use Account Settings → Preferences to turn email notifications on or off, enable the weekly digest, and set your timezone. Some transactional or security emails may still be sent when needed for account access, invitations, or compliance workflows. Slack account linking is managed separately under Account Settings → Integrations and does not change your email notification preferences. Its secure account-link prompt is delivered in Slack rather than by email. ## In-App Notifications GridWonk also has an in-app notification bell. The inbox supports mark-read, mark-all-read, dismiss, and an unread count that refreshes about every 30 seconds while the page is visible and online. Hidden and offline tabs pause checks. Email preferences and in-app notifications are related, but they are not the same delivery channel. When an accepted utility intake lane receives a formal packet, qualified reviewers receive a durable in-app receipt linked to the application. Private developer packet reviews send no utility receipt. This receipt does not add an email type. If sign-in expires, the bell clears its outdated count and offers sign-in in another tab. Your workspace remains open; return after signing in or choose **Try again**. Service failures are shown as failures, not as an empty inbox. If the account or organization changes in another tab, notifications pause rather than showing a different workspace's data. Save unsaved edits before choosing the offered workspace reload. Updates that are refused or unavailable do not appear successful. If GridWonk requires acceptance of updated legal terms, notifications also pause. Save your work, accept the current terms, then reload the workspace before trying the bell again. For utilities where GridWonk has turned on procedure source monitoring, the bell also shows **Public page may have changed** alerts to the utility's reviewers, developers who follow that utility, and GridWonk admins. **Review document** opens the document where your organization reviews procedure documents. These alerts are in-app only. ### New client access (when enabled) When a client creates a new usable grant for your consulting organization, eligible active members receive a persistent bell alert. If email delivery is enabled, each recipient also receives an individual service email with the client, consulting organization, access level, project scope, and expiration. These channels are disabled by default until rollout is approved. This is **not an invitation**: sign in with your existing account; no invitation acceptance or client password is needed. You can discover the alert after your next login even if you never open the email or another organization is selected. Signing in again does not send another email. Older grants and people who join the consulting organization later are not backfilled. The bell is available in the shared header and in Console and Utility workspace controls. Opening it does not mark alerts read. Use **Mark read**, **Mark all read**, or **Dismiss**; these choices persist across sign-ins and devices. **View client access** opens Consultant Access without switching organizations automatically. Select your consulting organization if needed, then find the client and choose **Switch**. Your role and the grant both limit available actions. A Viewer remains read-only. Revoked or expired grants and inactive memberships no longer appear in the actionable inbox. A stale email link cannot restore access. See [Access Grants](/docs-site/help/access-grants) for navigation and troubleshooting. ## Related - [Organizations](/docs-site/help/organizations) — Organization roles and permissions - [Developer Notices](/docs-site/help/developer-notices) — Viewing and acknowledging deficiency notices - [Support & Contact](/docs-site/help/support) — How to get help from the GridWonk team --- # FERC Reporting & Analytics Queue analytics and FERC compliance reporting for utility organizations. URL: /docs-site/help/ferc-reporting ## What is FERC Reporting? The Federal Energy Regulatory Commission (FERC) requires utilities to track and report on their interconnection queues. GridWonk provides a built-in analytics dashboard that summarizes queue health, screening performance, and deficiency trends -- with prior-period comparison and export capabilities for compliance reporting. The current implementation builds the analytics snapshot from active `application_submissions`, scoped to the active utility organization and selected utility. It excludes archived synthetic demo history and loads up to 5,000 submissions for the selected reporting window. ## Accessing the Analytics Tab The analytics view is available in the **Utility Workspace** under the **Analytics** tab. It is accessible to users in **utility** organizations and to consultants with read-level grant access. ## Summary Metrics Four metric cards display at the top of the dashboard: | Metric | Description | |--------|-------------| | **Total Applications** | Number of applications submitted within the reporting window, with percent change vs. the prior period | | **Screened** | Applications that reached screened, notice draft, notice sent, or complete status, with completion rate and the number whose counts come from a packet review | | **Deficiency Rate** | Percentage of applications with at least one deficiency, plus total notices issued | Each card includes a comparison indicator showing how the current window compares to the equivalent prior window. ## Time Range Selection Use the range toggle to adjust the reporting window: | Range | Window | |-------|--------| | **30D** | Last 30 days | | **90D** | Last 90 days (default) | | **1Y** | Last 365 days | The prior-period comparison automatically adjusts to match the selected window length. ## Status Distribution A table breaks down application counts by screening status: - Pending - Queued - Screening - Screened - Notice Draft - Notice Sent - Resubmitted - Complete Statuses are sorted by count in descending order. ## Monthly Trend A trend table shows submissions per month within the selected window. Use this to identify seasonal patterns. ## Recent Applications The bottom table lists the 25 most recent applications with details: | Column | Description | |--------|-------------| | **Application #** | Unique application number | | **Project** | Project name | | **Status** | Current screening status | | **Deficiencies** | Total deficiency count from the latest completed packet review, or the legacy stored count | | **Critical** | Number of critical deficiencies from the same source | | **Source** | **Packet review**, **Legacy screening**, or blank when no review of either kind has completed | | **Screening Hours** | Time from submission to screening completion | | **Created** | Submission date | ## Export Options Two export formats are available: | Format | Description | |--------|-------------| | **Export FERC CSV** | Downloads a CSV file with all applications in the current window. Includes application number, project name, state, capacity (MW), status, deficiency counts, review source (`packet-review`, `legacy`, or `none`), timestamps, and screening hours. | | **Export FERC PDF** | Generates the PDF on the server from the same organization-scoped analytics snapshot, then returns it for download with summary metrics, status breakdown, and the recent applications list. | Exported filenames include the current date (e.g., `ferc-queue-report-2026-02-18.csv`). CSV export cells are encoded so formula-like values from project or application data cannot become spreadsheet formulas when a report is opened in a spreadsheet application. ## Refreshing Data Click the **Refresh** button to reload the analytics snapshot with the latest data. The dashboard queries application submissions in real time, so refreshing reflects any changes since the page was last loaded. ## Data Scope and Access Control - Analytics are scoped to the current organization and utility selection. - Consultants with granted access see only the projects included in their grant scope. - Rate limiting applies (30 requests per minute per user) to prevent excessive load. --- # Files Reuse uploaded files across utilities without uploading the same evidence again. URL: /docs-site/help/files ## File Library Overview The File Library shows files your active organization and access permissions let you reuse, including your uploads, organization-visible files, and eligible files shared with you. You must also have an approved, current session. If GridWonk asks you to accept updated legal terms, complete that step in the browser before retrying a File Library action. Uploader and visibility filters narrow the accessible list. A project-scoped consultant grant does not grant access to the organization's whole library; project documents remain available in scope. Use File Library when you want to preview a document, refresh the list, or link an existing file to the utility currently selected in the console. From a project's **Documents** view, use **Attach from library** to add an eligible File Library file directly to that project instead of uploading a duplicate. ## Linking Files To A Utility When a utility is selected, Files shows which vault entries are already linked to that utility and state. Click **Attach To Utility** to reuse a file in the current utility workflow without uploading another copy. Linked files can then appear in document-selection, validation, and assistant context for that utility. Linking does not delete the original vault asset, and the same asset can have links for more than one utility or state. When GridWonk links a vault file to a utility, it also looks for the latest applicant-document projection for the same asset and state. That is why linked rows can show digitization and validation status when a projection exists. **Attach from library** creates a separate document identity for each project while reusing the same eligible organization asset. Project versions remain independent without duplicating source bytes. ## Previewing Files Click **Preview** to open the PDF viewer for a File Library file. If GridWonk cannot resolve a preview document for that file, the viewer shows an error and the file remains in File Library. ## Deleting Files Click **Delete** to remove a file you no longer need from the File Library. Delete appears only for a file that is in no project: remove it from each project's **Documents** first. You can delete your own uploads; organization Owners and Admins can also delete a colleague's file they can see. A deleted file leaves the File Library at once and is not reused if you upload the same file again. For 90 days, support can restore it: email contact@gridwonk.com. Automatic permanent deletion is not enabled yet. Removing a document from a project does not delete it from the File Library. ## Native CAD Companions A native DWG is not an ordinary File Library document. Upload it from the selected project's shared **Upload Project Files** control, where GridWonk safely pairs it with the exact current site-plan PDF version. The general **Attach from library** and **Attach To Utility** actions list only supported applicant document formats, so a private DWG cannot accidentally enter the PDF digitization or utility-link workflow. When native viewing is enabled, GridWonk shows an authorized derivative; it never sends the original DWG bytes to the browser. ## Refresh And Pagination Use **Refresh** after an upload or link operation if the list looks stale. File Library loads files in pages; click **Load 200 More** when more files are available. ## Related - [Upload PDF](/docs-site/help/upload) — Upload new applicant evidence - [Documents](/docs-site/help/documents) — Utility procedure documents - [Results](/docs-site/help/results) — Validation output from linked evidence --- # Help Center Set up your workspace, connect the GridWonk plugin, and review interconnection packets. URL: /docs-site/help Read these guides without signing in. Sign in to work with your organization's files and reviews. ## Set up your account - [Create or join a workspace](/docs-site/help/self-service) — Verify your email, accept the terms and privacy policy, and invite your team. - [Connect an app](/docs-site/help/connected-apps) — Choose the workspace the GridWonk plugin may use and revoke access when needed. - [Trial and prepaid processing](/docs-site/help/processing) — Understand review allowances, processing limits, and payment status. - [Account settings](/docs-site/help/settings) — Passwords, profile, preferences, and integrations. - [Workspace access](/docs-site/help/access-grants) — Understand direct membership, client grants, and the permissions each provides. ## Prepare and review a packet - [Developer guide](/docs-site/getting-started/for-developers) — Research requirements, prepare a private project, and review findings. - [Upload files](/docs-site/help/upload) — Add supported files and follow processing progress. - [Packet review](/docs-site/help/packets) — Run an eligible review, then inspect findings and Coverage when **Review Finished** appears. - [Packet requirements](/docs-site/help/packet-requirements) — Understand required evidence and document roles. - [Results](/docs-site/help/results) — Read findings with their source citations. - [Private reviews and submissions](/docs-site/help/private-reviews-and-submissions) — Decide when to share a completed package. ## Utility workflows - [Utility guide](/docs-site/getting-started/for-utilities) — Claim your affiliation and work with authorized applications. - [Applications](/docs-site/help/applications) — Follow intake, screening, and the application lifecycle. - [Notices](/docs-site/help/notices) — Review, approve, and track notices. - [Support](/docs-site/help/support) — Get help with access or a blocked workflow. --- # Jobs Tray Monitoring background jobs and workflows in GridWonk. URL: /docs-site/help/jobs ## Salesforce connector work Salesforce connector operations have their own durable import and delivery records; the connector remains disabled pending acceptance. A generic job identifier or utility role does not grant access to captured source data. Ordinary cancel, reprocess, and review controls cannot bypass the source-managed import gate. After activation, inspect connector progress and its explicit quota, provider, or processing wait reason. ## Job Types The active transitional job appears in the tray as **Compliance Validation**. | Job Type | Description | |----------|-------------| | **Document Discovery** | Locating relevant utility procedure documents | | **Packet Review** | Reviewing the uploaded packet against published requirements | | **Compliance Validation (Transitional)** | Existing upload and screening flows can still start the legacy single-document workflow until PR11 | | **Document Digitization** | Processing your uploaded PDF documents | | **Finding Locations** | Pinpointing deficiency locations in your documents | | **Generating Report** | Creating scorecard and deficiency reports | Older job history can also show **Requirements Extraction**. Packet Review is the canonical packet-intake path; the other labels belong to the legacy path that PR11 will remove. ## Status States and Icons | Status | Icon | Color | Meaning | |--------|------|-------|---------| | **Pending** | Clock | Gray | Waiting to start | | **In progress** | Spinner | Blue | Currently running — the badge shows the specific active state (`discovering`, `parsing`, `extracting`, `fetching`, `analyzing`, or `validating`) | | **Complete** | Checkmark | Green | Successfully finished | | **Failed** | X | Red | Error occurred | The tray auto-expands when jobs start so you can monitor progress. An idle tray floats as a small **Jobs** pill at the bottom-right instead of holding a full-width row; select it to open the job history. Speech-input users can address it by the word it shows, **Jobs**. With no job history at all, the idle tray renders nothing. ## Workflow Grouping Related jobs are grouped into workflows showing the complete pipeline: **Example: Transitional Single-Document Workflow** 1. Digitize (Prepare your document) 2. Validate (Check one document against legacy requirements) 3. Locate (Mark deficiency locations) 4. Report (Generate scorecard) This grouped display describes the transitional workflow, not packet Review. Packet Review has its own submission-scoped run history. ## Reliability and Delivery GridWonk now runs pipeline stages with durable orchestration and queue-backed dispatch for long-running tasks. For users, this means: - Lower chance of stalled multi-step workflows - Better retry behavior for transient provider failures - More consistent completion/failure states in the jobs tray - Packet review and related document processing use durable workflow paths You still use the jobs tray the same way; these changes improve execution reliability behind the scenes. ## Progress Monitoring The permission-aware live-update rollout is gated until database and browser checks pass. Once enabled, the tray reconciles missed completed/failed jobs through authorized reads, keeps current data during transport failures, and removes jobs only when reads confirm they no longer belong in the current view. Pagination is not evidence of removal. Existing tabs need a refresh after rollout. Short interruptions are silent. After eight seconds the header distinguishes **Connecting live updates…** from **Live updates interrupted — reconnecting…**. Successful periodic refreshes stay quiet. Document, finding and project changes also have scheduled refresh coverage because not all changes emit job events. A successful jobs read cannot hide a failed read elsewhere. **Some live updates are unavailable.** offers **Retry updates** without a page reload or a new job. Offline browsers warn that displayed information may be out of date; expired sessions offer **Sign in**. A successful reconnect alone never proves that displayed data is current. Each job displays: - **Progress bar** — Percentage complete (0-100%) - **Current step** — Description of current activity - **Completion stats** — Items processed vs total Click any job to see detailed timeline, individual step status, and results. ## Cancel and Retry ### Cancel a packet review Use **Review Actions → Cancel Packet Review** in the project when your review permissions allow it. Cancellation settles the linked run and prevents further packet results from that run; completed document findings stay available. A provider request already running may finish in the background. The project action warns when stopping the background workflow cannot be confirmed, including older runs whose runtime identity is unavailable. Read that warning and contact support before starting another packet review. ### Cancel Use **Cancel** to mark an active job as failed with **Cancelled by user** and remove it from the active tray. This status change is not a guaranteed hard stop for work already dispatched to an external worker. Outputs written before cancellation can remain, so check the destination before starting the workflow again. ### Retry Some surfaces expose targeted retry actions, such as retrying upload digitization or report generation from the Results panel. The jobs tray itself supports canceling active jobs and removing history; do not rely on a generic failed-job retry creating a new job entry. ### Remove from History Use **Remove from History** to clear completed jobs from the list. This does not delete any actual results. ## Best Practices 1. Let jobs complete before canceling unless necessary 2. Review error messages before retrying 3. Monitor discovery and packet-review jobs; duration varies with source size and provider response time 4. Clear old jobs periodically --- # Notices Deficiency notice workflow — draft, review, approve, and send. URL: /docs-site/help/notices The dependent notice-interface release adds [REST, SDK and CLI workflows](/docs-site/api/utility-lane#package-bound-notices) for direct utility members and read-only MCP access. Schema activation and deployment remain separate approvals. Programmatic send recipients must be current addresses on file; existing authorized console recipient entry is unchanged. Source-managed applications cannot acquire notice-write permission through either interface. ## Deficiency Notice Overview The public plugin can read notices within its confirmed workspace and current permissions. Drafting, editing, approving, sending, and acknowledging notices remain website workflows for that connection. Switching the website's active workspace does not retarget the plugin connection. Deficiency notices are formal communications sent to applicants when their interconnection application has issues that need to be resolved. GridWonk automates the drafting process while keeping humans in control of review and approval. ## Notice Lifecycle A notice can move through five stages: | Status | Description | Available Actions | |--------|-------------|-------------------| | **Draft** | A structured notice is composed from accepted and edited package findings | Save Draft, Submit for Review | | **Review** | Engineer reviews and edits the notice content | Save changes, Send Back to Draft, Approve | | **Approved** | An authorized reviewer approved the current content revision | Request sending; revoke only before any delivery attempt | | **Sent** | The email provider accepted the notice for sending; this is not proof of inbox delivery | Read-only (shows recipient and timestamp) | | **Acknowledged** | Applicant has viewed and acknowledged the notice | Read-only | The workflow moves forward: Draft → Review → Approved → Sent → Acknowledged. Reviewers can send a notice back to Draft from Review. Approval can be revoked before any delivery attempt; once sending has started or its outcome is uncertain, resolve delivery first. Once sent, the notice waits for applicant acknowledgment. In the broader lifecycle, a sent notice usually leads to a developer revision cycle and then a resubmission on the same shared submission record. ## Starting a Draft Open the application from **Applications**, choose **Review** in the header, and click **Begin deficiency notice**. GridWonk composes a structured draft from the selected package's findings: 1. Accepted and edited findings are included; dismissed findings are excluded 2. Findings are ordered by severity and carry their requirement citations 3. The draft carries a subject line, an introduction explaining the deficiency review, the categorized list of findings, and a response deadline (30 days by default) The control is only available when the screening decision allows it: the package must be the latest one, the application must be awaiting a screening decision (no draft already open for this round), every blocking finding must have a recorded decision (deferred findings still count as unresolved), and at least one accepted finding must remain to include. Drafting requires current review results for every document in the packet. If a document was replaced and its current version has not been re-reviewed yet, GridWonk hides the findings tied to the older bytes and keeps the control unavailable until the review has been re-run. A notice is a formal communication, so it is never generated from a packet where any document is still waiting for re-review — re-run the review first, then draft. Notices created before package-bound review kept their original generated draft. For those notices, if you modify the body and want to revert, the **Restore AI Draft** button next to the body field (marked with a rotate icon) replaces your edits with that original; it only appears when the current body differs from it. Package-bound drafts have no separate original to restore. ## Editing Notices The notice composer provides a split-pane editor: - **Left panel** — Edit the notice subject, recipient email, response due date, deficiency checklist, and body text (Markdown supported) - **Right panel** — Live preview showing the notice as the applicant will see it, with GridWonk branding ### Deficiency Checklist Each deficiency item in the notice can be: - **Included or excluded** — Toggle items on/off to control what appears in the final notice - **Modified** — Edit the description, severity, or recommendation The notice retains its original finding IDs and adjudication links. Editing cannot add or remove findings from that set; use the checklist to include or dismiss existing items. When you dismiss (uncheck) an item, an amber-highlighted textarea appears below it labeled **"Dismissal justification (required)"**. You must provide a written explanation for each dismissed finding. The Save Draft and Submit for Review buttons are disabled until every dismissed item has a justification. This is a compliance requirement — you cannot skip it. ## Review and Approval The workflow enforces a review chain: 1. **Save Draft** — Save your work at any time during the Draft stage 2. **Submit for Review** — Mark the notice as ready for review by another team member 3. **Send Back to Draft** — During Review, return the notice to Draft status for further edits 4. **Approve** — Approve the notice for sending after review 5. **Revoke Approval** — Move an approved notice back to Review only before any delivery attempt Notice mutations require a utility organization member, admin, or owner. A consultant using delegated access also needs a write or admin grant; read-only viewers cannot approve or send notices. Approval applies to the exact saved content revision. If another edit lands after you opened the notice, refresh and review that version before approving. Editing after revocation clears approval, so approve the new revision before requesting delivery. Older approved notices without revision-bound approval must be reviewed and approved again. Current membership and the exact delegated grant are rechecked when changing a notice and before dispatch. ## Sending Notices After approval, click **Send Notice** to save a delivery request. The sender defaults to `notices@gridwonk.com`, with replies routed to support; it is not a per-utility identity. The request freezes the recipient, sender, reply address, subject, and rendered notice. The composer shows delivery progress separately from notice status: - **Queued / Sending** — The saved request is waiting or being attempted. Do not resend. - **Retry scheduled** — The same saved request will retry automatically; its next attempt is shown. - **Provider accepted; finalizing** — The provider accepted the message, but the application update is still pending. Do not resend. - **Held** — Sending needs review. Read the reason and contact an authorized operator; a new send request does not clear the hold. - **Status unavailable** — Use **Refresh status** before taking another action. **Sent** is recorded only after provider acceptance and the application's notice-sent update commit together. It does not prove inbox delivery. A failed or unconfigured transport does not mark the notice sent. Automatic retries retain the same request for at most eight attempts within 23 hours of the first attempt; uncertainty beyond those bounds is held. The dependent receipt layer can retain verified provider delivery, bounce, or other email events as separate evidence. A receipt does not mark the notice Sent, resend it, or acknowledge it for the applicant. It is not proof that a person read the message, and this layer adds no receipt viewer to the composer. Receipt configuration, schema activation, and production release require separate approval. Before the first attempt, **Revoke Approval** can cancel the pending request. Reapproving unchanged content can resume the same frozen request for its original authorized sender; it cannot silently replace the recipient or create a fresh delivery key. Pending, attempted, held, or accepted-but-unfinalized delivery blocks conflicting application decisions. Each draft creation, edit, send, and reviewer status change is appended to the notice's edit history with who did it, when, and a provenance record naming the credential and surface it came through (a console session today) and the request id. When the utility-event layer is released, actual lifecycle changes also create one durable integration event for the receiving utility's subscriptions. Editing content, requesting a send, receiving a provider receipt, or repeating an acknowledgment does not create another status event. ## Developer Acknowledgment When the applicant's organization is on the GridWonk platform: - They can view the notice in their developer console - They can acknowledge receipt of the notice - Acknowledgment is recorded with a timestamp - They can work toward the next resubmission round from the developer side without losing the notice history Acknowledgment requires a developer or utility organization member, admin, or owner. A read-only viewer cannot acknowledge a notice. Acknowledging an already acknowledged notice is a successful no-op; it does not add another history entry. After a notice is sent, the developer organization can select **Start response** from its project Overview or Review view. Utility and GridWonk reviewer organizations do not receive that developer-only control. Starting the response moves the shared project into **Resubmission Under Development** and records the stage change in application history, so you can see when the applicant began working on corrections without losing the earlier submitted package. ## Follow-Up Notices (Rounds) If an applicant resubmits after addressing deficiencies, you can: 1. Re-screen the resubmitted application 2. Generate a new notice (Round 2, 3, etc.) 3. Each round links to the previous notice for a complete audit trail The round number is displayed on each notice so you can track the full communication history. ## Notices List View The Notices tab shows all notices with: - **Filtering** — Filter by status (draft, review, approved, sent, acknowledged) or notice round - **Search** — Search the notice subject and body - **Sorting** — Sort by date, status, or notice round - **Pagination** — Navigate through large notice volumes - **Status badges** — Color-coded indicators for each lifecycle stage ## Edit History Notice edits are tracked for audit in the underlying record. The current notice UI does not expose a full edit-history viewer. ## Related - [Screening Pipeline](/docs-site/help/screening) — How screening produces the findings that feed into notices - [Application Queue](/docs-site/help/applications) — Managing the application queue - [For Utilities](/docs-site/getting-started/for-utilities) — Utility workspace overview ## Corrected package handoff After the applicant addresses a notice and resubmits, the corrected immutable package returns to **Pending** in the receiving utility's queue. Select the application and choose **Screen Selected** to review that package. The earlier package and notice remain history. Once the new review finishes, complete screening or begin another notice from its current findings; resubmitting alone does not send a new notice. --- # Organizations Manage your organization workspace and switch between teams. URL: /docs-site/help/organizations ## Create or join a workspace When self-service registration is available, verified users who accept the current terms and privacy policy can create a developer workspace. Repeating the same creation request resumes that workspace. Joining an existing team requires an invitation to your own email address; a shared email domain does not grant membership. Utility affiliation requires independent staff review. See [account and workspace setup](/docs-site/help/self-service). Owners and Admins of developer and utility workspaces can open **Billing** from the organization selector when purchases are enabled. Trial eligibility remains tied to the workspace and its original creator. Switching the website's workspace does not retarget an existing public-plugin connection; manage that separately in [Connected apps](/docs-site/help/connected-apps). Available prepaid packs and payment history belong to the selected workspace. Purchases happen on the website; a connected plugin cannot purchase credits or change billing. ## Switching Organizations Use the **Organization and role** selector in the header to switch between organizations where you have a direct membership and client contexts available through an active access grant. The selector shows the active organization and persona before you open or change project data. A granted client context is not a direct membership. When you switch, the dashboard updates to the data allowed by that membership or grant. Test and demo organizations carry a **Synthetic** label in the selector. The label does not change membership, grant scope or access permissions. Approval, membership, and grant scope are not enough when GridWonk asks you to accept updated legal documents. Save any work, accept the current documents, then reload before using customer data or workspace actions. GridWonk still uses one `organizations` table for all tenant types: - utility - developer - consultant - GridWonk platform administration The internal platform label is the canonical `gridwonk` value after the Batch 8 database rename. The selector presents that organization as **GridWonk**. Switching organizations changes which tenant context you are working in. It does not rewrite who owns a shared submission row. The switch writes the canonical GridWonk active-organization cookie, marks the effective audience as resolved for the docs host, and clears the legacy active-organization cookie. Organization, membership, grant, and switch mutations are parsed only after a route-specific body size check. Oversized requests receive `413` before database work; normal organization and grant updates are limited to 32 KiB, member and invitation updates to 16 KiB, and organization switches to 8 KiB. Field and list limits still apply after parsing. Project and curated demo deep links are validated against this active context. If the named project is missing, ambiguous, outside the organization, or unauthorized, GridWonk refuses the link rather than switching organizations automatically. ## What Changes When Switching Your view updates to show: - Documents uploaded by your organization - Deficiency reports for your organization's projects - Agent sessions run by organization members - Dashboard statistics for your organization Every organization has one type — **utility**, **developer**, **consultant**, or the internal GridWonk platform type — and the type, not the role, decides which features exist at all. ## What Stays the Same Some reference data, such as public utility procedure information and queue analytics, may be shared as market intelligence. Customer uploads, validation runs, deficiency reports, and notices remain scoped to the active organization or grant. ## Organization Roles | Role | Description | |------|-------------| | **Viewer** | Read-only access to organization data | | **Member** | Can view and work with organization data | | **Admin** | Can manage organization settings and members | | **Owner** | Full control; can request organization deletion from support | Platform administrators can create a tenant from **Admin Console > Organizations > Create Organization**. Enter the customer's **Owner email** to invite that person as the first Owner; the operator is then not added to the organization and supports it from the admin console. If the invitation cannot be sent, the dialog says so and links to the organization, where the **Team** tab can resend it. Leave the field empty and the creator becomes the first owner. Utility organizations must be linked to an existing utility record that is not already assigned to another organization. Only platform administrators can create a utility organization or set a paid billing tier when creating an organization. Utility organizations represent real utility affiliations and are provisioned by the GridWonk platform team. An ordinary authenticated user cannot claim an existing utility by submitting its `utilityId`; contact GridWonk to set up utility access. Consultant access can also come from grants. Grants may be read, write, or admin level, can expire, and can be scoped to a specific project. Grant-derived access is separate from direct organization membership. Role is only one part of authorization. The organization type must support the action, and a granted context must also have an active in-scope grant. For mutations through a grant, the receiving user must be a **Member**, **Admin**, or **Owner** and the grant must be **write** or **admin**. Some actions, including developer project creation, still require direct membership. For shared submission workflows: - the utility organization owns the review queue row - the developer organization is linked as the applicant on that row - consultant organizations participate through grants rather than by becoming one of those owner columns ### Permission Details This table shows the normal direct-membership floor for features that the organization type supports. It does not override stricter org-type, grant-scope, or action-specific rules. | Action | Viewer | Member | Admin | Owner | |--------|--------|--------|-------|-------| | View documents & reports | Yes | Yes | Yes | Yes | | View dashboard statistics | Yes | Yes | Yes | Yes | | Run agent sessions | No | Yes | Yes | Yes | | Review interconnection requirements | No | Yes | Yes | Yes | | Upload documents | No | Yes | Yes | Yes | | Manage organization settings | No | No | Yes | Yes | | Invite & manage members | No | No | Yes | Yes | | Manage access grants | No | No | Yes | Yes | | Promote members to admin | No | No | Yes | Yes | | Promote members to owner | No | No | No | Yes | | Request organization deletion (through support) | No | No | No | Yes | "Manage organization settings" covers workspace preferences and the workspace **Features** page, where an admin or owner can turn the Slack and Microsoft Teams assistant transports on or off for the whole organization and connect the organization's Slack workspace or Microsoft 365 tenant. Slack uses its authorization page. Teams uses two steps: install GridWonk from the Teams Store, then send the generated one-time command in a private bot chat and confirm in the browser. The tenant connection identifies the organization; each person still links their own GridWonk account. Which features an organization may control is decided by GridWonk from the platform-wide feature registry; the currently opened chat controls are recorded in an audit history and each change requires a short written reason. A setting made by the GridWonk team takes precedence — the page shows it read-only with a contact-support note rather than offering the toggle. Feature management requires direct admin or owner membership — grant-based admin access does not include it. Platform-managed configuration — API and MCP access, usage limits, and billing status — is provisioned by GridWonk for each organization and cannot be changed from organization settings, even by an owner. Repeated setting updates may return HTTP 429; wait before retrying. An admin or owner may deactivate and reactivate either platform installation from the same page. A Microsoft 365 tenant already connected to another GridWonk organization cannot be taken over through self-service; contact GridWonk support to resolve the ownership conflict. A directly assigned Admin or Owner can also enable **Assistant skill sets** and assign versioned guidance for interconnection research, project coordination, or deficiency review. Assignments are audited and affect Slack prompt guidance only; they add no tools or data access. Grant-derived admin access cannot manage either feature switches or skill-set assignments. ## Billing Direct Owners and Admins of developer or utility workspaces can choose **Billing** from the **Organization and role** selector. The page checks current account approval, verified email, membership and legal acceptance before showing that organization's purchase history. Grant-derived client access does not authorize purchases or purchase history. Purchases are unavailable by default and require separately approved payment configuration. Returning from Checkout is not payment confirmation: credits appear only after verified settlement. A held purchase remains on hold for support review. ## Team and logo Open the **Organization and role** selector and choose **Team and logo** to see who belongs to the active organization. Every direct member sees the active directory. Grant-derived access does not open another organization's team. Owners and Admins also see pending invitations and manage the team from the same page: - **Invite people** by work email with a role and an optional access end date. GridWonk emails a single-use link. A person without an account sets a password first; a person with an account signs in and accepts. The answer is the same in both cases, so the page does not reveal who already has an account. In an organization that GridWonk did not provision, a brand-new account also waits for GridWonk approval. - **Resend** a new link, which stops the previous one, or **cancel** a pending invitation. - **Change role**, **suspend**, **reactivate** or **remove** a member. Removing someone ends their access to this organization only; their account and history stay. - **Approve** or **decline** a join request from a person whose email domain matches the organization. Only an Owner can invite or appoint an Owner, change an Owner's access, or make another member an Owner. An Owner may step down to Admin while transferring ownership. Every organization keeps at least one active Owner, and Owner access has no end date. The last Owner cannot leave, be demoted, suspended or removed, even when two changes arrive at the same time. Every change is recorded in the audit log, and repeated changes may return HTTP 429. Owners and Admins can also set the organization **logo**. Enter the company website, and GridWonk shows the logo its logo index has for that website in the selector and on the Team page, or the initials when it has none. GridWonk support can also set a custom `https://` image URL, which takes precedence; if it fails to load, the website logo and then the initials appear. Contact support to set or remove a custom image. The website is for display only and never changes the sign-in domain that decides join requests. ## Workspace appearance Direct Owners and Admins of **developer** and **utility** organizations use **Team and logo > Workspace appearance**. Choose colors in the local preview, then select **Save appearance** to apply full branding to the organization. Grant-based admin access does not include this setting. Consultant workspaces do not support these schemes. 1. Save the company website in the logo settings, then choose **Find brand colors** if more source colors are needed. This reads the public website and supported logo images; it does not apply a scheme. 2. Choose **Light**, **Brand color**, or **Dark brand**. Only the preview changes while you choose. 3. If needed, choose **Main brand color**, **Accent color**, and **Dark brand color** from the source swatches. You cannot enter an unrelated custom color. 4. Select **Save appearance** to apply full branding for the organization. **Cancel** restores the saved selection without changing the workspace appearance. | Scheme | Sidebar | Content | |--------|---------|---------| | **Light** | White with brand accents | Light | | **Brand color** | The selected main brand color | Light | | **Dark brand** | A readable dark color from the source palette | Light | **Dark brand** is unavailable when the sources contain no usable dark color. GridWonk does not invent a darker shade. Action fills and accents use the selected source colors; readable neutral text and surfaces remain. The dark-sidebar option does not turn on a site-wide dark mode. A saved full-branding scheme keeps its chosen appearance even when a personal dark theme is selected. Source colors can come from the saved logo.dev brand, the company website, or supported PNG, JPEG, and WebP logo images. Discovery is a limited inspection, so it may miss colors or fail on a blocked website or unsupported image. An unsuccessful discovery or save keeps the saved appearance. If the website or saved appearance changed while you were editing, refresh the card and choose again. Saving applies the scheme to this organization's developer or utility workspace; other members see it on their next page load. It does not change the sign-in domain. Displayed logos still use the support-approved logo override, the website's indexed logo, or initials. Finding a logo image for color evidence does not approve it as the displayed logo. Contact GridWonk support for a custom logo or to turn off full branding. ## Need Access? Contact your organization admin to be added as a viewer or member. If you work across multiple organizations, ask about multi-organization access and review [how grant-based access is decided](/docs-site/help/access-grants#how-grant-based-access-is-decided). ## Tips - Your default organization loads automatically when you log in - The Organization and role selector shows all organizations and client contexts you can access - Switching organizations takes effect immediately - Your personal settings stay the same regardless of which organization you're viewing ## New client access alerts When enabled, eligible existing members of a consulting organization receive a persistent bell notification for a new client grant; email is controlled separately. This is not a membership invitation and needs no acceptance. The alert remains visible when another organization is selected. See [Access Grants](/docs-site/help/access-grants) for navigation, role limits, and notification eligibility. --- # Packet Requirements Review and approve the utility rules GridWonk uses for application packet checks. URL: /docs-site/help/packet-requirements ## Where To Find Packet Requirements Open the Utility workspace and choose **Rules & Sources → Packet Requirements**. Applications remains the default destination. Old Program Setup bookmarks redirect here. ## Role-Based Review Requirements are grouped by packet role, including Application Form, Single-Line Diagram, Site Plan, Equipment Specifications, Site Control, and Whole-Packet Checks. The top of the workspace shows one compact summary for the selected set with its status, effect, packet-profile rule, publication context, and review progress. The summary strip shows the total number of sets and reviewed requirements, plus sets needing review, changed sets, and active sets. Use **Previous** and **Next** to move directly through the reviewable roles. Each control names its destination, and the center control shows the current role plus its position in the reviewable set. On smaller screens, **Change requirement set** stays above the directional controls so switching roles remains visible without pushing the requirement list down the page. Open **Change requirement set** to choose from every role. Read-only evidence and blocked sets stay visible with their packet-profile, cardinality, evidence, and blocking details, but Previous and Next skip them because they cannot be opened for requirement review. A utility with more than one interconnection lane (for example a simplified, fast-track, and study process) has one requirement set per role **per lane**; the variant label on each set names the lane, and each set is judged against its own lane's readiness policy. **Evidence only** means the packet profile expects evidence for that role but no deficiency checks are published for it. ## Utility Rules And Common Recommendations A utility requirement must cite that utility's source documents. A shared consistency check is a **Common requirement** from GridWonk's catalog instead: the list names it by its catalog id and version and shows its named basis (which utility sources back it). Serving it beside a utility's own requirements does not turn it into a utility rule. A citation to another utility is not evidence that the selected utility requires it. A common recommendation can also be conditioned on a packet fact defined by its published catalog entry. That condition travels with the common whenever its version is served; it does not convert the common into a utility rule or bypass a utility-authored override. The advisory baseline for the four shared whole-packet comparisons covers the connection point, inverter identity, system ratings, and equipment spec sheets. Publishing that baseline for a utility and lane supplies **Low** severity, which does not block packet readiness. Check any saved reviewer severity adjustment before treating a changed rule as advisory. A blocking utility requirement needs its own source-grounded rule and review. Updating the shared baseline in code does not automatically republish any utility's stored requirements. ## Approve Or Reject 1. Use **Previous**, **Next**, or **Change requirement set** to select a role. 2. Review each requirement, finding, severity, and procedure citation. 3. Choose **Approve** or **Reject**. Rejections require a reason. 4. Use **Reset review** to clear the current decision and presentation edits. Reviews are intentionally individual; there is no bulk approval in the first release. A stale decision shows **Reconfirm approval** or **Reconfirm rejection**. Read the current requirement before reconfirming; an ordinary edit does not silently refresh the earlier decision. If a saved wording or severity edit no longer fits the current baseline, repair the edit or reset the review before approving or rejecting it again. ## Review Progress And What Developers See Developer requirement surfaces show every published requirement **except** the ones a utility reviewer has explicitly rejected. A **Reject** decision is the only thing that removes a requirement from those surfaces; it is dropped on the server and never reaches a developer. Every other requirement is shown, carrying its review status: `approved` once a current **Approve** decision covers it, `pending` until then. A change to decision-relevant rule logic, producer severity, or structured provenance makes its earlier decision stale and returns it to the review worklist. This includes a change to the named basis of a common recommendation. Preserving the requirement's identifier preserves its history, not approval of the changed rule. Presentation-only wording changes do not automatically make a decision stale, but any saved reviewer edit that no longer fits the current wording is still incompatible. Stale approvals, stale rejections, and incompatible edits all count as unfinished review — the affected requirement shows as `pending` re-review; it is never silently dropped or hidden. Compatible saved reviewer edits are not automatically cleared when a decision becomes stale. Check the displayed effective severity and any saved wording before reconfirming it. Readers report unfinished review as review progress alongside the list, not as an empty list. API, MCP, CLI, SDK, and chat responses use the same served requirement groups and preserve a typed `releaseStatus` describing that progress, with each row carrying its own `reviewStatus`. This is not limited to NES and does not depend on any commercial relationship with the utility. Normal surface authentication and rate limits still apply. Returned procedure sources are citations attached to derived packet requirements, not access to raw procedure documents. Slack Deep Research uses a narrower operator-only procedure corpus. Its default procedure lane can search only current documents that supply provenance for published packet-review requirements, and only for utilities in the packet-review release list. It does not expose the broader procedure catalog or documents from another utility. ## Procedure And Requirement Decisions Stay Separate Procedure-document review and requirement review stay separate. Rejecting a document from the procedure catalog does not silently suppress a requirement that the utility already approved. The requirement keeps its citation, resolved through the shared utility-scoped document lookup, until an authorized requirement reviewer changes the requirement decision or publication. A citation opens the copy of the document that GridWonk stored and indexed, so it shows the text the requirement was drawn from even if the utility's published file later changes. When no stored copy is available, or the document is not visible to developers, the citation opens the utility's published link instead. A citation to a form or appendix that GridWonk separated from a larger document names its pages, for example "pages 115–131 of" the parent document, and opens only those pages. ## Status Meanings | Status | Meaning | |--------|---------| | **Ready** | Every stable requirement has a current decision and compatible saved edits. | | **Needs review** | At least one requirement has no decision. | | **Changed** | A requirement changed after its current decision, or a saved edit no longer fits the current baseline. | | **Blocked** | A profile, stable identifier, or source configuration is missing, so the role cannot be reviewed safely. | | **Evidence only** | The role participates in readiness but has no deficiency checks. | Packet readiness itself (which documents a complete packet must contain, and how many of each) comes from the utility's published packet shape and readiness policy — published data, so it is available for every onboarded utility without a software release. ## Review Decisions Do Not Activate Screening Recording decisions controls what developers see on requirement surfaces, but does not activate deficiency screening. GridWonk separately activates an exact utility, phase, packet variant, and document role in **shadow** or **enforce** mode. Shadow computes the reviewed result without changing production analysis; enforce applies current decisions to the analyzer — there, a rejected requirement is excluded from automated analysis too. Since November 2026 every role set that reads its common requirements from GridWonk's catalog is in enforce mode, so a utility's decisions take effect in every onboarded lane; a lane onboarded later is switched on with its own reviewed activation. A developer with a valid project can run Packet Review regardless of how far the utility's requirement review has progressed. ## Permissions Utility members, admins, and owners can record decisions for their directly linked utility. Viewers, grant-based collaborators, and synthetic demo utilities are read-only. GridWonk platform reviewers can support cross-utility review only from their native GridWonk organization context. When a platform admin impersonates a utility, the requirement picker and detail reads are limited to that utility, and platform-only editing permissions do not carry into the impersonated session. A common requirement served from GridWonk's catalog is edited like the utility's own: the utility's reviewers and GridWonk's cross-utility reviewers can reword it, change its presentation, and adjust its severity, and the edit is recorded against that utility's lane only. It never changes the catalog or another utility's copy of the same common. Only platform admins can edit a requirement whose source is unrecognized or that is still a frozen copy of a common. ## Requirement-Set Identity and Publication Safety Every published requirement carries a stable identifier, an affirmative customer-facing title, and complete structured provenance — including the cross-cutting whole-packet rules. The publication step enforces this: a requirement set missing identifiers, carrying unresolved placeholder titles, deficiency-style wording, or incomplete source evidence cannot be published. Publishing a utility's requirement bundle is all-or-nothing: readers always see the complete previous bundle or the complete new bundle, never a mixture. Each publish records an append-only ledger entry — who published, the whole-bundle content signature (even for single-role publishes), and a link to the previous publish for rollback. The signature covers the producing model era too, so a republish from a different producer generation is always a distinct ledger entry. Review decisions, publishes, and activation changes all move the requirement-set identity that packet reviews pin, so a review that ran against superseded rules stops counting as current instead of silently standing. This is enforced at runtime: every automatically scheduled packet review runs against the exact rule set captured when it was scheduled, a review still in flight when the rules change is stopped before it can record results, and a completed review whose rules have since moved must be re-run before a packet can be submitted. After a republish, affected packets are re-checked automatically on a rolling schedule (operators can also trigger an immediate re-check — see the packet requirement republish runbook). The captured set covers every role the evaluator can consult, including whole-packet checks and explicit markers for roles that had no published row. The review loads those stored entries by their content signature and fails closed if the stored snapshot is missing or no longer proves its signature; it never substitutes the latest live rules into an already scheduled review. --- # Application Packet Review Prepare, run, and interpret a source-backed pre-submission review across an active application packet. URL: /docs-site/help/packets ## Self-service processing availability Self-service processing remains unlaunched. Its guarded packet path requires an eligible workspace, processing credit, and a supported processing route before paid work can begin. A stopped or unconfirmed paid attempt does not count as a successful review or automatically restore credit. It cannot continue through a different provider or a general assistant job to bypass that stop. The review and source-checking guidance below remains applicable to completed, authorized reviews. If your workspace is limited to PDF review, its packet sources must be standalone PDFs. The server refuses images, ZIP archives, and native CAD files for that scope, including saved File Library attachments and existing packet sources. A supported upload control or an earlier upload does not override the current workspace restriction. A PDF-only review does not waive the utility's required evidence or establish that a packet is ready for submission. When following a review through an assistant or integration, keep its returned job and review-run identifiers. Check the same run after an interruption before starting another attempt. Preserve source document and page citations when sharing its findings; an upload receipt, a queued job, or an individual-document result does not establish completed packet-review evidence. ## Trial and prepaid reviews New packet work needs a current [processing allowance](/docs-site/help/processing). One logical review covers its preprocessing, document checks, eligible platform retries, and automatic follow-up checks for the same input snapshot. Saving a usable packet report consumes one credit, including when cached evidence avoids another provider call. Reading an existing report is free. Trial upload allowances count the ZIP container and each expanded source entry. Resuming the same entry does not count it again. Native DWG processing is unavailable for trial and prepaid workspaces, including archive entries; purchasing capacity does not change that restriction. A utility's required-evidence policy still applies and cannot be bypassed by uploading only a PDF. ## Point of interconnection Turning this optional feature off for the packet's applicant organization stops new geographic processing and hides the geography panel and coordinate checks, including on saved reports. Historical evidence remains in the saved report and authorized API, CLI and MCP report reads. Required utility findings, including service-point requirements, remain visible and unchanged. When this feature is enabled for your organization, **Projects → Review → Report** includes a **Point of interconnection** section to help you check locations before submission. Every observed coordinate retains its source document, page, role and interpretation. Select a row to see distances to other explicit POI observations; distance is advisory because two documents may describe different physical points. The feature does not create deficiencies. Choose **View source** to open the safe PDF rendition of the reviewed document version and page. **Show POI map** plots all explicit POI observations with usable coordinates. Select coincident pins separately through their source rows. Site, equipment and point-of-common-coupling coordinates remain separately labelled in the table. External **Open in Google Maps** links work without the embedded map. Loading a map shares geographic context with Google. When the review read the drawings for POI labels, a **Marked on drawing** table under the observations lists each label as written, what it states and how many reads agree, with **View source** focused on the label. A marker is not a coordinate and is not placed on the map. Approximate NAD83 conversions show their accuracy qualification. Coordinates with an unknown geographic datum may have a provisional map position; incomplete projected coordinates remain unresolved. **Document coverage** shows which attachments were inspected, need more review, failed or were not geographically inspected. ### Geographic review coverage Standard geographic review covers application forms, site plans, single-line diagrams, equipment specifications and site-control documents. Supporting documents and native DWGs are not geographically inspected. An accepted PDF companion can contribute evidence when it has one of those document roles. No coordinates found is reported only after every page has been explicitly inspected by at least two complete interpretations. Missing text recognition does not block the ordinary document review; available interpretations can use the PDF without text assistance. ### Coordinate interpretations and text evidence The report shows the actual interpretation count for each coordinate. One interpretation requires source review and does not establish a map location. The report also states how many interpretations used existing text and how many text transcriptions they shared. Reusing one optical character recognition (OCR) transcription is not independent confirmation of its digits. Conflicting evidence stays unresolved and is not mapped, even when several interpretations repeat the same text transcription. Check the source page and highlighted region before acting on it. ### Recording a location decision Choose **I checked this observed location on the map** or add a note and **Record issue**. Decisions are independent per observation and source version; they do not approve the packet, certify a survey, or remove differences elsewhere. Historical decisions remain readable after sources change, but cannot be applied to a new review. Utility reviewers see the same evidence in submitted packages with separate, package-bound decisions. Mandatory CAD follows the published utility/process policy and its cited requirement. NSP's current published policies make CAD optional; supported NES behavior retains its 50 kW rule. Completed document checks remain applicant self-checks, and only a genuine packet run provides completed packet-review evidence. ## Background updates The gated permission-aware rollout coordinates packet details, document findings, readiness, and history refreshes. Failed reads preserve the last snapshot; only confirmed removal or access loss clears it. A successful job refresh cannot conceal a failed document or findings refresh. Recovery waits for required snapshots, not merely a reconnected channel. See [live-update status](/docs-site/help/jobs). ## Captured application fields The default-disabled credentialed Salesforce connector can supply typed application answers without inventing an application-form PDF. Field citations identify the source object and field, record, application answer path, capture time, and exact snapshot fingerprint. Selecting an older run or package retains that captured identity, not the current Salesforce value. Signature-dependent checks still need real signature evidence. Read access is rechecked against current linked-reviewer and source permissions; connector activation and full revision acceptance remain pending. The separate outbound-only installed application remains disabled. Its Layer 1 foundation records the Salesforce reviewer without creating an individual GridWonk account, and ordinary packet/report readers deny that content. It does not yet submit packets or display Salesforce results. The normal project review workflow below is unchanged. ## What a Packet Review Does Application packet review checks the documents linked to one project before formal submission. It can run document-specific checks and cross-document consistency checks, then save a durable report with findings, coverage, and review history. Split controls and automatic-review readiness are resolved on the server for the applicant organization that owns the packet. Another organization's feature settings cannot enable those controls for this packet. This is decision support, not a final utility, engineering, or legal determination. Confirm each finding against its cited requirement and the applicant evidence before acting on it. ## Where to Find It **Create Project** lists only utilities enabled for full application packet review, including authorized synthetic choices backed by those utilities. **Utility Research** still searches the full catalog. Review support covers the utility's supported state and interconnection program; it does not imply support for every program or state the utility serves. Open **Projects**, select the project, use **Documents** to manage the packet, then open **Review**. That destination is addressed by `view=projects&project=&subview=review` in the URL, so a copied link reopens it; older `?tab=packets&submissionId=` links still redirect there. ### Packet review workflow ## Prepare the Packet Reserved uploads can recover after a refresh in the same tab and account. Return to **Documents** and reselect the unchanged original files when prompted. Recovery keeps the same upload identities and exact CAD target; accepted files are not uploaded again. Dismissing the browser recovery record does not cancel server work or release the review/freeze gate. A rejected new file selection is not an interrupted upload: correct the selection and try again. Use **Retry Recovery** when the account or saved upload cannot be verified. 1. Select the correct project and utility context. 2. Add the current working files to the project. **Documents** accepts PDFs, images, DWGs, or one ZIP through the same control. It can also attach a file already in your File Library; attach it to the project when it belongs in the packet, or link it to the utility only when it is reusable reference evidence. 3. Preview the safe, sanitized rendition when needed, then wait until the current document has a valid review artifact — the sanitized file used as review evidence. The Documents progress card labels **Upload**, **Text recognition**, and **Document review** separately. A completed review reads **Document review: Complete**, even if independent text recognition failed. A file without a valid current artifact that is genuinely pending, processing, or failed is not ready for the same review work as a completed document. 4. Assign the role that matches each document's actual purpose. 5. Use the compact **N of M required roles assigned** summary to check role assignments, then open **Review** readiness for all blocking requirements, human confirmations, and documents needing attention. A complete role count alone does not prove the packet is ready. Do not force an unrelated document into a role just to complete the checklist. Submitted package documents are immutable history. When correcting a working document, use the project's replace or delete controls only for the current working set while the packet is a draft or resubmission under development, then follow the [upload safety states](/docs-site/help/upload#applicant-document-safety-states) and use a distinct working copy when the interface requires one. ### Human confirmations Open **Overview** → **Human confirmations** when readiness asks for a fact that automated document checks cannot establish. On an applicant-owned packet, these are still applicant confirmations. On a utility-owned packet, a direct, active utility member with write access can confirm the utility's own evidence while the packet is a draft or resubmission under development. Viewers, grantees, and impersonated sessions cannot author these confirmations; utility reviewer access to an applicant's packet does not allow changing the applicant's confirmations. | Confirmation | What to check before saving | | --- | --- | | Separate placard checklist | Verify every listed claim, including placement, materials, mounting, and contacts. Seeing a drawing alone is not enough to establish every fact. | | Embedded placard confirmation | Verify the same claims and identify the exact current document, page, and location containing the evidence. | | Native CAD delivery attestation, where available | Record actual receipt or delivery with the required file identity and receipt details. Planned delivery does not satisfy readiness. When native CAD upload is enabled, upload and attach the DWG instead. | | Study-documentation completeness | Check the existing case requirement and confirm that the set covers every current study document. This does not create or change the utility's study requirement. | GridWonk never pre-checks these statements from an AI result. Each confirmation records its authenticated author, organization, time, and exact document versions. A utility-authored record is labeled **Confirmed by utility staff** in the confirmation view and, when it satisfies the requirement, readiness. This is not a customer signature or a substitute for a customer declaration. Replacing a linked document makes the previous confirmation out of date; check the replacement before confirming again. Human confirmation writes remain in the console, not REST, CLI, SDK, or MCP tools. Utility-owned confirmations require the reviewed repair migration and matching application deployment to be active. See [Utility-owned packets and developer details](/docs-site/help/applications#utility-owned-packets-and-developer-details) for ownership and privacy boundaries. ### Split a combined PDF Choose **More actions → Split PDF** on an eligible accepted 2–250-page PDF. Assignment, an earlier review, and a missing classifier warning do not prevent splitting. The possible-combined hint opens the same dialog. 1. Review the sanitized page thumbnails; raw original bytes are never shown. 2. Correct the proposed page ranges so every page is covered exactly once. 3. Confirm a canonical packet role for every document range. Mark only true separator or blank ranges as discarded. 4. Select **Confirm and create documents** and wait for completion. Invalid ranges are rejected immediately, before any background work starts. If the split outlives the short status poll, the dialog stays open in a still-processing state instead of assuming success. The split keeps running in the background, and **Check status** refreshes that exact split attempt. Opening, analyzing, and canceling change nothing. Analysis failures offer **Try again**, with manual page-range editing when page previews are available. Confirmation pauses new reviews and submission. Reopen **Split PDF** for progress; a failed split offers **Retry split** and **Keep original**. Keeping the original abandons that attempt without changing its type or review history. After successful completion, the original PDF and earlier reviews remain available as history, but the source leaves the readiness checklist, editable packet list, review input, and submitted package. Its derived children take those ordinary roles. Only the applicant developer organization (or a platform administrator) can confirm a split, and only while the project stage is editable. Utility and consultant org contexts are read-only; a consultant can confirm only after switching into a granted developer-client context that still has write-capable, in-scope access. Children require fresh review; an earlier clean parent review never counts as a review of the children. The existing per-organization feature controls govern enablement; no new developer setting, API operation, or re-upload is required. ### Upload a packet ZIP Choose one ZIP in the project's shared **Upload Project Files** control to use it as a temporary container for 1–12 PDF, PNG, JPEG, or DWG files. GridWonk validates the complete archive before handing any file to ordinary Packet Intake; one unsafe or unsupported entry rejects the whole ZIP. The ZIP itself never becomes part of the packet or enters review. Each accepted file follows the same preparation, role-confirmation, and review path as an individual upload. Retrying an interrupted ZIP keeps files already handed off. If the interruption happened after a child file was copied but before processing began, recovery rechecks your current permission and resumes the same valid upload attempt; it does not create another child or charge another upload reservation. Expired or retired attempts are not silently revived. If the file was already accepted and initial processing stopped without recording an error, recovery resumes that unfinished work on the same document. It does not repeat completed processing or use one of your failed-processing retry cycles. When the archive or its coordinating upload batch becomes terminal, GridWonk checks packet readiness once and reserves a review only when the remaining evidence is eligible. Abandoning the container does not remove an already handed-off document or attached CAD companion; immutable child work remains in the packet and the readiness profile decides whether it is sufficient. ### Attach a native DWG Each site-plan card offers **Attach DWG**, including before a companion exists. That action targets the exact displayed site-plan version through the ordinary validated upload workflow. **Replace DWG** accepts a new companion; replacing the PDF requires reconfirming or replacing its companion. The card distinguishes required, optional, processing, failed, attached, and outdated evidence. Required CAD comes from the selected published utility/process policy with a cited requirement, not a global project-size rule. NSP's current published policies make CAD optional; NES retains its supported 50 kW rule. Open the project’s **Documents** view and use **Upload Project Files**. You may select a site-plan PDF and matching DWG together; each file may be up to 30 MB. GridWonk pairs only when one current site plan is proven. An ambiguous drawing asks you to choose the matching site plan. For a simultaneous replacement, pairing waits until the sibling PDF is the authoritative current **Site plan**. The DWG is never attached to the version that happened to be current before that PDF finished processing. If processing is interrupted, the same accepted source can be retried or found by bounded recovery; it is not silently treated as packet evidence while unattached. The server validates the file extension, AutoCAD header, exact byte count, and SHA-256 source hash. Upload, retry, cancel, and status checks use the same authorized byte-transfer rules as ordinary documents while preserving the CAD-specific validation and attachment result. The original DWG stays private. The interactive viewer loads Autodesk's derivative rather than the raw source, and its short-lived credential is restricted to the exact companion the session is already authorized to read. A replacement creates a new logical site-plan version and preserves the prior version; it does not edit either file in place. Utility readers can see safe attachment metadata but cannot replace the applicant's drawing. When a reviewed Autodesk derivative is ready, select **Review PDF and DWG**. The rendered PDF stays on its existing viewer; the native tab streams an authorized derivative with layout selection and the Autodesk toolbar for layers, selection, properties, measurements, and view reset. The evidence summary states the detected version, units, coordinate metadata, layers, layouts, Xrefs, and proxy objects. A replacement also shows structural changes and which preflight items are new, still present, or resolved. Preflight items are mechanical prompts to verify; they do not replace engineering review. When a utility has a reviewed CAD procedure profile, GridWonk can use the exact stored evidence to flag Xrefs, coordinate metadata, units, layers, layouts, proxy objects, and missing required drawing content. It can also compare extracted address, inverter, system-size, and point-of-interconnection evidence with the application. These first-rollout findings are advisory and require reviewer confirmation. An exact finding selects a CAD entity only while the source hash and derivative identities match; otherwise GridWonk shows approximate or unresolved guidance without a highlight. Upload, visualization, and evidence summaries are available to authorized accounts. Utility-specific findings still require a configured CAD procedure profile. Nashville Electric Service is the first profile: its DWG is optional below 50 kW and required for readiness at 50 kW or more. **Attached** proves immutable delivery; processing remains protected by operational kill switches. CAD pairing and recovery do not create another review lane. The existing packet-review scheduler waits for active mixed-upload coordination to settle, then uses the current immutable PDF and DWG identities in the ordinary packet input fingerprint. Autodesk evidence that becomes ready later can start a new deduplicated review against that updated evidence set. ## Document previews in Review For a utility-created project with no applicant organization, the utility owns the packet. Authorized utility reviewers can preview the current sanitized document version in **Review** without first creating a submitted package. For an applicant-owned project, utility reviewers still preview the version saved in a submitted package. The Review findings view requires that saved version to match the current document; without a matching submitted version, the preview remains unavailable. Access checks and document privacy still apply to both paths. ## Run the Review Read **Upload**, **Text recognition**, and **Document review** independently. Failed text recognition does not relabel an already-completed review as failed. If an individual review failed, use its retry control only after any known platform issue is resolved; retrying review does not retry OCR or upload a new PDF. See [Document troubleshooting](/docs-site/help/document-troubleshooting). Eligible projects start typed document checks automatically and in parallel, including site control. Each finished check saves current extraction evidence and rechecks packet readiness; the full packet review starts automatically after all present typed documents and required packet evidence are ready. The Documents view states whether that full review has not run, is active, last completed, or failed. The Review toolbar shows **Findings**, **Report**, and **History** as full-size tabs, with the active one underlined, beside a labeled readiness status and **Review Actions**. Open readiness only when you need its explanation, missing requirements, documents needing attention, package details, or report links. Use **Review Actions** for a deliberate manual run or rerun. This is the developer's applicant self-check; historical utility-authority results remain in a separate review lane. **Review Actions** uses that same readiness result. If document roles are missing, it offers **Assign Document Roles** and opens Documents. If another required document or human confirmation is missing, **Run Review** stays disabled and tells you to complete the requirements shown in the readiness row. Returning to Review after changing roles or confirmations refreshes that result. If your active role cannot edit applicant documents, missing roles remain a blocker instead of opening a read-only Documents view. This prevents a click from looking successful when the server cannot start a review. The developer console defaults to the applicant lane and does not show a large authority card. Utility teams run utility screening from their utility organization context. GridWonk can enable a compact **Review as** selector for an authorized operator when exceptional cross-organization testing is needed; that presentation control never grants either authority by itself. 1. Open **Review Actions** and select **Run Review** or **Run Review Again** when a deliberate manual run is needed. 2. Review the confirmation. GridWonk reuses saved document extractions when their identities still match and reads changed or unmatched documents again, so a routine rerun can finish much faster than a first or fully fresh review. 3. Confirm the run. 4. Follow its queued or running state while the background workflow processes the packet. Completion is pushed to the page in real time — even though the review executes in the connecting utility's workspace — with a periodic check as backup, so the finished state appears without reloading. 5. Open **Report**. It shows the current completed applicant packet review, or an immediate partial report from current document checks while that full review is outstanding. Utility confirmation is not needed to see applicant self-check results. Use **History** for earlier or out-of-date runs; a clearly labeled utility fallback is used only when no current applicant results exist. Starting the same active review again reuses the in-progress work instead of creating a conflicting second run. ### Cancel an active packet review Open **Review Actions → Cancel Packet Review**, then confirm the exact active run. This action is available only to users authorized to run reviews in that same applicant or utility review lane. Access to another lane's results does not grant permission to cancel it. Cancellation ends that run's status and prevents it from saving further packet results. It does not delete completed document findings, cancel their separate reviews, or repair failed text recognition. A request already being processed by an external provider may finish in the background. If GridWonk cannot confirm that the background workflow stopped, it shows a warning; contact support before starting another packet review. A review that completed before cancellation keeps its completed result. ### Review an individual document In **Documents**, open a row's **More actions** menu for **Review** or **Retry review** when available. That per-document review saves the document's extracted content. Automatic checks can run together; the final completed extraction triggers the full-packet readiness check. When a utility publishes multiple programs for the chosen connection level, **Create Project** requires you to select a program. The application form is checked against that program rather than used to guess your choice. A refused form shows whether it appears to be the wrong instrument, a different revision, or could not be verified, together with the recorded reason and observed differences. This explanation appears in both normal and compact Documents rows and disappears after a successful retry or replacement. Upload the correct form before retrying. When a required-documents roster cannot be determined at all, both Documents presentations (the packet view and the compact projects view) say so explicitly and **Run Review** stays closed until it can. **Retry review** on a failed document review re-opens that same review attempt; it does not count as a revalidation unless an earlier review of that document had completed. On eligible editable demo packets, a platform administrator also sees **Force fresh document perception** for synthetic quality assurance. It deliberately re-reads every reviewable PDF with the current models, takes longer, and uses additional compute. Ordinary customer runs do not expose this control. **Findings** opens on the document with the most severe findings already selected, so evidence is on screen as soon as you arrive. The chosen document is marked as selected in the document row, and picking a different one replaces it — your choice is then kept, including across the automatic background refresh. A document whose file changed after its last review is only opened when nothing current has findings, and it keeps its **Review out of date** warning. When no document has findings, the workspace says which situation you are in rather than leaving the area blank: **No findings** once every document in the packet was reviewed and came back clean, **No findings yet** when the reviewed documents are clean but others have not been reviewed (it names how many), or **Nothing reviewed yet** before any review has run. The Review toolbar carries a compact document switcher — a combobox listing every reviewable document with its status — and `[` and `]` step to the previous and next document without opening the list. Your selection is written to the URL, so a copied link reopens the same document. Whole-packet findings appear as a compact count beside the switcher. Open that count to see each finding's severity, description, and source. A retained-snapshot warning uses the same compact pattern if a background refresh fails, leaving the findings and PDF workspace available. Completed current document findings remain available while a packet review is queued, running, failed or cancelled. The workspace labels them **Individual-document review results**, not whole-project results or utility approval. A current completed packet result takes priority over overlapping document results. An older file version or an earlier successful document check is not restored as current evidence when that document's newer review failed. **History** keeps this project's resolved and superseded findings beside every packet review run. Opening it re-checks for work finished since you last looked, so a review that completed while you were on another tab appears there without reloading the page. ## Respond to a Sent Notice When a project has a sent deficiency notice, a developer organization can select **Start Response** from the project toolbar above **Overview**, **Documents**, **Review**, or **Activity**. The action moves the live project into `resubmission_under_development`, records the transition in application history, and unlocks the working documents for correction. The toolbar then changes to **Resubmit Project** until the revised package is submitted. Utility and GridWonk reviewer organizations do not see this developer-client action. A consultant may see it after switching into a granted developer-client context, but the server succeeds only when that context still has write-capable, in-scope access. If a teammate already started the response, refresh the project; the action is idempotent and does not write a duplicate history row. ## Checks This optional workspace has its own organization feature flag. Turning it off hides all six supplementary categories and the Checks queue: map coordinates, AI follow-ups, engineer stamp, site-control terms, equipment listing and fees. It does not stop the core utility requirement review, resolve findings, or hide incomplete required checks. Saved decisions remain preserved. When packet review checks are enabled for your organization, the Review toolbar adds a **Checks** tab beside Findings, Report and History. Checks is the human pass after the AI packet review. It reads the current completed review and lists what a reviewer still confirms by hand: - **Coordinates on the map**: one element at a time, the point of interconnection first, then site, point-of-common-coupling and equipment locations. The panel is a console: the title row, one verdict line, the pictures, and the decision bar. The **(i)** beside the title says what the check asks. The verdict line reads **Same place**, **One read only**, **2 places within 14 m**, **2 places, 1.2 km apart**, **Not on the map** or **Not stated**, with the counts of reads and documents and a gauge of the farthest read. Chips on that line carry the hedges; hover or focus one for its sentence. The drawing crop around the coordinate label and the satellite map fill the rest, side by side, so you compare the drawing and the imagery. The document and page, the previous/next pager, the text as written and **Open page** sit on the drawing; the pin legend, the shown position and the **Google Maps** link sit on the map. **Coverage** at the top right lists every document and how much of it was inspected. One decision per place. The rules behind the words: reads of one element are grouped across documents and pages, and reads within 2 m are one place. Places more than 50 m apart are a discrepancy to look at before you decide. **N reads uncertain** means the model's own interpretations of a read disagree, or fewer than two agree; open the source before you decide. **N reads not on the map** means the document states the element but its text gives no confirmable position; the chip's tooltip says why (the source evidence conflicts, not enough reads agree, or the coordinates have no supported map position). A location drawn on a site plan without written coordinates is not a place. When the documents put the element in more than one place, a digit strip above the pictures marks the digits of each document's coordinates that differ from the first and the distance that difference amounts to; the strip also appears when a read is uncertain, with that document's row marked, so you know which page to open. When every document agrees and no read is uncertain, there is no strip. **Comparison only** marks a place or marker that another organization decides; it is shown so you can compare, not record. - **Marked on drawing**: when the review read the drawings for POI labels, the applicant's own "point of interconnection" label on a drawing is an item beside the point of interconnection: the label as written, what it states (feeder, substation, voltage, structure) as chips, and how many reads agree, with the drawing crop showing the label and its leader outlined. A marker is not a coordinate and has no pin; the map keeps showing the stated coordinates. Confirm by eye that the marked place sits where the site coordinates and the imagery put the site, then record one decision per marker. **1 of 3 reads saw it** or **Reads disagree** on the marker line means the reads of that drawing did not agree on the label; open the page before you decide. Reviews made before drawing-marker reading is activated have no such item; an empty list never means a drawing has no POI label. - **AI follow-ups**: every item the AI review could not verify or did not perform. Marking one "Reviewed myself" records that you looked at it; it is not a pass. - **Documents**: manual items such as the engineer stamp and license, the site-control term and signer, the equipment listing, and fees received. Pick a check in the left rail (icons with a status dot; the arrow at the top expands it to titles, and the choice is remembered in your browser), then record **Mark checked**, **Record issue** or **Not applicable**. An issue or a not-applicable decision needs a short note. Decisions are append-only and bound to the exact review run and evidence. When a new review runs, the checks start again. The utility sees applicant decisions read-only on a submitted package; applicant users never see utility decisions. A role that can only view the checks sees the decision buttons disabled and a **View only** chip; hover or focus the chip for the reason. A check records your review. It never approves the packet, creates or resolves a deficiency, or changes the AI verdict. Keyboard: `j` and `k` move between checks, `c` marks the selected item checked, `i` and `n` open the note for an issue or not applicable, and `?` lists every shortcut. Shortcuts are off while you type in the note. The left rail also gains a **Checks** destination under Projects. From inside a project it opens that project's checks. Otherwise it opens the project you last chose there, or the **queue** when there is none: a table of every project with checks (newest review first) with its utility, review date, progress and what needs attention. Filter it to open checks, recorded issues or all projects. A row opens that project's checks in a side panel, so you can clear several projects without leaving the table; `↑` and `↓` move through rows, `Enter` opens one, and `[` and `]` move the panel to the previous or next project. A project view adds a switcher strip: **Previous** and **Next**, a dropdown of every project with checks and its progress, **Open project** to jump into that project's own Review tab, and the queue icon at the left to return to the table. `[` and `]` move between projects there too. The Report tab shows one line, "Checks: 3 of 7 reviewed", with a link into the Checks tab. ## Read the Report The **Report** tab follows current results without pinning the first run it sees. Explicit run links from **History** stay pinned; selecting **Report** returns to current results. A current completed packet review replaces overlapping document results, so findings are never counted twice. Before that review completes, **Partial report — document checks** shows real completed document checks and their critical, high, medium, and low counts. It lists missing requirements, unfinished or failed processing, stale results, and cross-document checks not yet completed. It is not a fabricated packet run, utility approval, or proof of submission eligibility. Uploads, replacements, deletions, role changes, and CAD attachments refresh the current view as their packet updates arrive. Background refresh failures retain the last snapshot with an explicit out-of-date warning. Unchanged polling responses do not trigger extra findings or CAD reads. Hidden findings panels refresh when visible again. If a new packet retry fails, current document checks remain the partial result; older completed packet findings are not relabeled as document checks. Cards and Overview show **Findings unavailable** when the current counts cannot be loaded. If no current applicant results exist, a completed utility review can appear with a **Latest completed utility review** notice. It remains pinned utility evidence, not the current applicant report. Failed reads show an unavailable state rather than claiming no report exists. This also applies when the last saved snapshot was empty: a failed refresh cannot silently switch to a utility report. Start with the result, then inspect its limits: - **Review Finished** means processing has ended for that review. The report shows findings and their severity. Open **Coverage** to see which checks ran, which did not apply, and which still need evidence. Expand a check for its recorded reason and any next action. - **Deficiency identified** — Required information is missing or the evidence demonstrates a problem. Read the finding to distinguish a completeness gap from a technical issue. - **Unable to verify** — The check was attempted but could not reach a supported conclusion. - **Not applicable** — Evidence establishes that the requirement does not apply to this project. Unknown or unreadable evidence is not a reason for N/A. - **Not evaluated** — The check was not performed; Coverage gives the reason, such as an absent document, missing context or a separate review step. - **No deficiency identified** — Only the completed checks found no deficiency. This is not utility approval or proof that every possible requirement was checked. - **Missing documents** — Shows required roles without an assigned document. An uploaded file may still need its role confirmed. A missing required site plan can be a deficiency while its downstream content checks remain not evaluated. - **Classification** — Shows the project classification and thresholds used for the review. - **Coverage** — Lists completed, unfinished and partially evaluated checks with their reasons. A readable spec sheet or breaker does not hide another unreadable one. Expand a group for check names and any applicability evidence. - **Finding groups** — Organize document-specific and cross-document findings with source-backed evidence. A check not performed is not a pass. If coverage was not recorded for an older run, its completeness is unknown. Findings already identified still apply. A known out-of-scope requirement is resolved as N/A; absence of a document alone cannot establish that the requirement is optional. ## Correct and Rerun 1. Review the cited utility requirement and the applicant evidence for each finding. Each card names the requirement, the source document and page, and the verbatim cited text. 2. Correct the current project working set without changing an earlier submitted package. 3. Wait for changed documents to finish digitization and confirm their roles. 4. Run packet review again. 5. Compare the new report with earlier history. Revalidation reports can identify findings that were resolved or superseded. Keep earlier runs as review history. A newer result does not rewrite the evidence or conclusions stored with an older run. ### Explain a finding before acting Select **Explain this finding** on a finding to inspect quotations from its original source edition. The server rechecks project access and verifies each quotation before showing it. Nearby passages are kept separate, and governing scope and project applicability remain explicitly unconfirmed. The assistant does not invent interpretations or section references, inspect your drawing again, decide pass or fail, or treat publication as utility approval. The selected finding stays visible for follow-up questions and retries. Select **Clear finding** to change topics. If an older review, a form-model finding, or a missing or ambiguous source lacks enough saved evidence, the assistant explains that limit instead of substituting today's rule. See [Explain a Review Finding](/docs-site/help/assistant#explain-a-review-finding). ## Review Boundaries - Only documents available to the active organization and project can be reviewed. - A developer's pre-submission review stays private. A utility can see the review frozen with a formally submitted package and its own later screening, not a developer's draft corrections. - Unassigned, unreadable, or unsupported documents may not receive document-specific checks. - Supporting documents can contribute to readiness without having their own automated analyzer. - Customer-facing conclusions should rely on approved, current utility procedure sources. - Human review remains required for ambiguous evidence, checks that could not be verified, and final submission decisions. ## Related - [Upload](/docs-site/help/upload) — Add and safely revise project documents - [Requirements](/docs-site/help/requirements) — Understand the utility rules behind findings - [Results](/docs-site/help/results) — Work with document-level deficiencies and source locations - [Applications](/docs-site/help/applications) — Understand submission and review lifecycle states - [Developer Notices](/docs-site/help/developer-notices) — Respond after utility review ## Confirm or Decline a Finding as an Applicant On a completed packet review, an owner, admin or member of the applicant organization can choose **Confirm** or **Decline** on each finding. Declining requires a reason. A consultant working under a write grant from the applicant organization for that project can also record decisions; a read-only grant can see them. Viewer seats can read the organization's decisions but cannot record them. Utility membership and platform admin status never grant permission to decide on the applicant's behalf. Anyone who can see the decisions but not record them, such as a viewer seat or a platform admin, sees the same **Confirm** and **Decline** buttons greyed out: the applicant's answer is shown pressed, or the card says **No applicant response yet**. A changed decision adds a new version; the latest version counts and earlier decisions remain in history. A new review has its own findings to decide. Before you submit, your decisions on your own self-checks stay private to your organization, its consultants and platform admins. Once a review is part of a submitted application, the receiving utility can see your responses on that review's findings, which helps it focus on the findings you agree with. Decisions do not change the utility's adjudication, fix the underlying finding, or replace review, correction and submission requirements. --- # Portfolio Dashboard Browse projects, document status, and validation readiness. URL: /docs-site/help/portfolio # Portfolio Dashboard **Projects** is the console's default destination and its project board. It shows the projects your organization can access, and opening one lands in **Overview**, with **Documents**, **Review**, and **Activity** beside it in the app header. Old `?tab=portfolio` links still redirect here. The selected project's one current developer action — **Submit Project**, **Start Response**, or **Resubmit Project** — sits in the app header beside the project's views. It does not repeat a lifecycle-status badge and shows no action while the utility owns the next step. When readiness blocks submission, the readiness panel owns the explanation so the compact header does not repeat it. ## Background updates The gated permission-aware rollout refreshes every loaded project without resetting scroll or replacing the list with loading placeholders. Missing rows on a page are not treated as deletions; authorized reconciliation confirms removal separately. Project-scoped subscriptions prioritize the selected project and visible rows, capped at 50 topics per tab; remaining loaded rows refresh periodically. See [live-update status](/docs-site/help/jobs). ## What Counts as a Project A project is the durable container for work that should persist: uploaded project files, validation runs, deficiencies, scorecards, remediation status, and reports. Creating a project asks for a name, capacity, and the distribution/transmission track. When the selected utility publishes more than one interconnection program for that track, a **Program** dropdown appears and must be answered — the project declares its program up front and the review runs against that program's rules. Utilities with a single program never show the dropdown. The **Create Project** utility picker requires a released, full packet setup for the selected utility, state, and program. By default, a normal choice does not need a receiving organization for private review. Authorized synthetic choices require a valid test pairing backed by a released utility; they do not activate real utility submissions. A utility inherited from Research must qualify too. The support check starts as soon as the dialog opens; choose another utility if yours is unsupported, or use **Retry** to run the check again if it could not be completed. Research still offers the full catalog; review coverage depends on the supported state and interconnection program. Contact support when utility setup is incomplete. An available choice does not guarantee exhaustive requirement coverage or utility approval. **Submit Project** is available only after GridWonk and an authorized utility representative accept that exact state and program and the utility has an active reviewer. **Resubmit Project** after a deficiency notice is not blocked by that acceptance; see [Private Reviews and Utility Submissions](/docs-site/help/private-reviews-and-submissions). If you selected an authorized synthetic utility, the project still uses the named canonical utility's documents and requirements. The server re-checks the active applicant organization and reciprocal test pairing before routing the project to the synthetic utility organization. A stale or forged synthetic selection is rejected. Internally, GridWonk stores projects in the existing `application_submissions` table. In the UI we call them projects because that is the user-facing object. GridWonk creates a hidden internal reference for new console projects and can later map or replace it when a utility system assigns an official application number. ## Documents During Creation You can select optional documents in **Create Project**. After a valid selection, the drop area closes and a file count appears. Filenames and removal controls stay visible; **Add files** reopens the drop area, and removing the last file restores it. The title and action buttons remain visible while the form scrolls on short screens or at larger browser zoom. Choose up to 12 PDF, PNG, JPEG, or DWG files (30 MB each, 120 MB combined), or one ZIP by itself. Invalid additions show an error without discarding accepted files. **Create and upload** creates the project, then starts upload on Documents, where upload permissions and ZIP availability are checked again. You can still create a project without documents. Enter the AC (alternating current) nameplate capacity. **Capacity help** expands the unit definitions; the short conversion stays visible: 1 MW = 1,000 kW. ## How Projects Are Grouped Capacity entry defaults to **kW** (kilowatts), with an explicit **MW** (megawatts) selector. Storage and APIs use MW: 11.4 kW is 0.0114 MW. Overview shows capacity, the application's declared AC/DC rating when available, and discrepancies rather than silently replacing the entered value. Cards and Overview use the same current findings as Documents and Review. Completed document checks produce a **Partial document review** summary immediately; a current completed packet review shows **Review Finished** and replaces overlapping document checks. Open its Coverage section to inspect missing inputs. A partial summary never enables submission. Utility labels use display names. Activity shows persisted upload, document-review, CAD-attachment, and packet-review events, without inventing historical events. Projects are listed in two sections, **Needs your attention** first and **Other projects** below, each with its own count. Long lists load a page at a time; use **Load more projects** for the rest. Developer organizations also get **Create project** here. ## Project Cards Each project card shows: | Element | Description | |---------|-------------| | **Project** | Project name, or the application number when the project has no name | | **Demo badge** | Marks a demonstration project | | **Utility** | Utility and state for the project | | **Documents** | Number of linked project documents | | **Review summary** | Current review state for the project | | **Next action** | The developer-facing step this project is waiting on | | **Updated** | When the project last changed | Each card is a link, so you can open a project in a new tab or copy its address. An ordinary click opens that project's **Overview**. Changing or clearing the selected project also clears any packet-review selection. ## Aggregate Rollups Are Retired The old portfolio aggregate view moved to the console's Analytics destination, and that destination has been removed. Utility-level application counts, average readiness, deficiency totals, and the portfolio CSV export are no longer available in the console. Per-project status lives here on Projects. ## Related - [Upload](/docs-site/help/upload) — Draft files and project-linked validation - [Results](/docs-site/help/results) — Project-scoped validation output --- # Private Reviews and Utility Submissions How developers check a packet privately, and when a utility can receive a formal submission. URL: /docs-site/help/private-reviews-and-submissions Reviewing a packet and submitting it to a utility are two separate steps. A developer can check a packet privately while its processing allowance and supported workflow remain available. A formal submission is possible only after the receiving utility has agreed to accept submissions for that state and program. ## Private packet review (developers) A developer can create a project and run Packet Review for any utility that has a released, complete packet setup for the project's state, connection type (distribution or transmission) and, where the utility publishes more than one, program. - **The project state is required.** A utility's packet requirements are specific to a state. For example, Delmarva Power's Maryland requirements never make a Delaware project reviewable. - **Unavailable combinations are refused at creation.** If the utility has no released setup for the chosen state, connection type or program, project creation explains that packet review is not available yet. - **Drafts and private review results stay private.** Utility users cannot see a developer's draft project, its working documents or its private review results. They see only what is in a formal submission package, plus reviews the utility itself runs on that package. A private review is a self-check. Running one never sends anything to the utility. Private review is the default for supported packets without needing a receiving utility organization. Trial and prepaid workspaces also require an enabled, qualified processing path and current [processing allowance](/docs-site/help/processing). It remains available by choice even when the utility accepts formal submissions. ## Formal submission **Submit Project** sends a frozen package of the project's documents to the receiving utility. It is available only when all three of these are true for the project's state, connection type and program: 1. **GridWonk has approved** the utility for that state and program. 2. **An authorized utility representative has accepted** submissions. This must be an active owner or admin of the utility's own organization, not GridWonk staff. 3. **The utility has an active qualified reviewer**, meaning an owner, admin or member of the utility organization who is not platform staff or a test account. Submissions to **real utilities are off by default**. The separate, verified reciprocal synthetic QA pairs used for internal testing accept by default and can be revoked by a platform admin; they do not turn on intake for their real-utility counterparts. Until all three real-utility conditions are met, the Submit button is disabled and shows: *"This utility is available for private packet review, but is not accepting submissions for this state and program yet."* Private review keeps working in the meantime. The Submit page rechecks automatically every 30 seconds while submission is blocked, and again when you return to the browser tab, so you do not need to reload after a utility starts accepting. If the check itself fails, for example during a brief outage, the page says it could not check and to try again. That message does not mean the utility has declined. The server repeats every check when you press Submit, so a stale page can never send a packet to a utility that is not accepting. ### What the first accepted submission does - **Binds the receiving utility.** The project is permanently linked to that utility organization. - **Freezes the package.** The exact document versions sent are stored as an unchangeable package. - **Shares the pinned report.** The receiving utility can read the packet report included in that package. Other private review history and private document reviews remain applicant-only. - **Notifies the utility.** Each qualified reviewer at the utility receives an in-app notice, *"New application packet"*, with a **Review application** link. Notices appear in the same notification inbox as other alerts and can be marked read or dismissed. Synthetic QA submissions do not create real-utility receipts or notices. ## Resubmission after a deficiency notice A resubmission is the developer's corrected packet after the utility sends a deficiency notice. It goes to the same utility that already accepted and reviewed the original submission. **Resubmission does not require the utility to be currently accepting new submissions.** The **Resubmit Project** button is never blocked by the acceptance status. This means: - If the utility later stops accepting new submissions, or GridWonk withdraws approval, developers who are already answering a notice can still send their corrections. - If the utility has no qualified reviewer at that moment, the resubmission is still delivered and stored on the project, but no reviewer receives an in-app notice. The utility sees it in its applications list when a reviewer is next available. All the other resubmission checks still apply, including linked documents, upload completion, project stage and the signed-in user's authority. ## For utilities: managing which submissions you accept Utility owners and admins control acceptance in **Settings → Integrations → Application packet submissions → Manage packet submissions** (`/utility/submission-acceptance`). The page lists each state and program your utility has a released packet setup for. Each row shows three statuses: | Status | Meaning | |---|---| | **GridWonk: approved / pending** | Whether GridWonk has approved this state and program | | **Utility: accepted / pending** | Whether an authorized representative of your utility has accepted | | **Reviewer: available / unavailable** | Whether your organization has at least one qualified reviewer | When all three are in place, the row reads *"Developers can submit packets."* - **Accept submissions** turns on your side of the agreement for that row. - **Stop accepting** revokes it. Revoking by either party clears both approvals, so reopening requires GridWonk to approve and your utility to accept again. - Revoking blocks **new** submissions immediately. It does not remove packages already received, their notices, or developers' ability to send corrections for applications already under review. - An acceptance counts only while the person who accepted is still an active owner or admin. If that person leaves or loses the role, another owner or admin must accept again. GridWonk operators manage GridWonk's side in **Admin → Organizations → Packet submissions**. ## Related pages - [Applications](/docs-site/help/applications) — submission stages, package history and resubmission flow - [Developer Notices](/docs-site/help/developer-notices) — responding to a deficiency notice - [Application Packet Review](/docs-site/help/packets) — building a packet and running Packet Review - [Email Notifications](/docs-site/help/email-notifications) — notification preferences --- # Trial and prepaid processing Understand review credits, processing limits, and purchase status. URL: /docs-site/help/processing ## Trial allowance An eligible new workspace receives a trial limited to **30 days**, **10 completed packet reviews**, and **$50 of processing**, whichever is reached first. The clock starts with the first admitted processing operation, which can include file preprocessing before a report. A trial belongs to the workspace and its original creator; transferring ownership, creating another key, or deleting files does not replenish it. One trial packet review can run at a time. The trial also admits at most 120 source-file versions totaling 1,200 MiB. Per-file and packet limits still apply: up to 30 MiB per file, 12 files and 120 MiB per batch, and 250 pages per PDF. An archive container and each expanded source entry count toward the allowances. Resuming the same accepted entry does not count it again; deleting it does not restore the allowance. The service-wide trial processing limit can temporarily prevent new work even when your own allowance remains. An allowance applies only to formats supported by your workspace. If it is limited to PDF review, use standalone PDFs: images, ZIP archives, and native CAD files are refused, including when reusing saved sources. The archive allowance described above does not grant permission to process an archive. A PDF-only review does not waive the utility's required evidence. See [supported uploads](/docs-site/help/upload). ## How reviews count A logical packet review reserves one credit before processing and consumes it when a usable report is saved. Its preprocessing, document checks, platform retries, and automatic follow-up checks share that review operation for the same source files, project inputs, and requirement version. A new deliberate review or a changed review snapshot can use another credit. Saving a new usable report still consumes a credit when cached evidence avoids new provider work; reading an existing report does not. Utility screening uses the reviewing utility workspace's allowance and the exact submitted package, independently of the developer's private review. A platform failure without a usable report releases the review credit, while processing already performed still counts. If a provider's result is uncertain, the reserved processing allowance stays held until it can be reconciled. Repeatedly restarting or uploading the same file does not resolve that uncertainty. Contact support if work remains blocked. New processing stops when an allowance expires or is exhausted. Existing authorized reads and exports remain available, and expiry does not delete your files. Unsupported processing paths are unavailable in this rollout, including native DWG processing, unrestricted assistant chat, generic jobs, and legacy digitization. Use supported packet intake and review. Purchasing capacity does not change file support or utility coverage. ## Prepaid packs When purchases are enabled, a workspace Owner or Admin opens **Billing** on the website. Select your organization, review the offered pack and its limits, then choose **Continue to secure checkout**. Current pack quantities and prices appear there. There is no subscription or automatic refill. Purchases are a website workflow. Returning from checkout does not confirm payment. **Payment pending** means verification is still underway; **Credits added** confirms that processing capacity was recorded. Recent organization purchases appear in the same page. Billing shows packs and purchase receipts; a combined trial/prepaid balance display is not yet available. If purchases are unavailable, no checkout starts. A refund, dispute, or inconsistent payment record can place the remaining capacity **on hold** for review. Usage already consumed remains in the history. A changed dispute or refund status does not automatically replenish or release capacity. Contact support for reconciliation. --- # Requirements Understanding interconnection requirements extracted from utility tariffs. URL: /docs-site/help/requirements ## What are Interconnection Requirements? Requirements are the technical, procedural, and financial rules utilities impose on energy projects. They define: - What documentation is needed - Equipment specifications required - Processes to follow for grid connection approval ## Requirement Categories Requirements are organized into four main categories: ### Site Control Land documentation proving you have rights to the interconnection location: - Deeds - Leases - Easements - Letters of intent See [Site Control](/docs-site/help/site-control) for the workflow that connects extracted utility requirements to uploaded applicant evidence. ### Technical Requirements Equipment and engineering specifications: - Inverter certifications (UL 1741 SA) - Protection settings - Voltage ride-through capabilities - Anti-islanding requirements ### Application Requirements Forms and documents needed for submission: - Completed application forms - One-line diagrams - Site plans - Insurance certificates ### Fees Financial requirements: - Application deposits - Study deposits - Processing fees - Per-kW charges ## Published Packet Requirements The developer Requirements view shows the published requirements for exactly one packet variant at a time: every published requirement **except** the ones a utility reviewer has explicitly rejected. Rejected requirements are removed on the server and never reach the page. Each requirement carries its own review status. **Approved** means the utility's reviewers signed off on it. **Pending** means it is still awaiting a current utility decision — including a requirement whose logic changed after a decision, which returns to pending re-review rather than being dropped or hidden. A saved reviewer edit that no longer fits the new wording likewise puts the requirement back into pending re-review. This mirrors what a packet deficiency report can raise: reports cite requirements from the same all-except-rejected set, so the list shows what a report may cite, with pending rows labelled honestly instead of hidden. Utility review **progress** is reported separately from the list. Where a role's review is still in progress, the page says so and reports how many of the shown requirements are awaiting a decision — but the requirements themselves are still listed. Automated checks published for a role are shown whatever its review progress. API, SDK, CLI, and MCP clients receive the same information: a typed review-progress state plus a per-row review status. A zero-row result means no technical publication exists, or every in-scope row was rejected — never that review is merely unfinished. ### Page Layout The page title names the selected program, for example "Requirements for the Expedited Process". The page has three titled sections. **Interconnection Application Documents** lists the documents the selected program's application packet includes, built from the utility's published packet shape and readiness policy. Each row gives the document's name and one line saying what it is. Documents needed only in specific situations are marked **If applicable**, with a short line explaining that they do not block submission by default. If the packet shape or readiness policy is not published, or the published shape and policy disagree, the section shows a short notice instead — published rules still render when they are available. **Specific Document Requirements** groups the published rules by document: - **Application Form** - **Single-Line Diagram** - **Site Plan** - **Equipment Specifications** - **Site Control** **Document Cross-Checks** holds the **Whole-Packet Checks**: facts that must match across documents, checked over the whole packet. These groups use the exact published interconnection-level and tier discriminator. The program (packet variant) is chosen in the console header’s **Program** segment (Utility › Program), which Procedure Docs shares, so both tabs show the same program; when the URL names none, the view picks the first published program and the header reflects it. GridWonk never merges rules from different application variants or exposes raw discovery candidates. Each rule shows its reviewed requirement statement, when it applies, what happens if it is unmet (some findings are always blocking or advisory, while others depend on the specific result), and every citation, linked to the source utility document where a public copy is available. A rule whose reviewed wording is still pending shows the document-role label with a "Wording pending review" badge instead of unreviewed text. Requirement chat answers omit pending wording, report that review state when every match is pending, and exclude those hidden rows from the available-result count. They also preserve the difference between reviewed-but-empty and not-published results, and report how much of what they return is still awaiting a utility decision. If no packet shape or technically published rule set exists for the selected utility, the page shows a clear "Published requirements unavailable" notice rather than rules from a different application path. Published rules can still appear without a checklist when the utility has rules but no packet shape. The Requirements total counts individual served rules. Group headings organize those rules but do not count as requirements themselves. Packet requirement groups start collapsed so the page opens with an overview of the available document roles. Select a group heading to expand its rules, citations, and source detail. ## Live Updates Indicator The **Live** badge means the reference requirement list refreshes automatically when its stored data changes, without needing to refresh the page. Published packet groups load with the page and change only when a reviewed set is published. They are not continuously re-extracted or automatically re-verified against utility source documents. Developer views refresh from the served requirement set when source data changes. Reviewer-only rows do not create **new requirement** badges or update notices for developers. ## Reviewing Requirements Requirement reviewers work from the published Packet Intake catalog. They can: - **Approve** — Confirm a published requirement is correct. - **Reject** — Keep an incorrect requirement out of effective packet checks. - **Refine** — Correct allowed customer-facing text or severity without changing executable rule logic. - **Reset** — Remove the decision and return the requirement to review. Platform reviewers use **Admin → Requirements Review**. Utility reviewers use the Packet Requirements workspace for their own utility. ## Source Traceability Published requirements carry reviewed provenance. When a utility procedure document is the source, the review surface shows its public link and cited excerpt. Common-practice and reviewed-form requirements are labeled separately. Source linkage means GridWonk can show which procedure document produced the requirement. A requirement is safer when it points back to a current usable source document and, when available, to the same text version GridWonk used during extraction. The review surface fails closed if a published set cannot be projected safely. Raw executable rule fields and content fingerprints are not sent to the browser. ## Review Status Individual published requirements are **approved**, **rejected**, or **unreviewed**. A published set is summarized as ready, needs review, changed, blocked, or evidence-only. When the assistant answers requirement questions, it uses the published Packet Intake reader and cites the utility procedure source when available. For focused questions, the assistant should preserve the user's requested term in the answer. Examples include site-control variants such as `site-control`, `land control`, `shared site`, `right-of-way`, easement, exclusivity, deposit-in-lieu, timing, milestone, and minimum lease term. If the published set does not contain that detail, the answer should say so. ## Customer-Usable Requirements Customer-facing requirement views use only the published Packet Intake catalog. A rejected row is omitted. An approved or still-pending row is labeled honestly, and no legacy requirement is mixed into the result. If the requested utility or packet variant has no published set, GridWonk shows an unavailable state. It does not substitute a similar utility or fall back to the frozen legacy table. ## Site Control Details Site-control requirements should preserve the details users need for validation: - Accepted document or evidence types - Timing, such as documents required at application or before agreement execution - Minimum term or exclusivity rules - Deposit-in-lieu policy when the tariff allows one - Jurisdiction or transmission/distribution track - Source document references ## Transmission vs Distribution Interconnection requirements differ based on whether a project follows a **transmission** or **distribution** track. Do not classify a project from one universal megawatt or voltage threshold. The selected utility, governing procedure, queue, and saved project track determine which rules apply. Names such as **LGIP** (Large Generator Interconnection Procedure) and **SGIP** (Small Generator Interconnection Procedure) appear in some tariffs and queues, but they are not universal labels for every transmission or distribution project. Study steps, deposits, fees, and jurisdiction must come from the current source for the selected utility and track. ### Using the Filters The published packet view uses its exact packet-variant selector and never merges transmission and distribution variants. Changing the selector loads the complete published set for that exact variant. ## Key Terminology | Term | Meaning | |------|---------| | **Deposit in Lieu** | Tariff-specific cash alternative to site-control evidence, only when the governing source allows it | | **Exclusivity** | Sole land control requirement | | **Timing Requirements** | When documents must be submitted at different project phases | | **Project Term + Decommissioning** | A lease-term formula only when the governing source explicitly requires it | ## Asking the Assistant About Requirements Useful requirement questions include: - "What site control documents does Duke Energy require in North Carolina?" - "What application fees should I expect for Duke Energy NC?" - "Show me PJM site control requirements." --- # Results Validation results and deficiency management for your compliance documents. URL: /docs-site/help/results ## Project-Scoped Results The default-disabled Salesforce connector can produce application-field citations without a PDF. These show the object and field, source record, answer path, capture time, and exact snapshot fingerprint. An older selected run retains its own captured identity. Current linked-reviewer and Salesforce permissions are still required to read its findings, files, or report links; working-copy edits cannot change the Salesforce source. See [Salesforce preparation](/docs-site/integrations/salesforce). Historical reports now require current permission for all committed captured fields, including fields removed from the current mapping. A revoked older field can also deny the current view. Malformed history and more than 200 revisions are refused; live sandbox acceptance remains open. Results are saved inside a project. Review opens inside a project workspace, so when no project is selected the console shows the Projects list and you select or create a project before any validation history appears. A developer's pre-submission findings stay private to the developer organization. The receiving utility can read the review frozen in a formal package and its own screening, not later private correction reviews or replacement files. This keeps deficiencies, scorecards, remediation work, and status tied to a durable project record instead of a loose utility-wide file list. You can still browse procedures and requirements without a project, but validation outputs require one. ## Split-View Layout With permission-aware live updates enabled, findings keep their 60-second refresh cadence and History refreshes periodically while visible and online. Temporary connection or permission-service failures retain saved results with a warning; they do not prove a project was deleted. Confirmed removal or access loss clears the affected results. Return to the tab or use **Retry updates** to request fresh authorized data. An unrecoverable session offers **Sign in**. After a confirmed PDF split succeeds, the retained original and its earlier findings remain in **History**. Current findings use the resulting documents and a packet review of that exact set. Each new document requires its own review; the parent's clean result does not carry over. Pending or failed confirmed splits pause new reviews and submission. Use **More actions → Split PDF** to inspect progress, retry a failed split, or keep the original. On desktop, Results display in a two-panel split view: - **Left panel** — Deficiency list with severity, status, and quick actions - **Right panel** — Source PDF evidence with page navigation and source-location status On a phone, use the **Findings** and **Document** tabs to switch between those same panels. The **Deficiencies** and **Document Viewer** titles are announced to screen readers instead of taking a header row, so the review evidence receives more of the available height: the severity counts and list tools share one compact row, and the viewer's own pager shows the page position once the document loads. On desktop the document pane also carries a **Hide findings** toggle (`Cmd+\` / `Ctrl+\`) plus a **Full screen** mode that `Esc` exits, where the browser supports it. The toggle shortcut keeps working while a toolbar disclosure such as readiness or the document switcher is open; it stands down only for a full dialog. On the project Review page, Findings, Report, and History share one compact toolbar with a labeled readiness status and **Review Actions**. Open readiness for missing requirements, documents needing attention, package details, and report links. Manual packet runs and reruns live under **Review Actions**. When the packet is incomplete, that menu links to missing document roles or names the requirements that must be completed before a manual run can start. Whole-packet findings and retained-snapshot warnings open from compact disclosures in the document selector row instead of full-width messages, leaving most of the page height for the evidence workspace. Click any deficiency to sync the PDF evidence to that finding. Project Findings is read-only; working-copy editing and retry controls are not offered in this view. The PDF panel shows the current page and total page count after the document loads. When a selected deficiency only has page-level evidence, the panel warns that exact source bounds are unavailable. When no reliable source location exists yet, the panel tells you to review the document manually instead of pretending the map is exact. The deficiency list supports keyboard navigation while that panel has focus: press `j`/`ArrowDown` and `k`/`ArrowUp` to move between deficiencies, `Enter` or `Space` to expand the focused deficiency, and `Escape` to collapse the open deficiency. These are bare-key bindings: modifier chords such as `Cmd+K` never move the focused deficiency. ## Document Preview Versions ### Upload, text recognition and review are separate An accepted upload, searchable text and a completed document review are three different outcomes. Text recognition (OCR) can fail while the safe PDF preview and a completed review remain available. That OCR failure must not be read as a failed review. Results belong to the version that was reviewed; replacing a PDF preserves earlier results as history and starts a separate current-version lifecycle. Completed individual-document results can appear in a partial report while the whole-project review is still outstanding. They also stay visible in **Findings** while a packet review is queued, running, failed or cancelled, labeled **Individual-document review results**. A current completed packet result takes priority and is labeled **Whole-project review results**; the two sources are not added together. Neither is utility approval. Results from replaced files, or from before a newer failed document review, are not restored as current results. For recovery choices, see [Document troubleshooting](/docs-site/help/document-troubleshooting). To stop an active packet review, use **Review Actions → Cancel Packet Review** when your review permissions allow it. Cancellation preserves completed document findings. A provider request already in progress may finish in the background; read any cancellation warning before retrying. See [Cancel an active packet review](/docs-site/help/packets#cancel-an-active-packet-review). ### Which PDF version opens In Review, utility-owned projects preview the current sanitized document version without a submitted package. A utility-created project with no applicant organization is utility-owned. For applicant-owned projects, utility reviewers still need a submitted package version that matches the current document; otherwise the Review findings preview remains unavailable. Document privacy and access checks continue to apply. ## How Location Works (Plain English) Each deficiency now has two pointers: 1. **Working pointer**: where the issue sits in the editable digitized copy. 2. **Source pointer**: where supporting evidence was found in the original PDF. A stored working pointer does not make the Project Findings view editable. Use the source PDF to inspect evidence, and prepare corrections in your document editor. A reviewer must confirm approximate or unresolved locations before treating them as exact citations. ## Severity Levels | Level | Dot | Meaning | |-------|-----|---------| | **Critical** | Red | Highest-priority finding; requires immediate review | | **High** | Amber | Significant gap requiring attention | | **Medium** | Blue | Non-critical issue to address | | **Low** | Green | Minor suggestion or informational | The underlying severity values and visible groups are `critical`, `high`, `medium`, and `low`. High findings are not counted under Critical. Address Critical and High findings first, but a severity badge is not itself a final utility or regulatory decision. Current document checks appear immediately in project counts and the partial report; no utility confirmation is required. Cards and Overview show **Findings unavailable** when current counts cannot be loaded. A failed background refresh retains an explicit warning, including when the prior results were empty. It never silently substitutes an older utility report for unavailable applicant results. ## Deficiency Card Anatomy Every finding card, on the developer console and the utility adjudication view alike, shows the same body: 1. **Severity** — the coloured dot before the finding (see the table above); the open card spells it out on a Severity line. The card carries no other badges: the document is already named by the list you are in or the section heading above the card. 2. **Finding** — what GridWonk detected, as the card title. In the developer console a collapsed card shows only the dot and the finding; expand it for the lines below. 3. **Type** — only when the category changes what you should do: **Project eligibility** (no document fix resolves it) or **Documents disagree**. 4. **Requirement** — the utility's published requirement statement, when the review's published set carries one. 5. **Source** — the utility, the source document (linked when it is published), the page, and the verbatim cited text with its surrounding context. This is the same provenance the utility sees under Rules & Sources. 6. **Location** — one line: a validated page highlight, an approximate page, or why nothing can be highlighted (for example, an absence finding cites no document text). Below the body, the developer card offers **View in PDF** and **Explain this finding**, which opens the assistant for a quotation-first explanation of that exact saved finding. The server rechecks project access and verifies quotations against the source edition used by the review. Nearby text is not treated as governing scope; applicability remains unconfirmed. It does not invent section references or re-read the applicant's drawing. The utility card carries adjudication controls instead. Whole-packet findings (the toolbar's packet-findings disclosure) render on the same card, with the same Requirement and Source lines. The assistant shows the selected finding and keeps it for follow-up questions and retries. Use **Clear finding** to leave it, or choose another finding. Changing user, organization, or project clears the selection. If the historical requirement or cited quotation cannot be verified, the assistant explains the limitation instead of using a different edition or guessing. A published requirement is not necessarily human-approved, and a common-practice recommendation is not utility text. See [AI Assistant](/docs-site/help/assistant#explain-a-review-finding) for source limits. ## Location Statuses - **Exact** — Verified source bounding box and quote. - **Approximate** — Reliable page-level evidence, but no trustworthy box. - **Unresolved** — No safe source mapping (contextual/inferential findings). Selecting a finding with an exact location, or choosing **View in PDF**, zooms the viewer so the highlight fills the pane and centres it; a finding without a highlight opens its page at fit width. You can zoom further with the viewer's zoom buttons and menu, `Cmd`/`Ctrl` with `+`, `-`, or `0`, or `Cmd`/`Ctrl` + scroll. Approximate and unresolved locations are still useful for review, but they should not be treated as exact legal citations until a reviewer confirms the source evidence. ## Remediation Workflow 1. Select a deficiency and inspect its cited evidence in the PDF panel. 2. Prepare corrections in your document editor; Project Findings does not edit the source. 3. Upload the corrected file through the project's supported replacement or intake action. 4. Run an eligible review and compare the current results with retained History. Trial and prepaid customer workspaces use supported packet-processing actions. Generic chat, legacy digitization and other unsupported processing paths remain unavailable; credits do not unlock them. See [Document troubleshooting](/docs-site/help/document-troubleshooting). ## Reports Use the project's **Report** tab for the current packet report or available individual-document partial report. **History** retains earlier runs. Project Findings does not show the legacy **Scorecard** download button. Report access is checked against the project and selected run. ## Re-Validation After fixing deficiencies: 1. Export or prepare the corrected PDF. 2. Upload changed content under a new filename when the existing document identity cannot be replaced. Documents frozen into a submitted package remain immutable history. 3. Eligible, classified site-control documents in a selected project can start validation automatically. Otherwise, start validation from the available upload or results action. 4. Review the newest run for current findings. Prior validation and submission history remains available; do not assume an older finding was deleted merely because it does not appear in the newest run. ## Asking the Assistant About Results Useful results questions include: - "What critical deficiencies remain for this document?" - "Where did GridWonk find the site-control issue?" - "How do I fix this lease-term deficiency?" --- # Screening Review package-bound application findings and utility screening decisions. URL: /docs-site/help/screening ## How Automated Screening Works The Salesforce connector remains disabled pending acceptance. Its independent review gate stays closed until every captured field and declared file is transferred, processed, and resolved; failed or expired intake batches cannot permit a partial review. Source-managed packets cannot use ordinary **Screen Selected** to bypass that gate. After the exact completed review, connector recovery now freezes an immutable package with the real human or service actor before completing the import. It does not change queue status, decisions, or notices. Live pilot acceptance remains open. Connector retries reuse the saved package only after rechecking current access and the exact completed review. A revoked permission or changed source revision blocks reuse; it does not turn the saved result into a new screening decision. When you trigger screening for selected applications, GridWonk runs the whole-packet review engine in the **utility lane**: one `utility_screening` run per application, the same engine that reviews a developer's packet before submission. The run reviews the current document versions against your utility's published packet requirements and records findings with citations. Only formal submissions enter the utility queue. A developer's private draft, replacement files, and private correction reviews are not available for utility screening. Previously received frozen packages remain visible during a correction round. ## The Screening Pipeline Each run is a durable workflow, shown as grouped stages in the jobs tray: | Stage | What It Does | |-------|-------------| | 1. Digitize | Converts each current document version to extractable text | | 2. Review | Checks the whole packet against your utility's published packet requirements | | 3. Findings | Records each deficiency with severity, citation, and page reference | | 4. Package | For a packet your utility originated, the immutable package is frozen pinned to the completed run: automatically when the `utility-packet-screening` feature is on for your organization, otherwise with **Freeze package** | ### Which utilities can screen Automated review is switched on per utility (the packet-review switchboard). For a utility that is not on it, **Screen Selected** reports **Automated review is not yet available for this utility** for each of that utility's rows. Those rows stay unchanged and notices stay manual; there is no fallback to the retired per-document pipeline. Screen Selected reports its result per application: started rows leave the selection, and refused rows stay selected with the reason shown above the table. A combined PDF whose applicant confirmed a split is retired source material: screening selects and aggregates only its derived child documents, so the retained combined source never contributes duplicate findings or counts alongside its children. Project lists, the portfolio, and status views apply the same rule, so document and deficiency counts match across every surface. Screening work is tied to the exact uploaded document generation it started from. If an applicant replaces a document during processing, the older generation stops without attaching stale findings or a stale validation verdict to the replacement file. The replacement generation owns the next screening result. Until that replacement finishes review, the Review view hides findings from the replaced bytes and shows **Document re-review pending**. Aggregate counts do not reuse the older result, and **Begin deficiency notice** remains unavailable so the utility cannot send an incomplete packet-wide notice. ## Reviewing Screening Results After screening completes, open the application from **Applications** and choose **Review** in the header. The selected immutable package determines which document versions and findings you see. The other header views are Overview, Documents, Communications, and History. Findings show severity, description, page reference, and requirement provenance when available. Use the package selector to inspect an older snapshot; historical packages are read-only. If no review is pinned, or its stored identity does not match the selected package, the view explains that state rather than displaying unrelated results. The old six-tab shell and standalone Screening view are removed. Existing Screening bookmarks redirect to the current application workspace. Stored legacy scores remain historical data; this change does not delete or recalculate them. ## Point-of-interconnection evidence When enabled for the packet owner, the selected package report can include a **Point of interconnection** section. It shows extracted coordinates, source pages, inspection coverage, and comparisons between explicitly labelled points of interconnection (POIs). Open the source to check the original document before recording a human decision. Missing coordinate-system information or unsupported documents remain unresolved; nearby coordinates do not prove that two labels describe the same physical point. Standard geographic review covers application forms, site plans, single-line diagrams, equipment specifications and site-control documents. Supporting documents and native DWGs are not geographically inspected. An accepted PDF companion contributes evidence only when it has one of those document roles. **Document coverage** preserves missing, incomplete and failed interpretations; no coordinates found requires every page to have been explicitly inspected by at least two complete interpretations. The report shows actual interpretation counts and the number of existing text transcriptions they used. One interpretation requires source review and does not establish a map location. Multiple interpretations sharing one optical character recognition (OCR) transcription are not independent confirmations of its digits. Conflicting evidence remains unresolved and is not mapped, even when the same transcription is repeated. **View source** opens the safe PDF rendition of the reviewed version, page and available region. Missing text recognition does not block the ordinary document review from using the PDF. POI decisions are separate from deficiency adjudication and packet approval. They belong to the selected review and source version; changing the documents requires a new review. Older package evidence remains read-only. Map display is optional and loads only after **Show map**; the evidence table remains available when the map is unavailable. Developer review begins in [Projects → Review → Report](/docs-site/help/packets). ## Generating a Notice from Screening When you're ready to communicate deficiencies to the applicant: 1. Review and adjudicate the package findings in **Review**. 2. Use the package screening decision to begin a notice when the current package is eligible. 3. Continue in the [Notice Composer](/docs-site/help/notices) for review, approval, sending, and applicant acknowledgment. Notice eligibility remains server-checked against the selected package and current review. Removing the old screen does not bypass authorization, finding decisions, or document re-review requirements. ## Real-Time Updates Screening status updates appear as the selected application refreshes and as reviewers revisit the queue. If a run is still in flight, keep the application selected or reopen the row after the queue status changes. ## Related - [Application Queue](/docs-site/help/applications#application-and-review-lifecycle) — Managing your application queue - [Document provenance](/docs-site/help/documents#from-utility-source-to-cited-finding) — How indexed utility sources become cited findings - [Deficiency Notices](/docs-site/help/notices) — The notice workflow - [For Utilities](/docs-site/getting-started/for-utilities) — Utility workspace overview --- # Create or join a workspace Verify your account and establish the right developer or utility workspace. URL: /docs-site/help/self-service ## Create an account When registration is available, open **Sign up** from the login page. Enter your email and password and complete the verification challenge. Follow the email verification link, sign in, and accept the current terms and privacy policy. Onboarding resumes after verification; you do not need to create a second account. If registration is unavailable, use the support contact shown on the login page. A missing verification email does not mean you have an active account. Check the address and spam folder before requesting another email. If signup expired before an account was created, start signup again and complete the verification challenge. Requesting another verification email alone does not create or renew a signup. Use **Forgot password** for an existing account. An invitation or new signup does not override a suspended or rejected account. ## Developer workspaces Create a developer workspace during onboarding. You become its Owner. Repeating the same creation request resumes that workspace. A matching email domain does not automatically join you to anyone else's workspace. To join a team, accept an invitation sent to your own email address, finish verification, and accept the current terms and privacy policy. Eligible developer team invitations can complete onboarding; other invitations may require staff approval. Owners and admins manage invitations and roles in **Team**. Changing owners does not restart a trial. ## Utility affiliation Choose **Utility affiliation** during onboarding and search for the official utility. Submit a clear explanation of your authority and an HTTPS evidence link. GridWonk staff independently verifies the claim; an email domain alone is insufficient. You can see whether your claim is pending, approved, or rejected, and read the decision rationale. Approval creates a utility workspace with you as Owner, or grants Member access to an existing workspace explicitly selected by staff. A claim cannot replace or reactivate an existing membership. If rejected, you may submit a fresh claim with additional evidence. Claim approval does not activate application intake or expose private developer drafts. Formal intake also requires the utility's state/program acceptance and an active qualified reviewer. See [private reviews and submissions](/docs-site/help/private-reviews-and-submissions). ## Next step Open your workspace, or [connect the GridWonk plugin](/docs-site/help/connected-apps). --- # Account Settings Profile and security settings for your GridWonk account. URL: /docs-site/help/settings Account settings open as an account settings sheet. The `/account/settings` route is a helper that opens that sheet and returns to the last authenticated dashboard path recorded in the current browser tab. If no safe dashboard path exists, it opens the sheet on `/dashboard`; it never follows browser history back to a public page. If browser privacy settings block per-tab storage, a one-use URL signal opens the sheet on `/dashboard` instead. The sheet and its account state are loaded only on authenticated dashboard routes. The current tabs are **Profile**, **Security**, **Preferences**, and **Integrations**. ## Profile Information | Field | Description | |-------|-------------| | **First and last name** | Editable profile names | | **Email address** | Your login email. Changes are submitted through Supabase email verification. | | **User ID** | Unique account identifier | | **Account creation date** | When your account was created | | **Role badge** | Account-level user or administrator label when available | ## Password Requirements Strong passwords must have: - **Minimum length**: 12 characters - **Character types**: Mixed case letters, numbers, and special characters - **Strength rating**: Must be at least "Good" to submit ### Strength Meter Levels | Level | Description | |-------|-------------| | **Weak** | Does not meet minimum requirements | | **Fair** | Meets minimum but could be stronger | | **Good** | Acceptable security level | | **Strong** | Recommended security level | | **Excellent** | Maximum security level | ## Changing Your Password 1. Go to the **Security** tab 2. Enter your **current password** 3. Enter your **new password** 4. Confirm the new password (enter it again) 5. Check that strength meter shows at least "Good" 6. Click **Update Password** ### Forgot Your Password? 1. Log out of the application 2. Click **Forgot Password** on the login page 3. Enter your email address 4. Check your email for reset instructions 5. Follow the link to set a new password ## Preferences The Preferences tab saves: - **Default Organization** — Your workspace when you log in. It must be an active, unexpired direct membership; a grant-only client context cannot be selected as the default. - **Email Notifications** — Whether GridWonk can send event emails - **Weekly Digest** — Whether to receive a weekly activity summary - **Timezone** — Saved preferred timezone. Account creation dates currently use the browser timezone. Workspace colors are shared organization settings. Direct Owners and Admins of developer and utility organizations use **Team and logo > Workspace appearance** to preview colors and choose **Save appearance**. See [Workspace appearance](/docs-site/help/organizations#workspace-appearance) for schemes and source-color limits. ## Integrations Open **Organization integrations** from account settings to see setup for the active workspace. Developers use `/console/integrations`, utilities use `/utility/integrations`, and consultants use `/consultant/integrations`. The hub separates saved access, effective availability and connection status. An enabled service can still require credentials, sign-in or platform configuration. Organization owners and admins can create runtime API keys when API access and self-service key creation are enabled. Save a new secret when shown; it cannot be retrieved again. Existing `/console/api-keys` and `/utility/api-keys` pages remain available. Set **Expires in (days)** to 1–365, or leave it blank for no expiry. Ordinary members retain personal connection permissions and cannot manage organization keys or installations. MCP setup provides connection guidance for Claude Desktop and Codex Desktop. Complete the client's credentials or sign-in flow; enabling access does not connect a client automatically. Provider approval and live-client acceptance remain separate requirements. Disabling MCP refuses subsequent MCP requests, including already connected apps, while permitted REST calls continue. Disabling API also blocks MCP and new key creation; browser revocation remains available. **Connected apps** at `/settings/connected-apps` shows your connections and their bound workspace. Revocation stops local access before any retryable provider cleanup. Changing the active workspace does not retarget an existing connection. See [Connected apps](/docs-site/help/connected-apps). Utility owners and admins can open **Packet submissions** from account Integrations to review approved state/program lanes. Accepting a lane requires current utility authority and a qualified reviewer; it does not expose private developer draft reviews. The account **Connected Accounts** card shows your individually linked Slack and Microsoft Teams accounts. Connecting a workspace or tenant to an organization does not link every employee automatically. Ask the bot a protected product question, then open the secure one-time account link it sends you while signed into GridWonk. For Slack, a complete command such as `/gk requirements duke-energy NC` triggers the account check; a bare `/gk requirements` command only shows usage help because it is missing the utility argument. Re-authorize Slack when an administrator asks you to upgrade an older installation; this replaces legacy plaintext token storage with encrypted installation data. ## Salesforce Installed-App Pilot The separate outbound-only app is in Layer 2 development and remains disabled. Reviewers use their Salesforce identity without individual GridWonk accounts; no Salesforce tokens are stored in GridWonk. The account settings screen, API keys and legacy automation grants cannot enable it. The private receipt and direct-upload workflow still needs full native verification. Preparation does not start a review. Every expected file needs independent byte acceptance, and a separate unconditional compute gate blocks extraction, optical character recognition (OCR) and model processing. Read-only progress does not start a review or return findings. Navigation may resume an unfailed attempt; an explicit failure report counts once and prevents that attempt's reuse without releasing its physical slot early. Limits remain two imports, two uploads per import, six failed storage attempts and one original 24-hour deadline. Signed results/history, retention/purge and package onboarding remain later layers. See [Salesforce installed application](/docs-site/integrations/salesforce#installed-application) for the distinction between source implementation, native evidence and activation approval. ## Salesforce Utility Connector Utility workspaces also show the **Salesforce packet reviews** card with **Salesforce connections**, opening `/utility/integrations/salesforce`. The connector is disabled by default and is not ready for customer activation. A setup screen does not mean its import or MCP operations are available. In an approved credentialed-connector pilot, reviewers link their own Salesforce accounts. This individual linking is not part of the separate installed app. Utility owners or admins separately approve mappings, enable reviewers, and authorize expiring automation grants. Save a new service secret when it is shown; it cannot be displayed again. Change source-owned answers and files in Salesforce, not through ordinary GridWonk packet editing. Adding or changing a different reviewer does not interrupt unrelated imports or result deliveries. Changes to a saved operation's own reviewer link, mapping, or service identity/grant stop that work at its next authorization check. Restoring permission requires a new request; old work does not restart automatically. Turning automation off affects service work only; disabling the connection affects all work. Live Salesforce permission checks remain required. See [Salesforce Utility Connector](/docs-site/integrations/salesforce) for preparation and access rules. ## Public plugin connections Open **Connected apps** to see the public plugin's selected workspace and revoke its access. Changing your default workspace does not retarget an existing connection. See [Connected apps](/docs-site/help/connected-apps). Workspace Owners and Admins can open **Billing** to view [prepaid processing](/docs-site/help/processing) when purchases are available. --- # Keyboard Shortcuts Available keyboard shortcuts for efficient console navigation. URL: /docs-site/help/shortcuts The findings list has separate Critical, High, Medium, and Low groups. Its existing keyboard navigation remains unchanged; high findings no longer contribute to the Critical group heading. The shared severity labels keep those group names consistent with the finding cards; this does not change any shortcut. ## Navigation Shortcuts | Shortcut | Action | Platform | |----------|--------|----------| | `Cmd+B` | Toggle sidebar | Mac | | `Ctrl+B` | Toggle sidebar | Windows/Linux | | `Cmd+K` | Open command palette | Mac | | `Ctrl+K` | Open command palette | Windows/Linux | On the utility workspace v2 the same shortcut opens the utility destination palette: Applications, Notices, Rules & Sources (Packet Requirements, Procedures), Analytics, the selected application's views, and the sidebar toggle. ## Chat & Messaging Shortcuts | Shortcut | Action | Context | |----------|--------|---------| | `Enter` | Send message | AI Assistant or Remediation Agent | | `Shift+Enter` | Insert new line | When typing in chat input | The embedded assistant keeps these bindings after first-use loading. While a question is pending, the composer is disabled; use **Cancel request** before sending a different question. ## File Management Shortcuts | Shortcut | Action | Context | |----------|--------|---------| | `Backspace` | Remove last attachment | When text input is empty | | `Cmd+V` / `Ctrl+V` | Paste files | Paste clipboard content as attachments | ### Removing Attachments When you've attached files to a chat message, clear the text input (if any text exists), then press `Backspace`. The most recently attached file is removed. ### Pasting Files Copy a file in Finder/Explorer, click in the chat input, and paste (`Cmd+V` / `Ctrl+V`). The file is added as an attachment. This shortcut only adds the file to the current web chat composer. The current assistant submit path does not forward the file bytes for analysis; use **Upload Project Files** in the project's Documents view when GridWonk needs to process or validate the document. ## Tips for Power Users 1. **Toggle sidebar** frequently to maximize document viewing space 2. **Use Enter** to quickly send follow-up questions 3. **Multi-line messages** are useful for providing context or lists 4. **Use the project's Upload Project Files control for document analysis** rather than relying on a chat attachment Project and lifecycle actions currently use standard button, link, select, and form-submit focus behavior. There are no dedicated keyboard shortcuts for creating projects, submitting or resubmitting projects, or opening a project from the Projects list. The PDF evidence viewer also supports `ArrowLeft` or `PageUp` for the previous page and `ArrowRight` or `PageDown` for the next page. These page shortcuts run only while the evidence viewer is visible. While the pointer or the focus is on the viewer, `Cmd++` and `Cmd+-` (`Ctrl++` / `Ctrl+-` on Windows/Linux) zoom in and out through fixed steps, `Cmd+0` (`Ctrl+0`) returns to fit width, and `Cmd+scroll` (`Ctrl+scroll`) or a trackpad pinch zooms around the pointer; the viewer's zoom menu also offers fit page, actual size, and fixed percentages. Anywhere else those keys keep their browser meaning. When the page is larger than the viewer, drag it with the mouse to pan around it. The sanitized document preview offers the same zoom controls, shortcuts, pinch and drag-to-pan: the Documents-tab **Preview** and the upload preview in the developer console, and the application Documents preview in the utility console. Zoom does not change where review tasks are completed; the preview is read-only. If its preview fails, use **Try again** without leaving the current Findings view. While the deficiency panel has focus, use `j`/`ArrowDown` and `k`/`ArrowUp` to move focus, `Enter`/`Space` to expand the focused deficiency, and `Escape` to collapse it. `Cmd+K` (`Ctrl+K` on Windows/Linux) opens the command palette for jumping to any destination, project view, or review tab. `[` and `]` step to the previous and next project document while the Findings tab is active; in the cohort-gated **Checks** workspace, the same keys step through the previous and next queued project. `Cmd+\` (`Ctrl+\` on Windows/Linux) shows or hides the findings panel of the desktop split view, and the document workspace offers a **Full screen** mode that `Esc` exits. `Cmd+K` and `Cmd+\` keep working while a Review toolbar disclosure such as readiness or the document switcher is open; they stand down only for a full dialog, which owns the keyboard while it is up. ## Accessibility Notes All shortcuts have visual alternatives: - Sidebar toggle button in the header - Send button in chat input - Remove (X) button on attachments - Upload button for file selection - Try again button for a failed PDF preview - Findings-panel and Full screen toggle buttons on the document workspace - Zoom out, zoom level menu, and zoom in buttons on the pager of the document viewer and the sanitized document preview ## Asking the Assistant About Shortcuts Shortcut questions are stable platform facts and can use quick answers. The most common shortcut answer is: `Cmd+B` on Mac or `Ctrl+B` on Windows/Linux toggles the sidebar. --- # Site Control How GridWonk reads, validates, and explains site control requirements. URL: /docs-site/help/site-control Completed site-control checks contribute immediately to the project's current findings and partial report. Processing completion alone does not mean a clean review, and a partial report never proves submission readiness. Findings and CAD status refresh after document or review changes. Unchanged background polling does not reload those results; a failed refresh shows a warning rather than claiming a clean check. ## Background updates With the permission-aware rollout, findings and CAD readers share background scheduling. Findings retain a 60-second cadence; active processing refreshes faster. A failed refresh retains the prior snapshot and cannot claim recovery or a clean check. Confirmed removal or lost access clears inaccessible data. See [live-update status](/docs-site/help/jobs). ## Salesforce-sourced site-control evidence The default-disabled Salesforce connector uses the same utility site-control requirements, but source files must be corrected in Salesforce and captured again. A mapped application field does not replace a required deed, lease, or other supporting document, and inaccessible source evidence must not become a false missing-evidence finding. That correction rule also applies to files imported by a service identity: the absence of a human uploader does not authorize an ordinary delete or replacement. Retained results require current source access to fields across the complete captured history. ## What Site Control Means Site control is proof that a project has the legal right to use the land or corridor needed for interconnection. GridWonk treats site control as a requirement-backed workflow, not a generic document checklist. When site-control evidence is uploaded, the upload boundary accepts only a bounded PDF payload and validates its decoded bytes before digitization or requirement matching begins. The stored byte count comes from those decoded bytes even when the upload is linked to an existing project. The accepted evidence depends on the utility, state, and interconnection track. Common evidence types include: - Property deed or ownership record - Lease or lease option - Purchase option - Easement or right-of-way - Development rights or exclusivity agreement - Shared site agreement when co-location is allowed ## How GridWonk Uses Extracted Requirements When procedure documents have been processed, GridWonk stores structured rows for site control in the requirements database. The assistant and validation workflow should answer site control questions from those extracted rows when they exist. Each row can include: - Accepted document or evidence types - Timing, such as documents required at application - Minimum term or exclusivity rules - Deposit-in-lieu policy when the tariff allows one - Jurisdiction or transmission/distribution track - Source document references If no extracted requirement exists for the selected utility, the assistant should say that and point you to the workflow that creates requirement rows. If you ask about a specific site-control detail, such as an easement, right-of-way, shared site agreement, exclusivity, deposit-in-lieu option, or minimum lease term, GridWonk should keep that focus in the answer. When the extracted rows do not list the requested evidence type or term, the assistant should say that the item is not listed instead of filling the gap with a generic site-control checklist. ## Usable Site-Control Requirements A usable site-control requirement is a requirement GridWonk can safely use for customer-facing validation. It must be validated by a reviewer and linked to a current usable procedure document. In plain English: GridWonk should not reject, warn, or advise a customer based on an old rulebook, an unapproved rulebook, or a requirement that cannot be traced back to its rulebook. After current-procedure enforcement is on: - Customer answers, validation results, deficiency reports, and remediation guidance use only usable site-control requirements. - Pending, deprecated, rejected, unlinked, or stale-source requirements may disappear from customer outputs. - Reviewers can still inspect those rows with clear status labels so they can clean them up. ## Developer Workflow Before starting, sign in to the selected organization and complete any requested legal acceptance. 1. Select the utility and state in the console. 2. Create or select a project before running validation. You only need a project name, capacity, and distribution/transmission track. 3. Upload PDF evidence from the project's **Documents** view with **Upload Project Files**. Site-control evidence must be a PDF, up to 30 MB per file. 4. Confirm or override the detected document type. 5. When automatic review is enabled, the site-control document review starts alongside the other typed document reviews as soon as its role and prepared artifact are ready. 6. After the last present typed document has current extraction evidence and the required packet documents are ready, GridWonk starts the full packet review automatically. 7. Open the project's **Review** view to see whether the evidence satisfies the selected utility requirements. Uploaded documents are separate from utility procedure documents. Procedure documents define requirements; uploaded documents are the evidence checked against those requirements. A native DWG companion is also separate from site-control evidence. It belongs to an exact site-plan PDF version and cannot be attached through the ordinary File Library or counted as a deed, lease, easement, or other proof of land rights. This keeps drawing review aligned to the utility's CAD procedure profile without changing the site-control evidence rules. When one PDF contains multiple packet roles, GridWonk may mark it as a possible combined document. For an enabled applicant organization, a developer must open the split review, account for every page, and confirm each document role. GridWonk never lets an automated suggestion silently decide which pages become site-control evidence. After completion, the derived children are reviewed and the combined source remains only as immutable lineage. An optional packet ZIP is only an upload container. It does not count as site-control evidence and never enters review. After the whole ZIP passes safety checks, each accepted PDF, PNG, or JPEG enters ordinary Packet Intake and must independently carry the right evidence and accepted role. A retry remains tied to the exact stored document generation that was checked as eligible. If the source generation changes before the reset or while classification runs, the older retry stops rather than attaching stale digitization or classification results to the newer file. Compliance validation follows the same rule. Its findings and document verdict are written only while the reviewed document generation is still current. If you replace the file during review, the older run stops without reporting a customer-facing failure; the replacement generation owns the next result. ## Utility Workflow Utility teams manage source procedure material from the Procedures tab. 1. Review discovered procedure documents. 2. Extract requirements from the relevant procedure documents. 3. Validate or dispute extracted requirement rows. 4. Use Screening to check submitted application documents against those requirements. 5. Use Notices to draft and approve applicant deficiency notices when evidence is missing or insufficient. Pending requirement rows can still be useful because they came from candidate procedure documents, but they must be shown with their review status. Deprecated and unlinked rows are cleanup records, not customer-facing rules. Reviewers can temporarily use `/console` filters to inspect this work: - Documents: `Current usable`, `Pending review`, `Deprecated`, and `All reviewable` - Requirements: `Current usable`, `Pending source document`, `Deprecated source document`, `Missing source document`, and `All reviewable` These filters are saved in the URL, so reviewers can share links to the exact cleanup view for a utility, state, interconnection level, and status. ## Deposit in Lieu Do not assume a deposit can replace site control. Some tracks allow a deposit-in-lieu policy, while others require actual site rights. GridWonk should answer this from the extracted requirement row for the selected utility, state, and track. ## Nashville Electric Service Pilot Cleanup Nashville Electric Service (NES) is the first pilot for this cleanup model. The goal is not to delete useful history. The goal is to decide which NES procedure documents are current, approve and read those documents, re-extract site-control requirements from them, validate those requirements, and retire or migrate older unlinked rows. Until that cleanup is complete, NES may show fewer customer-facing site-control requirements after enforcement because GridWonk is waiting for approved source-backed requirements. Reviewers can still use the temporary filters to see the pending, deprecated, and missing-source records that need cleanup. ## Related - [Requirements](/docs-site/help/requirements) - [Document provenance](/docs-site/help/documents#from-utility-source-to-cited-finding) - [Upload](/docs-site/help/upload#applicant-document-safety-states) - [Screening](/docs-site/help/screening) - [Deficiency Notices](/docs-site/help/notices) --- # Support & Contact How to get help, report issues, and reach the GridWonk team. URL: /docs-site/help/support ## Contact For general inquiries, partnership discussions, or platform access requests, email us at [contact@gridwonk.com](mailto:contact@gridwonk.com). For technical support and bug reports, email [support@gridwonk.com](mailto:support@gridwonk.com). ## Support Channels | Channel | Use For | Address | |---------|---------|---------| | **General Contact** | Account access, demos, partnerships | [contact@gridwonk.com](mailto:contact@gridwonk.com) | | **Technical Support** | Bug reports, API issues, platform errors | [support@gridwonk.com](mailto:support@gridwonk.com) | | **AI Assistant** | In-app questions about requirements and documents | Available in your dashboard | The in-app help sheet also links technical issues to `support@gridwonk.com`; public site contact metadata uses `contact@gridwonk.com`. ## Reporting Bugs When reporting a bug, include the following so we can investigate quickly: 1. **What you were doing** — the page or action that triggered the issue 2. **What happened** — the error message or unexpected behavior 3. **What you expected** — the correct behavior 4. **Browser and OS** — e.g., Chrome 120 on macOS 5. **Screenshots** — if applicable For a document issue, include its project and version, approximate time and time zone, and the separate upload, text-recognition and review statuses. Do not send credentials, API keys or signed download links. [Document troubleshooting](/docs-site/help/document-troubleshooting) helps you choose the right action while support investigates. ## Requesting Features We welcome feature requests. Email [contact@gridwonk.com](mailto:contact@gridwonk.com) with: - A description of the feature or workflow improvement - The problem it would solve for your organization - Any examples or references that illustrate the idea ## Response Times GridWonk does not currently publish a general support-response service-level agreement (SLA). An SLA is a contractual response-time commitment. Include the impact and urgency in your message so the team can triage it; if your organization has a signed support commitment, that agreement controls. ## Help Resources - [Help Center](/docs-site/help/documents) — Guides for current documented platform workflows - [API Reference](/docs-site/api/overview) — REST API documentation for integrations - [AI Assistant](/docs-site/help/assistant) — In-app AI help for requirements and documents - [Getting Started](/docs-site/getting-started/for-utilities) — Onboarding guides by organization type ## About GridWonk GridWonk is focused on reducing grid interconnection deficiency rates through AI-powered automation. The platform is under active development. If you encounter missing features or rough edges, please let us know — your feedback directly shapes our roadmap. --- # Upload File upload and document digitization for compliance validation. URL: /docs-site/help/upload ## Trial and prepaid intake You must have an approved, current session to start or change an upload. If GridWonk asks you to accept updated legal terms, complete that step in the browser before retrying the action. For trial and prepaid workspaces, supported uploads require a current processing allowance before an upload authorization or background processing starts. The trial source allowance includes the ZIP container and each expanded source entry; resuming that same entry does not count it twice. Native DWG processing is unavailable in this rollout, including DWG entries inside archives. A format listed for an existing integration does not override this workspace restriction. See [processing allowances and recovery](/docs-site/help/processing). If your workspace is limited to PDF review, use standalone PDFs. The server refuses images, ZIP archives, and native CAD files in that scope, including saved File Library attachments and existing packet sources. Reusing an earlier upload or changing clients does not override the restriction. A PDF-only review does not waive the utility's required evidence. ## Salesforce-managed packets The Salesforce connector remains disabled pending acceptance. For a packet marked as Salesforce-managed, ordinary upload, replacement, deletion, role changes, working-copy edits, and manual reprocessing are refused. Change the source in Salesforce and request a new connector capture after activation; a utility administrator role does not bypass this boundary. Existing file formats, limits, and ordinary packet uploads are unchanged. The separate outbound-only installed application is also disabled. Its Layer 2 work adds exact Salesforce file checks inside the shared intake code, not a new upload button or permission to open Salesforce content from the File Library. Uploading files does not bypass its separate processing gate. The ordinary upload workflow on this page is unchanged. ## Select Files While Creating a Project **Create Project** accepts optional files before the project exists. Its compact drop area closes after selection; **Add files** reopens it while filenames and removal controls remain visible. Choose up to 12 PDF, PNG, JPEG, or DWG files (30 MB each, 120 MB total), or one ZIP alone. Empty, unsupported, oversized, or incompatible additions show an error without discarding accepted files. Upload starts after creation; Documents still checks permissions, ZIP availability, and file content. ## A refused application form A failed form review may explain that the PDF appears to be the wrong form, a different revision, or could not be verified for the selected program. Read its reason and observed differences in Documents, then upload the correct form before retrying. The explanation belongs to the current failed review and clears after a successful retry or replacement; it does not mean the file transfer failed. ## Supported File Format The selected project's **Upload Project Files** control supports PDF, PNG, JPEG, and DWG files up to 30 MB each, or one ZIP up to 30 MB, subject to the workspace's current server restrictions. Word documents are not supported. It is the console's only upload lane: the older single-PDF uploader with its 3 MB limit was retired on 2026-09-30, and an organization whose secure intake is not enabled sees that upload is unavailable rather than a fallback. ### Native CAD companion upload For an existing site plan, choose **Attach DWG** directly on its card. The chosen version is fixed before upload and validated by the server; a concurrent PDF replacement cannot silently retarget the upload. The same card offers **Replace DWG** and shows required/optional, failed, processing, attached, or outdated states. A replacement PDF needs its companion reconfirmed or replaced. Where the workspace permits native CAD, DWG uploads are available for every utility by default, even when its checklist does not require CAD. An administrator can disable native CAD intake for an organization. The selected published utility/process policy separately determines whether CAD is mandatory: NSP's current policies keep it optional, while NES retains its requirement for systems at or above 50 kW. A utility does not need a CAD review profile to accept an upload. Only DWG is supported for native CAD intake; DXF is not currently accepted. In a project's **Documents** view, use **Upload Project Files** for PDFs, images, and AutoCAD DWGs. You can drag the site-plan PDF and matching `.dwg` together. Each file may be up to 30 MB. GridWonk prepares the PDF and privately inspects the DWG, then attaches the drawing only when one current **Site plan** match is proven. Matching basenames may pair automatically; ambiguous drawings show **Choose the Matching Site Plan** and never guess. When the PDF and DWG arrive together, GridWonk waits for the PDF to finish becoming the current site-plan version before it pairs the drawing. It does not attach the DWG to an older site-plan version just because that version was current when the upload began. A retryable processing failure keeps the same private upload available for retry, and a bounded background recovery pass resumes safe queued or waiting pairings without creating a second copy. The PDF remains the packet document. Its DWG is an immutable native companion that supplies layouts, layers, entity properties, measurement, and extracted review evidence. Replacing it creates a new logical site-plan version. The original stays private. Intake and visualization are utility-neutral; utility-specific checks require that utility's reviewed procedure profile. ## The Digitization Process After upload, AI extracts text from your PDF: 1. **Upload** — Select and upload your PDF file 2. **Processing** — AI extracts text content 3. **Classification** — AI detects document type automatically 4. **Ready** — Document available for compliance validation Each processing run is tied to the exact stored file generation. If a newer generation replaces the run's input through an internal or future versioned workflow, stale digitization, classification, and text-location results are discarded instead of being attached to the newer file. ## Project Context You can upload and digitize files before creating a project. Those files are shown as **Draft files**. Draft files are useful for research and cleanup, but validation results must belong to a project. To validate a draft file: 1. Click **Create project to validate** 2. Enter a **Project name**, capacity, and distribution/transmission track 3. Attach the draft file to the project 4. Run validation in that project If you upload while a project is already selected, the file is linked to that project automatically and can auto-validate when the document type is ready. The console does not ask you to enter a utility application number. GridWonk creates an internal placeholder behind the scenes and can later map or replace it when the utility system assigns an official number. ## Manage Project Documents Current finding counts are visible without opening **More**. Select a count to read its findings. Processing completion is not a clean review: unreviewed, failed, and stale checks remain explicit. Findings and CAD status refresh after document changes, accepted uploads, or review changes. Unchanged background responses do not reload them. A failed findings refresh remains visible instead of being treated as a clean result. These counts use the same current source as Overview, Findings, and the partial Report view. With permission-aware live updates enabled, temporary connection failures retain the displayed documents while authorized background reads recover. A connection warning is not an upload failure. Successful scheduled refreshes stay quiet; they do not imply measured delivery delay or proof that processing finished. If updates remain unavailable, use the offered refresh/retry action; if your session expires, use **Sign in**. See [progress-update troubleshooting](/docs-site/help/document-troubleshooting#when-progress-stops-updating). This behavior remains gated until rollout; tabs opened before the upgrade need a refresh. The full uploader stays visible while a project has no documents. After the first document exists, use **Add documents** in the Documents header to expand it when needed, or **Attach from library** to reuse an eligible file. Active storage-native uploads and upload errors remain visible until they are resolved. Each compact or expanded document row labels **Upload**, **Text recognition**, and **Document review** separately. Upload completion means the file was received, not that text recognition or review passed. The review progress bar describes only the individual review. On a phone, Preview and More remain beside the filename while the full-width role selector uses a deliberate second row. Open **More** for Review or Retry, Findings, Replace, and Delete. Delete still requires confirmation. Open a role suggestion to read its rationale and confirm it; abstentions and possible combined-document warnings remain visible without expanding every row. The required-role checklist starts as an **N of M assigned** summary and expands on demand. ### Read the three processing states | Label | What it tells you | | --- | --- | | **Upload** | Transfer and server verification: **Verifying** is not yet **Complete**. A retry or expiry message concerns the transfer. | | **Text recognition** | Optical character recognition (OCR): **Not started**, **Queued**, **In progress**, **Retry pending**, **Complete**, or **Failed**. **Status unavailable** means the state could not be established. | | **Document review** | The individual review: **Queued**, **In progress**, **Complete**, **Failed**, **Could not start**, or **Superseded**; **Not started** means no current review has begun. | An intake card can say **Document review: Check document** because that card does not read the review record. Check the settled document row for its result. Text recognition may fail while a document review is complete; preserve and read the review findings instead of assuming all work failed. A complete document review is not a clean result, a full-packet review, or utility approval. ### Applicant-document safety states ## Document Classification AI automatically detects your document type with a confidence score. The manual selector currently focuses on site-control evidence types used by validation. Site-control validation focuses on evidence such as deeds, leases, options, easements, rights of way, development rights, exclusivity agreements, and shared site agreements. Application forms and permits may be uploaded and digitized, but they do not automatically satisfy site-control evidence requirements unless the extracted utility requirement allows that evidence. | Type | Description | |------|-------------| | **Deed** | Fee simple ownership | | **Lease** | Leasehold interest | | **Option to Purchase** | Option to buy property | | **Option to Lease** | Option to acquire leasehold | | **Easement** | Right to use property | | **Right of Way** | Linear infrastructure corridors | | **Development Rights** | Right to develop a site | | **Exclusivity Agreement** | Exclusive business relationship | | **Shared Site Agreement** | Co-location for multiple facilities | | **Other** | Requires manual classification | Review and confirm the classification to ensure accurate validation. You can override the AI classification if needed. ### Packet content roles For supported interconnection packets, GridWonk classifies the content role from the safe viewing copy while text extraction runs separately. A positive result for application form, single-line diagram, site plan, equipment specification, or site control is accepted automatically when the project is in the enabled rollout. Unknown, not-evaluated, possible-combined, and supporting-role results still require a person. Check the assigned role and reason in project Documents. If the role is wrong, select the correct role and choose **Correct**. The human correction becomes authoritative, the automatic assignment stays in audit history, and the analysis applicable to the corrected role runs again. Once document processing is ready, an accepted reviewable role can start its individual review automatically and can also make the full packet eligible for automatic review. **Review** and **Retry review** remain manual recovery actions. ### Combined PDFs In project **Documents**, choose **More actions → Split PDF** for an eligible, accepted PDF with 2–250 pages. This works after assigning a document type or completing a review, even if automatic classification did not flag the combined content. **Possible combined document** is an additional shortcut, not a requirement. Existing uploads do not need to be uploaded again. 1. Select **More actions → Split PDF** from the project or packet document list. 2. Check the safe page thumbnails and the suggested ranges. 3. Make every range continuous and non-overlapping so every page is included exactly once. 4. Assign a packet role to each document range, or explicitly discard separator/blank pages. 5. Select **Confirm and create documents**. Opening, analyzing, or canceling the dialog does not change the document. The original remains available; only a successful split makes its existing review historical. Each resulting document enters processing and requires its own review. Suggestions are drafts, not decisions. If analysis fails, use **Try again** or enter page ranges manually when page previews are available. Confirmed work continues in the background; reopen **Split PDF** to see progress. A failed attempt offers **Retry split** or **Keep original**. New reviews and submission remain paused until the split succeeds or you keep the original. Keeping the original preserves its document type and review history. Splitting is enabled by default for applicant organizations; administrators can restrict it through the existing feature controls. There is no new developer setting or public API. Unsupported files, imported/source-managed documents, and read-only packets are not eligible. Pages are split as whole pages; content within a page is not cropped. ### Packet ZIP uploads Choose one ZIP in **Upload Project Files** to use it as a temporary container. GridWonk validates the whole archive first, then sends each accepted PDF, PNG, JPEG, or DWG through its ordinary processor. The ZIP itself never becomes a packet document or enters review. - Keep the compressed ZIP at or below 30 MB and include 1–12 files. - Use only PDF, PNG, JPEG, or DWG entries. Nested or encrypted ZIP files and unsafe paths are rejected. - If any entry fails validation, no entry is handed to Packet Intake. - The control appears only when the storage-native upload experience and the ZIP upload feature are both enabled for the applicant organization (server-side, per-organization settings), and only while the project is in an editable stage. - Upload the ZIP by itself; a selection that mixes a ZIP with loose files is rejected with guidance. ZIP upload is a convenience, not a different review path. After successful handoff, each document follows the normal preparation and review rules, while each DWG follows safe site-plan pairing, immutable attachment, visualization, and evidence extraction. GridWonk waits for the whole upload batch to settle before reserving a whole-packet review. A CAD item settles when its immutable site-plan attachment is complete; Autodesk evidence may arrive later and can trigger a new review against the updated packet fingerprint. Cancelling or failing one optional item does not turn it into packet evidence—the ordinary readiness rules decide whether the remaining documents can be reviewed. This also applies when you start a packet review manually: finish or cancel the unfinished uploads, abandon their batch, or wait for it to expire before retrying. Accepted documents stay attached. Individual document reviews can still run while the rest of the batch is unfinished. If a retry resumes an item after its coordinating batch expired, the expired batch remains truthful history while the file's own status continues to completion. The Documents list keeps polling that file directly, so a temporary batch-status failure cannot hide a successful retry. The same safety rule works in reverse. If a whole-packet review is already reserved or running, GridWonk asks you to retry the new upload after that review finishes instead of reviewing a packet while its files are changing. A recoverable review-start failure does not block uploads while idle; if GridWonk retries it, the retry first claims the same submission lock and becomes queued before a new batch can be accepted. ## Document Status States | State | Description | |--------|-------------| | **Digitizing · N%** | The document is being prepared for review | | **Digitization complete** | The upload card's preparation work finished | | **Categorizing · N%** | GridWonk is determining the document's role | | **Reviewing · N%** | The individual document review is running | | **Ready for review** | The document is digitized and its role is assigned, and no review has been started | | **Review complete** | The individual document review finished | | **Digitization failed** | Needs retry | | **Review: Failed** | The individual review needs a retry | Site-control documents review alongside the application form, single-line diagram, site plan, and equipment spec sheets. When all present typed documents have current extraction evidence and the packet's required documents are ready, automatic full-packet review can start. The Documents view states whether the full packet review has not run, is in progress, last completed, or failed. Open **Review** to see the result, findings, or retry action. ## Retry and Delete Options If you refresh after a secure upload has started, return to the same project's **Documents** in the same browser tab and account. **Reselect original files to resume** checks the original files before continuing the same upload. Already accepted files are not uploaded again, and an **Attach DWG** upload keeps its original site-plan version. Files selected before a project exists are still temporary; no upload has been reserved for them yet. Recovery remembers identifiers and file fingerprints, not document contents or upload credentials. If recovery cannot be verified, use **Retry Recovery**. **Dismiss Local Record** removes only the browser's recovery record: it does not cancel server processing or release an unfinished upload gate. Use the file's cancellation control to stop an eligible unfinished upload. An empty, unsupported, or unreadable new file shows a normal upload error, not recovery controls. Correct the selection and choose the file again. **Retry Recovery** remains available when the account or saved upload cannot be verified, even if no recovery record could be loaded. - **If the transfer is interrupted or its authorization expires**: Follow the upload card's message and use **Retry** when offered. An eligible retry keeps the upload's identity but starts a fresh transfer from byte zero. A service rejection does not mean the PDF is invalid; contact support if the message asks you to. If finishing reports that the upload changed, another retry replaced it: the card refreshes and keeps **Retry** available when the file still needs bytes. - **If preparation fails after upload**: Use the processing **Retry** offered for that accepted file. This reuses the stored source rather than uploading it again; only eligible internal failures can be retried, within the recovery limit. If the file changed before the retry started, refresh the page and retry the current version. - **If document review fails**: Use the document's review recovery action. Upload recovery does not rerun a completed review. - **To remove an unpinned document**: While the packet is a draft or resubmission under development, click **Delete** - **Submitted-package safety**: A document frozen into a submitted or resubmitted package cannot be changed or removed Refresh after an uncertain result. The server may have received the bytes even when the browser reported a transfer failure; verified completion wins. An expired or abandoned upload selection stays closed, but each unfinished file keeps its own **Retry**, and quota checks still apply. Keep accepted documents and follow the current on-screen recovery guidance instead of repeatedly creating replacement uploads. If an accepted file's text recognition or review remains failed, contact support with the project, filename and affected outcome. Support may be able to recover processing from the stored file after a scoped check; this is not a customer OCR-retry control. Do not rerun a completed review merely because OCR failed. If the original upload was never accepted, processing recovery cannot recreate its bytes. See [Document troubleshooting](/docs-site/help/document-troubleshooting) before uploading another copy or replacing a document. Tell support if the document or project review inputs change while recovery is being prepared, including a change to the project's state. Support must check the current inputs and obtain a new approval before proceeding; the earlier approval does not authorize recovery of changed inputs. GridWonk does not currently promise automatic 30-day cleanup for applicant documents. Keep documents until you no longer need the working copy, subject to submitted-package retention and your organization's records policy. ## Document Type Confirmation After AI classifies a document, a confirmation modal appears: 1. **Review** — The modal shows the AI's detected type and confidence score 2. **Confirm or Override** — Accept the classification or select the correct type from the dropdown 3. **Save** — The confirmed type is saved and the document proceeds to validation-ready state This step ensures classification accuracy before compliance checks run. ## Packet Review Authority The developer console uses the applicant self-check lane by default. Utility teams run utility screening from their utility organization context. An optional compact **Review as** selector may be enabled for an authorized GridWonk operator, but the server still decides which lanes that user can exercise. ## Attach from Files Vault Reuse a previously uploaded vault file in an eligible utility or project context without uploading the bytes again. A document identity already linked to another project cannot also be attached to a second project; create or upload a distinct working copy when the UI requires one. 1. Click **Attach from Files** in the "Your Documents" section 2. A side sheet opens listing files from your personal vault 3. Files already linked to the current utility are filtered out 4. Click **Attach** next to a file to link it to the selected utility 5. The file appears in your document list immediately This is useful when the same site-control source is relevant in more than one utility context, while keeping each project's document linkage unambiguous. ## Document Revision Rounds When an assistant or integration returns upload, job, or review-run identifiers, keep them with the project and packet identifiers. Check the same operation after an interruption before starting another attempt, and include those references when asking support about an unresolved result. Preserve source document and page citations when sharing review findings. A completed upload or individual-document result is not a completed packet review. For transfer failures, expired authorization, review retry and splitting, use [Document troubleshooting](/docs-site/help/document-troubleshooting). **Retry upload** sends the unchanged source through a fresh attempt; **Replace** is for a corrected document version. Do not repeatedly retry a protocol rejection before the underlying platform issue is resolved. For a corrected PDF in an editable project's **Documents** view, choose **More → Replace** on the document you intend to revise. This versioned intake creates a new current logical version; it does not overwrite the bytes used by an earlier review or submitted package. - Re-uploading byte-identical content may reuse the existing document and restore missing references without creating a new version - Replacement is checked against the version selected when you opened the action. If that version changes before acceptance, refresh and select the intended document again - Earlier review results remain attached to their original version; processing and review of the new version are separate outcomes - A direct overwrite through an older upload interface may still be refused. Use the project's explicit **Replace** action, not a same-filename upload, to request a revision - Documents frozen into formal submission packages remain immutable review history Do not treat a conflict as a completed revision round. Confirm the document shown in the current project before running validation or submitting. ## PDF Preview Click a document card to open a full PDF preview: - Opens in a 70% width side sheet on the right - Uses the annotated PDF viewer with page navigation - View the original document alongside the digitized content - Close the preview to return to the document list ## Best Practices 1. Ensure PDFs are not password-protected 2. Use high-quality scans for handwritten documents 3. Check the limit shown by the upload control: project uploads support up to 30 MB per file 4. Name files descriptively for easy identification 5. Use the Files Vault to reuse eligible source files, while keeping each project's document linkage distinct 6. Correct any automatic role assignment that does not match the document ## Asking the Assistant About Uploaded Files Useful uploaded-file questions include: - "Which documents have I already uploaded for this utility?" - "Do I have a lease uploaded for Duke Energy NC?" - "Can I attach a file from my vault instead of uploading it again?" --- # Utility Selector Finding, filtering, watching, and selecting utilities for interconnection requirements. URL: /docs-site/help/utility-selector ## Utilities Available for New Projects In **Create Project**, normal utility choices require a released, full packet setup for the chosen state and program. By default, a real receiving organization is not needed for private review. Authorized synthetic choices require a validated test pairing backed by a released utility; they cannot activate real utility intake. A Research selection must qualify too. If availability cannot be confirmed, use **Retry**; if setup is incomplete, contact support. Availability does not guarantee exhaustive requirement coverage, utility approval, or permission to submit a packet to the utility. **Utility Research** still searches the full catalog. A research listing alone does not mean packet review is supported. Review coverage depends on the utility's supported state and interconnection program. The RTO overview is available in Research, not in the new-project picker. ## Search vs Browse Modes ### Search Mode Type keywords to find utilities by: - Name (e.g., "Duke Energy") - Known alias (e.g., an acronym such as "NSP") - State (e.g., "North Carolina") - Region (e.g., "Southeast") ### Browse Mode View utilities grouped by ISO/RTO for discovery: - All utilities in a region displayed together - Easy comparison of options - See queue statistics at a glance ## Canonical and Synthetic Options The selector keeps canonical EIA-backed utility records separate from authorized synthetic test tenants. Synthetic results have a **Synthetic** badge and state which canonical utility supplies their requirements. - A regular result is the canonical utility record used for research and requirements. - A result with a **Synthetic** badge is an authorized test utility tenant. Its subtitle names the canonical utility whose requirements it uses. Platform administrators can find every valid, reciprocally paired synthetic utility. Other users can find only the synthetic utilities explicitly paired to their active applicant organization. One test developer can have several utility destinations, with one destination per canonical utility. Invalid or one-sided test pairings remain hidden. Selecting a synthetic option keeps document, requirement, and validation context on the named canonical utility. When a project is created, the server verifies the active organization and reciprocal pairing again before choosing the synthetic destination; the visible label is not treated as authorization. ## Filtering by Utility Type Use the type filter tabs at the top of the dialog: | Type | Description | |------|-------------| | **All** | Show all utility types | | **IOU** | Investor-Owned Utility (e.g., Duke Energy, Dominion) | | **RTO** | Regional Transmission Organization (e.g., PJM, MISO) — opens the RTO Overview Dashboard | | **Municipal** | City-owned utilities | | **Coop** | Rural electric cooperatives | ### State Filter Dropdown A state dropdown sits alongside the type tabs. It narrows results to utilities operating in a specific state. All service states are populated automatically. Combine with type filters for precise results (e.g., IOU + North Carolina). ## Multi-State Utility Selection Inside **Create Project**, the utility and state controls stack at full width. The state-selection **Cancel** control dismisses only the pending utility choice; it does not create or close the project. Some utilities operate in multiple states with different requirements: **Example: Duke Energy** - Duke Energy NC (North Carolina rules) - Duke Energy SC (South Carolina rules) - Duke Energy FL (Florida rules) When selecting these, you **must also choose the specific state** for accurate requirements. Each state has its own regulatory framework, fee structures, notice requirements, and community engagement rules. ## RTO Overview Dashboard Selecting the **RTO** type filter tab displays an RTO Overview Dashboard instead of a utility list. Each RTO card shows the RTO name, active capacity, project count, and other aggregate statistics. Click an RTO card to drill into the utilities under that RTO. A "Back to RTOs" breadcrumb appears at the top to return to the overview grid. ## Understanding Utility Information Each utility row shows: | Element | Description | |---------|-------------| | **Logo** | Favicon from utility website | | **Name** | Utility display name | | **Synthetic badge** | Marks an authorized test utility tenant; its subtitle names the canonical requirements source | | **Type label** | Full label — "Investor-Owned Utility", "Regional Transmission Org", "Municipal Utility", or "Electric Cooperative" | | **Service states** | Geographic coverage with map pin icon (truncated to 4 states, then "+N") | | **Balancing authority / Region** | Regional grid information | | **Queue stats** | Active capacity and wait time — shown in search mode only | | **Customer count badge** | Approximate customer count (e.g., "5.8M", "450K") | | **Watch button** | Star icon to subscribe/unsubscribe to change monitoring (see below) | | **Program chips** | One chip per published program (for example Simplified, Expedited, Standard); clicking one opens that program — see Programs in the Selector. Utilities without a reviewed program show the document and requirements count badges instead | ## Watch/Unwatch Utility Subscriptions Each utility row has a star icon button for change monitoring subscriptions. - **Watch** — Click the star to subscribe. You will receive notifications when that utility's interconnection procedures or requirements change. - **Unwatch** — Click the star again to unsubscribe. - When a state filter is active or the utility has a single service state, the subscription is scoped to that state. Multi-state utilities without a state filter subscribe at the utility level. - Watch status loads when the dialog opens and updates instantly on toggle. If the active organization cannot use change monitoring, the management link stays hidden rather than sending the user to a dashboard section they do not have. - **Manage Watched Utilities** in the dialog header opens the dashboard's Requirements Change Monitoring card, which lists every active subscription and recent detected changes. It appears only for organizations that have change monitoring. The star is the only place to subscribe — the console header no longer carries a watch control, because a subscription belongs to a utility rather than to the project you happen to have open. Watch and Unwatch are available only in a developer organization context and are write operations. Direct users need an active **Member**, **Admin**, or **Owner** role. Grant-derived access also needs a **write** or **admin** grant and a Member-or-higher role in the receiving organization. Viewer and read-grant access remain read-only. ## Programs in the Selector A program is the utility's interconnection track (in Massachusetts: Simplified, Expedited, Standard). The selector captures which program you care about so Utility Research opens on it directly. - **Click a program chip** on a utility row — Selects the utility AND opens **Utility Research** on **Procedure Docs** for that program. - **Click the row itself** — Selects the utility, then a small **Which program?** step lists its published programs. Pick one, or **Skip, show all programs**; closing the step counts as skip. A utility with one program lands on it without asking. - For multi-state utilities, state selection comes first; a chip's program carries through to the state step. - GridWonk remembers the program per utility in this browser. Switch programs any time from the **Program** segment in the console header (Utility › Program). - Utilities without a reviewed program show the document (blue) and requirements (purple) count badges; those open Procedure Docs or Requirements. The document badge follows current-procedure enforcement and counts current usable procedure documents when that safeguard is enabled. The requirement badge counts individual requirements in the technically published Packet Intake catalog. It does not count rows in the frozen legacy requirements table. ## Resizable Dialog The selector dialog can be resized by dragging the handle in the bottom-right corner. | Property | Value | |----------|-------| | Default size | 700 x 500 px | | Minimum size | 450 x 300 px | | Maximum size | 1200 x 800 px | | Persistence | Dimensions saved to localStorage | | Reset | "Reset size" button appears when dimensions differ from default | ## Virtualized List For performance with 1000+ utilities, the list uses virtualization — only visible rows are rendered. This keeps scrolling smooth regardless of result count. ## How Selection Affects Console Selecting a utility loads that utility-specific: - **Documents** — Discovered procedure documents - **Requirements** — Published Packet Intake requirements - **Validation rules** — Utility-specific deficiency checks - **Queue analytics** — Regional data In the project-first console, selecting or opening a project can also set the utility, state, and distribution/transmission filter from the project record. A shared URL with `submissionId` points GridWonk at the saved project first, then hydrates the matching utility context. Changing the research utility updates reference context and clears transient selections. It does not delete project documents or stored review results; reopen the project to return to its work. Utility application review requires an organization linked to a utility. If the active organization is not linked to one, the Applications and Screening views show an empty utility-linked state instead of loading another utility's queue. ## Asking the Assistant About Utilities Useful utility-selection questions include: - "Which Duke Energy state should I choose?" - "Why does GridWonk need a specific state for Duke Energy?" - "Show utilities in North Carolina with extracted requirements." --- # Watchlists & Change Monitoring Subscribe to utilities and receive alerts when interconnection procedures change. URL: /docs-site/help/watchlists ## What are Watchlists? A watchlist is your set of tracked utilities. When you watch a utility, GridWonk continuously monitors its interconnection requirements for changes and notifies you when something differs from the last known state. This keeps your team informed without manual checking. ## Watching and Unwatching a Utility In the **Utility Selector** dialog, each utility row displays a **Watch** button with a star icon. | Action | How | |--------|-----| | **Watch** | Click the star button on any utility row. The button turns amber and reads "Watching". | | **Unwatch** | Click the amber "Watching" button again to stop tracking that utility. | If a state filter is active, the subscription is scoped to that specific state. For single-state utilities, the state is set automatically. Multi-state utilities with no filter are watched at the utility level across all states. The star is the only place to subscribe. The console header used to carry its own watch control; it was removed because a subscription belongs to a utility rather than to whichever project you happen to have open. To review what you are watching, use **Manage Watched Utilities** in the Utility Selector header, which opens the Requirements Change Monitoring card on your dashboard. ## What Changes are Detected The monitoring pipeline computes a fingerprint of each watched utility's technically published Packet Intake requirements and compares it to the previous scan. It does not read the frozen legacy requirement table. A state still scopes the subscription and notification; the published requirement catalog itself is currently keyed to the exact utility rather than a separate state row. Detected change types include: | Change Type | Description | |-------------|-------------| | **Requirements Updated** | Requirement text, count, or content hash changed | | **Document Added** | A new procedure document appeared for the utility | | **Document Removed** | A previously tracked document is no longer found | | **Validation Rule Updated** | A form-validation or cross-document rule changed | Each change event records a title, summary, severity, and metadata about what shifted. The first scan of a newly watched utility records a **monitoring baseline** instead of an alert: there is no previous scan to compare against, so the event is logged and no notification is sent. The move to Packet Intake requirements did the same thing once per already-watched utility. Alerts resume with the next real change. ## Severity Levels Severity is assigned automatically based on how much the requirement set changed: | Severity | Criteria | |----------|----------| | **Low** | Fingerprint changed but requirement count stayed the same (text-only edits), or the event is a monitoring baseline | | **Medium** | Requirement count changed | | **High** | Requirement count changed by 20% or more compared to the previous scan | High-severity changes indicate substantial procedure revisions that may affect active applications. ## Detection Frequency GridWonk runs a single automated pipeline every 30 minutes: | Pipeline | Frequency | Purpose | |----------|-----------|---------| | **Detect Requirement Changes** | Every 30 minutes | Scans watched utilities for fingerprint changes, then delivers pending email notifications | Both detection and notification delivery happen in the same cron handler. Up to 200 scopes are checked per detection run and up to 50 notifications are processed per delivery run. ## How Notifications Work When a change is detected, a notification row is queued for each user subscribed to that utility and state. The notification pipeline then: 1. Looks up the user's email address 2. Sends a **change alert email** with the utility name, state, summary of what changed, and a link to the dashboard 3. Updates the subscription's `lastNotifiedAt` timestamp If delivery fails, GridWonk stores a redacted failure reason for diagnosis and raises an operational alert grouped by failure type. The cron fallback gets a fresh three-alert budget for each sweep. Queue deliveries do not share that budget, so a warm server instance cannot permanently silence later failures; the alert service's 15-minute, failure-class throttle controls repetition across requests. The operational alert identifies the affected account when it is stored with the subscription, and the user as the notification recipient. It does not attribute a system delivery failure to that user. Non-email notification methods (e.g., in-app events) are marked as delivered immediately for future expansion. ## Viewing Change History Recent change events are available through the **Recent Changes** list, which can be filtered by: - **Utility** — Show events for a specific utility - **State** — Narrow to a two-letter state code - **Search query** — Free-text search across event titles and summaries Events are sorted newest-first and display the severity, title, summary, and detection timestamp. ## Where Change Signals Surface Watchlist subscriptions drive both the change event data and the notification delivery for high-severity procedure updates. The console's aggregate Analytics destination that used to summarize those signals has been retired; the [Portfolio view](/docs-site/help/portfolio) covers project status, and the change events themselves reach you through notifications. ## Who Can Use Watchlists Watchlists are available in **developer** organization contexts. Each subscription is scoped to the user and organization, so team members manage their own watch preferences independently. Creating or deleting a subscription is a write operation. Direct users need an active **Member**, **Admin**, or **Owner** role. [Grant-derived access](/docs-site/help/access-grants#how-grant-based-access-is-decided) also requires a **write** or **admin** grant and a Member-or-higher role in the receiving organization. Viewer and read-grant access can inspect allowed data but cannot change watch preferences. --- # Claude Code and Codex Setup Connect Claude Code or OpenAI Codex to GridWonk as an external user or an authorized internal operator. URL: /docs-site/integrations/agent-tools This is the canonical setup guide for using GridWonk tools from Claude Code or OpenAI Codex. It supports two access lanes: | Lane | Intended user | Connection | Access | |------|---------------|------------|--------| | External | Customer, partner, or approved integration developer | Hosted GridWonk MCP endpoint | Broad organization tools with an API key, or exact-scope packet tools with a partner OAuth token | | Internal | GridWonk developer or authorized operator with repository access | Repository `gridwonk` plugin 0.2.6, serving `gridwonk` and `gridwonk-admin` | Repository skills, runtime tools, and optionally protected admin tools | Plugin 0.2.6 displays as **GridWonk Internal** and retains the `gridwonk` package identity, both existing servers, and the bundled docs, tasks, and admin workflow skills. Update an installed plugin and start a new session to load those bundled instructions. MCP means Model Context Protocol: a standard way for an AI tool to discover and call another application's tools. Both Claude Code and Codex support MCP. Choose one lane. External users do not need the private GridWonk repository and must not be given internal admin credentials. ## Before You Start You need: - Claude Code or Codex installed and signed in. - A current Node.js release only for the internal repository plugin. The GridWonk repository uses Node.js 24. - Your own GridWonk credential, issued for the organization and environment you are authorized to use. Keep credentials in environment variables or an approved secret manager. Never commit them, paste them into an AI chat, or copy another person's credential. The current production URL is: ```text https://gridwonk.com ``` ## External Setup External users connect to the hosted runtime endpoint: ```text https://gridwonk.com/api/v1/mcp ``` The hosted endpoint supports stateful Streamable HTTP sessions. OAuth clients should request `resource=https://gridwonk.com/api/v1/mcp`; the session is then pinned to that token audience and partner scope set, when present. The local stdio package bridges to the same Streamable HTTP endpoint. Use an organization-scoped GridWonk runtime API key for the broad tool catalog. Use a short-lived OAuth token carrying `partner.read`, `partner.write`, or both when the client needs packet tools; a raw key never discovers packet tools, and a scoped token never discovers broad tools. The examples use the canonical `GRIDWONK_API_KEY` environment variable. Pre-rebrand `GRIDBOOST_*` names remain accepted temporarily for existing hosts, but new configuration should use `GRIDWONK_*`. The local connector applies that same split. Hosted MCP also exposes `assist` through the shared server runtime; an existing local release may retain its REST helper. Assistant execution remains deployment-gated and subject to organization admission. Partner, mixed, empty or unknown-only catalogs never gain broad assistant authority. Broad customer credentials can also discover project list, get, create, and update tools. Those tools are developer-organization scoped and intentionally omit submit, resubmit, and synthetic-demo creation. Eligible utility callers use the existing `start_packet_review` tool with `partner.write`; the server selects utility authority and checks the utility lane and current write membership. Four Salesforce-specific tools are implemented but disabled by default and exposed only to authorized connector callers after approved enablement. See the [Salesforce integration status](/docs-site/integrations/salesforce) before planning Agentforce or Salesforce-hosted MCP connections; neither direction is activated by connecting this client. The connector identifies each running process with one anonymous instance ID and a versioned user agent. Closing Claude Code, Codex, or the parent stdio connection closes the hosted MCP session too; cleanup has a bounded timeout so a stalled remote connection cannot keep the local process alive. The package manifest, modern and fallback handshakes, and that user agent share one release version. After upgrading the connector package, fully restart the client so this lifecycle behavior and the current hosted catalog are both loaded. Use package 0.3.2 or later (0.4.0 is current). A 401 or 403 stops after the modern request instead of retrying the same credential through the legacy proxy. If logs show many rejected requests with different instance IDs, correct the credential, remove duplicate `gridwonk`/`gridwonk-admin` registrations, and restart the MCP host; that pattern is repeated process startup, not one healthy session polling. Authorized internal Codex sessions may use the separate `gridwonk-admin` catalog to inspect organizations, members, grants, explicitly scoped agent sessions, and the model catalog. Organization responses omit payment identifiers and private settings, and session responses omit free-form metadata. Impersonation, billing overrides, and model-catalog writes are not delegated to Codex. The protected `organizations.activity.list` tool also provides bounded organization-owned packet activity, upload-attempt states and linked automatic outcomes. Use its actor/date/category filters and pagination, and retain its coverage warnings: missing events are not proof of feature non-use. It is read-only, contains no provider errors or raw metadata, and does not expose personal user analytics or repair actions. External customer credentials cannot use this Admin tool. Make the variable available to the process that starts Claude Code or Codex: ```bash export GRIDWONK_API_KEY='gw_live_...' ``` Use your secret manager's shell-injection feature when available so the value is not stored in shell history. ### Claude Code — External Create or update `.mcp.json` in the external user's project. The file may be committed because it references the environment variable without containing its value: ```json { "mcpServers": { "gridwonk": { "type": "http", "url": "https://gridwonk.com/api/v1/mcp", "headers": { "Authorization": "Bearer ${GRIDWONK_API_KEY}" } } } } ``` Start Claude Code from that project, accept the MCP trust prompt, and run: ```text /mcp ``` The `gridwonk` server should be connected and should list organization-scoped runtime tools. ### Codex — External Add the hosted server without writing the credential into Codex configuration: ```bash codex mcp add gridwonk \ --url https://gridwonk.com/api/v1/mcp \ --bearer-token-env-var GRIDWONK_API_KEY ``` Verify the saved connection: ```bash codex mcp list --json codex mcp get gridwonk --json ``` Restart Codex if it was already open when the server was added. ### External Smoke Test Use a read-only prompt first: ```text Use the GridWonk MCP server to search public documentation for "MCP setup". Do not create, update, cancel, approve, or delete anything. Report the server and tool name you used. ``` The call should use the `gridwonk` server and `search_docs` tool. Results remain scoped to the API key's organization. For a packet-tool smoke, create a separate connection whose Bearer environment variable contains a partner-scoped OAuth token. `partner.read` should list only the currently registered read tools; `partner.write` should list only the registered mutation tools. Do not expect `search_docs`, resources, or prompts on that scoped connection. ## Use The Connected Runtime After the read-only setup checks, use `tools/list` to discover the tools available to the current credential and protocol revision. The [MCP API reference](/docs-site/api/mcp#available-tools) maintains the full catalog and scope rules. The docs-host `/.well-known/mcp.json` requires a docs session; API-key and OAuth clients can use authenticated `GET /api/v1/mcp` for runtime metadata. ### Continue A Work Item These tools require a broad credential and a modern stateful MCP session. The local connector maintains that session; direct HTTP clients must follow the [session lifecycle](/docs-site/api/mcp). 1. Call `get_active_work_item` with `{}` to inspect the context already bound to this session. 2. To resume another item, call `list_recent_work_items` with `{"limit": 5}` and select the intended result. Pass its actual work-context ID to `set_active_work_item` as `workContextId`. 3. Call `get_active_work_item` again to verify the binding before asking `chat` a follow-up through its `message` argument. Requirement and application queries can inherit this context. 4. Before starting unrelated work, call `clear_active_work_item` with `{}` to clear inherited context, then bind the intended new work item explicitly. Keep the same MCP session for follow-ups. If access changes or the session expires, initialize a new session and inspect its context before continuing. A work-context ID does not grant access to another organization or another person's private documents. When reporting a `chat` result, retain its citations and disclose a partial answer or error; see the [chat result contract](/docs-site/api/mcp#partial-answers-from-chat). ### Create And Inspect A Supported Job Job tools belong to the broad credential catalog. First use `list_jobs` and `get_job_status` to inspect existing work. Once the user has authorized the exact new work and you have established the target organization, utility, and state, a discovery call can use these tool arguments: ```json { "name": "run_job", "arguments": { "jobType": "discovery", "utilityName": "duke-energy", "state": "NC" } } ``` Replace the example utility and state with the authorized target. Save the returned `jobId` and call `get_job_status` with `{"jobId": ""}`. Follow the returned polling instructions; per-user OAuth callers use the MCP polling tool rather than API-key-only REST URLs. Creation means the job was accepted, not completed. If the start response is lost or ambiguous, inspect existing jobs before creating another. The other supported new job type is `document-digitization`, which requires an authorized `metadata.documentId` and `metadata.tableName: "ix_procedure_documents"` for procedure documents. See the [Jobs API](/docs-site/api/jobs) for metadata and access rules. Historical site-control, deficiency, and report-generation jobs remain readable but cannot be created again, including through admin `tasks.run`. Current packet validation uses [Packet intake Review](/docs-site/api/packets). There is no standalone job-retry MCP tool. A separately authorized replacement of a supported job creates a new job ID. To cancel authorized active work, call `cancel_job` with its exact `jobId` and read the returned `cancelled`, `runtime`, and `warning` fields; an in-flight provider call may still finish after cancellation. ## Internal Setup This lane requires access to the private `GridWonk/gridwonk` GitHub repository. The shared plugin runs the repository's local connector, so start Claude Code or Codex from the repository checkout. ### Prepare The Repository ```bash git clone git@github.com:GridWonk/gridwonk.git cd gridwonk git pull --ff-only origin main npm ci ``` Supply only the credentials needed for your role to the process that starts Claude Code or Codex: ```bash export GRIDWONK_BASE_URL=https://gridwonk.com export GRIDWONK_API_KEY='gw_live_...' # Authorized internal operators only: export GRIDWONK_ADMIN_API_KEY='gw_live_...' ``` - `GRIDWONK_API_KEY` is an organization-scoped runtime key. - `GRIDWONK_ADMIN_API_KEY` is optional and is restricted to approved GridWonk internal management keys. - `GRIDWONK_CLIENT_USER_ID` and `GRIDWONK_DELEGATION_TOKEN` are optional and may be used only for an approved delegated-user workflow. Do not provide an admin key to an external user. A customer runtime or customer management key cannot call the protected GridWonk admin endpoint. Plugin 0.2.3 and later do not read `.env.local`, `.env`, or any other repository environment file. Use an approved secret manager to inject the variables when possible. If the credential required by a configured connection is absent, the launcher exits before making a network request. The underlying server's explicit `--api-key` option remains supported for MCP hosts that already use it, although the repository plugin manifest uses process environment injection. The skills and both MCP servers ship as one plugin, so disabling it removes the skills too. To run the skills without a given MCP connection, simply leave that connection's credential unset: the skills keep working and only that launcher exits. ### Claude Code — Internal The repository declares `gridwonk@gridwonk-private` in `.claude/settings.json`. After the repository is trusted, accept Claude Code's prompts to add the private marketplace and install the plugin. If the prompts were previously skipped, run: ```bash claude plugin marketplace add GridWonk/gridwonk --scope local claude plugin install gridwonk@gridwonk-private --scope local ``` Then start a new session or run: ```text /reload-plugins ``` Verify the installation: ```bash claude plugin validate . claude plugin validate ./plugins/gridwonk claude plugin marketplace list --json claude plugin list --json ``` The plugin ID must be `gridwonk@gridwonk-private` and enabled. In Claude Code, the following skills should be available: ```text /gridwonk:gridwonk-docs /gridwonk:gridwonk-tasks /gridwonk:gridwonk-admin ``` ### Codex — Internal For local development worktrees, select the checked-in `gridwonk-core` environment in `.codex/environments/gridwonk-core.toml`. Automatic setup links configuration only. Use its explicit **Install dependencies** action when execution is needed; that action selects the pinned Node.js and npm versions, checks free space, and runs the guarded install without browser downloads. The runner also provides check, unit-test, type-check, lint, dev-server, local-build, and Chromium-install actions. See `.codex/environments/SETUP.md` for details. Setup links optional local configuration from the main checkout when available, preserves real worktree files, and skips missing sources. It does not link `_memory/`. The check action reports whether `.env.local` exists without reading its values; plugin credentials and backend access still need the separate checks below. Add the repository-backed marketplace and install the same plugin: ```bash codex plugin marketplace add GridWonk/gridwonk --ref main codex plugin add gridwonk@gridwonk-private ``` Verify it: ```bash codex plugin marketplace list codex plugin list ``` Fully quit and reopen Codex after the first installation. Search the plugin picker for `GridWonk`; the plugin ID is `gridwonk@gridwonk-private`. ### Internal Smoke Tests Run read-only checks before allowing a tool to mutate platform data: ```text Use the GridWonk docs skill to search public documentation for "MCP setup". Use the GridWonk tasks skill to list recent jobs without starting or cancelling anything. If I am an authorized internal operator, use the GridWonk admin skill to list pending users without changing them. Report the server and tool name used for each check. ``` The only MCP server names installed by plugin 0.2.3 and later are `gridwonk` and `gridwonk-admin`. The older `gridboost` and `gridboost-admin` aliases were removed because the duplicate registrations made every session spawn four processes for two servers and show each tool twice. ## Authorization Rules Protected document recovery is a human-operator exception, not a setup smoke test. The Admin implementation declares `documents.recovery.preview`, `.apply`, and `.get`; management API keys cannot use them. A session or separately enabled administrator OAuth lane must retain current platform authority. Apply additionally binds the preview token, exact targets, numeric spending ceiling and absolute deadline. Missing qualified pricing refuses provider calls. Migration, release and each paid recovery require their own approval; a connected plugin does not authorize execution. These tools are absent from public MCP, customer SDK/CLI and chatbot mutation surfaces. The Admin plugin also exposes confirmed user, invitation, team access, ownership, branding, organization-feature and model-assignment actions. Use the matching preview/apply pair with one UUID `idempotencyKey` and the unchanged payload; apply additionally requires the opaque `confirmationToken` from preview. Approval lasts ten minutes and binds the actor, credential, lane, tool, organization and state. An exact successful retry returns the stored safe receipt with `replayed: true` for 24 hours. Changed reuse is refused; executing, ambiguous or failed results require inspection and a new preview. A connection or preview alone does not authorize a live change. Organization features use `organizations.features.get`, followed by `organizations.features.preview_update` / `organizations.features.apply_update`. Resolve an explicit organization and choose one catalog feature and `action: "enable"`, `"disable"` or `"reset"`, with a written reason. Reset clears the override. Inspect the preview's effective availability before applying: environment overrides or dependencies may prevent the saved choice from taking effect. These tools require current platform-admin authority and cannot change global defaults, customer self-service policy or release controls requiring a deployment. Reread with get after apply. These mutations require a browser admin session, or an internal management key or administrator OAuth connection after the separately authorized `ADMIN_MCP_REMOTE_MUTATIONS_ENABLED=true` rollout. The flag defaults off, depends on the reviewed organization administration merge and four verified database guards. Administrator OAuth also requires its independently enabled lane, approved client and current role/membership. The legacy `agent_model_configs.update` stays session-only and deprecated. Invitation acceptance and legal consent remain invitee-only. Team owner/admin and last-owner checks, sign-in-domain isolation and model-catalog validation remain enforced by the shared services. See [MCP Servers — Admin Tools](/docs-site/integrations/mcp-servers#admin-tools). - Default to read-only calls during setup and testing. - Keep every runtime request organization-scoped. - External users use only the hosted `gridwonk` runtime connection. - Only approved GridWonk internal operators may use `gridwonk-admin`. - Preview a supported admin change before applying it. - Treat the synthetic-project cleanup tools as a narrow exception, not general deletion: use only exact empty Seven States synthetic-loop draft IDs and carry the preview token and unchanged inventory digest into apply. - Never run, cancel, approve, update, or delete production data unless the user has explicitly authorized that exact action. - A successful connection does not grant permission for a mutation. - For Salesforce-owned copies, ordinary packet reads still require the effective human viewer's current Salesforce record and field permissions. A shared service credential is not a substitute for that person's access, including for historical reports. ## Troubleshooting ### The server or plugin is missing 1. Confirm Claude Code or Codex is current. 2. Confirm the setup command was run from the intended project or repository. 3. Confirm the marketplace and plugin ID are exactly `gridwonk@gridwonk-private` for the internal lane. 4. Reload Claude plugins or fully restart Codex. ### Authentication fails 1. Confirm `GRIDWONK_BASE_URL` is `https://gridwonk.com`. 2. Confirm the required environment variable is present without printing its value. 3. Confirm the credential belongs to the intended organization and environment. 4. Confirm an internal management key, not a customer key, is being used for the protected admin lane. 5. Ask a GridWonk administrator to issue or rotate your own credential; do not borrow another user's key. ### Internal skills load but MCP calls fail 1. Run `npm ci` in the repository root. 2. Confirm the required credential is explicitly present in the parent process environment without printing its value. Repository environment files are intentionally ignored by the launcher. 3. Confirm the installed plugin is version 0.2.4 or later: `claude plugin list --json` reports the version and the MCP servers it registers; `codex plugin list` reports only the version, so use `codex mcp list` to confirm just the `gridwonk` and `gridwonk-admin` connections are present. 4. If the installed version is older, fetch the update first (`claude plugin update gridwonk@gridwonk-private`; for Codex, upgrade the marketplace and reinstall) — restarting applies an already-fetched update, it does not fetch one. Then fully restart the task or application so it loads the installed plugin version and the repaired process environment. Reconnecting an existing connection does not update plugin code. The installed plugin supplies the launcher, so an older copy of the launcher in the task's worktree cannot bypass the fix. ## Reusable Setup Prompt Copy this prompt into either Claude Code or Codex: ```text Set up this machine to use GridWonk safely. First, read the canonical guide in the GridWonk repository at: content/docs/integrations/agent-tools.mdx If that repository file is unavailable, use the published copy at: https://docs.gridwonk.com/integrations/agent-tools Determine whether I am: 1. an external GridWonk customer or partner, or 2. an authorized internal GridWonk developer/operator. Also detect whether this tool is Claude Code or OpenAI Codex, then follow only the matching access lane and tool instructions from the guide. Rules: - Never print, echo, commit, or paste an API key into chat. - Never give an external user the internal plugin or admin MCP connection. - Use a least-privilege organization runtime key for external setup. - Use the internal admin lane only when the user is an authorized GridWonk operator and already has their own approved management credential. - Do not create, update, cancel, approve, or delete anything during setup. - Run the guide's read-only verification and smoke tests when setup is complete. - Report the installed plugin or MCP server names, the tests that passed, and any missing credential or access requirement without exposing secret values. ``` This page is the source of truth. Tool-specific compatibility pointers elsewhere in the repository should link here instead of copying these instructions. One behavior note for requirement queries made through these tools: published requirement rows carry a per-row `reviewStatus` of `approved` or `pending` (utility-rejected rows never appear). External tools use `query_published_requirements`; the retired public `query_requirements` tool is no longer advertised or callable. See [Requirements API](/docs-site/api/requirements) for the contract. --- # Chatbot Channels (Web + Slack + Teams + API + MCP + CLI) How GridWonk delivers consistent chatbot behavior across all surfaces using a shared orchestration core. URL: /docs-site/integrations/chatbot-channels ## Availability for trial and prepaid workspaces Unrestricted assistant chat is unavailable for workspaces enrolled in trial or prepaid processing. Enabling a chat channel or purchasing a pack does not remove that restriction. Use the supported [public plugin tools](/docs-site/api/mcp), packet intake and review, and public help instead. The channel behavior below applies where ordinary chat is authorized. See [processing allowances](/docs-site/help/processing). GridWonk provides conversational assistance across six surfaces: the web app, Slack, Microsoft Teams, the public API, the MCP gateway, and the CLI. All use the same shared orchestration core, but authorized context, available capabilities, and presentation can differ by channel. Slack and Teams are enabled by default for every organization, but each organization admin can turn either transport off from the workspace **Features** page. A platform admin can override the setting from the organization's **Features** tab. A connected Slack workspace or Microsoft 365 tenant is still required before that transport can reach organization data. ## Shared Core All channels call `executeChatbot()` — a single async generator. Ordinary chat follows this pipeline; the console's selected-finding route has the stricter boundary described under [Web Chat](#web-chat): 1. **Canonical FAQ** — Instant deterministic answers filtered to the caller's effective audience (zero LLM cost) 2. **Direct tool fast paths** — Uploaded-document inventory and narrow requirement lookups can call `query_user_documents` or `published_requirements` before classification 3. **Query classification** — Intent detection and tool profile selection 4. **Requirements preflight** — Preserve review-pending or reviewed-empty release wording; use generic no-coverage guidance only for a true not-published result 5. **Route planning** — Choose `direct_llm`, `eve`, or a typed deterministic clarification, refusal, or unavailable result 6. **Execution and recovery** — Run the selected lane; a direct-model failure before output may recover through Eve, but an Eve-accepted turn is never replayed through another runtime 7. **Persistence** — Session and message recording 8. **Analytics** — Structured telemetry for every interaction For ordinary chat, all channels share: - Same query classification categories and confidence thresholds - Same routing and typed recovery behavior - Same utility/state-aware context model - Same canonical FAQ responses - Same direct-tool metadata for fast-path `published_requirements` and `query_user_documents` answers - Same requirements preflight logic - Same MCP tool controls and safety posture The administrator's **Database Access** control follows the turn across every channel. Before an Eve turn starts, the shared server signs the resolved control into its short-lived delegated token; database-backed product tools refuse the call unless that verified value is explicitly enabled. The web adapter derives its docs audience from both the trusted platform role and the active organization context. A platform administrator impersonating a customer is therefore restricted to public docs and public quick answers for the full request. Every channel carries the authenticated user and organization scope into session reads, message history, and completion writes. Opaque session IDs do not grant access by themselves, and caller metadata cannot choose a different organization. The requirements fast path and preflight use the same reader as the published REST API, SDK, CLI, and MCP gateway: every published row except the ones a utility reviewer explicitly rejected, each carrying `reviewStatus` (`approved` or `pending`). A scope whose utility review is unfinished still returns its rows, labelled pending, alongside an honest review-progress state. The tool-backed agent loop uses that reader unconditionally. The temporary cutover flag and legacy fallback were removed after the production cutover proved stable. The authenticated project/work context still chooses the exact utility and state. Across every channel, rows awaiting approved customer wording are omitted from usable requirement results. If all matches are pending, the response says the wording is under review; counts of available requirements exclude those hidden rows. Zero-row answers also preserve the difference between review-pending, reviewed-but-empty, and not-published results. Supported retrieval, requirements, and orchestration turns use Eve when the deployment audience and that channel's independent gate permit it. If Eve is unavailable or cannot safely prepare the turn, the core returns a typed clarification, refusal, or recoverable error. Once Eve accepts a turn, the core does not replay it through the Claude Agent SDK. For a safe, self-contained documentation question, Eve can emit its required first `search_docs` call directly instead of paying for a model request whose only permitted result is that same call. Context-dependent follow-ups stay on the normal model-controlled search path. This runtime detail is shared across every enabled transport and does not change the channel event contract. Eve is enabled **per channel**, not globally. Each channel is opened deliberately after its own authorization and disconnect checks pass, so it is normal for the web app to be answering on Eve while API, CLI, or MCP remain disabled. Enabled channels emit the same event contract; this does not guarantee identical evidence access or answers. Rollback selects a previously accepted Eve deployment instead of replaying customer turns through the Agent SDK. ## Self-service availability Self-service processing remains unlaunched. Metered packet-processing workspaces are refused at the shared chat boundary before FAQ routing, classification, or model execution. This applies to web chat, Slack, Teams, API, MCP, and CLI turns that reach that boundary; channel installation, Eve flags, and packet-processing credit do not grant generic chat access. Existing eligible workspaces keep the channel-specific authorization and rollout controls described here. ## Channel Adapters Each surface maps the shared `ChatbotEvent` stream to its native format: | Channel | Adapter | Output Format | |---------|---------|---------------| | **Web Chat** | `lib/chat/transports/console-ui-message-projection.ts` (via `app/api/chat/route.ts`) | Vercel AI SDK UIMessageStream | | **Slack** | `lib/chat-sdk/bot.ts` + `stream-adapter.ts` | Native processing status in Agent View; threaded replies can edit progress into the final reply, while root direct messages post one final message; legacy `AsyncIterable` fallback | | **Microsoft Teams** | `lib/chat-sdk/bot.ts` + `@chat-adapter/teams` | Single posted message; user-scoped thread continuity | | **Public API** | `app/api/v1/agents/chat/route.ts` + `sse-transformer.ts` | Server-Sent Events (SSE) | | **MCP** | `lib/mcp/public-gateway.ts` (`chat` tool) | Single buffered tool result | | **CLI** | `packages/cli` → the public API endpoint | Rendered terminal output over SSE | ### Web Chat Finding-card **Explain this finding** actions carry a structured reference to the project, saved review, and finding—not browser-supplied source text or document URLs. The server rechecks current access, resolves the review's saved requirement snapshot, and verifies the source edition's content fingerprint before preparing bounded, exact source passages. The evidence is loaded before model execution with raw text offsets and page labels; page or list boundaries do not establish which section governs a requirement. Embedded source text is data, not instructions. Common-practice origins remain distinct from utility text, and publication is not presented as human approval. The server persists the selected finding before model execution. Typed follow-ups, resumed conversations, and retries retain it and bypass generic requirement-list and platform-help shortcuts. The console shows the selection with **Clear finding**; choosing another finding replaces it, and changing user, organization, or project clears it. Access is checked again for every turn. Unavailable or incomplete evidence returns an explicit limitation: older unpinned reviews, unverified form-model fields, missing source editions, fingerprint failures, ambiguous citations, and reading limits are reported rather than replaced by current requirements or a guessed answer. Finding answers bypass both the general tool-backed answer loop and docs-only Eve retrieval. A stateless, tool-free selector can choose known passage identifiers, but its prose is never displayed or saved. The server always includes the saved citation, may add validated nearby passages, and renders literal quotations with their source edition and page labels. Governing section scope, equipment applicability, and whether the applicant's drawing passes remain unconfirmed. Invalid model output returns a fixed source-first response, not a second general-agent attempt. Clearing a finding restores ordinary routing in a fresh conversational context so previous finding answers are not reused as evidence. This change does not select a different model or change Eve rollout controls. Selected-packet metadata still comes from the current browser session and active organization, including visible teammate attachments. A denied lookup remains unavailable rather than falling back to personal File Library totals. Saved-finding selection is console-only; it creates no authentication bridge or new source access for Slack, Teams, public API, MCP, or CLI credentials. The web adapter authenticates the session and organization before consuming the request. It rejects serialized chat bodies over 256 KiB before JSON parsing; invalid JSON and non-object bodies stop at the adapter, so oversized transcripts cannot reach the shared chatbot core. The in-app assistant at `/assistant` provides the richest experience: - Real-time text streaming with sentence-boundary buffering - Tool call visibility (expandable sections showing what the AI is doing) - Reasoning display (thinking blocks) - Attachment UI support (PDF, JSON). Attachments can be selected in the chat UI, but the `/assistant` page does not yet process uploaded files for analysis in that surface. - Session metadata for conversation continuity ### Slack Bot The GridWonk Slack app provides: - Threaded conversations with multi-turn context - Native processing status in Agent View; threaded replies can update a progress message into the final answer, while root direct messages post one final message - Citations listed under **Sources** at the end of the reply - Error messages formatted as blockquotes. If a turn half-answered and then failed, the partial answer is kept and marked incomplete rather than discarded — and a turn that failed having said nothing shows the reason alone, without claiming an answer was cut short. A failed turn always carries a reason; a blank explanation is replaced with a generic one rather than shown empty. The same holds when the connection behind a turn drops rather than the turn reporting a failure: text the assistant had already composed but not yet posted is still delivered, along with any citations it had gathered, instead of being lost with the connection - Rate limiting per user - Slash commands including `/gk help`, `/gk requirements`, `/gk status`, `/gk context`, and the feature-gated `/gk research`, `/gk research status`, and `/gk research stop` `/gk status` links to the console for validation job monitoring; it is not a native Slack job list. The Slack transport and the Teams transport use the same Chat SDK `4.41.1` release train. GridWonk keeps `chat`, the Slack adapter, the Redis state adapter, and the Teams adapter pinned to that exact version together. The repository also carries a versioned product-bot manifest for Slack Agent View, but publishing that manifest is a separate maintenance-window action; merging or deploying the application does not irreversibly switch the Slack app to Agent View. When Agent View is enabled, the Slack adapter supplies native session status, automatic titles, stop handling, app-home/context lifecycle events, and cross-instance turn cancellation through its Redis state. GridWonk passes the SDK turn cancellation signal into the shared chatbot core. Thread context comes from the SDK transcript instead of Slack channel history because Agent View direct message history exposes only the user's side. The custom uninstall event remains responsible for deleting the adapter installation and marking the organization installation inactive. Organization administrators can separately enable **Assistant skill sets** and assign versioned instruction bundles for interconnection research, project coordination, or deficiency review. The Slack adapter resolves those audited organization assignments and supplies them as trusted prompt guidance. A bundle never adds a tool, widens data access, or bypasses an ordinary authorization or confirmation check. Other transports do not accept client-selected bundles. When **Deep Research** is enabled for the organization, `/gk research` starts a bounded durable workflow. The default lane searches only current procedure sources that back published packet-review requirements for a release-switched utility. Organization-private documents are searched only when the user explicitly selects that lane. Paid web search is also explicit and remains disabled for customer organizations. Every lane fails closed when its source is unavailable. Slack returns a durable, organization-scoped report link with citations, while `status` and `stop` inspect or request cancellation of the user's run. The workflow checks its durable cancellation marker between collection and synthesis steps. Slack installation callbacks consume signed state once and re-check the current approved platform administrator before storing a workspace mapping, so copied or stale callbacks cannot replay an older installation authorization. Direct-message replies that finish after the webhook response recover Slack's raw `D…` channel ID from the signed event or encoded thread ID, reload that event's workspace installation, and bind its bot token before posting. This keeps delayed answers on the correct organization's Slack connection even after request-local credential context has ended, without leaking Chat SDK's `slack:D…` thread encoding into Slack's channel API. **Installation:** An organization admin connects their own workspace from the workspace **Features** page, or a platform admin installs it via the "Add to Slack" button on `/admin/integrations`; both start the same OAuth flow for the active organization, and the callback returns each to the page the flow started from. A workspace already connected to a different organization is refused for org admins — only a platform admin can move a workspace between organizations. The OAuth callback at `app/api/chat-sdk/slack/callback/route.ts` stores the workspace bot token in Redis and provisions a `chat_platform_installations` record mapping the Slack workspace to a GridWonk organization. Both records are required for replies, so reauthorizing from `/admin/integrations` restores them together. Mention the installed **GridWonk** app in a channel, or message it directly. Follow-up messages in the same thread continue the conversation. See [Set up and use GridWonk in Slack](/docs-site/integrations/slack) for the complete administrator and member walkthrough. **User linking:** Slack users must be linked to a GridWonk account. The auth bridge (`lib/chat-sdk/auth-bridge.ts`) resolves Slack workspace IDs → GridWonk organizations and Slack user IDs → GridWonk user accounts via `chat_platform_installations` and `chat_user_mappings` tables. Unlinked users receive a sign-up/link prompt directing them to `/chat/slack/link`. For ordinary Slack access, the linked account must have an active, unexpired organization membership. Revoked or expired memberships are denied even when the account retains a platform-admin role. ### Public API The `POST /api/v1/agents/chat` endpoint provides (citations require `includeSources: true`): - SSE streaming for real-time responses - Full orchestration pipeline (FAQ, classification, routing) - Session continuity via `sessionId` - Structured event types (`content`, `usage`, `tool_use`, `tool_result`, `complete`, `error`, and `source` when opted in) - Completion diagnostics that include `directToolName` when a direct tool fast path answered without a model-backed tool event When an API client disconnects, the streaming adapter closes the upstream chatbot iterator as well; the turn can therefore release its session and lease promptly rather than waiting for timeout. The close takes effect at the turn's next pause point, so a request already in flight finishes before the release — prompt, not instant. Every other channel gets this for free, because each drains its turn with a loop that closes the stream on the way out; the API lane is the one that had to ask. See [Chat Streaming API](/docs-site/api/chat) for full endpoint documentation. ### MCP The hosted MCP gateway exposes a `chat` tool that runs the same pipeline. Unlike the streaming channels it returns a **single buffered result**, so a long answer arrives all at once rather than progressively. The result carries the answer's citations both inline (a **Sources** list at the end of the text) and structurally on `sources`, plus the tools the turn ran on `tools`. ### CLI `gridwonk agents chat` routes through the public API endpoint and renders the SSE stream in your terminal. It carries its own channel label, so CLI usage is distinguishable from other API traffic in your organization's analytics. The CLI opts into citation frames: human-readable output appends a de-duplicated **Sources** list, while `--json` emits the structured `source` events as NDJSON. ### Microsoft Teams The Teams channel is shipped and account-controlled. The feature defaults to on for every organization; an organization admin can turn it off from **Features**, and a platform admin can force it on or off from the organization detail page. GridWonk operates one single-tenant Azure Bot and requires its app ID, client secret, and home-tenant ID before registering the Teams webhook. An organization administrator starts a customer connection from GridWonk. The server creates a random Redis-backed code that expires after 10 minutes and opens a personal bot chat with `connect ` prefilled. The bot accepts that command only in a 1:1 chat, consumes the code once, and reads the Microsoft tenant ID from the signed Teams activity. It then returns a browser confirmation that works only for the same signed-in GridWonk user. Confirmation rechecks current organization-admin authority and the Teams feature before atomically creating the tenant mapping and linking that Teams user. Expired or replayed codes, Redis failures, missing tenant IDs, and cross-organization tenant conflicts fail closed; only a current GridWonk platform administrator may resolve a tenant reassignment. From the workspace **Features** page, the customer-facing flow has two steps: install GridWonk from the Teams Store, then open the generated private bot chat and send the one-time connection command. The same page shows the connected tenant and lets an organization administrator disconnect or reactivate it. Customers do not supply Azure credentials; GridWonk owns the bot registration and Store app. After connection, @mention the bot in a channel or message it 1:1. Each additional person links their own Teams identity to their GridWonk account through a separate one-time secure link before the assistant answers them. Teams replies arrive as single messages (no in-place streaming status), and each person keeps their own conversation memory across follow-up turns. In shared channel threads, session keys include the Teams user id and stored thread state is reused only for the same author, so one member cannot inherit another member's session or selected work context. The same organization scoping, identity, and audit rules apply as on Slack. ## Who can see internal documentation Most documentation is public to signed-in users. A small set of internal pages is restricted to GridWonk platform staff, and that restriction is applied per request on every channel — never inherited from where the question was asked. | Channel | Internal docs reachable by | |---|---| | Web app | A platform administrator working natively in the GridWonk organization. Administrators impersonating a customer see exactly what that customer sees. | | Slack | A Slack user who has **linked** their account and is a platform administrator | | Microsoft Teams | A Teams user who has **linked** their account and is a platform administrator | | Public API / CLI / MCP | Not by default. An API key is a weaker credential than a signed-in session, so keys do not inherit their creator's internal access unless the deployment explicitly opts in. Acting on behalf of another user never grants you their access. | Everyone else — including every customer organization on every channel — receives public documentation only, and a test API key never receives internal documentation at all. ## Operational Verification 1. Send the same query to web chat and Slack — verify matching routing decisions in logs 2. Ask a canonical FAQ question — all channels should return the same instant response 3. Check session analytics — `executionMode`, `taskCategory`, and `routingReason` should be consistent 4. Trigger a direct-model failure before output — verify one Eve recovery attempt and no `agent_sdk` execution record 5. Ask the same documentation question on every enabled channel — final text, citations, and completion metadata should match, whichever lane answered 6. Confirm an unlinked Slack user is prompted to link rather than answered, and that a non-admin cannot retrieve internal documentation on any channel 7. From an unconnected Microsoft tenant, confirm an ordinary question cannot reach product data and only a private `connect ` command can begin tenant setup --- # CLI Command-line interface for GridWonk API operations, built for humans and AI agents. URL: /docs-site/integrations/cli last-updated: "2026-10-27" --- Project capacity remains megawatts for `--capacity-mw`; the console's new kW/MW selector does not change CLI units. Partial document reports and direct site-plan Attach DWG are console views, not new CLI operations. Prompt inspection is read-only: `prompts list` and `prompts diff` remain; snapshot, activate and rollback commands are removed. Prompt changes require reviewed Git changes and separately authorized database activation. Repository `eval:check`, `eval:compare` and `eval:verify` scripts are not packaged CLI commands and do not authorize paid execution or release acceptance. ## Overview The Salesforce installed application's Layer 2 packet-submission source adds no GridWonk CLI command. Salesforce will initiate its runtime requests over a separate signed API; the Salesforce CLI used by engineers for development and testing is not a runtime transport. The installed-app endpoint and processing remain disabled. The `optimize` command and `opt` alias, including status and list, are no longer available. Prompt history and evaluation commands remain. The `@gridwonk/cli` package provides the GridWonk command-line interface (CLI). The package scope is canonical; the executable command remains `gridwonk` during the binary naming transition. It is the command-line projection of the Canonical Capability Manifest, which is the source of truth for capability IDs, auth lanes, lifecycle, risk metadata, and surface identifiers. A projection is a surface-specific catalog of the same capability contract, not a separate source of truth. The manifest's operation-level bindings distinguish reads, writes, confirmation requirements, and optional OAuth scopes so a CLI command cannot imply broader authority than its shared capability operation. Guarded Codex-only administration is recorded separately from CLI authority: adding a read to the protected admin MCP catalog does not silently create a CLI command or grant impersonation, billing, or model-catalog write access. Protected document recovery follows the same boundary: `admin-document-recovery` adds no CLI or customer SDK command. Its human-operator preview/apply/status flow does not change the existing packet upload-retry commands or authorize paid recovery through a stored CLI key. The `review-application` capability's forced fresh-perception option is likewise console-only, limited to platform administrators on demo packets. It does not add a CLI command or broaden the partner packet review command. **Packet Owner Evidence** keeps the stable capability ID `packet-applicant-evidence`. Its human confirmations—including utility staff confirmations on their own editable packets—remain in the console, not CLI commands, SDK methods, REST writes, or MCP calls. The utility-owner repair does not broaden packet write credentials or introduce a developer invitation command. The CLI provides terminal access to the GridWonk API v1, session-backed admin workflows, and Model Context Protocol (MCP) gateway operations. It supports two output modes: an interactive [Ink](https://github.com/vadimdemedes/ink) terminal UI for human operators, and a `--json` flag for machine-readable output consumed by AI coding agents (Claude Code, Codex) and CI/CD pipelines. Most runtime commands use `@gridwonk/sdk`; browser login, bootstrap, and session-only helper commands call the matching GridWonk route APIs directly. SDK-backed commands inherit SDK retry logic, rate limiting, and error mapping. ### Canonical GridWonk host The CLI defaults to the canonical `https://gridwonk.com` API origin. An authenticated request therefore needs no base URL or trust override: ```bash gridwonk utilities list --state CA --json ``` Use `--base-url` only for an approved alternate environment. Custom origins also require `--allow-untrusted-base-url`. Exact legacy production hosts are accepted for compatibility and normalized to `https://gridwonk.com` before an authenticated request is sent. ## Quick Start ```bash # Install the CLI (requires GitHub Packages ~/.npmrc setup — see below) npm install -g @gridwonk/cli # Store your API key gridwonk auth login --api-key gw_live_YOUR_KEY # Inspect the locally configured credential source and effective host gridwonk whoami # Verify the credential with a real API read against the canonical GridWonk host gridwonk utilities list --state CA --json ``` The package installs **two** commands: `gridwonk`, the canonical one, and `gridboost`, the pre-rebrand name kept so existing scripts and aliases keep running. Both are the same launcher, so they behave identically — but help, usage, examples, and shell completions all speak `gridwonk`, and completions are registered for that name. ```bash # Legacy gb_live_/gb_test_ keys are no longer accepted; use gw_live_ or gw_test_ keys. # Query customer-released requirements against the canonical GridWonk host gridwonk requirements published --utility "nashville-electric-service" --json ``` > **GitHub Packages setup:** The `@gridwonk/cli` package is hosted on GitHub Packages. > Add the following to your `~/.npmrc` (one-time setup): > > ```ini > @gridwonk:registry=https://npm.pkg.github.com > //npm.pkg.github.com/:_authToken=ghp_YOUR_TOKEN > ``` > > Local installs require a GitHub personal access token **(classic)** with `read:packages` > scope and access to the package. See [GitHub's registry authentication guidance](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#authenticating-to-github-packages) > for local installation and GitHub Actions credential options. For human session-backed CLI access, use browser login: ```bash gridwonk auth login --browser gridwonk auth status --json gridwonk orgs list --json gridwonk orgs switch gridwonk auth connect --client codex --org ``` Browser-backed login is the baseline path for session-only mutations. Once you have a stored session and active org, the same terminal can execute high-risk writes that are intentionally blocked for API keys. The CLI acts as you, so browser login first asks you to accept any updated legal terms, then finishes the login. The CLI waits two minutes for the browser; if it times out while you review the terms, run `gridwonk auth login --browser` again and it finishes right away. If the terms change while you hold a session, `auth bootstrap-status` and `auth bootstrap-key` answer `403 FORBIDDEN` with reason `legal_acceptance_required` and a link to accept; other session commands are refused until you accept in the browser. For direct session-token fallback or agent handoff, the CLI still accepts an explicit session token: ```bash export GRIDWONK_SESSION_TOKEN=sb_... gridwonk auth connect --client codex gridwonk capabilities --json gridwonk orgs switch gridwonk admin models list --json ``` ## Authentication API keys are resolved in order of precedence: 1. `--api-key ` flag (highest priority) 2. `GRIDWONK_API_KEY` shell environment variable 3. Opted-in project `.env.local` (allowlisted keys only) 4. `~/.gridwonk/config.json` (stored via `gridwonk auth login`) Project `.env.local` loading is **opt-in only**. Supported keys: - `GRIDWONK_API_KEY` - `GRIDWONK_BASE_URL` The pre-rebrand `GRIDBOOST_*` variables and `~/.gridboost/config.json` are still read when their `GRIDWONK_*` / `~/.gridwonk` counterparts are absent, so an existing shell or CI job keeps working. The CLI prints a one-time deprecation warning; rename them when convenient. Setting a `GRIDWONK_*` variable to an empty string means "cleared" and does **not** fall back to the legacy name, project file, or stored config. Config writes always target `~/.gridwonk/config.json`; the first write carries forward fields read from a legacy-only config. A failed first write leaves the legacy config active, and `gridwonk config show` reports the file actually being read. `gridwonk auth logout` removes stored credentials from both locations. ```bash # CI/CD: use environment variable export GRIDWONK_API_KEY=gw_live_... gridwonk jobs list --json # Interactive: store API key locally gridwonk auth login # Opt-in project .env.local for one command gridwonk --project-env auth status # Opt-in project .env.local in automation GRIDWONK_ENABLE_PROJECT_ENV=1 gridwonk usage --json ``` The config directory is created with `0o700` permissions and the config file with `0o600` to protect stored credentials. Session-backed commands resolve auth in this order: 1. `--session-token ` flag 2. `GRIDWONK_SESSION_TOKEN` shell environment variable 3. `~/.gridwonk/config.json` (stored via `gridwonk auth login --browser` or `gridwonk auth login --session-token ...`) Session-only mutation commands reject API keys and point operators back to: ```bash gridwonk auth login --browser gridwonk auth connect --client codex gridwonk orgs switch ``` ## Global Options | Flag | Description | |------|-------------| | `--json` | Machine-readable JSON output (NDJSON for streams) | | `--api-key ` | Override stored/env API key | | `--session-token ` | Override stored/env session token | | `--base-url ` | Override the API base URL; the default is `https://gridwonk.com` | | `--org ` | Override active organization for operator or session-backed commands | | `--project-env` | Opt-in loading allowlisted CLI environment variables from `.env.local` | | `--show-secret` | Display raw secrets in human output when explicitly requested | | `--allow-untrusted-base-url` | Permit an approved custom origin outside the GridWonk, legacy compatibility, localhost, and project-owned Vercel allowlist | | `--dry-run` | Preview supported destructive actions without executing; support is command-specific | | `--yes` | Skip confirmation prompts for destructive operations | | `--no-color` | Disable ANSI colors | | `-v, --verbose` | Show request/response details | | `-q, --quiet` | Suppress non-essential output | ## Command Reference Every command listed here is covered by `npm run capabilities:contracts`: a capability whose `cli` binding is marked available must resolve to a registered command path, so this reference cannot silently drift from what the CLI actually ships. The active `packet-combined-split` capability remains console-only behind a server-side per-organization setting (the `COMBINED_SPLIT` dial merged with database rows that organization admins and platform admins manage). The manifest deliberately has no CLI binding for proposing, confirming, retrying, discarding, or materializing a split. Developers use **More actions → Split PDF** in the console for eligible PDFs, including those already assigned a document type or reviewed. The mixed-upload coordinator now binds through `packets intake-batches` (manifest operation family `utility-packet-intake.upload-batch`). It reserves, reads, heartbeats, pairs, cancels unstarted items, and abandons selections while preserving the existing intake identities. ZIP creation and recovery use `packets archive-intake`; standalone CAD upload still has no CLI create command. Applicant-owned inspected CAD items or archive children can be paired with `intake-batches pair`. The standalone native-CAD intake, visualization, and preflight capabilities have no CLI binding. The intake contract provides a partner REST route, while this layer has no command for uploading, downloading, viewing, or inspecting a DWG. Optional DWG companions are available for any utility through the existing console and partner REST intake; see [Upload](/docs-site/help/upload). The high-risk `admin-purge-empty-synthetic-projects` capability also has no CLI binding. It is limited to the protected GridWonk admin MCP preview/apply flow so it cannot become a general-purpose project deletion command. ### `projects` — Manage Developer Projects ```bash gridwonk projects list [--utility ] [--state ] [--limit ] [--offset ] gridwonk projects get gridwonk projects create --utility --name --capacity-mw \ --interconnection-level [--state ] \ [--declared-tier-slug ] --yes gridwonk projects update [--name ] [--capacity-mw ] \ [--state ] [--interconnection-level ] --yes ``` Create and update support `--dry-run` and explicit `--yes` confirmation. These commands manage real developer projects only; synthetic demo creation and project deletion are not customer CLI capabilities. `--declared-tier-slug ` declares the interconnection program (the API's `declaredTierSlug`) and is required when the utility publishes two or more programs for the chosen level (and refused otherwise). The API's refusal message lists the valid slugs, and `--json` output carries them under `error.details.programs` together with `error.reason` on `503` responses. `projects update` cannot change the declared program, and `--interconnection-level` is refused when the change would leave the project in a state creation would not have accepted: a project that declared a program is bound to its track, and an undeclared project cannot move onto a track where the utility publishes two or more programs. Create a new project with `--declared-tier-slug` instead. ### `auth` — Manage Authentication ```bash gridwonk auth login [--api-key ] # Store API key gridwonk auth login --browser # Browser-assisted session login gridwonk auth login --session-token # Store session token directly gridwonk auth connect --client codex # Validate key or session + show onboarding gridwonk auth logout # Remove stored credentials gridwonk auth status # Show current auth context gridwonk auth token [--expires-in ] # Exchange API key for JWT gridwonk auth bootstrap-status --org # Check first-key bootstrap eligibility gridwonk auth bootstrap-key --org --name "Initial Management Key" ``` `bootstrap-key` requires an explicit, nonblank `--org ` flag, either before or after the subcommand. It does not choose the target from stored configuration or environment variables. Use `--dry-run` to preview the target without making a network request. `bootstrap-status` and `bootstrap-key` return `403 FORBIDDEN` with reason `legal_acceptance_required` while your account has updated legal terms to accept; the error message includes the accept link. `bootstrap-status` reports `not_allowlisted` with the reason `API access is suspended for this organization` or `This organization is suspended` when a platform admin has suspended the organization's API and MCP access or the account is suspended; `bootstrap-key` is refused in the same state. Contact support to restore access. Utility and consultant organizations are allowlisted by default, so an owner or admin of either can bootstrap a first management key without a platform-admin step; developer organizations still report `not_allowlisted` until a platform admin enables their API profile. Utility owners and admins can also mint keys in the browser at `/utility/api-keys`. **`auth status --json` response:** ```json { "data": { "authenticated": true, "apiKeyAuthenticated": true, "sessionAuthenticated": true, "source": "config", "sessionSource": "env", "keyPrefix": "gw_live_ab...", "sessionPrefix": "sb_ab...", "baseUrl": "https://gridwonk.com", "organizationId": "org_123" } } ``` ### `capabilities` — Agent Discovery ```bash gridwonk capabilities --json # Machine-readable CLI catalog ``` `gridwonk capabilities --json` returns the CLI-specific agent discovery catalog from `packages/cli/src/capabilities.ts`. That catalog tells agents which CLI commands are useful, which auth lane they need, and whether JSON output is supported. It is a CLI projection of the Canonical Capability Manifest, not the canonical manifest itself. The manifest declares CLI bindings today; `npm run capabilities:contracts` verifies available manifest bindings against registered CLI command paths, while `npm run capabilities:surface-report` highlights broader CLI-only commands that may need manifest bindings or reduction decisions. ### `orgs` — Session Organization Context ```bash gridwonk orgs list # List accessible orgs gridwonk orgs get # Get org detail gridwonk orgs switch # Persist active org for session commands ``` ### `notifications` — User Inbox ```bash gridwonk notifications list gridwonk notifications read gridwonk notifications read-all gridwonk notifications dismiss ``` ### `feedback` — Discovery Feedback ```bash gridwonk feedback list gridwonk feedback summary gridwonk feedback submit-document --document-id --type document_incorrect ``` ### `remediation` — Working Copies And Export Bundles ```bash gridwonk remediation draft get --document-id gridwonk remediation draft patch --document-id --span-id --text "Updated language" gridwonk remediation export create --document-id gridwonk remediation export get --export-id --json ``` The remediation commands read working-copy spans, patch an edited span after mutation confirmation, create clean/redline/evidence export bundles, and fetch export status plus artifact URLs. ### `admin models` — Platform Model Management ```bash gridwonk admin models list gridwonk admin models assign --agent-id --task-category --model provider:model gridwonk admin models catalog gridwonk admin models lifecycle ``` ### `admin utilities` — Internal Review Queues ```bash gridwonk admin utilities list gridwonk admin utilities get gridwonk admin utilities url-reviews list gridwonk --org admin utilities url-reviews approve --utility-id gridwonk --org admin utilities url-reviews reject --utility-id gridwonk admin utilities delete gridwonk admin utilities url-reviews stats gridwonk admin utilities discovery-reviews list gridwonk admin utilities discovery-reviews get gridwonk admin utilities digitization-reviews list gridwonk admin utilities digitization-reviews get gridwonk admin utilities published-requirement-reviews list gridwonk admin utilities published-requirement-reviews list --review-status needs-review gridwonk admin utilities published-requirement-reviews stats ``` These commands summarize the published Packet Intake review catalog. Open `/admin/requirements-review` to approve, reject, or refine an individual requirement. `--review-status` accepts `ready`, `needs-review`, `changed`, `blocked`, or `evidence-only`, and filters server-side. Omit it to list every requirement set in scope. Both commands are scoped by `--org` the same way the other operator review commands are. `admin utilities delete` refuses roster-managed utilities (rows the utility roster catalog matches) with HTTP 409 — remove them via the `domains/utilities` publish flow instead (ADR-068). ### Session-Only Mutation Examples Workspace appearance is selected in **Team and logo > Workspace appearance** using the local preview and **Save appearance**. The session-authorized browser route does not create a CLI or SDK appearance command; existing organization branding administration remains separately scoped. ```bash gridwonk --org changes subscriptions create --utility pge --state CA --json gridwonk --org changes subscriptions delete --json gridwonk admin users update --role admin --json gridwonk admin users bulk-reject --ids , --reason "Missing verification" --json gridwonk admin orgs impersonate start --reason "Support escalation follow-up" --json gridwonk admin orgs billing-override set --reason "Contract grace period" --json gridwonk admin chatbot presets apply --preset-id --json gridwonk admin chatbot capabilities update --payload '{"capabilities":[{"id":"cap-id","enabled":false}]}' --json gridwonk admin chatbot mcp-servers update --payload '{"enabled":false}' --json ``` ### `admin users` — Platform User Operations ```bash gridwonk admin users list gridwonk admin users get gridwonk admin users update [--action approve|reject] [--rejection-reason ] [--role user|admin] gridwonk admin users deactivate gridwonk admin users reinvite gridwonk admin users reset-password gridwonk admin users bulk-approve --ids , gridwonk admin users bulk-reject --ids , --reason "" ``` ### `admin orgs` — Organization Admin Operations ```bash gridwonk admin orgs list gridwonk admin orgs get gridwonk admin orgs members list gridwonk admin orgs grants list gridwonk admin orgs impersonation-audit [--organization-id ] gridwonk admin orgs impersonate start --reason "" gridwonk admin orgs impersonate stop [--organization-id ] gridwonk admin orgs billing-override set --reason "" [--expires-at ] gridwonk admin orgs billing-override clear ``` ### `admin monitoring` — Benchmark And Session Ops ```bash gridwonk admin monitoring performance trends --agent-id gridwonk admin monitoring performance agent gridwonk admin monitoring sessions list [--utility ] [--status ] gridwonk admin monitoring diagnosis-check [--yes] [--dry-run] [--json] ``` The diagnosis check requires platform-admin authority and explicit approval to send a synthetic system incident to the configured operational Slack channel and reserve at most $0.10 for its private-queue AI assessment. Without `--yes`, the command asks for confirmation; `--dry-run` sends nothing. Only one attempt is allowed per 24 hours across operators and deployments. No customer data or prompt is accepted. A queued result does not prove inference or Slack delivery; verify the matching incident ID and completion log. With the operational Slack bot configured, the assessment is a reply beneath the original synthetic alert; it does not request Claude triage. Native Vercel Agent billing is separate. ### `admin chatbot` — Chatbot Runtime Administration ```bash gridwonk admin chatbot access-rules list gridwonk admin chatbot access-rules create --payload '' gridwonk admin chatbot access-rules update --payload '' gridwonk admin chatbot access-rules delete --ids , gridwonk admin chatbot tools list gridwonk admin chatbot tools create --payload '' gridwonk admin chatbot tools update --payload '' gridwonk admin chatbot mcp-servers list gridwonk admin chatbot mcp-servers get gridwonk admin chatbot mcp-servers update --payload '' gridwonk admin chatbot presets list gridwonk admin chatbot presets create --payload '' gridwonk admin chatbot presets update --payload '' gridwonk admin chatbot presets delete --ids , gridwonk admin chatbot presets apply --preset-id gridwonk admin chatbot capabilities get [--category ] gridwonk admin chatbot capabilities update --payload '' gridwonk admin chatbot ai-elements get gridwonk admin chatbot ai-elements update --payload '' gridwonk admin chatbot prompt-preview --utility ``` ### `changes` — Change Monitoring ```bash gridwonk --org changes subscriptions list gridwonk --org changes subscriptions create --utility [--state ] gridwonk --org changes subscriptions delete gridwonk --org changes status --utility [--state ] gridwonk --org changes events list [--utility ] [--state ] ``` ### `sessions` — Org Session Visibility ```bash gridwonk --org sessions list [--utility ] [--agent ] [--status ] ``` ### `utilities` — Utility Catalog ```bash gridwonk utilities match --name "Duke Energy" --state NC gridwonk utilities list --state CA --type iou gridwonk utilities search --query "municipal electric" ``` ### `docs` — Document Operations ```bash gridwonk docs classify --text "$(cat extracted-document.md)" gridwonk docs classify --file ./extracted-document.md gridwonk docs digitize --document-id [--table ] [--utility ] ``` `docs classify` accepts text or extracted markdown. It rejects PDFs directly; upload PDFs through packet intake (the `packets` commands), then classify the extracted text. The former `docs upload` command was removed with the legacy 3 MiB upload on 2026-09-30. Both `docs` commands are **deprecated** pre-packet compatibility adapters. They still work unchanged and are not scheduled for removal, but packet workflows use Storage-native intake and the pinned, authoritative role-decision flow instead. New integrations should target those rather than building on `docs classify` / `docs digitize`. ### `assist` — Low-Cost CLI Assistant ```bash gridwonk assist --prompt "Summarize Duke Energy NC site-control requirements" gridwonk assist --prompt "Answer from this context" --context ./requirements.md --stream ``` ### `ferc` — Utility Analytics Exports ```bash gridwonk --org ferc analytics [--start-date ] [--end-date ] gridwonk --org ferc export [--start-date ] [--end-date ] ``` ### `agents` — AI Agent Operations ```bash gridwonk agents list # List available agent IDs gridwonk agents chat --utility \ [--state ] [--message ] \ [--session-id ] # Chat with an agent gridwonk agents execute --agent-id \ --utility --query \ [--state ] [--watch] # Execute a named agent ``` **Single-message mode** (non-interactive): ```bash gridwonk agents chat --utility "PG&E" \ --message "What docs do I need for 5MW solar?" --json ``` Human-readable responses append a de-duplicated **Sources** list when the answer has citations. With `--json`, the response is NDJSON — one JSON event per line from the SSE stream, including structured `source` events. **Interactive mode** (no `--message` flag) opens a full-screen Ink chat TUI with keyboard input and streaming responses. **Agent execution with `--watch`** streams job progress via SSE: ```bash gridwonk agents execute --agent-id procedures-discovery-agent \ --utility "Duke Energy" --query "Refresh procedure documents" --watch ``` ### `jobs` — Async Job Management ```bash gridwonk jobs list [--status ] \ [--type ] [--limit ] # List jobs (table UI) gridwonk jobs get # Job details gridwonk jobs cancel # Cancel a running job gridwonk jobs watch # Live SSE progress bar ``` Cancelling an authorized packet-review job also settles its linked active review and prevents late packet results without deleting completed document findings. It does not broaden the key's job-organization scope. A successful CLI cancellation is not proof that an already-running provider request stopped. Use the project's **Review Actions → Cancel Packet Review** control or ask support to confirm runtime-stop warnings before retrying a stuck packet. **Illustrative `jobs list` output:** Ink renders an auto-formatted table: ```text ┌──────────┬─────────────┬──────────┬──────────┐ │ ID │ Type │ Status │ Progress │ ├──────────┼─────────────┼──────────┼──────────┤ │ abc12345 │ compliance │ complete │ 100% │ │ def67890 │ discovery │ running │ 42% │ └──────────┴─────────────┴──────────┴──────────┘ ``` **`jobs watch`** provides a live progress bar and status updates powered by Server-Sent Events: ```bash gridwonk jobs watch abc12345 ``` With `--json`, the stream is output as NDJSON: ```bash gridwonk jobs watch abc12345 --json # {"type":"job.update","data":{"status":"running","progress":42}} # {"type":"job.update","data":{"status":"running","progress":85}} # {"type":"job.complete","data":{"status":"complete","progress":100}} ``` ### `webhooks` — Webhook Subscriptions ```bash gridwonk webhooks list # List subscriptions gridwonk webhooks get # Details + delivery attempts gridwonk webhooks create --url \ [--events ] [--secret ] # Create subscription gridwonk webhooks update \ [--url ] [--events ] \ [--active ] # Update subscription gridwonk webhooks delete # Delete subscription ``` Webhook secrets are masked in terminal output (only last 4 characters shown). The existing `--events` option also accepts the five `utility.*` families documented in [Webhooks](/docs-site/integrations/webhooks#utility-events). Their schema activation and production release remain separately held. Subscription management still requires the existing management-key authority, and utility events are scoped to the receiving utility organization. Subscribing does not grant notice-sending or human-decision permission. There is no new CLI command for provider receipts or resetting an exhausted utility-event delivery. ### `keys` — API Key Management ```bash gridwonk keys list [--status ] # List org API keys gridwonk keys create --name \ [--env ] [--rpm ] # Create a new key gridwonk keys get # Key details gridwonk keys update \ [--name ] [--status ] [--rpm ] # Update key gridwonk keys revoke # Permanently revoke key ``` | Subcommand | Description | |------------|-------------| | `list` | List API keys for the authenticated organization. Filter by `--status` (active, suspended, revoked). | | `create` | Create a new API key. The plaintext key is shown **once** — store it securely. | | `get` | Show key details including usage stats and rate limits. | | `update` | Update key name, status (active/suspended), or rate limit. | | `revoke` | Permanently revoke a key. Cannot be undone. Self-revoke is blocked. | `keys update --allowed-endpoints ` accepts a comma-separated list. It trims entries, removes empty entries between commas, and preserves order and duplicates. Omitting the option or passing `--allowed-endpoints ""` leaves `allowedEndpoints` out of the request. Whitespace-only or comma-only input sends an explicit empty list (`allowedEndpoints: []`); it is not equivalent to omission. Use `keys update --dry-run --json` with the key ID and proposed options to inspect the parsed settings before confirming a change. Existing access requirements are unchanged. **Example — create and list keys:** ```bash $ gridwonk keys create --name "CI Pipeline" --env test --rpm 120 Key created: gw_test_... WARNING: Store this key securely. It will not be shown again. $ gridwonk keys list --status active --json {"data":{"keys":[...],"total":3}} ``` ### `apps` — Application Queries ```bash gridwonk apps query [--utility ] \ [--status ] [--limit ] \ [--include-reports] # Query applications ``` ### `requirements` — Utility Requirements ```bash gridwonk requirements published --utility \ [--state ] \ [--category ] \ [--ix-type ] \ [--limit ] [--offset ] # Query published requirements ``` Categories: `site_control`, `technical_specs`, `forms`, `fees` #### `requirements published` The current command. It wraps the SDK `queryPublishedRequirements()` method, which calls `GET /api/v1/published-requirements`, and prints the response `summary` followed by each requirement with its cited sources. `--limit` accepts 1-200 (default 50); when more rows remain, the renderer tells you to page with `--offset`. The capability manifest assigns both this replacement command and the console Requirements view to `published-requirements`; the legacy capability no longer claims the UI destination. Coverage is everything published except utility-rejected rows, with honest gaps: - **The utility name is not fuzzy-resolved.** This command sends your input straight through and lets the server resolve it exactly (name, then canonical slug). An unknown utility returns an honest empty result rather than a guessed neighbour. - **Only utility-rejected rows are omitted.** Every other published row is returned. With `--json`, each row carries `reviewStatus`: `approved` (utility reviewers signed off) or `pending` (awaiting a current utility decision). In the human-readable output, pending rows are marked `[pending utility review]`. A decision made stale by a later change reverts that row to `pending`; it is never dropped. - With `--json`, `data.releaseStatus` (`released`, `partially_released`, `review_incomplete`, or `not_published`) reports the utility's review **progress**. It does not gate what comes back — a `review_incomplete` scope still returns its rows. - `--category fees` always returns an empty set — the published store has no fee role. - Rows whose published wording is still under review are withheld and reported in the summary. That is a separate mechanism from `reviewStatus`. ```bash gridwonk requirements published --utility "nashville-electric-service" --state TN --category forms --json ``` The old `requirements query` and `requirements list` aliases have been removed. Existing scripts must migrate to `requirements published`. ### `deficiencies` — Deficiency Reports ```bash gridwonk deficiencies query \ [--utility ] [--severity ] \ [--status ] [--location-status ] \ [--finding-state ] [--remediation-status ] [--include-anchors] \ [--limit ] # Query deficiency reports ``` Severity levels: `critical`, `high`, `medium`, `low` `--status` is a backward-compatible alias that accepts either location states (`exact`, `approximate`, `unresolved`, `pending`) or remediation states (`open`, `in_progress`, `pending_revalidation`, `resolved`, `wont_fix`). Use `--include-anchors` when you need source and working-copy anchor details. ### `usage` — API Usage Statistics ```bash gridwonk usage [--days ] # Default: 30 days ``` ### `mcp` — MCP Protocol Operations ```bash gridwonk mcp tools # List available MCP tools gridwonk mcp call --method \ [--params ] # Call MCP JSON-RPC method ``` **Example — query published requirements via MCP:** ```bash gridwonk mcp call --method tools/call \ --params '{"name":"query_published_requirements","arguments":{"utility":"nashville-electric-service","state":"TN"}}' ``` The MCP commands reach the same public MCP gateway described in [MCP Servers](/docs-site/integrations/mcp-servers). The CLI does not own MCP tool definitions; it lists and calls the current gateway projection, which is backed by `lib/mcp/public-tool-definitions.ts` and checked against the Canonical Capability Manifest. `query_published_requirements` therefore behaves exactly like `gridwonk requirements published`, including the all-except-rejected rule and per-row `reviewStatus`. The old public MCP `query_requirements` tool has been removed. The internal chat-runtime tool that shares its short name is separate and always reads published Packet Intake requirements — see [Requirement Lookups](/docs-site/integrations/mcp-servers#requirement-lookups). ### `prompts` — Prompt Inspection and History ```bash gridwonk prompts list [--agent ] \ [--status ] # List prompt versions gridwonk prompts diff # Show diff between versions ``` The former write commands are not registered and make no API request. Read authentication and historical source labels remain unchanged. ### `evals` — Evaluation Runs Run dispatch currently accepts only the checked-in deterministic location and digitizer Markdown datasets. An optional path must equal that agent's registered path; arbitrary paths are rejected. Paid chatbot runs are unavailable until immutable target reconstruction and server-owned spending approval exist. Stored or copied approval fields do not authorize a run. History/report remain readable. ```bash gridwonk evals list [--agent ] \ [--status ] # List eval runs gridwonk evals run --agent \ [--dataset ] # Trigger an eval run gridwonk evals report # Show eval run details ``` ### `config` — CLI Configuration ```bash gridwonk config show # Display config (keys masked) gridwonk config set # Set apiKey or baseUrl gridwonk config unset # Remove a config value gridwonk config path # Show config file location ``` ### `whoami` — Authentication Context ```bash gridwonk whoami # Inspect local auth state + key source; no API request ``` **Illustrative output:** The base URL is the effective locally configured API origin. Run a read command such as `utilities list --state CA --json` to verify the credential with the server. ```text Authenticated Key: gw_...cdef Source: config Base URL: ``` ### `completion` — Shell Completions ```bash # Bash eval "$(gridwonk completion bash)" # Zsh (add to .zshrc) eval "$(gridwonk completion zsh)" # Fish gridwonk completion fish | source ``` ## Command Aliases | Full Command | Alias | |-------------|-------| | `requirements` | `req` | | `deficiencies` | `def` | | `utilities` | `util` | | `remediation` | `rem` | | `webhooks` | `wh` | Aliases can be used anywhere the full command name is accepted: ```bash gridwonk req published --utility "nashville-electric-service" # same as: gridwonk requirements published gridwonk def query --severity high # same as: gridwonk deficiencies query gridwonk rem export create # same as: gridwonk remediation export create ``` ## Exit Codes | Code | Meaning | SDK Error Class | |------|---------|-----------------| | 0 | Success | — | | 1 | General error | `Error` | | 2 | Authentication error | `AuthenticationError` | | 3 | Not found | `NotFoundError` | | 4 | Rate limited | `RateLimitError` | | 5 | Server error | `GridWonkError` (status >= 500) | ## AI Agent Integration The `--json` flag makes every command consumable by AI coding agents. Combined with exit codes, the CLI becomes structured tooling for automated pipelines. This runnable document pipeline requires an authenticated CLI, `jq`, and the id of a document that already exists in a packet (upload it through packet intake first): ```bash GRIDWONK_CLI=(gridwonk) DIGITIZE_JSON="$("${GRIDWONK_CLI[@]}" docs digitize \ --document-id "$DOCUMENT_ID" \ --json)" printf '%s' "$DIGITIZE_JSON" | jq -er '.data | {success, alreadyDigitized}' ``` Application session IDs are not document IDs. Query applications as a separate read-only pipeline, using a supported status such as `active`: ```bash gridwonk apps query --utility "PJM" --status active --json | \ jq -r '.data.applications[].id' ``` Streaming commands (`agents chat`, `jobs watch`) output NDJSON when `--json` is set — one JSON object per line, suitable for incremental parsing. ## Binary Distribution The CLI can also be installed as a standalone binary (no Node.js required). The `bun compile` build produces a single-file `gridwonk` executable for each platform. **GitHub Releases:** Automated via `.github/workflows/cli-release.yml`. Each release publishes binaries for macOS (arm64, x64) and Linux (x64). ```bash # Download and install (macOS arm64 example) curl -L https://github.com/GridWonk/gridwonk/releases/latest/download/gridwonk-darwin-arm64 -o gridwonk chmod +x gridwonk sudo mv gridwonk /usr/local/bin/ ``` The binary bundles all dependencies — the SDK, Ink UI, and Commander CLI framework — into a single executable. No `npm install` or GitHub Packages token is required. ## Related - [API Overview](/docs-site/api/overview) — REST API reference - [MCP Servers](/docs-site/integrations/mcp-servers) — MCP tool integration - [Webhooks](/docs-site/integrations/webhooks) — Event-driven notifications - [Authentication](/docs-site/api/authentication) — API key and OAuth 2.0 ## `gridwonk packets` (partner lane) Partner packet intake and review. Every command requires a **partner-scoped access token** (`POST /api/v1/oauth/token` with `scope=partner.read partner.write`) passed as the API key — raw operator keys are refused on these endpoints. | Command | Description | |---|---| | `packets intake create` | Create a Storage-native intake and receive upload authorization (`--submission`, `--idempotency-key`, `--file-name`, `--mime-type`, `--size-bytes`; optional `--replace-document`, or both `--batch` and `--batch-item`) | | `packets intake finalize ` | Prove the uploaded object and start processing | | `packets intake status ` | Safe processing status projection | | `packets intake-batches reserve --submission --idempotency-key --source-kind --items ` | Reserve an immutable 1–12 item upload manifest; identical retries return the original batch | | `packets intake-batches status --submission ` | Read batch and item status | | `packets intake-batches heartbeat --submission ` | Extend an active batch's idle deadline | | `packets intake-batches pair --submission (--batch-item \|--archive-entry ) [--target-version ]` | Pair an inspected DWG item to a current site plan | | `packets intake-batches cancel-item --submission --item ` | Cancel one unfinished item | | `packets intake-batches abandon --submission ` | Abandon an unfinished batch | | `packets archive-intake create --submission --file-name packet.zip --size-bytes [--idempotency-key ] [--batch --batch-item ]` | Reserve a ZIP; a retry key is required without both batch identifiers | | `packets archive-intake status --submission ` | Read safe archive and entry progress | | `packets archive-intake finalize --submission ` | Finalize or resume processing using the same archive identity | | `packets archive-intake abandon --submission ` | Retire an archive still uploading | | `packets intake cancel ` | Cancel an unaccepted document upload | | `packets intake reauthorize ` | Create a new byte-zero upload attempt, keeping the intake ID | | `packets intake retry-processing ` | Retry accepted internal processing failures, up to three user cycles | | `packets documents list --submission ` | Documents with current roles and preserved classifier lineage | | `packets documents attach --submission ` | Attach an owner-organization File Library asset to an editable packet | | `packets documents delete --submission ` | Permanently delete a document from a draft or resubmission working set after confirmation | | `packets documents review --submission [--retry-failed]` | Start or reuse one exact document review (120/hour per user+org, plus the organization review budget) | | `packets documents text --submission --version-id ` | Sanitized OCR text + coordinates | | `packets documents set-role --role ` | Correct or explicitly confirm a content role; a correction re-runs the analysis applicable to that role | | `packets review start --submission ` | Start an applicant or eligible utility packet review through the shared review budget (50/hour per user+org); active, unexpired upload batches return HTTP 409 until settled, abandoned, or expired | | `packets review get --submission ` | Review run with the cited deficiency report, coverage, and recorded per-check outcomes | | `packets status --submission ` | Canonical workflow status + immutable packages | | `packets screening --submission ` | Utility-only package-bound screening status | | `packets documents pdf --submission --version-id [--package ]` | Short-lived signed URL for the accepted sanitized rendition (never the original upload); prints the typed preparing/unavailable status while the rendition is cold | All three document mutations use the standard confirmation prompt and accept `--yes` or `--dry-run`. Dry-run prints the planned request without contacting the server, so it does not prove authorization. Use `--retry-failed` only with `packets documents review`; the MCP review tool does not expose that option. ### `gridwonk utility` (utility partner lane) Utility draft creation and shape changes validate capacity before sending it: invalid numbers are refused by both direct commands and the interactive navigator. The API accepts capacities from `0.000001` through `99999999.999999` MW in whole-watt increments and returns `409` when an application number already belongs to the utility organization. A utility organization's partner-scoped token (`partner.read`) reads its own Applications workspace. The organization comes from the token; no flag selects another organization. Utility screening uses the existing `packets review start --submission ` command with `partner.write`; the server selects utility authority. It requires the utility cohort, matching utility identity, an eligible application stage, and current write membership. It cannot screen a developer draft or use a utility-issued consultant grant to enter the utility lane. For a formal application in `pending`, `queued`, or `resubmitted`, the command records `screening` together with the queued review before work is dispatched. Completion moves it to `screened`; a failed start or run restores the prior status when no other utility review is active. Console, REST, SDK, and MCP starts use these same transitions. Re-screening preserves existing decisions and notice states, and utility-owned drafts keep their package-freeze path. | Command | Purpose | |---|---| | `utility applications list [--query] [--screening-status] [--generation-type] [--min-capacity-mw] [--max-capacity-mw] [--sort-by] [--sort-order] [--limit] [--offset] [--include-drafts]` | The Applications queue with canonical workflow statuses | | `utility applications get --submission [--package ]` | One application with its package-bound detail (summary only, `package: null`, for a utility-owned draft) | | `utility applications packages --submission ` | Every immutable submitted package, newest first | | `utility applications findings --submission --package ` | The pinned review, report snapshot, adjudication ledger, and screening decision of one package | | `utility applications history --submission ` | The immutable application history | | `utility applications create [--application-number] [--project-name] [--capacity-mw] [--interconnection-level] [--program] [--request-key]` | Create one utility-owned draft (`partner.write`); a blank number is generated | | `utility applications batch-create --manifest [--request-key]` | Create a manifest of drafts in one retry-safe call (`partner.write`). Rows take the same fields as `create`; a row with an unknown or misspelled field, or without an `applicationNumber`, is refused before anything is sent | | `utility applications shape --submission [--capacity-mw] [--interconnection-level] [--declared-tier-slug \| --clear-declared-tier-slug]` | Set a utility-owned draft's capacity, level, and program (`partner.write`) | | `utility applications freeze --submission ` | Manually freeze an eligible utility-owned draft; returns the immutable package identity (`partner.write`) | | `utility adjudicate --submission --package --run --finding --decision --expected-version [--rationale ]` | Record `accept`, `dismiss`, `defer`, or `edit` against the exact latest package/run/finding; use version `0` for the first decision | | `utility screening complete --submission --package ` | Complete the exact latest package's screening; a repeat reports already complete, not project approval | | `utility study-requirement set --submission --scope-description --requirement-text [--case-reference ]` | Record a requirement for the next submission while the current screened round remains open | | `utility notices list --submission ` | Read notice summaries for the application (`partner.read`) | | `utility notices get --submission --notice ` | Read exact application-bound notice content and delivery progress (`partner.read`) | | `utility notices create --submission --package ` | Create a package-bound draft from current finding decisions (`partner.write`) | | `utility notices edit --submission --notice ` | Edit permitted draft/review content; finding provenance is server-owned (`partner.write`) | | `utility notices submit/approve/return/revoke/acknowledge --submission --notice ` | Perform the named lifecycle edge, never an arbitrary status assignment (`partner.write`) | | `utility notices send --submission --notice --recipient-email
` | Commit a send request using an eligible address on file (`partner.write`) | Mutations honor the global `--dry-run` and `--yes` flags. The notice commands are implemented in the dependent utility-notice stack; deployment and schema activation remain separate approvals. They require current direct utility membership, and writes require a writer role. A notice from a different application is refused even within the same organization. API send recipients must be the recorded applicant address or an active, unexpired owner/admin/member address in the applicant organization. No command lists contact addresses. Pending, held and provider-accepted delivery are reported separately from canonical notice status; none proves inbox delivery. A repeated finalized send or acknowledgment reports no change. See [notice contracts](/docs-site/api/utility-lane#package-bound-notices) before retrying. All four manual-decision commands require `partner.write` and a current utility writer role. They use the console's shared cores and are excluded from MCP. `--dry-run` makes no HTTP request and does not prove server authorization. Dismiss, defer, and edit require `--rationale`; an edit also requires one or more of `--edit-title`, `--edit-description`, `--edit-recommendation`, and `--edit-severity`. Refresh the package findings after a version conflict. Study requirements leave the existing frozen package and report unchanged. See the [utility lane guide](/docs-site/api/utility-lane) for lifecycle constraints and receipts. Salesforce has no dedicated CLI binding. The [connector is implemented but disabled](/docs-site/integrations/salesforce), and ordinary packet commands cannot recapture or edit source-owned evidence. Reads of those copies require the effective human viewer's current Salesforce permissions. If a utility queue query matches more than 200 Salesforce-owned applications, narrow its filters; lowering `--limit` alone does not reduce the permission-check candidate set. During a temporary Salesforce permission-check outage, `utility applications list` keeps ordinary and successfully authorized applications available and prints a partial-list/count warning. JSON output includes `salesforceReadUnavailable: true`; rows and `total` exclude unverified source applications. Retry the command to recheck live permissions. No old permission result is reused. The partner CLI can confirm or correct a role, but it does not expose the platform-admin aggregate that counts later human changes to automatic assignments. That measurement remains read-only and internal; it does not add a CLI activation switch. Combined-PDF splitting remains console-only. ZIP expansion uses `packets archive-intake` and the same owner checks and file limits as the [packet API](/docs-site/api/packets#zip-intake-and-recovery). Create prints short-lived upload authorization: keep that output private. Upload the bytes, then finalize. Retry a `503 WORKFLOW_START_FAILED` using the same archive or intake ID. Utility ZIP uploads accept PDF, PNG and JPEG; native CAD remains excluded. Mutations support `--dry-run` and require the normal confirmation or `--yes`. Native-CAD companion intake has no CLI binding. Use the console or partner REST routes so the exact site-plan version and direct binary upload authorization remain explicit. Interactive CAD visualization and preflight also remain console-only; the CLI receives neither native DWG bytes nor Autodesk viewer tokens. --- # MCP Servers Connect the public GridWonk plugin or maintain an approved organization integration. URL: /docs-site/integrations/mcp-servers description: Discover and use GridWonk MCP-compatible tools with stateful work-item continuity. last-updated: "2026-10-27" --- The public GridWonk plugin connects an AI client to your selected workspace. Start with the [customer MCP guide](/docs-site/api/mcp) and [Connected apps](/docs-site/help/connected-apps). The package needs neither an internal GridWonk account nor a private repository. ## Choose the right connection | Connection | Identity and scope | | --- | --- | | Public GridWonk plugin | Your verified user session, explicitly bound to one workspace in the browser | | Existing organization integration | Organization credentials provisioned for the agreed API/MCP profile | The catalogs differ. An integration key does not become a public-plugin user connection, and a public-plugin connection cannot access operator tools. Never copy credentials between them. ## Hosted runtime The endpoint is `https://gridwonk.com/api/v1/mcp`. Clients negotiate the supported protocol during initialization. Existing organization integrations use their returned transport session. The public plugin is stateless and reauthorizes its exact OAuth session on every call; it does not require a new MCP transport session after browser confirmation. Use the exact protected-resource metadata for interactive OAuth; do not substitute a machine-token issuer into a user sign-in flow. When interactive sign-in is enabled, resource discovery advertises only its identity scopes. Machine integrations discover `partner.read` and `partner.write` from their authorization server's `/.well-known/oauth-authorization-server` document. For the public plugin, complete the exact-session workspace confirmation when `connection_status` asks for it. Its customer tool list stays stable across activation. Ordinary calls need current membership, approval, role, and any required processing allowance. Revoke the existing connection and finish provider cleanup before signing in again to select another workspace. For an existing organization integration, follow [API authentication](/docs-site/api/authentication) and use its assigned credentials. An organization's API access and usage limits still apply. Only request operations shown by its credential-specific `tools/list` response. Caller-supplied organization, actor, project, or document identifiers do not grant authority. ## Working with packets Use supported intake tools and returned upload instructions. Follow job and review status with bounded polling, honoring `Retry-After`. Keep the same returned operation identity while recovering from a transport interruption; a lost response does not prove that work failed or that no cost was incurred. Unsupported or uncertain processing stops new work until it can be resolved. The server decides which source formats your workspace can process. If your workspace is limited to PDF review, use standalone PDFs: images, ZIP archives, and native CAD files are refused, including when attaching an existing File Library item or starting a review of an existing packet. A client cannot override that refusal. A PDF-only review does not waive the utility's required evidence. Keep the returned project, packet, upload, job, and review-run identifiers with the status or report they identify. When summarizing findings, preserve the report's source document and page citations. Use the existing identifiers to check interrupted work before starting another attempt; an upload receipt or completed document check is not a completed packet review. The public plugin supports research, authorized draft preparation, eligible intake/review starts, and status/results. Formal submission, document-role decisions, adjudication, notice sending, membership administration, and purchases remain website workflows. Read-only access does not start processing. Review completion does not mean utility approval. ## Discovery and troubleshooting Public help and the public plugin contract describe customer capabilities. Complete docs-host OpenAPI/MCP documents and the operator catalog require native internal authorization. Approved organization integrations can retrieve their separately authenticated API contract as described in the [API overview](/docs-site/api/overview). For connection problems, use [Connected apps](/docs-site/help/connected-apps). For payment or allowance status, use [trial and prepaid processing](/docs-site/help/processing). Never post access tokens, credentials, or signed upload URLs in a conversation or support transcript. ## Workspace appearance Organization admins preview and save source-palette color schemes in the signed-in website. Appearance discovery and saving have no public or Admin MCP mutation tool. Finding logo colors does not approve a logo for display. See [organization settings](/docs-site/help/organizations). --- # Integrations Overview Connect your AI agents and external tools to GridWonk. URL: /docs-site/integrations/overview ## Public plugin availability When the public rollout is enabled, install the [GridWonk plugin](/docs-site/api/mcp), sign in, and confirm one workspace in your browser. It exposes a curated customer catalog separate from existing organization integrations. Human decisions, membership changes, and purchases remain website workflows. Its transport is stateless: the server checks the exact OAuth session on every request, while the tool list stays stable before and after activation. Trial and prepaid workspaces use supported packet intake and reviews within their [processing allowances](/docs-site/help/processing). The broader integration capabilities below do not enable native DWG processing, legacy digitization, generic jobs, or unrestricted chat for those workspaces. GridWonk is built from the ground up to be used by AI agents and integrated into other platforms. ## 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. ## Integration Methods ### API Access Direct REST API access with raw organization API-key or OAuth JWT Bearer authentication and SSE streaming responses. The complete authenticated partner OpenAPI document covers every machine-credential operation (its remediation working-draft and export routes are documented as always-on since 2026-08-26). Its only omissions are the two session-only bootstrap routes and the authenticated route that serves the OpenAPI document itself. See the [API Reference](/docs-site/api/overview). Partner-scoped REST also includes DWG companion intake. Standalone CAD creation has no matching SDK, CLI, or MCP binding; use the documented `/api/v1/packets/cad-intake` routes directly. Batch reserve, status, heartbeat, pairing, item cancellation, and abandonment have all four bindings. CAD declarations and pairing remain applicant-only; ordinary document batches also support utility-owned drafts. ZIP create/status/finalize/abandon and individual document cancel/reauthorize/retry-processing also have REST, SDK, CLI, and MCP bindings. Utility ZIPs accept PDF, PNG and JPEG, and recovery retains the original archive or intake identity. See [Partner Packets](/docs-site/api/packets). File Library attachment and exact-document review use the same packet identity and authorization checks across REST, SDK, CLI, hosted MCP, and local MCP. Document deletion is deliberately absent from MCP; use the confirmed CLI command or REST/SDK binding while the packet is editable. The cohort is a server-side applicant-organization allowlist and is not tied to NES. Utilities gain automated drawing checks independently through reviewed CAD procedure profiles, so the same intake contract can serve more utilities without duplicating routes. The [utility lane](/docs-site/api/utility-lane) also exposes manual package freeze, finding adjudication, screening completion, and study requirements through REST, SDK, and confirmed CLI commands. These human decisions are excluded from MCP and the agent-facing OpenAPI projection. MCP may start authorized utility screening; it cannot make the utility's decision. Notice REST/SDK/CLI operations are now implemented, with current direct utility membership, named transitions, strict fields, and on-file recipients for send. MCP and the curated OpenAPI projection expose notice list/detail reads only. Delivery progress is separate from canonical `sent` status and inbox delivery. The dependent utility-event layer extends existing webhook subscriptions without giving a subscriber decision or send authority; schema activation, package publication, and production release remain separate gates. The app host builds a smaller curated OpenAPI document for `/openapi.json` and `/.well-known/openapi.json`. Anonymous publication is off, so both routes return 404 today. It contains the OAuth token exchange and only active partner packet operations that also have hosted MCP bindings. Each operation has a stable function-safe identifier, a named schema for every status it can return, and an exact `partner.read` or `partner.write` requirement. Its wording is written for partners rather than copied from the operator document, so it omits internal rollout gates, quota figures, and processing vendors — fetch the complete document when you need those. The public [developer guide](https://gridwonk.com/developers) and root `/llms.txt` explain when to use REST, MCP, CLI, or the human web workflow. Public integration requests are bounded before parsing. Oversized JSON, form, webhook, agent, or PDF payloads are rejected with safe client errors, and internal agent details are not echoed to external callers. PDF clients may send wrapped or URL-safe base64; the upload boundary normalizes it before validation. ### Session CLI Access Session-backed CLI access for user and admin workflows. This is the path for Claude Code, Codex, and similar coding agents that need full platform parity beyond the external API. ### MCP Server Discovery Machine-readable catalog of GridWonk's MCP tools at `/.well-known/mcp.json`. Fetching this catalog requires a docs session — it names every tool GridWonk exposes, so it is not served anonymously. At runtime, the gateway filters that catalog by credential. Organization API keys and scope-less tokens see broad tools; `partner.read` / `partner.write` OAuth tokens see only packet tools granted by those scopes. The same policy guards direct tool calls, so discovery cannot overstate authority. Standard OAuth metadata at `/.well-known/oauth-authorization-server` and `/.well-known/oauth-protected-resource` describes the live client-credentials flow and exact public MCP resource audience. Separately gated user-OAuth lanes add account sign-in with PKCE only after their own approved registration and activation. The admin MCP endpoint remains a separate operator lane: machine client-credentials tokens do not authorize it. Its user-OAuth lane requires its own client/audience and current administrator authority. Confirmed remote mutation pairs also require the separate remote mutation gate; that gate does not disable administrator read operations. Neither hosted MCP surface currently offers a standalone server-initiated event stream. An event-stream GET receives `405` even when the media type uses mixed letter case; normal JSON discovery GETs remain available. MCP clients should treat `405` as final rather than reconnecting. To connect Claude Code or OpenAI Codex, follow the [Claude Code and Codex Setup](/docs-site/integrations/agent-tools) guide. It provides separate least-privilege paths for external users and authorized internal operators. Developer project list, read, create, and editable-draft update operations share one tenant-scoped service across REST, SDK, CLI, and the broad MCP catalog. They use organization-key authority; fine-grained project OAuth scopes are not live. Requirement lookup is consistent across REST, SDK, CLI, and MCP integrations. The current lane (`/api/v1/published-requirements`, `queryPublishedRequirements()`, `gridwonk requirements published`, `query_published_requirements`) serves rows through one reader: every published row except the ones a utility reviewer explicitly rejected, with each row marked `reviewStatus: "approved"` or `reviewStatus: "pending"`. All four bindings return the same typed `releaseStatus` (`released`, `partially_released`, `review_incomplete`, or `not_published`), which reports utility-review progress rather than gating what is served, so unknown utilities and uncovered categories remain explicit rather than becoming a near miss. The legacy SDK, CLI, and MCP bindings have been removed. The old authenticated REST URL remains only as a permanent `410 Gone` notice that names `/api/v1/published-requirements` as its replacement. See [Requirements API](/docs-site/api/requirements). The root `/llms.txt` endpoint is a public marketing-content index and operating guide for AI agents. It inlines every public marketing page, including the Developers page, and links the developer guide, anonymous curated OpenAPI document, authenticated MCP endpoint, contact route, sitemap, and robots file. `/llms.txt` does not expose the protected docs corpus or the complete authenticated capability map. The negotiated Markdown twin for the public Developers page links directly to `/openapi.json`, so an agent requesting Markdown can move from the integration overview to the curated machine contract without guessing a discovery URL. Those public pages do not mount the account-settings or URL-state providers used by the authenticated dashboard. Their server-rendered HTML keeps the integration explanation and discovery links available to readers that do not run client-side JavaScript. ### Webhooks Event-driven notifications when jobs complete, jobs fail, or documents are digitized. The retired legacy requirements read no longer emits events, and published-requirements reads emit none. The legacy `deficiency.found` and `screening.complete` names remain reserved unless they appear inside a job completion payload. Five separate `utility.*` families describe actual human screening determinations, finding decisions, study requirements, package freezes, and canonical notice changes. They commit with the business change, preserve originating identity, and deliver in application order for each receiving-utility subscription. They require the separately approved utility-event release and do not backfill history. See [Webhook Integration Guide](/docs-site/integrations/webhooks#utility-events). ### Salesforce: implemented, not activated The [Salesforce utility connector](/docs-site/integrations/salesforce) implements source snapshots, four authenticated REST/MCP/SDK operations, current permission across captured history, and durable service-owned package freezing. It remains disabled pending sandbox acceptance and separate activation approval. Existing utility packet review commands do not enable Salesforce imports or delivery; the immutable package makes no queue/status, decision, or notice changes. ## Authentication Most external runtime integrations can use an organization API key directly or exchange that key for a short-lived OAuth bearer JWT. This runnable API-key request uses the direct form: ```bash curl -X GET https://gridwonk.com/api/v1/jobs \ -H "Authorization: Bearer gw_live_..." ``` Legacy `gb_live_`/`gb_test_` keys are no longer accepted. Use a `gw_live_...` or `gw_test_...` key. API keys and the OAuth tokens issued from them are organization-bound and enforce tenant isolation. Session-only bootstrap/OpenAPI routes and the client-credentials token exchange have separate authentication rules. 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` (`api_access_suspended` or `billing_suspended`). See [Authentication & Rate Limiting](/docs-site/api/authentication) for the full lane matrix, key management, rate limits, and security best practices. Use the credential lane documented by each integration. Internal workflow and docs-service calls use `WORKFLOW_INTERNAL_TOKEN`; scheduled-job `CRON_SECRET` values are not interchangeable with that service credential. Management keys own key lifecycle operations. Runtime keys can call allowed API endpoints but cannot create, update, or revoke keys. For CLI parity workflows, use a GridWonk user session token: ```bash export GRIDBOOST_SESSION_TOKEN=sb_... gridwonk auth connect --client codex gridwonk capabilities --json gridwonk orgs list --json ``` ## Machine-Readable Endpoints | Endpoint | Purpose | |----------|---------| | `/llms.txt` | Public product-level LLM context and agent instructions on the app host | | `/openapi.json` | Curated OpenAPI 3.1 projection on the app host; unpublished, returns 404 | | `/.well-known/openapi.json` | Same unpublished projection on the app host; complete specification on docs hosts behind the docs session | | `/api/v1/openapi.json` | Complete partner specification for raw API keys and scope-less OAuth JWTs | | `/.well-known/mcp.json` | MCP server discovery catalog on docs hosts, behind the docs session | The host matters: docs-host `/.well-known/openapi.json` and `/.well-known/mcp.json` routes sit behind the docs session, as do full docs search, raw docs reads, and protected docs pages. The app-host OpenAPI routes carry the curated projection and are currently unpublished, returning 404. Search and raw reads apply the active organization's effective audience, so customer and impersonated sessions cannot read internal pages. Every API or MCP operation described by public metadata still requires its documented Bearer credential. --- # PowerClerk Integration How GridWonk works alongside PowerClerk for AI-powered interconnection screening. URL: /docs-site/integrations/powerclerk The console's kW/MW selector does not change PowerClerk capacity mapping or ownership. Project capacity remains MW in storage; partial applicant reports do not represent a utility decision. # PowerClerk Integration GridWonk is designed to act as an **AI intelligence layer on top of PowerClerk** — not a replacement. The current codebase includes a typed PowerClerk API client, credential storage schema, field mapping schema, SDK fields for `powerclerk_sync`, and application query filters for external IDs. GridWonk keeps its own internal lifecycle as the canonical product model. PowerClerk status is stored as external provider data; the credential and field-mapping schema can carry per-program status mapping rules, but the current sync/write-back workers are still future integration work. The 2026-08-11 retirement of the SDK's legacy requirements success path does not change this integration: PowerClerk-linked application filters and fields are unchanged. Any integration that also needs requirement reads must use `queryPublishedRequirements()`. That also means PowerClerk does not replace GridWonk's org model: - GridWonk still uses one `organizations` table for utility, developer, consultant, and gridwonk orgs - shared submission rows still use utility ownership plus developer applicant linkage - PowerClerk contributes external provider state on top of that model This page separates what is implemented today from the approved target workflow. Do not assume a utility has active PowerClerk automation unless its credentials and mapping have been explicitly configured. ## Current Integration Surface | Area | Current Evidence | |---|---| | Typed API client | `lib/integrations/powerclerk/client.ts` | | PowerClerk entity types | `lib/integrations/powerclerk/types.ts` | | Encrypted credentials and field mappings | `lib/db/integration-schema.ts` | | Application linkage | `application_submissions.external_source`, `external_id`, and `intake_method='powerclerk_sync'` | | Implemented client calls | `getPrograms`, `getProjects`, `getForms`, `getFormSchema`, and project lookup by number | | Public API filtering | `/api/v1/applications/query` supports `external_source`, `external_id`, and `intake_method` filters | Project sync workers, attachment import, and write-back workers are future Gate 8 integration work. The current `/admin/integrations` UI manages platform-installed chat transports and API key counts; organization admins can connect their own Slack workspace and control Slack or Teams access from the workspace Features page. It does not yet provide PowerClerk credential entry, program selection, field mapping, or sync enablement. The separate [default-disabled Salesforce connector](/docs-site/integrations/salesforce) does not change this status. Its source snapshots, authorization, and delivery path do not implement PowerClerk sync or write-back. PowerClerk credentials, mappings, and client calls remain separate. The outbound-only Salesforce installed-app contract is also separate and hard-disabled. It adds no PowerClerk transport, credential, synchronization or write-back capability. Protected Admin document recovery also excludes source-managed projects, including PowerClerk. It does not add a PowerClerk retry endpoint, override source ownership, or implement attachment sync/write-back. Credentials, mappings, existing client calls and activation status remain unchanged. The service-only recovery database foundation does not activate sync workers or authorize customer replay. The optional Combined-PDF split is an internal GridWonk packet preparation step, not a PowerClerk status or attachment-sync contract. When enabled for the applicant organization (a server-side, per-organization setting), a confirmed split replaces the combined source with derived child documents only in GridWonk's current packet projections; it does not imply an external attachment upload or change PowerClerk ownership/status mapping. ## Coexistence Model GridWonk is designed to be **invisible to the end-user's daily workflow**. Utility engineers and developers stay in PowerClerk — GridWonk intelligence appears as data within their existing system. | GridWonk Provides | PowerClerk Provides | |---|---| | AI document validation and classification | No-code workflow builder | | Automated deficiency detection with citations | Multi-program management | | Readiness scoring (0-100, A-F grade) | Applicant portal and submission UI | | Cross-application deficiency analytics | Communication template engine | | FERC compliance reporting | Payment and incentive processing | | Change monitoring on utility requirements | DocuSign, Stripe, ArcGIS integrations | ## Target Data Flow ### Step 1: Discovery (One-Time Setup) When a utility connects their PowerClerk instance, GridWonk can discover the program structure with implemented client calls: - `GetPrograms()` — Identify the interconnection program - `GetForms()` — Find which forms contain site control attachments - `GetFormSchema()` — Discover attachment slots and data field IDs - `GetProjects()` and project lookup by number — inspect current project records This generates a stored field mapping configuration that translates between PowerClerk's dynamic form fields and GridWonk's standard schema. ### Step 2: Incremental Sync Target workflow: GridWonk polls PowerClerk at configurable intervals using `changed_since` for efficiency: - `GetProjects(changed_since=last_sync)` — Only new/modified projects - `GetProjectData()` — Structured metadata (capacity, generation type, location) - `Download Attachment()` — Site control PDFs (deeds, leases, easements) Imported data maps to GridWonk's `application_submissions` table with `external_source='powerclerk'`, `external_id` set to the PowerClerk ProjectId, and the PowerClerk status stored as external provider state. Directional status mapping belongs in the stored integration mapping configuration until a utility-specific sync worker is enabled. ### Step 3: AI Screening Imported applications are utility-owned rows, so **Screen Selected** on the utility queue starts one whole-packet review run in the utility lane per application (the same engine that reviews a developer's packet before submission): 1. **Digitization** — PDF to structured text 2. **Packet review** — Check against utility-specific effective-analysis requirements in `ix_packet_requirements`; this is separate from the utility's requirement review, which controls the per-row approved/pending labeling on the public requirements reference surfaces 3. **Deficiency detection** — Identify missing or non-compliant elements with page citations 4. **Findings** — Severity, citation, and page reference per finding. Automated review is switched on per utility; for a utility that has not yet been onboarded for automated review, Screen Selected reports that automated review is not yet available and leaves the rows unchanged. When an eligible formal application starts a utility review, GridWonk records **Screening** before work is dispatched and **Screened** on completion. A failed start or run restores the prior status once no other utility review is active. Authorized integration starts and the console use the same transitions. They preserve existing decisions and notices; utility-owned drafts keep their package-freeze path. These are GridWonk workflow states, not PowerClerk write-back or regulatory decisions. Results are bound to the imported document generation that produced them. If a later sync replaces the bytes, GridWonk hides the older findings and blocks notice drafting until the replacement has been screened; an approved future write-back worker must use those current-generation results. ### Step 4: Push Results Back Target workflow: after screening, an approved integration can write current packet-review results back to PowerClerk. It must use the result's current document generation: - `SetProjectData()` — Deficiency Count and other approved current-result metadata - `Upload Attachment()` — Deficiency report PDF - `SetAttachmentMetadata()` — Approve/Reject site control documents - `AddCommunication()` — Analysis summary email - `SetProjectStatus()` — Advance project status based on results ### Step 5: Follow-Up - `changed_since` polling detects resubmissions — auto re-screen with delta comparison - The developer response stage (`resubmission_under_development`) is internal GridWonk lifecycle state on the shared submission; it is not mapped to PowerClerk. Only the explicit write-back calls above change PowerClerk state - Change monitoring alerts when utility requirements are updated - Cross-application analytics identify deficiency patterns across the queue ## Compatibility Matrix | PowerClerk Entity | GridWonk Entity | Mapping | |---|---|---| | `ProjectId` | `application_submissions.external_id` | Stored with `external_source='powerclerk'` | | `ProjectNumber` | `application_submissions.application_number` | Direct mapping | | `ProjectOwner.Email` | `application_submissions.applicant_email` | Direct mapping | | `CurrentStatus.StatusId` / `CustomId` / `Name` | External status snapshot; optional future review-workflow mapping | Stored in provider metadata / `external_field_mappings.statusMapping` once configured | | `DataField (capacity)` | `application_submissions.capacity_mw` | Via `external_field_mappings.dataFields` | | `Attachment` | `ix_applicant_documents` | Downloaded and stored in Supabase Storage | | `Form` | `external_field_mappings.forms[]` | Schema discovery maps forms to document types | ## Authentication PowerClerk uses **OAuth 2.0 client credentials** with an additional `X-ApiKey` header. GridWonk stores encrypted credentials in the `integration_credentials` table, scoped to each utility organization. Credentials support both sandbox (`cleanpowerdemo.com`) and production (`powerclerk.com`) environments. ### GridWonk OAuth 2.0 GridWonk also provides its own OAuth 2.0 endpoint for programmatic access: ```bash # Exchange API key for a short-lived JWT curl -X POST https://gridwonk.com/api/v1/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials&client_id=gw_live_a1b2c3d4&client_secret=gw_live_..." ``` Legacy `gb_live_`/`gb_test_` keys are no longer accepted. Use a `gw_live_...` or `gw_test_...` key. Response: ```json { "access_token": "eyJ...", "token_type": "Bearer", "expires_in": 3600, "scope": "api:read api:write" } ``` The JWT bearer token can then be used on most organization-scoped API v1 runtime endpoints. Session-only bootstrap/OpenAPI routes and the token-exchange route itself follow their separate authentication lanes. ## Rate Limits | System | Limit | Strategy | |---|---|---| | PowerClerk API | 60 operations/minute | Client-side rate limiter with backoff | | GridWonk API | Per-key configurable (default 60/min) | Atomic counter with per-minute + daily caps | ## Setup Status Today, PowerClerk setup is an implementation/admin task, not a self-service Settings flow. Utilities should coordinate credential exchange, field mapping, and sync/write-back approval with GridWonk before any automation is enabled. ## SDK Usage `PowerClerkSyncClient` is an internal client for talking to PowerClerk. It is **not** the public `@gridwonk/sdk` `GridWonkClient` documented elsewhere in these docs, and it is unaffected by the public SDK's requirements-method deprecations. The public SDK defaults to `https://gridwonk.com`; the dedicated PowerClerk client still uses the configured PowerClerk sandbox or production base URL instead. The public SDK's `listProjects`, `getProject`, `createProject`, and `updateProject` methods manage GridWonk developer projects only; they do not activate a PowerClerk sync or write data back to it. ```typescript import { PowerClerkSyncClient, POWERCLERK_BASE_URLS, } from '@/lib/integrations/powerclerk'; const client = new PowerClerkSyncClient(); await client.configureSync({ provider: 'powerclerk', environment: 'sandbox', organizationId: 'your-org-id', pollIntervalSeconds: 300, clientId: 'your-client-id', clientSecret: 'your-client-secret', apiKey: 'your-api-key', agencyId: 'your-agency-id', programId: 'your-program-id', baseUrl: POWERCLERK_BASE_URLS.sandbox, }); // Test connection const connected = await client.testConnection(); // Discover programs const programs = await client.getPrograms(); // Inspect projects modified in the last hour const projects = await client.getProjects({ changed_since: new Date(Date.now() - 60 * 60 * 1000).toISOString(), }); ``` ## Endpoint Reference The current typed client implements the subset needed for discovery and read-side project inspection: | Endpoint | Method | Purpose | |---|---|---| | GetPrograms | GET | Program discovery | | GetProjects | GET | Project search and incremental reads | | GetProjectsByNumber | POST | Targeted project lookup | | GetForms | GET | Form discovery | | GetFormSchema | GET | Discover data model dynamically | Attachment import, status mapping, write-back, communications, and bulk sync are target workflows until their workers and utility-specific configuration are enabled. --- # Salesforce Utility Connector Credentialed connector boundaries, installation blockers, and the separate outbound-only feasibility pilot. URL: /docs-site/integrations/salesforce # Salesforce Utility Connector The retained credentialed connector is implemented in the review stack and disabled by default. The four REST, MCP, and SDK operations below are implemented; they are not a deployed or customer-enabled contract. Salesforce sandbox acceptance and separate activation approval are still required. Salesforce remains authoritative for application answers, source files, and regulatory queue status. GridWonk captures exact review inputs and returns decision support. It does not approve applications, change their Salesforce queue status, or send applicant notices. Source-managed lifecycle and package-freeze writes also refuse unresolved GridWonk notice delivery under the application lock. Pending, held or accepted-but-unfinalized delivery must be resolved first. This safeguard neither enables the connector nor adds a Salesforce notice action. The protected Admin document-recovery implementation explicitly blocks source-managed projects. It cannot bypass Salesforce ownership, remote permissions, connector retry or result-delivery controls. No Salesforce endpoint, credential, import behavior or activation gate changes with it. ## Installed application The installed-app pilot uses a different authorization model: Salesforce initiates every connection, GridWonk stores no Salesforce access or refresh tokens, and reviewers do not need individual GridWonk accounts. A Salesforce-held certificate authenticates a fixed approved test installation while Salesforce derives and checks the acting reviewer's identity and access. Layer 1 contracts and installation authentication are merged separately from the retained connector below. Layer 2 packet submission is approved and in progress, not complete or customer-ready. The installed-app API is hard-disabled; no existing connector flag, API key or OAuth token can enable it. A second unconditional gate blocks extraction, optical character recognition (OCR) and model review. The canonical plan's remaining approval gates still apply. Layer 1 also carries the installation and Salesforce reviewer through the existing intake, review job and saved-package records without creating a GridWonk user. Ordinary document/result readers and direct authenticated database reads deny this mode, including staff access; the retained connector's recovery and result-delivery sweeps skip installed imports. An in-flight installed import stays valid across a connection policy bump that none of its own fences caused, using the same policy snapshot rule as the retained connector. Human and service actors on the retained connector keep their separate authorization and remote permission checks. Import creation uses a shared connection lock to avoid lock-upgrade deadlocks between concurrent imports; it still waits for an exclusive pairing change, so the two transports cannot race. The separate Layer 1 Apex contract passed seven native check-only tests after the second review on September 16 (job `0AfQL00000rYdy80AC`). It derives the org and reviewer, checks current record/field/file access, pins the exact PDF version, and shares its request-body fixture with TypeScript. The rerun also proved the review corrections: the emitted org and user IDs are the 18-character forms the server binds, and a compound field such as `BillingAddress` is refused in Salesforce rather than signed as an object the server would reject. Its public entry remains hard-disabled; these tests neither install the classes nor execute its certificate-signing lines. The later eight-test native checksum/contract check is also narrow evidence: it does not prove the whole Layer 2 configuration, private receipt, controller or browser workflow. Their source is now implemented, but integrated verification remains in progress. Neither result resolves the retained connector's per-user credential blocker described below. Stage A demonstrated a valid 31,457,280-byte PDF read through Lightning Data Service and uploaded directly to private test storage, with matching independent hashes. A small newer version published during transfer did not replace the selected original bytes. Certificate-signed requests, rejection of unauthorized/replayed requests, upload recovery after page reopening, and private saving and reopening of signed synthetic findings passed. Removing the probe permission blocked subsequent result access. The test installation is inactive; no real packet review has run. These fixed-source, single-page probes do not prove a full 12-file/120 MiB packet, production finalization, retention, customer pairing, multi-page history or managed-package installation. The 30 MiB file and 120 MiB packet requirements remain unchanged. James approved Layer 1 on September 16 and Layer 2 on September 17, with every existing approval gate retained. Signed results/history, retention/usage and packaging remain Layers 3–5, not built or approved by Layer 2. Production activation and real model processing require separate approval. ### Layer 2 packet submission Source services now validate the exact approved field/program/file manifest, create an import with its external Salesforce reviewer, reserve direct-storage upload attempts, and compare received bytes before acceptance. They reuse the existing source-managed revisions, private intake, accepted assets and review engine. No storage token or review job is created by preparation. An unchanged packet can reference an already committed current revision without creating another review or replacing its original reviewer attribution. The route dispatches preparation, upload authorization, finalization and read-only progress behind its unconditional gate; native/browser verification remains in progress. These source functions are not a live feature. Apex reads the checksum of the exact Salesforce file version independently of the browser. Received size and MD5 are compared with that descriptor; received SHA-256 must also match the declared SHA-256 and becomes the accepted asset identity. MD5 is a consistency check, not strong proof against deliberately constructed checksum collisions. A browser-supplied matching SHA-256 alone is not independent proof of Salesforce origin. Security acceptance must retain this limitation. The native receipt protocol saves a private Salesforce receipt before submission, keeps recovery tokens and upload-resource details privately in Salesforce rather than GridWonk, and rechecks current access before releasing them. Do not treat source or unit tests as proof of those native permissions. No Salesforce credential is stored in GridWonk, and large file bodies do not pass through its API. The native component provides selection/preview, receipt saving, reopening and continuing the same submission. Its permission set grants guarded Apex access, not direct access to private receipt objects. Hidden or closed pages clear the private view and in-memory credentials. Retries preserve two active imports per installation, two outstanding uploads per import, six failed storage attempts and the original 24-hour processing deadline. A physical upload reservation is committed before signing and has a fixed conservative expiry of two hours plus 60 seconds; the actual token may expire earlier. A lost token response does not cause another token to be minted for the same reservation. Navigation may resume an unfailed attempt using its saved private token and resource. An explicit failure report counts once, permanently prevents that attempt's reuse, and keeps its physical slot until expiry. Reopening the record cannot renew budgets. Every expected file must be independently accepted before extraction, OCR or review can be considered. Even then the separate compute gate refuses processing. Behind it, finalization uses the existing pipeline, commits only a complete revision, and freezes its completed review before marking the import completed. Read-only progress returns safe file/status metadata; it does not start or advance processing, reset limits or return findings. Dispatch uses the existing maximum of three processing retry cycles and a five-minute lease; it does not claim exactly-once execution. Failed storage-attempt limits and processing retries are separate controls. No real full-packet review, 30-day purge guarantee or package installation has been demonstrated by this Layer 2 source work. The manifest declares `salesforce-installed-app` with installation-signature authentication and a planned REST binding. Salesforce signs small requests; PDF bodies use direct private-storage transfer. No new MCP, SDK, CLI or chatbot connection is part of this mode. Approval binds the utility, Salesforce org, deployment audience, program mapping and public key; the utility and platform approvals must come from two different administrators, and pairing requires the 18-character Salesforce org ID. Reviewers keep their Salesforce identity without receiving a GridWonk account. Each signed attempt carries a nonce, a one-use request token. Retrying requires a fresh signature and token but keeps the saved submission identity and original deadline. Expired-token cleanup checks both application and database time, so waiting for a database lock does not incorrectly reject a valid retry. Replay protection and the durable request-rate limit remain enforced. The rest of this page describes the retained credentialed connector, including remote Salesforce access, automatic processing and result delivery. Those behaviors are not part of the outbound-only pilot. ## Implemented credentialed scope - A manually requested review and automatic review after an approved ready-status change or relevant file/answer change. - Individually linked reviewer accounts and separately granted service identities for automation. - Multiple isolated Salesforce connections belonging to one utility organization each. - Salesforce Files containing supported PDF, PNG/JPEG, DWG, or ZIP inputs. - Internal review findings, field/file citations, revision history, and authenticated report links. External file repositories, applicant access, AppExchange distribution, and editing Salesforce applications from GridWonk are outside this release. There are no in-app chatbot transport changes. ## Prepare a pilot 1. Identify the exact operating utility, state, interconnection program, and review-profile version. A parent-company name such as Xcel is not a review-coverage approval. 2. Supply a real utility sandbox and representative synthetic packet. Discover the actual object and field schema; there is no assumed Salesforce industry application object. 3. Approve versioned field mappings against a reviewed form model, including readable program filters, ready-status values, and file access. A typed name or checkbox is not signature proof. 4. Resolve the individual-reviewer credential blocker and pass native validation before installing the source kit. Then configure its private objects, permissions and separate credential lanes. 5. Complete the acceptance checks with the exact code, migrations, configuration, and authenticated browser sessions. Customer activation requires separate approval. No deployment, database migration, customer credentials, purchase, or paid evaluation is authorized by these preparation steps. The source kit is not an installed or sandbox-verified connector. September 15 check-only native validation accepted all 13 Apex classes after compiler/metadata repairs, but completed zero package tests: Salesforce rejects the legacy human credential's `Custom` plus `PerUserPrincipal` configuration. A supported per-user design is required; the shared automation identity must not replace it. The gateway now sends `idempotencyKey` and `acknowledge: true`, with a shared Apex/API fixture. Native package tests and Lightning acceptance remain separate requirements. ## Account and permission boundaries The utility-owned packet repair preserves `private.guard_salesforce_source_owner()` unchanged: a Salesforce source packet must remain utility-owned with `applicant_org_id IS NULL`. Recording a developer's contact details does not link an applicant organization or grant developer access; future invitations must not populate that ownership field. Console-only packet-owner human confirmations add no Salesforce operation and do not activate either connector mode. The utility account's **Integrations** tab has a **Salesforce packet reviews** card linking to **Salesforce connections** at `/utility/integrations/salesforce`. When the deployment switch is off, the page explains that the connector is disabled without querying its new database tables. Utility owners and administrators configure connections, approve mappings, enable reviewers, and issue or revoke automation identities. Reviewers link their own Salesforce accounts. Interactive access requires both current utility membership and that person's current Salesforce source access; an automation account never substitutes for a failed employee authorization. The utility Layer 3 REST/SDK/CLI decision bindings retain this source-access boundary. A definite source denial returns an opaque not-found response; an authorization-service outage does not become a successful read or decision. These bindings do not enable either Salesforce connector mode or authorize changes to Salesforce-owned evidence. Automation grants are limited to the saved connection and approved program, with explicit operations and expiry. Newly issued service secrets are shown once. Stored Salesforce tokens are encrypted and never returned in setup responses, operation progress, or MCP results. Adding or changing another reviewer does not interrupt unrelated imports or result deliveries. Saved work stops when its own actor, mapping, or service grant changes, even if that permission is immediately restored; request new work after approval. Turning automation off affects service work only. Disabling the connection affects all work. These rules do not replace live source permission checks. Results require approved reviewer access and current source-record access. An old report link, utility administrator role, or private Salesforce record alone does not grant access. Applicant portal users are not eligible readers. Generic packet, package-comparison, and document readers check current Salesforce permissions against every committed captured revision, including fields removed from today's mapping. This conservative rule can also deny the current view when an older field is no longer readable. Foreign review identities, malformed snapshots, and histories exceeding 200 revisions are refused; the authorization proof is never silently truncated. Ordinary non-connector reads are unchanged. During a temporary Salesforce permission-check outage, mixed application lists keep ordinary applications and successfully authorized Salesforce applications available. A warning marks lists and counts as partial; unverified Salesforce applications are omitted from both. Refresh retries current permissions, without reusing an old access decision. Application-list database query failures still report an error, and a direct report or artifact read never returns unverified source data. ## Snapshot and revision rules Mapped answers preserve types and source object, record, and field references. Blank answers are different from denied, unmapped, unreadable, or invalid inputs. Connector access failures must not be reported as applicant deficiencies. A PDF-free application can use mapped field evidence; the connector does not fabricate a PDF or page reference. The worker reads the full paginated file inventory and relevant fields twice, downloads exact `ContentVersion` IDs, and rechecks before committing the review inputs. This detects changes; it is not a Salesforce transaction spanning all those reads. Repeated changes end in `source_changing` without a partial review. One source application keeps one GridWonk application ID. Confirmed removals leave the current packet while old package evidence remains intact. A failed or denied inventory is never a file removal. Ordinary GridWonk edits cannot change Salesforce-owned answers or documents. Revisions stop for staff review after adjudication or notice work begins; closed or withdrawn applications are never automatically reopened. Every declared input must be transferred, processed, and resolved before the connector opens its independent review gate. Failed/expired upload batches or unresolved DWG pairing do not permit a partial review. A fully captured packet can still be reviewed for genuinely missing requirements. The shared manual-review path separately refuses active, unexpired upload batches. Source revision or authorization failures retain their source-readiness explanation; they are not reported as an unfinished upload batch when no such batch exists. After a completed review, the import worker freezes an immutable package before marking the import complete. It rechecks current connection, actor, mapping, grant, and packet authority under a lock, and requires the exact completed run and captured revision. A retry reuses that package after the same checks. Service-created packages retain a service identity, not a fabricated human user. This step changes no queue status, decisions, or notices. The dependent utility-event layer adds `utility.package.frozen` to that existing transaction only when a new package is created. It preserves the exact stored import and review-job origin, checks that human, service, or installed-reviewer identity against current authorization, and refuses missing or inconsistent provenance rather than fabricating a user session. Reusing an existing package emits nothing new. Receiving-utility webhook subscriptions are separate from Salesforce's private result-delivery path; neither enables imports, write-back, or applicant notices. Connector activation and the utility-event schema/release gates remain separately held. ## Limits and waiting states The connector uses the existing intake and review budgets. It does not increase quotas. | Control | Default | |---|---| | Active connector imports | Two per utility, across connections | | Source-file streams | Two per import | | Automatic debounce | 120 seconds without relevant changes | | Recovery schedule | Every five minutes, bounded work per sweep | | Loose-file batch | At most 12 files, 30 MiB each, 120 MiB total | | ZIP intake | One archive; do not mix a ZIP with loose files | `quota_wait`, `capacity_wait`, `provider_throttled`, `processing_wait`, and `pairing_required` explain why an operation is waiting. `held` requires staff attention. Retry the same logical request with its original request key; do not create repeated new requests to bypass a wait. Result delivery also retries temporary authorization-check outages, up to ten attempts. Every attempt confirms current access before calling Salesforce. Revoked access cancels delivery. Disabling a connection blocks new and queued work and stops a running worker at its next safe authorization checkpoint. Captured evidence is retained under existing retention rules. Re-enabling does not silently restart cancelled work. ## Authenticated interfaces The console's packet-cancellation control and the ordinary job-cancellation lifecycle repair add no Salesforce operation or permission. The four connector bindings below, source-managed import restrictions and separate activation gates are unchanged. All four bindings use the same connection-scoped services. Reads require `partner.read` or connector read authority; import requires `partner.write` or connector write authority. A connector service token is bound to its connection and REST or MCP resource audience. Approved human OAuth clients use only the narrow MCP tool set; an MCP token cannot be reused on REST. Every request also checks current source permissions and organization access, rate limits, and usage policy. The shared capability manifest also records the bounded evaluation-dispatch contract. Refusing unapproved paid evaluation does not change these four Salesforce operations, quotas, or pilot gates. The shared capability manifest also declares the Prompt Ops source-catalog workspace, while the SDK exposes read-only prompt history. Removing direct prompt mutations does not change these four Salesforce operations or their activation, connection, and source-permission gates. | Operation | MCP tool | SDK method | |---|---|---| | Search permitted applications | `search_salesforce_applications` | `searchSalesforceApplications` | | Inspect mapped answers and file inventory | `get_salesforce_packet_manifest` | `getSalesforcePacketManifest` | | Request import and review | `import_salesforce_packet` | `importSalesforcePacket` | | Follow an import | `get_salesforce_import` | `getSalesforceImport` | The REST base is `/api/v1/integrations/salesforce/{connectionId}`: | Method and suffix | Required input | |---|---| | `GET /applications` | Query `mappingId` and `query` (2–80 characters; no `%` or `_` wildcards) | | `GET /applications/{recordId}/packet` | Query `mappingId`; returns approved mapped answers and exact file metadata, never download URLs | | `POST /imports` | JSON `mappingId`, `recordId`, `idempotencyKey`, and `acknowledge: true`; returns `202` progress | | `GET /imports/{importId}` | Exact connection and import; returns current progress, not report content | Reuse the same idempotency key after an uncertain import response; the SDK does not automatically retry this POST. Inputs cannot override the actor, utility, credentials, or connection path. Responses are private and non-cacheable. Documentation and discovery still require sign-in. The setup page is available; a separate packet-search/import browser interface remains planned. Agentforce calling GridWonk and an existing MCP client calling Salesforce's hosted MCP server are separate configurations. Both need sandbox compatibility tests. Connection administration, permission changes, manual package freezing, adjudication, deletion, and notices are not connector MCP tools. --- # GridWonk for Slack Connect the GridWonk Slack app, link your account, and use Agent View, skill sets, and Deep Research safely. URL: /docs-site/integrations/slack GridWonk brings the same organization-scoped interconnection assistant used in the console into Slack. Slack adds its own Agent View experience, `/gk` commands, optional organization skill sets, and a managed Deep Research pilot. Microsoft Teams and the internal chat console use the shared assistant core, but they do not expose those Slack-only controls. ## What is available where | Capability | Internal chat console | Slack | Microsoft Teams | |---|---|---|---| | Shared assistant answers and authorized tools | Yes | Yes | Yes | | Saved-finding source quotations from **Explain this finding** | Yes | No | No | | Native progress, stop, automatic titles, and Agent View transcript | No | Yes, after Agent View activation | No | | Organization assistant skill sets | Configure only | Yes, when enabled | No | | `/gk` requirements and context commands | No | Yes | No | | Start, check, or stop Deep Research | No; completed reports open in the console | Managed pilot | No | | Reply delivery | Live streaming with tool details | Native processing status; threaded replies can update a progress message into the final reply, while root direct messages post one final message | One completed message | “Yes” means the capability is implemented. The organization feature control, connected workspace, linked user, active membership, deployment configuration, and pilot approval still have to allow it. ## Before you connect Slack You need: - An active GridWonk account and organization membership - Organization administrator or owner access in GridWonk - Permission to install apps in the target Slack workspace, or help from a Slack administrator - One Slack workspace that is not already connected to another GridWonk organization ## Connect your workspace 1. Open your GridWonk workspace and choose **Features**. 2. Make sure **Slack assistant** is enabled for the organization. 3. Under **Chat platform connections**, choose **Connect Slack**. 4. Review Slack's requested permissions, choose the correct workspace, and approve the install. 5. Return to **Features** and confirm that the workspace shows **Active**. 6. In Slack, open the GridWonk app and send a direct message. If prompted, follow the secure link to connect your Slack identity to your GridWonk account. Each person links their own Slack identity. A workspace install does not grant every Slack member access to organization data, and a revoked or expired GridWonk membership is denied. A linked identity acts as you, so it follows your GridWonk acceptance of the current legal terms. When the terms are updated, GridWonk answers your next message or `/gk` command with a link to review and accept them, and runs nothing else until you do. A channel mention gets the link in a direct message and a `/gk` command gets it in a reply only you can see; a direct message or group DM gets it in that conversation. After you accept in the browser, retry the request in Slack. Microsoft Teams follows the same rule and posts the link in the conversation where you asked. To use GridWonk in a channel, invite the app when Slack requires it and mention **@GridWonk**. Use a thread for follow-up questions so the conversation transcript and work context stay together. ## Set useful context Use `/gk context` to inspect the channel's current defaults. Set a utility and state with: `/gk context ` Example: `/gk context duke-energy NC` Then ask a focused question in a direct message or by mentioning GridWonk in a channel. For a single lookup, you can bypass the conversational wording with: `/gk requirements ` Use `/gk help` in Slack for the current command list. `/gk status` currently links you back to the GridWonk console for validation job monitoring; it is not a native Slack job tracker. ## Use Agent View effectively With Agent View active, Slack shows GridWonk as an agent instead of a conventional bot thread. The adapter uses Slack's transcript for follow-up context, publishes native processing status, assigns an automatic title, and honors Slack's stop control. Stop cancels the active assistant turn across serverless instances through the shared Redis state. Agent View activation is an operator-managed maintenance change because Slack does not allow the app to switch back to the legacy Assistant View. Installing the repository manifest alone does not enable Agent View for an organization. ## Choose assistant skill sets An organization administrator can enable **Assistant skill sets** from **Features** and select one or more curated bundles: - **Interconnection research** prioritizes utility-published sources, exact citations, and a clear separation between evidence and inference. - **Project coordination** keeps answers anchored to the active project, blockers, owners, and next actions. - **Deficiency review** applies GridWonk's precision-over-recall standard to evidence-backed findings. Skill sets change instructions, not authority. They never add tools, widen data access, or bypass a confirmation. They currently apply to Slack turns only. ## Run Deep Research Deep Research is disabled by default. Customer organizations cannot use its paid web-search lane. GridWonk operators with both Deep Research controls enabled can start a cited report with: `/gk research [--sources=web,gridwonk,organization]` The default uses only current, approved procedure documents that support published packet-review requirements for a utility onboarded for automated review. Set utility and state context first. Only GridWonk operators can explicitly add `--sources=web`; web search is never selected by default. Add `organization` only when the run needs your organization's private documents. Organization-private research must start in a one-to-one direct message with the app. It is rejected in public channels, private channels, group direct messages, and Slack Connect. Private sources are never selected by default, every requested lane must return usable evidence, and only the requester can open a report that used private sources. GridWonk records provider usage for cost auditing even when a paid web search returns no usable sources and the run fails. Check or stop a run with: - `/gk research status [run-id]` - `/gk research stop [run-id]` A stop request is durable and takes effect before the workflow's next collection, synthesis, or completion step. Pilot limits are one active run per person, five per organization, three starts per person per hour, and 20 sources per report. ## Ask better questions - Name the utility, state, project, and interconnection track when they matter. - Ask for the source you need: utility requirements, your uploaded evidence, or public research. - Keep one topic in one thread and correct the context before asking a follow-up. - Use a direct message whenever the question may involve organization-private data. - Treat citations as the evidence boundary. If a requested detail is not in the cited source, GridWonk should say it is not listed instead of filling the gap from general knowledge. ## Troubleshooting | Symptom | What to check | |---|---| | “Workspace is not connected” | Confirm the Slack connection is Active and **Slack assistant** is enabled in GridWonk **Features**. | | An existing thread went quiet | Disconnecting or uninstalling the Slack app stops replies in threads the assistant had already joined, not just new mentions. Reconnect the workspace, then start a fresh mention. | | GridWonk asks you to link | Open the secure link while signed in to the GridWonk organization connected to that workspace. | | No channel reply | Invite the app if required, mention **@GridWonk**, and continue in the same thread. | | Private research is refused | Move the command to a one-to-one app direct message, or remove `organization` from `--sources`. | | Web research is refused | Web search is GridWonk-only, disabled by default, and must be explicitly selected by an operator. | | Agent View is missing | The irreversible Agent View maintenance gate may not yet be active for this Slack app. | | A completed report will not open | Confirm you still have active organization membership and, for private runs, that you are the requester. | For the shared runtime and the Teams connection flow, see [Chatbot Channels](/docs-site/integrations/chatbot-channels). --- # Webhook Integration Guide Event types, payload schemas, retry semantics, signature verification, and integration patterns for GridWonk webhooks. URL: /docs-site/integrations/webhooks # Webhook Integration Guide GridWonk webhooks deliver real-time HTTP POST notifications to your HTTPS endpoints when async jobs, document operations, and compliance events occur. Utility manual freeze, adjudication, screening completion, and study-requirement bindings record their existing audit/history provenance. The dependent utility-event layer now implements five `utility.*` families for those saved changes and canonical notice transitions, with durable, ordered delivery through receiving-utility subscriptions. Schema activation and production release remain held. A subscription grants no decision, notice-send, or provider-receipt authority. For the complete CRUD API reference (create, list, update, delete subscriptions), see [Webhooks API](/docs-site/api/webhooks). The SDK and CLI default to the canonical `https://gridwonk.com` API origin, so authenticated subscription management does not need a base URL or trust override. ## Quick Setup 1. Create a subscription via the [Webhooks API](/docs-site/api/webhooks#create-subscription): ```bash curl -X POST https://gridwonk.com/api/v1/webhooks \ -H "Authorization: Bearer $GRIDBOOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-server.com/hooks/gridwonk", "events": ["job.completed", "job.failed", "document.digitized"] }' ``` 2. Save the `secret` from the response -- it is shown **only once** and is needed to verify delivery signatures. 3. Implement a handler at your URL that [verifies signatures](#signature-verification) and returns a `2xx` response within 10 seconds. Before each POST, GridWonk revalidates the destination through the public-network URL guard. Delivery does not follow redirects, and it reads at most the first 2,000 response characters for status and diagnostics. ## Event Types | Event | Description | Currently Emitted | |-------|-------------|-------------------| | `job.completed` | Async job finished successfully | Yes | | `job.failed` | Async job failed | Yes | | `document.digitized` | Document digitization completed | Yes | | `requirements.extracted` | Historical event from the retired legacy requirements read; no longer emitted because that endpoint is 410 | No | | `document.classified` | Document classification completed | Reserved | | `document.validated` | Validation workflow produced result | Via `job.completed` | | `deficiency.found` | Deficiency identified | Reserved | | `screening.complete` | Screening workflow completed | Reserved | | `utility.screening.determined` | Human screening determination saved | Implemented; dependent release held | | `utility.finding.adjudicated` | Finding decision saved | Implemented; dependent release held | | `utility.study_requirement.set` | Case-specific study requirement changed | Implemented; dependent release held | | `utility.package.frozen` | New immutable package created | Implemented; dependent release held | | `utility.notice.status_changed` | Canonical notice lifecycle changed | Implemented; dependent release held | **Reserved** events are defined in the schema but not yet emitted. Subscribe to them now for forward compatibility. The [default-disabled Salesforce connector](/docs-site/integrations/salesforce) does not gain activation or write-back authority from a subscription. Its existing authorized freeze transaction records `utility.package.frozen` with exact persisted import/job provenance when the utility-event layer is released. Its private result delivery remains separate. Subscribing to either a reserved screening event or a utility event does not enable the connector. ## Payload Schemas ### Utility events The utility-notice stack implements the five utility families together; schema activation and production release remain separate human approval gates. Events are committed alongside the business change, with no historical backfill. Receiving-utility subscriptions receive them; applicant/consultant membership or delegated application access does not widen subscription scope. ```json { "eventId": "c6dd50a1-9cd8-4dbd-95b3-bbf1479985de", "eventType": "utility.notice.status_changed", "payloadVersion": 1, "organizationId": "95da3428-9e60-47d3-852c-690567423009", "submissionId": "8996aa1c-f3c5-4f73-b477-309738428244", "sequence": "7", "occurredAt": "2026-10-10T12:00:00.000Z", "provenance": { "userId": "c2d4e8eb-45d0-4e1e-9a1e-dbd07f069bb1", "credential": "session", "surface": "console", "requestId": "example-request" }, "data": { "noticeId": "9d05ff96-9657-4bb8-9eb3-c35cc233ae46", "contentRevision": 2, "packageId": null, "packetReviewRunId": null, "fromStatus": "approved", "toStatus": "sent" } } ``` Keep `sequence` as a decimal string or arbitrary-precision integer, never a JavaScript number. `data` varies by event: | Family | Data | | --- | --- | | Screening | Package/run IDs and `screened` to `complete` | | Finding | Package/run/adjudication IDs, adjudication version, finding ID and decision | | Study | Evidence ID/version and normalized case-specific requirement | | Package | Package ID/number/type and pinned run ID when present | | Notice | Notice ID/content revision, optional package/run IDs, previous/new canonical status | Package events cover existing manual, automatic/recovery, Salesforce and applicant submit/resubmit freezes. Human screening events do not mean automated job completion; existing `job.completed` is unchanged. Replays, unchanged study requirements, content-only edits, send claims and provider receipts do not emit another canonical event. A failed event/fan-out insert rolls back the business change. Notice events omit recipient addresses and complete email bodies. Each subscription/application pair has its own ordered stream. A consumer may see sequence 1 followed by 3 when it did not subscribe to event 2. Stable IDs allow deduplication after a crash or lost response. Retries reuse the stored payload and ID, refreshing only signing time/signature. Persist your deduplication decision and accepted work before returning success. ### `job.completed` / `job.failed` ```json { "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "jobType": "discovery", "status": "complete", "error": null, "result": { "success": true, "response": "Found 12 interconnection requirements for Duke Energy...", "structuredOutput": { }, "tokenUsage": { "input": 5000, "output": 1200 }, "executionTime": 12345, "error": null } } ``` **Creatable job types:** `discovery`, `document-digitization`. Historical validation, location, and report job types remain readable but return `410 JOB_TYPE_RETIRED` when creation is attempted. Applicant-document jobs require an organization-visible document that the API key is allowed to process. Generic jobs reject Salesforce-owned documents; a webhook subscription does not grant processing permission. For the upload that creates a document-digitization job, compatible whitespace-wrapped and URL-safe base64 is normalized before the PDF signature and decoded-size checks. The stored size comes from the decoded bytes rather than the caller-provided count. ### `document.digitized` ```json { "documentId": "550e8400-e29b-41d4-a716-446655440000", "tableName": "ix_applicant_documents", "alreadyDigitized": false, "metadata": { "inputTokens": 2400, "outputTokens": 800, "durationMs": 1200 } } ``` ### `requirements.extracted` ```json { "utility": "duke-energy", "region": "NC", "category": "site_control", "count": 15 } ``` Historically, only `GET /api/v1/requirements` emitted this event. That route is now retired. The customer-release replacement `GET /api/v1/published-requirements` has no webhook side effect at all — a read is not an extraction. The legacy endpoint is now a permanent 410 tombstone, so `requirements.extracted` is no longer emitted. `requirements.extracted` has no other producer. The legacy endpoint now returns `410 Gone`, so the event has stopped permanently — an existing subscription stays valid but remains quiet. The shutdown is complete. The Sunset was `2026-08-11T19:00:00Z`, and authenticated calls now receive typed `410 Gone` with the published endpoint as the replacement. See [Retirement Stages](/docs-site/api/requirements#retirement-stages). If this event drives downstream work, migrate that trigger to your own scheduled read of `GET /api/v1/published-requirements` rather than waiting for the last delivery. That endpoint returns every published requirement except the ones a utility reviewer explicitly rejected, with each row marked `reviewStatus: "approved"` or `reviewStatus: "pending"`. `count` follows the same requirement lookup mode as the legacy API response that emitted the event. In shadow mode, it can reflect the existing displayable corpus; in enforcement mode, it reflects only customer-usable requirements linked to current usable procedure documents. ## Receiving Webhooks ### Delivery Headers Every webhook delivery includes these headers: | Header | Example | Purpose | |--------|---------|---------| | `Content-Type` | `application/json` | Payload format | | `X-GridWonk-Event` | `job.completed` | Event type | | `X-GridWonk-Event-Id` | `a1b2c3d4:job.completed` | Unique event ID (for deduplication) | | `X-GridWonk-Timestamp` | `1740009600` | Unix epoch seconds | | `X-GridWonk-Signature` | `sha256=abc123...` | HMAC-SHA256 signature | > **Removed aliases:** deliveries previously also carried `X-GridBoost-Event`, `X-GridBoost-Event-Id`, `X-GridBoost-Timestamp`, and `X-GridBoost-Signature` with identical values. Those aliases have been removed — use the `X-GridWonk-*` headers above. ### Signature Verification Subscription deliveries are signed using your subscription secret. Direct one-shot webhooks are signed with the platform direct-webhook signing secret when configured. **Always verify signatures** before processing payloads. #### Signing Algorithm ```text HMAC-SHA256(secret, "{timestamp}.{raw-json-body}") ``` The signature header contains `sha256=` followed by the hex-encoded HMAC digest. #### Node.js The verifier below is a runnable utility when passed the exact raw request body: ```typescript import { createHmac, timingSafeEqual } from 'node:crypto'; function verifyWebhook( headers: Headers, rawBody: string, secret: string ): boolean { const signature = headers.get('X-GridWonk-Signature') ?? ''; const timestamp = headers.get('X-GridWonk-Timestamp') ?? ''; // Reject stale deliveries (> 5 minutes old) const sentAt = Number(timestamp); const age = Math.abs(Date.now() / 1000 - sentAt); if (!Number.isFinite(sentAt) || age > 300) return false; const expected = `sha256=${ createHmac('sha256', secret) .update(`${timestamp}.${rawBody}`) .digest('hex') }`; const actualBytes = Buffer.from(signature); const expectedBytes = Buffer.from(expected); if (actualBytes.length !== expectedBytes.length) return false; return timingSafeEqual(actualBytes, expectedBytes); } ``` #### Python ```python import hmac, hashlib, time def verify_webhook(signature: str, timestamp: str, body: bytes, secret: str) -> bool: # Reject stale deliveries if abs(time.time() - int(timestamp)) > 300: return False expected = "sha256=" + hmac.new( secret.encode(), f"{timestamp}.{body.decode()}".encode(), hashlib.sha256 ).hexdigest() return hmac.compare_digest(signature, expected) ``` ### Handling Deliveries A minimal webhook handler should: 1. **Verify the signature** before any processing. 2. **Return `200 OK` immediately** -- perform heavy work asynchronously. 3. **Deduplicate** using the `X-GridWonk-Event-Id` header to handle at-least-once delivery. The following handler is illustrative because `enqueueEvent` is application-specific. It reads the request body exactly once, verifies those exact bytes, then parses the JSON: ```typescript export async function POST(req: Request) { const secret = process.env.GRIDBOOST_WEBHOOK_SECRET!; const rawBody = await req.text(); if (!verifyWebhook(req.headers, rawBody, secret)) { return new Response('Invalid signature', { status: 401 }); } const event = req.headers.get('X-GridWonk-Event'); const eventId = req.headers.get('X-GridWonk-Event-Id'); const payload = JSON.parse(rawBody); // Enqueue for async processing (don't block the response) await enqueueEvent({ event, eventId, payload }); return new Response('OK', { status: 200 }); } ``` ## Retry Semantics Subscription deliveries use an **at-least-once** model with exponential backoff. ### Retry Schedule This six-attempt schedule applies to legacy job/document subscription delivery, not utility events. | Attempt | Delay | Cumulative Wait | |---------|-------|-----------------| | 1 | Immediate | 0 | | 2 | 30 seconds | 30s | | 3 | 2 minutes | 2m 30s | | 4 | 10 minutes | 12m 30s | | 5 | 1 hour | 1h 12m 30s | | 6 | 6 hours | 7h 12m 30s | **Total: 6 attempts** (1 initial + 5 retries). Max wait before final attempt is approximately 7 hours. ### What Counts as Failure - HTTP response outside 200-299 range - Network error or timeout (10-second delivery timeout) - DNS resolution failure - URL resolves to a private or reserved IP address when the destination is revalidated for the delivery attempt ### What Counts as Success - HTTP 2xx response (any status in the 200-299 range) - On success, `consecutiveFailures` resets to 0 ### Circuit Breaker This subscription-wide breaker applies to legacy delivery only. After **10 consecutive failures**, the subscription is automatically disabled: - `isActive` set to `false` - `disabledAt` timestamp recorded - No further deliveries attempted To re-enable a disabled subscription, send `PATCH /api/v1/webhooks/{id}` with `{"isActive": true}`. This resets the failure counter. See the [Webhooks API](/docs-site/api/webhooks) for details. ### Utility-event retry and recovery Utility events have at most eight attempts. Minimum retry delays are 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 12 hours and 24 hours. An authenticated five-minute recovery job selects at most 50 eligible stream heads before applying its limit and publishes with concurrency five. A failed publication leaves the durable row due. A three-minute claim prevents duplicate workers from independently posting while the ten-second HTTPS request is active. An exhausted event holds its subscription/application pair and later events in that pair. Other applications and subscribers can continue. Utility attempts never alter subscription-wide failure counters or auto-disable it. A late worker can record its own attempt result but cannot regress a newer claim. Signature verification, HTTPS, private-address/DNS-rebinding checks, redirect refusal and bounded response reads apply to both delivery policies. Subscription event-list changes affect future fan-out only. Disable pauses new claims, though an in-flight request may finish; re-enable resumes eligible pending rows, not exhausted holds. Deletion removes that subscription's deliveries but retains source events. Do not reset held rows, attempt counts or event IDs to manufacture a retry; operator disposition requires separate review. ## Delivery Paths Packet-review cancellation emits its existing failed-job terminal notification only after the guarded job/review settlement succeeds. Notification failure cannot undo that settlement, and cancellation introduces no new event name or signing scheme. A terminal notification describes the saved job outcome, not proof that an already-running external provider request stopped. GridWonk has the following delivery mechanisms: | Path | Lifecycle | Retries | Logging | Use Case | |------|-----------|---------|---------|----------| | **Legacy subscription-based** | Persistent | Yes (6 attempts) | Full delivery log | Job/document monitoring | | **Utility-event subscription** | Per application/subscription | Up to 8; stream-local hold | Immutable event, logical delivery and attempt log | Ordered utility changes; dependent release held | | **Direct webhook** | Per-job | Normally one attempt; stale-job recovery permits up to five | Recovery outcome summary for stale jobs | Job completion callback | **Direct webhooks** are specified via the `webhookUrl` parameter on supported job creation endpoints (`POST /api/v1/jobs` and `POST /api/v1/agents/execute`) and require a configured direct-webhook signing secret. The normal direct path has no subscription-style delivery log or retry schedule. When stale-job cleanup repairs a workflow-owned job, its terminal notification is delivered asynchronously. This recovery path permits up to five direct attempts for network/DNS failures, HTTP 408/425/429 and 5xx responses. Other HTTP failures or unsafe destinations stop retries; missing signing configuration and disabled outbound delivery are recorded separately, not as success. Internal completion hooks still run after direct retries are exhausted. Recovery keeps the existing event IDs and payload contract. Always deduplicate: a successful POST followed by a sender crash can produce a repeated event. ## Best Practices 1. **Always verify signatures** -- never process unverified payloads. 2. **Respond quickly** -- return 2xx within 10 seconds. Process payloads asynchronously. 3. **Handle duplicates** -- use `X-GridWonk-Event-Id` for idempotency. The same event may be delivered more than once. 4. **Monitor subscription health** -- check `consecutiveFailures` via `GET /api/v1/webhooks` and re-enable disabled subscriptions after fixing your endpoint. 5. **Reject stale timestamps** -- discard deliveries older than 5 minutes to prevent replay attacks. 6. **Use HTTPS only** -- webhook URLs must use HTTPS. HTTP endpoints are rejected at subscription time. 7. **Log delivery IDs** -- store event IDs for debugging and auditing failed deliveries. ## Next Steps - [Webhooks API Reference](/docs-site/api/webhooks) -- full CRUD endpoint documentation - [API Quickstart](/docs-site/api/quickstart) -- end-to-end integration walkthrough - [Authentication & Rate Limiting](/docs-site/api/authentication) -- API key management