Skip to documentation
Design StudioAIDocumentation
DocumentationREST API
REFERENCE

REST API

The complete HTTP surface for projects, assets, generation, and delivery.

Use the server origin as your base URL. Request bodies are JSON unless stated otherwise. IDs in route patterns are placeholders: read real IDs from the server.

Authenticated readshell
curl "$DESIGN_STUDIO_URL/api/projects?sort=updated" \
  -H "Authorization: Bearer $DESIGN_STUDIO_API_KEY"

107 of 107 endpoints

GET/api/connections/agent-recipientsList owned active OAuth authorization identities for explicit connector grants; no tokens

List owned active OAuth authorization identities for explicit connector grants; no tokens

Interactive owner session

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/connectors/github/authorizeBegin separate GitHub App authorization for a verified installation

Begin separate GitHub App authorization for a verified installation

Interactive owner session

Request

{"connectionId":"","expectedRevision":1,"installationId":""}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/connectors/github/callbackComplete one-use GitHub authorization bound to the initiating session

Complete one-use GitHub authorization bound to the initiating session

Interactive owner session

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
GET/api/connectors/github/repositoriesList repositories accessible to the user and selected GitHub installation; connectionId and page query parameters

List repositories accessible to the user and selected GitHub installation; connectionId and page query parameters

Interactive owner session

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/connectors/github/resolveResolve a selected repository branch or tag to an immutable commit

Resolve a selected repository branch or tag to an immutable commit

Interactive owner session

Request

{"connectionId":"","repositoryId":"","ref":"main"}

Response

See live OpenAPI and the operation status returned by the server.
POST/api/connectors/github/webhookReceive signature-verified GitHub installation and authorization revocations

Receive signature-verified GitHub installation and authorization revocations

Protocol-specific authentication

Request

{}

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/sources/:sourceId/assetCopy a granted image snapshot into isolated project assets without changing the document

Copy a granted image snapshot into isolated project assets without changing the document

Owner session or explicit project connector grant

Request

{}

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/connector-operations/:operationId/reconcileReconcile an uncertain Drive upload or GitHub PR using recorded identities; never repeats external writes

Reconcile an uncertain Drive upload or GitHub PR using recorded identities; never repeats external writes

Owner session or explicit project connector grant

Request

{"expectedRevision":1}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/connector-operations/:operationId/artifactDownload an authorized prepared PDF, PPTX or React ZIP for inspection before upload

Download an authorized prepared PDF, PPTX or React ZIP for inspection before upload

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/connectors/google-drive/authorizeBegin separate session-bound Google Drive authorization

Begin separate session-bound Google Drive authorization

Interactive owner session

Request

{"connectionId":"","expectedRevision":1}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/connectors/google-drive/callbackRedeem a one-use Google callback for the initiating session

Redeem a one-use Google callback for the initiating session

Interactive owner session

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/connectors/google-drive/pickerObtain a transient selected-account access token for Google Picker; never returns refresh credentials

Obtain a transient selected-account access token for Google Picker; never returns refresh credentials

Interactive owner session

Request

{"connectionId":""}

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/connector-operations/:operationId/continuationSupply explicitly reviewed input to a paused MCP operation; creates a separately approved continuation

Supply explicitly reviewed input to a paused MCP operation; creates a separately approved continuation

Interactive owner session

Request

{"expectedRevision":1,"inputResponses":{}}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/runsList saved run metadata without advancing

List saved run metadata without advancing

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/runsPersist a bounded run at exact document and brief versions

Persist a bounded run at exact document and brief versions

Owner session or explicit project connector grant

Request

{"provider":"openai","prompt":"Refine design","bindingIds":[],"sourceSnapshotIds":[],"expectedDocumentRevision":1,"expectedBriefRevision":1,"idempotencyKey":"unique-request-key"}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/runs/:runIdRead run status, authorized proposal and provider usage

Read run status, authorized proposal and provider usage

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/runs/:runId/advanceAdvance exactly one run step with current grants

Advance exactly one run step with current grants

Owner session or explicit project connector grant

Request

{"expectedRevision":1}

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/runs/:runId/cancelCancel future steps and preserve uncertain in-flight outcomes

Cancel future steps and preserve uncertain in-flight outcomes

Owner session or explicit project connector grant

Request

{"expectedRevision":1}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/runs/:runId/proposalRevalidate a completed unsaved proposal against current authority and versions

Revalidate a completed unsaved proposal against current authority and versions

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/sourcesList private source metadata; agent results are limited to current source grants

List private source metadata; agent results are limited to current source grants

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/sources/:sourceIdDownload an authorized immutable source as inert data

Download an authorized immutable source as inert data

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/sources/:sourceId/refreshImport a new source snapshot without replacing existing content or brief

Import a new source snapshot without replacing existing content or brief

Owner session or explicit project connector grant

Request

{}

Response

See live OpenAPI and the operation status returned by the server.
DELETE/api/projects/:id/sources/:sourceIdRemove an owned source snapshot and invalidate dependent work

Remove an owned source snapshot and invalidate dependent work

Interactive owner session

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/connections/:bindingId/sourcesImport one selected MCP resource or Drive file as an immutable source snapshot

Import one selected MCP resource or Drive file as an immutable source snapshot

Owner session or explicit project connector grant

Request

{"uri":"resource://selected"}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/connector-operationsList the latest 50 operation records without private payloads

List the latest 50 operation records without private payloads

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/connector-operationsPrepare a selected tool operation against exact observed versions; unknown effects require human approval

Prepare a selected tool operation against exact observed versions; unknown effects require human approval

Owner session or explicit project connector grant

Request

{"bindingId":"","action":"","arguments":{},"idempotencyKey":"unique-request-key","expectedVersions":{"connectionRevision":1,"credentialVersion":1,"policyRevision":1,"documentRevision":1,"briefRevision":0,"sourceSnapshotIds":[]}}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/connector-operations/:operationIdInspect an operation and authorized private payload without advancing it

Inspect an operation and authorized private payload without advancing it

Owner session or explicit project connector grant

Request

No body; see live OpenAPI for query parameters.

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/connector-operations/:operationId/executeClaim approved operation once; uncertain results are never replayed

Claim approved operation once; uncertain results are never replayed

Owner session or explicit project connector grant

Request

{"expectedRevision":1}

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/connector-operations/:operationId/decisionApprove once or deny the exact operation in an authenticated browser session

Approve once or deny the exact operation in an authenticated browser session

Interactive owner session

Request

{"expectedRevision":1,"decision":"approve"}

Response

See live OpenAPI and the operation status returned by the server.
POST/api/projects/:id/connector-operations/:operationId/cancelCancel own pending operation with revision protection

Cancel own pending operation with revision protection

Owner session or explicit project connector grant

Request

{"expectedRevision":1}

Response

See live OpenAPI and the operation status returned by the server.
GET/api/projects/:id/connectionsList project connections

List project connections

Owner session or explicit agent discovery grants

Request

Project ID.

Response

{ connections }; agent selections are restricted by their grants.

Requires CONNECTORS_ENABLED. Human sessions can inspect disconnected bindings for recovery; agents receive only authorized connected bindings.

POST/api/projects/:id/connectionsBind a project connection

Bind a project connection

Interactive session and matching Origin only

Request

connectionId, role and explicit selection; see OpenAPI.

Response

201 { binding } with policyRevision.

Creates no agent authority. Grant access separately.

DELETE/api/projects/:id/connections/:bindingIdRemove a project connection

Remove a project connection

Interactive session and matching Origin only

Request

{ expectedPolicyRevision }

Response

{ ok }; related grants revoked, snapshots removed and dependent work invalidated.
POST/api/projects/:id/connections/:bindingId/grantsGrant project connector access

Grant project connector access

Interactive session and matching Origin only

Request

recipient, expectedPolicyRevision, capabilities, selection and expiresAt; see OpenAPI.

Response

201 { grant }.

Selection must be within the binding and expiry within 90 days. API-key, OAuth and WebMCP access are separate.

DELETE/api/projects/:id/connections/:bindingId/grants/:grantIdRevoke connector access

Revoke connector access

Interactive session and matching Origin only

Request

Project, binding and grant IDs.

Response

{ ok }; subsequent authorization fails.
GET/api/connectionsList external connection metadata

List external connection metadata

Owner session; agents require projectId and explicit discovery grant

Request

Optional projectId query; required for API, OAuth and WebMCP callers.

Response

{ connections }; no credentials.

Operator must enable CONNECTORS_ENABLED. Connector workflows are experimental and require configured external accounts. Tool-assisted runs use explicit approvals and return unsaved proposals.

GET/api/connections/:connectionIdRead connection metadata

Read connection metadata

Owner session or explicit project discovery grant

Request

Connection ID; projectId query for agents.

Response

{ connection } with status and revision.
POST/api/connectionsCreate pending connection

Create pending connection

Interactive session and matching Origin only

Request

displayName and config; see OpenAPI schema.

Response

201 { connection }; pending until verified.

Never put credentials in endpoint URLs. Native connector authorization is not enabled by creating metadata.

POST/api/connections/:connectionId/disconnectDisconnect and revoke connector authority

Disconnect and revoke connector authority

Interactive session and matching Origin only

Request

{ expectedRevision }

Response

{ connection }; credentials removed, grants revoked, active work invalidated.
POST/api/connectors/mcp/connectVerify anonymous or bearer MCP

Verify anonymous or bearer MCP

Interactive session and matching Origin only

Request

connectionId, expectedRevision, optional accessToken in request body.

Response

Verified connection metadata and negotiated protocol; no credential.

Successful connection does not establish catalog or tool access. API, OAuth and WebMCP callers cannot manage setup.

POST/api/connectors/mcp/authorizeStart outgoing MCP OAuth

Start outgoing MCP OAuth

Interactive session and matching Origin only

Request

connectionId, expectedRevision, options; modern CIMD or registered client, explicit legacy DCR.

Response

Authorization URL and new revision.

New authorization revokes previous grants. Callback is fixed to this installation.

GET/api/connectors/mcp/client-metadataRead OAuth client metadata

Read OAuth client metadata

Public when connectors enabled

Request

No body.

Response

Canonical client ID and exact redirect URI; no secret.
GET/api/connectors/mcp/callbackComplete outgoing MCP OAuth

Complete outgoing MCP OAuth

Original signed-in browser session

Request

Authorization server callback state, code, iss or error.

Response

Verified connection metadata.

One-use state; owner, session, issuer, resource and revision checked. Callback cannot grant local agent authority.

GET/api/observability/summarySummarize account activity and measured usage

Summarize account activity and measured usage

Session or Bearer; owner default, configured operator for scope=all

Request

Query: scope=owner|all; days=1..30 (default7); projectId, actorId (all only), channel, kind, status, action.

Response

{ scope, days, totals, usage, byAction, byActor, byProvider, coverage }

Unknown measurements remain null. OAuth cannot read all-account scope.

GET/api/observability/eventsRead paginated activity logs

Read paginated activity logs

Session or Bearer; owner default

Request

Summary filters plus limit=1..100 (default50), cursor from previous page.

Response

{ events, nextCursor }; safe metadata only, 30-day retention.
GET/api/observability/trace/:idFollow correlated request steps

Follow correlated request steps

Session or Bearer; owner default

Request

Trace ID from X-Request-ID or event. Query: scope, days (default7; maximum30).

Response

{ traceId, events, truncated }; 404 for unavailable traces.
POST/api/observability/client-eventsRecord an allowlisted browser event

Record an allowlisted browser event

Same-origin browser; owned project/correlation when supplied

Request

{ event, page?, action?, projectId?, requestId?, outcome?, errorCode? }; strict enums in OpenAPI schema.

Response

Accepted telemetry; optional PostHog forwarding is isolated from product operations.

Never send arbitrary text, credentials, names, URLs or exception messages. Not exposed as an agent mutation tool.

GET/api/healthCheck service health

Check service health

Public

Request

No body.

Response

{ "ok": true, "service": "design-studio-ai" }
GET/api/schemaRead live JSON Schemas

Read live JSON Schemas

Public

Request

No body.

Response

{ document: JSONSchema, operations: JSONSchema, designSystem: JSONSchema, interview: JSONSchema, scope: JSONSchema }; semantic validation still runs on writes.
GET/api/openapiDiscover API operations and request schemas

Discover API operations and request schemas

Public

Request

No body.

Response

OpenAPI document with path/query parameters, multipart uploads, and shared component schemas.
GET/api/design-systemsList your design systems

List your design systems

Session or Bearer token; library owner

Request

No body.

Response

{ systems: DesignSystem[] }; latest saved versions for this owner.
POST/api/design-systemsCreate a reusable design system

Create a reusable design system

Session or Bearer token; library owner

Request

Definition object matching /api/schema → designSystem.

Response

201 { system }; initial version is 1.

Includes theme tokens, component variants and reusable page compositions. Private media references cannot be captured; embed media or use public HTTPS URLs.

GET/api/design-systems/:idRead a library version

Read a library version

Session or Bearer token; library owner

Request

Optional positive integer query: version. Omit for latest.

Response

{ system: { id, version, definition, createdAt } }
GET/api/design-systems/:id/versionsList immutable library versions

List immutable library versions

Session or Bearer token; library owner

Request

No body.

Response

{ versions: [{ version, createdAt }] }; newest first.
PUT/api/design-systems/:idAppend a library version

Append a library version

Session or Bearer token; library owner

Request

{ expectedVersion, definition }; read the definition and its version first.

Response

{ system }; stale expectedVersion returns 409.

Previous definitions stay immutable. Never substitute a newer version number to force stale content through a conflict.

POST/api/design-systems/:id/applyApply a saved design system

Apply a saved design system

Session or Bearer token; project owner

Request

{ projectId, expectedRevision, version? }

Response

{ project }; project revision increments.

Own both library and project. Optional version selects a saved library version. Applies tokens/system while preserving authored component overrides; pins the library version in the project.

POST/api/design-systems/:id/insertInsert a library item

Insert a library item

Session or Bearer token; project owner

Request

{ projectId, expectedRevision, pageId, itemId, version? }

Response

{ project }; inserts the saved component/composition with fresh node IDs and remapped hierarchy/interactions.
DELETE/api/design-systems/:idDelete a design-system library

Delete a design-system library

Session or Bearer token; library owner

Request

No body.

Response

{ "ok": true }

Deletes this owned library and its versions. Previously applied project content remains embedded.

GET/api/fontsDiscover Google Fonts

Discover Google Fonts

Session or Bearer token

Request

Optional q query, maximum 200 characters; matches family/category without case sensitivity.

Response

{ fonts, source, message, fetchedAt? }; source is live, cache, or fallback.

The full catalog uses an operator Google Fonts API key. Without it, returns clearly labeled curated starter families. Choosing a Google font loads its face separately.

GET/api/providers/:provider/modelsDiscover provider model IDs

Discover provider model IDs

Account session or API key

Request

Provider: openai|anthropic|gemini|openrouter|fal|deepseek|leonardo|grok|custom-<slug>. Optional q query, maximum 200 characters; matches ID/name/category.

Response

{ models, source, message, fetchedAt?, truncated? }

Uses the saved provider connection. Custom endpoints and unavailable connections return labeled starter suggestions; manual model IDs remain available. OAuth MCP credentials cannot call this endpoint. No raw provider key is returned.

GET/api/catalogRead built-in design resources

Read built-in design resources

Public

Request

No body.

Response

{ themes, templates, blocks }
GET/api/configRead public configuration

Read public configuration

Public

Request

No body.

Response

Public feature configuration, including googleClientId, allowRegistration, githubEnabled, observability eligibility/retention, and analytics availability. Never includes provider keys or server secrets.
POST/api/auth/registerCreate an account

Create an account

Public; matching Origin header

Request

{ "email": "you@example.com", "password": "<12–128 characters>", "name": "Your name" }

Response

201 { user: { id, email, name } } + HttpOnly session cookie.

Registration must be enabled by the operator. Email is normalized; name is optional. Rate limited.

POST/api/auth/loginStart an email/password session

Start an email/password session

Public; matching Origin header

Request

{ "email": "you@example.com", "password": "<your password>" }

Response

{ user: { id, email, name } } + HttpOnly session cookie.
GET/api/auth/meRead the current account

Read the current account

Optional session or Bearer token

Request

No body.

Response

{ user: { id, email, name } | null }
GET/api/auth/githubStart GitHub sign-in

Start GitHub sign-in

Public browser navigation; configured GitHub OAuth app

Request

Navigate using the sign-in button. No request body.

Response

Redirects to GitHub authorization with browser-bound state and S256 PKCE; configuration errors redirect to /?auth_error=….
GET/api/auth/github/callbackComplete GitHub sign-in

Complete GitHub sign-in

Valid one-use state and initiating browser cookie

Request

GitHub supplies code and state, or an authorization error.

Response

Issues the studio session and redirects home on success. Errors redirect to /?auth_error=….

This is an OAuth callback, not an endpoint to call manually. Existing email/password accounts are not automatically linked by email.

GET/api/auth/github/statusRead your GitHub connection

Read your GitHub connection

Account browser session only

Request

No body.

Response

{ enabled: boolean, connected: boolean, login: string | null }
POST/api/auth/github/linkConnect GitHub to your existing account

Connect GitHub to your existing account

Account browser session; matching Origin

Request

No body.

Response

{ url }; navigate to the returned GitHub authorization URL.

The callback must complete in the same signed-in session. A GitHub identity already linked to another account is rejected.

POST/api/auth/logoutEnd a browser session

End a browser session

Session; matching Origin for cookie authentication

Request

No body.

Response

{ "ok": true }; clears the session cookie.

Logging out of a browser does not revoke API keys.

GET/api/projectsSearch and list projects

Search and list projects

Session or Bearer token

Request

Query: q (name/description), kind (web|slides|report|wireframe|3d|video), sort (updated|created|name).

Response

{ projects: ProjectSummary[] }; up to 500 owned projects. Summaries exclude document.
POST/api/projectsCreate or clone a project

Create or clone a project

Session or Bearer token

Request

{ "name": "Product story", "kind": "slides", "templateId": "product-deck" }

Response

201 { project: Project }; initial revision is 1.

Optional description, themeId, templateId, document. Supplying an owned document creates a new project and copies owned asset bytes; there is no separate REST clone route.

GET/api/projects/:idRead a project and revision

Read a project and revision

Session or Bearer token; project owner

Request

Replace :id with an actual project ID.

Response

{ project: { id, name, description, kind, document, revision, createdAt, updatedAt, publishedUrl? } }
PATCH/api/projects/:idUpdate project metadata

Update project metadata

Session or Bearer token; project owner

Request

{ "name": "Updated name", "description": "Updated description" }

Response

{ project: Project }; increments revision.

Both fields are optional. This metadata route checks the revision read by the server; use document PUT or CLI rename for an explicit client expectedRevision.

PUT/api/projects/:id/documentSave the canonical document

Save the canonical document

Session or Bearer token; project owner

Request

{ "document": "<complete DesignDocument object>", "expectedRevision": 1 }

Response

{ project: Project }; revision increments atomically. A stale expectedRevision returns 409.

document is an object, not a string: replace the illustrative placeholder. Preserve project ID/kind. Owned asset references must belong to this project. Targeted patch operations are available through CLI/MCP, which reuse this save contract.

POST/api/projects/:id/mergeMerge concurrent human and agent edits

Merge concurrent human and agent edits

Session or Bearer token; project owner

Request

{ baseRevision, base, document }; base is the complete document originally read, document is your edited copy.

Response

{ project: Project }; saves the reconciled document. Overlapping edits return 409 with error.code merge_conflict and error.details.paths.

baseRevision is the positive project revision originally read, separate from the brief revision. Preserve the exact base and project ID/kind. Never alter the base or invent its revision to force a merge; resolve overlapping changes explicitly.

GET/api/projects/:id/changesObserve the saved project revision

Observe the saved project revision

Session or Bearer token; project owner

Request

Optional query: since, the last observed nonnegative project revision; default 0.

Response

{ revision, unchanged: true } when since equals the saved revision; otherwise { revision, project: Project }.

Returns the current saved project when changed, not a history or operation log. Does not include unsaved browser edits.

DELETE/api/projects/:idDelete a project

Delete a project

Session or Bearer token; project owner

Request

No body.

Response

{ "ok": true }

Deletes the project, stored assets, and publications. This is destructive.

GET/api/projects/:id/checksInspect the saved design

Inspect the saved design

Session or Bearer token; project owner

Request

No body.

Response

{ projectId, revision, issues, counts: { warnings, information, total }, truncated, limitations }

Read-only deterministic preflight with node/page IDs and suggestions. Estimates bounds, text fit, opaque-hex contrast, missing/remote media, chart data, and duration limits. Does not certify accessibility or visual quality; inspect the actual preview.

GET/api/projects/:id/briefRead the design brief and scope

Read the design brief and scope

Session or Bearer token; project owner

Request

No body.

Response

{ brief: DesignBrief | null }

A brief has its own revision, separate from the document revision, plus request, status, message, questions, answers, scope, approvedAt, and updatedAt.

PUT/api/projects/:id/briefSave a brief, interview, answers, or scope

Save a brief, interview, answers, or scope

Session or Bearer token; project owner

Request

{ "expectedRevision": 0, "request": "Create a six-slide introduction for our team." }

Response

{ brief: DesignBrief }; increments the brief revision. Stale revisions return 409.

Revision 0 creates a brief and requires request. Supply at least one of request, interview, answers, or scope. Read interview/scope JSON Schemas at /api/schema. Answers map question IDs to text or multiple-choice arrays. Every edit invalidates prior approval. External agents can supply their own interview and scope without server BYOK.

POST/api/projects/:id/brief/interviewGenerate contextual interview questions or scope

Generate contextual interview questions or scope

Session or Bearer token; project owner

Request

{ "expectedRevision": 1, "provider": "openai" }

Response

{ brief: DesignBrief }; saves the validated provider response with revision protection.

Requires an existing brief and configured text-provider BYOK; charges may apply. Providers: openai, anthropic, gemini, openrouter, deepseek, custom-<slug>; model is optional. Returns up to eight contextual questions or a concrete scope. Invalid provider responses leave the saved brief unchanged.

POST/api/projects/:id/brief/approveApprove the current scope

Approve the current scope

Session or Bearer token; project owner

Request

{ "expectedRevision": 2 }

Response

{ brief: DesignBrief }; status becomes approved and approvedAt is recorded.

Requires a scope and answers to all required questions. Obtain explicit human approval of the current scope before calling. Approval increments the brief revision; it does not generate a design, save the document, or publish.

GET/api/projects/:id/assetsList project assets

List project assets

Session or Bearer token; project owner

Request

No body.

Response

{ assets: [{ id, name, type, mimeType, url, size }] }
POST/api/projects/:id/assetsUpload private media

Upload private media

Session or Bearer token; project owner

Request

multipart/form-data with a file field. Let your HTTP client set the multipart boundary.

Response

{ asset: { id, name, type, mimeType, url, size } }

Maximum 20 MB. PNG/JPEG/WebP/GIF, MP3/WAV/OGG, MP4/WebM, and GLB are supported with signature validation. Upload does not place a node on the canvas.

GET/api/assets/:idDownload private asset bytes

Download private asset bytes

Session or Bearer token; asset owner

Request

Replace :id with an actual asset ID.

Response

Binary response with the stored MIME type.
GET/api/projects/:id/messagesRead saved conversation

Read saved conversation

Session or Bearer token; project owner

Request

No body.

Response

{ messages: [{ id, role, text, createdAt }] }; latest 200 messages in chronological order.
POST/api/projects/:id/messagesAppend a conversation message

Append a conversation message

Session or Bearer token; project owner

Request

{ "role": "user", "text": "Make the title more concise." }

Response

201 { message: { id, role, text, createdAt } }

role is user or assistant; text is 1–30,000 characters. This stores a message; it does not invoke a provider.

POST/api/projects/:id/generateGenerate a design proposal

Generate a design proposal

Session or Bearer token; project owner

Request

{ "provider": "openai", "prompt": "Make the opening slide more spacious.", "expectedRevision": 1 }

Response

{ document: DesignDocument, usage? }

Optional model. Providers: openai, anthropic, gemini, openrouter, deepseek, custom-<slug>. Requires configured BYOK, may incur charges, and does not save. Prompt maximum 12,000 characters. Inspect, then save with the original revision.

POST/api/projects/:id/mediaGenerate or transform media

Generate or transform media

Session or Bearer token; project owner

Request

{ "provider": "fal", "kind": "audio", "prompt": "Warm ambient instrumental music", "durationSeconds": 30 }

Response

OpenAI, Gemini, Grok, custom: { asset }. fal and Leonardo: 202 { job: { id, status: "queued" } }.

kind: image|audio|video. Optional model, voice, sourceAssetId, durationSeconds, strength. Sources must belong to this project. OpenAI image/edit/speech; Gemini, Grok and Leonardo prompt-only images; custom OpenAI/Gemini compatible prompt-only images; fal image/edit, video/edit, music/effects/audio transformation. Requires BYOK and can incur charges.

GET/api/projects/:id/media/:jobIdPoll a media job

Poll a media job

Session or Bearer token; project owner

Request

Use the project ID and returned job ID.

Response

{ status: "queued" | "processing" } or { status: "completed", asset }.

Supports all fal media kinds. A completed result is reused on later polls. Failures return actionable errors; queued is not completed.

POST/api/projects/:id/exportDownload a rendered file

Download a rendered file

Session or Bearer token; project owner

Request

{ "format": "png", "pageIndex": 0, "expectedRevision": 1 }

Response

File bytes with Content-Type and Content-Disposition. No JSON success envelope.

Formats: json, html, svg, png, pdf, pptx, webm, mp4, react, glb, gltf. React returns a runnable frontend ZIP for Web/App or wireframe projects. GLB/glTF export the selected scene with geometry/materials/animation. pageIndex defaults to 0; expectedRevision is optional. PDF/PPTX include all pages. Import remote media before isolated cloud rendering. React source export does not require Chromium; GLB/glTF and raster/video formats use the configured browser renderer. Size and encoder limits apply.

POST/api/projects/:id/google-slidesCreate Google Slides

Create Google Slides

Session or Bearer token; project owner

Request

{ "accessToken": "<short-lived Google OAuth access token>" }

Response

{ url, presentationId }

Requires real Google authorization. Native text/shapes/HTTPS images are supported; unsupported complex nodes and private image URLs fail explicitly. Do not put the token in source files.

POST/api/projects/:id/publishPublish an immutable snapshot

Publish an immutable snapshot

Session or Bearer token; project owner

Request

No body.

Response

{ url, revision }

Makes this saved design and its referenced snapshot assets public. Later private edits do not change it.

DELETE/api/projects/:id/publishUnpublish a project

Unpublish a project

Session or Bearer token; project owner

Request

No body.

Response

{ "ok": true }; removes all public snapshots of this project.
POST/api/projects/:id/previewCreate a public preview link

Create a public preview link

Session or Bearer token; project owner

Request

No body.

Response

{ url, revision }

Creates the same immutable public snapshot as publish, under the preview naming used by agents. Later private edits do not change it.

DELETE/api/projects/:id/previewRemove preview links

Remove preview links

Session or Bearer token; project owner

Request

No body.

Response

{ "ok": true }; removes all public snapshots of this project.
POST/api/projects/:id/shareCreate a public share link

Create a public share link

Session or Bearer token; project owner

Request

No body.

Response

{ url, revision }

Creates the same immutable public snapshot as publish, under the share naming used by agents.

DELETE/api/projects/:id/shareRemove share links

Remove share links

Session or Bearer token; project owner

Request

No body.

Response

{ "ok": true }; removes all public snapshots of this project.
GET/published/:slugView a published snapshot

View a published snapshot

Public

Request

Use the slug from a publish response.

Response

HTML snapshot, including the trusted 3D/timeline viewer where applicable.
GET/published/:slug/assets/:idRead a snapshot asset

Read a snapshot asset

Public, scoped to this snapshot

Request

Use the snapshot asset URL. Private API asset URLs do not become public.

Response

Asset bytes only when this publication references the asset.
GET/api/providersList masked provider settings

List masked provider settings

Account session or API key

Request

No body.

Response

{ providers: [{ provider, name, baseUrl, model, protocol, authMethod, authHeader, configured, apiKey: "••••••••" }] }

API-key MCP clients can use list_provider_connections for these masked IDs. MCP OAuth tokens cannot access provider settings.

PUT/api/providers/:providerSave a BYOK connection

Save a BYOK connection

Account session or API key

Request

{ "apiKey": "<provider secret from secure input>", "model": "<optional model ID>" }

Response

{ provider, name, baseUrl, model, protocol, authMethod, authHeader, configured: true, apiKey: "••••••••" }

Providers: openai, anthropic, gemini, openrouter, fal, deepseek, leonardo, grok or custom-<slug>. Custom connections require name, baseUrl and model; protocol is openai, anthropic or gemini. authMethod: bearer, api-key (authHeader), basic (username:password credential), none. HTTPS origins must be operator-allowlisted. Omit apiKey to retain it; endpoint/auth changes require a new credential. Secrets are encrypted. Prefer CLI --key-env or --key-stdin; ChatGPT subscriptions do not include OpenAI API access.

DELETE/api/providers/:providerRemove a BYOK connection

Remove a BYOK connection

Account session or API key

Request

No body.

Response

{ "ok": true }
GET/api/tokensList API-key metadata

List API-key metadata

Account session or API key

Request

No body.

Response

{ tokens: [{ id, name, createdAt, lastUsedAt }] }

Raw keys are never returned by list. MCP OAuth cannot manage permanent credentials.

POST/api/tokensCreate an API key

Create an API key

Account session or API key

Request

{ "name": "Local design agent" }

Response

201 { id, token }; raw token is returned once.

Treat this response as a secret. Use the signed-in key-management UI to create your first key.

DELETE/api/tokens/:idRevoke an API key

Revoke an API key

Account session or API key

Request

Use the key ID from the metadata list, not the secret value.

Response

{ "ok": true }; revoked keys no longer authenticate.

Errors you can act on

JSON error shapejson
{
  "error": {
    "code": "revision_conflict",
    "message": "Project changed. Reload before saving."
  }
}
StatusMeaningNext step
400Invalid JSON, schema, source, or capabilityInspect error.code and optional validation details.
401Missing/invalid authenticationSign in or supply a valid Bearer token.
403Origin, scope, or configuration restrictionUse the correct account credential and trusted origin.
404Missing or other-user resourceRead IDs from your owned project list.
409Revision or account conflictRead current state and reconcile; do not blindly retry.
413Request, asset, or rendering budget exceededReduce bytes, dimensions, or workload.
429Rate limitedBack off before retrying.
502 / 503Upstream failure or unavailable rendering/configurationRead the actionable message; fix provider/browser configuration.

OAuth endpoints use the OAuth error shape, { error, error_description }, rather than the application JSON envelope.

Try the API

Requests run against this studio. Writes change your real project. The key stays in this page’s memory and is cleared when you leave.

OpenAPI JSON

CLI equivalent uses your environment key; no secret is included here.

curl -X GET 'https://studio.example/api/health' -H "Authorization: Bearer $DESIGN_STUDIO_API_KEY"