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.
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 sessionRequest
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 sessionRequest
{"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 sessionRequest
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 sessionRequest
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 sessionRequest
{"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 authenticationRequest
{}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 grantRequest
{}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 grantRequest
{"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 grantRequest
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 sessionRequest
{"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 sessionRequest
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 sessionRequest
{"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 sessionRequest
{"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 grantRequest
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 grantRequest
{"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 grantRequest
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 grantRequest
{"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 grantRequest
{"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 grantRequest
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 grantRequest
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 grantRequest
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 grantRequest
{}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 sessionRequest
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 grantRequest
{"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 grantRequest
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 grantRequest
{"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 grantRequest
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 grantRequest
{"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 sessionRequest
{"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 grantRequest
{"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 grantsRequest
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 onlyRequest
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 onlyRequest
{ 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 onlyRequest
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 onlyRequest
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 grantRequest
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 grantRequest
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 onlyRequest
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 onlyRequest
{ 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 onlyRequest
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 onlyRequest
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 enabledRequest
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 sessionRequest
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=allRequest
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 defaultRequest
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 defaultRequest
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 suppliedRequest
{ 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
PublicRequest
No body.Response
{ "ok": true, "service": "design-studio-ai" }GET/api/schemaRead live JSON Schemas
Read live JSON Schemas
PublicRequest
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
PublicRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
{ 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 ownerRequest
{ 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 ownerRequest
{ 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 ownerRequest
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 tokenRequest
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 keyRequest
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
PublicRequest
No body.Response
{ themes, templates, blocks }GET/api/configRead public configuration
Read public configuration
PublicRequest
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 headerRequest
{ "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 headerRequest
{ "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 tokenRequest
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 appRequest
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 cookieRequest
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 onlyRequest
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 OriginRequest
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 authenticationRequest
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 tokenRequest
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 tokenRequest
{ "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 ownerRequest
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 ownerRequest
{ "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 ownerRequest
{ "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 ownerRequest
{ 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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
{ "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 ownerRequest
{ "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 ownerRequest
{ "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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
{ "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 ownerRequest
{ "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 ownerRequest
{ "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 ownerRequest
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 ownerRequest
{ "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 ownerRequest
{ "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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
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 ownerRequest
No body.Response
{ "ok": true }; removes all public snapshots of this project.GET/published/:slugView a published snapshot
View a published snapshot
PublicRequest
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 snapshotRequest
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 keyRequest
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 keyRequest
{ "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 keyRequest
No body.Response
{ "ok": true }GET/api/tokensList API-key metadata
List API-key metadata
Account session or API keyRequest
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 keyRequest
{ "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 keyRequest
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
{
"error": {
"code": "revision_conflict",
"message": "Project changed. Reload before saving."
}
}| Status | Meaning | Next step |
|---|---|---|
| 400 | Invalid JSON, schema, source, or capability | Inspect error.code and optional validation details. |
| 401 | Missing/invalid authentication | Sign in or supply a valid Bearer token. |
| 403 | Origin, scope, or configuration restriction | Use the correct account credential and trusted origin. |
| 404 | Missing or other-user resource | Read IDs from your owned project list. |
| 409 | Revision or account conflict | Read current state and reconcile; do not blindly retry. |
| 413 | Request, asset, or rendering budget exceeded | Reduce bytes, dimensions, or workload. |
| 429 | Rate limited | Back off before retrying. |
| 502 / 503 | Upstream failure or unavailable rendering/configuration | Read 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.
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"