Developer Platform
Authentication and API clients
Use isolated draft credentials for unpublished page JSON and an explicit live credential for publication and production operations.
BuildWithHQ separates who is calling from what that caller is allowed to do. Human users use normal app or Builder Console sessions. Server-to-server integrations use one-time-displayed credentials created for one SaaS app.
Four client classes, three bearer schemes
| Client class | OpenAPI scheme | Purpose |
|---|---|---|
| Public | None | Health and explicitly public metadata only. |
| Draft app | DraftAppCredential / bwk_draft_ | Read, edit, and validate unpublished page JSON. |
| Live app | LiveAppCredential / bwk_live_ | Trusted-server production operations and explicit publication. |
| Delegated user | DelegatedUserCredential / bwu_live_ | Short-lived calls executed as one verified tenant user. |
The generated OpenAPI JSON and YAML attach these schemes per operation. Code generators can therefore distinguish draft authoring, app-level production access, and user-delegated access instead of treating every bearer token as interchangeable.
Draft and live are different credential classes
Use a bwk_draft_ credential while a developer, CLI, or coding agent creates pages and edits unpublished page JSON. Draft credentials can hold pages.draft.read and pages.draft.write, plus design.read, debug.read and debug.write; they cannot read live tenant data, publish, or change the live app. When the draft has been reviewed, deliberately switch the trusted server to a bwk_live_ credential with pages.publish. Publication names the exact draft-history ID and expected page version, so it cannot silently publish a newer or different draft. A live credential never reads or edits drafts.
# Draft key: save unpublished JSON
PUT /v1/apps/{saasAppId}/design/pages/Home/draft
# Draft key: validate and capture pageHistoryId + pageVersion
POST /v1/apps/{saasAppId}/design/pages/Home/validate
# Live key: the explicit release boundary
POST /v1/apps/{saasAppId}/design/pages/Home/publish
Builder keys design as the app owner
Design routes run on your app's own design code, the same code as the in-app Design studio. Inside your app, a builder key acts as the app's owner (the single active owner of your app's first organization), and every saved draft and publish records both that owner and the key. Only the builder's own keys can design: delegated user tokens and keys tied to one tenant user are refused. Changes that affect the live app at once, such as custom fields, user types, menus and tenant policies, need a live key with design.write.
Debug sessions started with a builder key are the owner's debug sessions: the CLI, your own tools and the owner's in-app + Debug drawer see the same sessions and history.
Let developers iterate on unpublished JSON with a draft key, from the CLI or your own tools. This reuses the canonical page history and validation system; there is no second development database to reconcile.
Development uses the production contracts
This is not a stub or mock mode. An unpublished page can bind forms, checkboxes, lists, uploads, and action buttons to the same reviewed API operations and stored procedures used after publication. The server still enforces application, user, DataRole, location, revision, and action scope on every call. Switching to the live key grants release authority; it does not replace the backend or change the component contract.
API clients
An API client is a non-human application identity. Each client has a name, an application boundary, an active/revoked state, and an explicit set of allowed scopes. The raw secret is generated securely and shown only when the client is created or rotated; the platform stores a non-reversible verification form rather than keeping the raw secret for later display.
- Create a separate client for each integration or environment.
- Give it only the scopes it needs.
- Rotate credentials without editing the integration's logical identity.
- Revoke a compromised or retired client immediately.
- Never place server credentials in public browser JavaScript.
How a key is checked
The gateway looks a key up on the BuildWithHQ platform at most once a day. On every request it asks only your app's own database: whether the app is active, and whether the key has changed since that daily lookup. So:
- Revoke stops the key on its next request.
- Rotate stops the old secret on its next request; the new secret works at once.
- Binding a key to a tenant user takes effect on its next request.
- Suspending the app stops every key for that app on its next request.
- A new key can take up to a minute to start working if it was tried before it existed.
If the Builder Console reports that the app has not been told about a key change, the platform change is saved but the old key may keep working for up to a day. Retry the action, or rotate the key again.
Current public scopes
| Area | Scopes |
|---|---|
| Records | records.read · records.write |
| Workflows | workflows.read · workflows.execute |
| Webhooks | webhooks.read · webhooks.write |
| Connectors | connectors.read · connectors.write · inbound.write |
| AI and logs | ai.read · ai.write · logs.read |
| Contracts, MCP, services | contracts.read · mcp.use · appliances.read · appliances.invoke |
| Page development | pages.draft.read · pages.draft.write · pages.publish |
| App design and debug | design.read · design.write (live key) · debug.read · debug.write |
First-class module routes add 48 registered least-privilege scopes in the form modules.<module-key>.read and modules.<module-key>.write. Use the exact requiredScopes value in catalog/operations.json or the API route explorer instead of constructing a scope from a page label.
Scopes are only the first gate
A scope such as records.read means the client may ask to read records; it does not mean every record becomes visible. The API still applies the application's server-side record, DataRole, location, and capability rules appropriate to that identity.
Human sessions
When a human-facing application calls the API on behalf of a signed-in user, the gateway uses that verified user context. UI decisions can hide unavailable actions for convenience, but the server repeats authorization on every request.
Signing in to your app is the only time the app asks the BuildWithHQ platform about itself. Each sign-in records that check in the app's own database; after that, requests and token renewals use the app's own database only.
OAuth connections are provider credentials, not API identity
The OAuth connection endpoints let an app connect to a registered external provider using authorization code + PKCE. They do not replace the BuildWithHQ API credential that authenticates the caller to the gateway.
Never accept CustomerAccountId, AppAccountId, user role, or permission claims from a normal request body as proof of identity. Those values must come from verified server-side context.
Capability review: 2026-09-14. See current features and setup requirements, the generated API Map and first-class module inventory.