Skip to documentation
Design Studio AI
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"

105 of 105 endpoints

POST/api/projects/:id/inspectVisually inspect a saved page or project

Visually inspect a saved page or project

Session or Bearer token; project owner

Request

JSON: mode page|overview (default overview), pageId or zero-based pageIndex (page mode only), expectedRevision, time 0–3600 (default 0), offset (default 0), limit 1–12 (default 6), columns 1–4 (default 3), tileSize 160–800 (default 400), maxDimension 256–2048 (default 1600). Discover visualInspection in /api/schema.

Response

{ scope: page|project, source: saved, total, offset, nextOffset, items, images }; PNG base64 in images[].data. Items map project/page IDs, revision, original dimensions, time and pixel bounds to imageIndex.

Private read-only rendering; no publication, provider call, or document/brief mutation. Page selectors are exclusive; page mode defaults to the first page. Overview paginates pages. Save unsaved browser edits first. Decode and actually view the PNG before claiming visual review. Renderer limits apply; invalid selections, stale revisions and rendering failures are explicit errors.

POST/api/projects/inspectVisually inspect workspace covers

Visually inspect workspace covers

Session or Bearer token; owned projects only

Request

JSON: offset (default 0), limit 1–12 (default 6), time 0–3600 (default 0), tileSize 160–800 (default 400). Discover workspaceInspection in /api/schema.

Response

{ scope: workspace, source: saved, total, offset, nextOffset, items, images }; first-page PNG covers with per-project saved revisions. Empty results have no items/images.

Projects ordered by ID. Follow nextOffset until null for remaining covers; concurrent creation/deletion can change offset pagination. Revisions describe individual project snapshots, not one atomic workspace snapshot. No publication or AI provider call. Use project page/overview inspection for the other pages.

GET/api/community/taxonomyDiscover Community categories, formats and limits

Discover Community categories, formats and limits

Public

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/listingsSearch live community designs with category, tags, formats, sort and cursor filters

Search live community designs with category, tags, formats, sort and cursor filters

Public

Request

q, kind, tags, format, period, creator, collection, sort, cursor, limit.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/listings/{id}Read a live design and its download files

Read a live design and its download files

Public

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/creators/{handle}Read a public creator profile

Read a public creator profile

Public

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/collectionsList curated Community collections

List curated Community collections

Public

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/collections/{id}Read a curated Community collection

Read a curated Community collection

Public

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/listings/{id}/versions/{version}/previewGet sandboxed HTML preview of a retained live version

Get sandboxed HTML preview of a retained live version

Public

Request

No body.

Response

Ready file bytes; Content-Type identifies the actual format.
GET/api/community/listings/{id}/versions/{version}/files/{fileId}Download real ready file bytes; first eligible download contributes to creator impact

Download real ready file bytes; first eligible download contributes to creator impact

Public

Request

No body.

Response

Ready file bytes; Content-Type identifies the actual format.
POST/api/community/preflightReview the public projection, disclosures, formats and digest before publishing

Review the public projection, disclosures, formats and digest before publishing

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/metadata/generateDraft a listing title, description and tags using an owned saved project revision and configured text provider. Sends bounded visible text/structure plus entered fields/instructions, incurs provider usage, and never saves or publishes. Defaults to the first configured text connection. Review the suggestion and run preflight with the approved fields before publication.

Draft a listing title, description and tags using an owned saved project revision and configured text provider. Sends bounded visible text/structure plus entered fields/instructions, incurs provider usage, and never saves or publishes. Defaults to the first configured text connection. Review the suggestion and run preflight with the approved fields before publication.

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/listingsExplicitly confirm CC-BY-4.0 and public disclosure to publish the reviewed revision; reuse exact operation ID and payload on retry

Explicitly confirm CC-BY-4.0 and public disclosure to publish the reviewed revision; reuse exact operation ID and payload on retry

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/listings/{id}/releasesPublish a new immutable release at the reviewed project and listing revisions

Publish a new immutable release at the reviewed project and listing revisions

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/listings/{id}/unlistRevoke public access to all listing versions at the observed listing revision

Revoke public access to all listing versions at the observed listing revision

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/jobs/{operationId}Read your durable Community operation status and result

Read your durable Community operation status and result

Session or Bearer token; owner checks apply

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/jobs/{operationId}/previewRead your private staged publication preview

Read your private staged publication preview

Session or Bearer token; owner checks apply

Request

No body.

Response

Ready file bytes; Content-Type identifies the actual format.
GET/api/community/jobs/{operationId}/files/{fileId}Download your private staged file

Download your private staged file

Session or Bearer token; owner checks apply

Request

No body.

Response

Ready file bytes; Content-Type identifies the actual format.
POST/api/community/listings/{id}/remixCreate an independent private project with owned assets and attribution from a pinned public version

Create an independent private project with owned assets and attribution from a pinned public version

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/importsImport a portable ZIP into an independent private project; operationId makes exact retries safe

Import a portable ZIP into an independent private project; operationId makes exact retries safe

Session or Bearer token; owner checks apply

Request

Multipart file ZIP and operationId; 20 MiB package limit.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/me/listingsList your publications including private management states

List your publications including private management states

Session or Bearer token; owner checks apply

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/me/bookmarksList your private saved Community designs

List your private saved Community designs

Session or Bearer token; owner checks apply

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/me/impactRead server-confirmed creator impact and milestone badges

Read server-confirmed creator impact and milestone badges

Session or Bearer token; owner checks apply

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/me/profileRead your opt-in Community profile and revision

Read your opt-in Community profile and revision

Session or Bearer token; owner checks apply

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
PUT/api/community/me/profileCreate or update your public profile at its observed revision

Create or update your public profile at its observed revision

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/me/profile/generateUse your configured text provider to suggest a public display name, handle and bio. Incurs provider usage; sends only supplied fields/instructions, defaults to your first configured text connection, and never saves or publishes. Review before set-profile; handle availability is checked again when saving.

Use your configured text provider to suggest a public display name, handle and bio. Incurs provider usage; sends only supplied fields/instructions, defaults to your first configured text connection, and never saves or publishes. Review before set-profile; handle availability is checked again when saving.

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
PUT/api/community/listings/{id}/bookmarkIdempotently save a live design to your private bookmarks

Idempotently save a live design to your private bookmarks

Session or Bearer token; owner checks apply

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
DELETE/api/community/listings/{id}/bookmarkIdempotently remove a private bookmark

Idempotently remove a private bookmark

Session or Bearer token; owner checks apply

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/listings/{id}/reportsReport a pinned design version with a reason and exact-retry operation ID

Report a pinned design version with a reason and exact-retry operation ID

Session or Bearer token; owner checks apply

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/moderation/reportsOperator session/API key only: list private reports

Operator session/API key only: list private reports

Operator session or API key; no OAuth

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/moderation/collectionsOperator only: list collections including unavailable reviewed items

Operator only: list collections including unavailable reviewed items

Operator session or API key; no OAuth

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/moderation/reports/{id}Operator only: inspect a pinned report and content availability

Operator only: inspect a pinned report and content availability

Operator session or API key; no OAuth

Request

No body.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/community/moderation/reports/{id}/previewOperator only: preview retained reported content

Operator only: preview retained reported content

Operator session or API key; no OAuth

Request

No body.

Response

Ready file bytes; Content-Type identifies the actual format.
GET/api/community/moderation/reports/{id}/files/{fileId}Operator only: download retained evidence bound to the report

Operator only: download retained evidence bound to the report

Operator session or API key; no OAuth

Request

No body.

Response

Ready file bytes; Content-Type identifies the actual format.
POST/api/community/moderation/reports/{id}/resolveOperator only: hide, restore or dismiss with observed report/listing revisions and a reason

Operator only: hide, restore or dismiss with observed report/listing revisions and a reason

Operator session or API key; no OAuth

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
POST/api/community/moderation/collectionsOperator only: curate explicitly reviewed listing versions

Operator only: curate explicitly reviewed listing versions

Operator session or API key; no OAuth

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
PUT/api/community/moderation/collections/{id}Operator only: update ordered curation at the observed collection revision

Operator only: update ordered curation at the observed collection revision

Operator session or API key; no OAuth

Request

Canonical request in /api/schema → community. JSON body requires the fields listed there.

Response

Validated JSON response; asynchronous writes return durable job status.
GET/api/projects/:id/sceneInspect 3D mesh and rig

Inspect 3D mesh and rig

Session or Bearer token; project owner

Request

Optional pageId and time (seconds).

Response

Revision, topology diagnostics, bones and sampled deformation bounds.
POST/api/projects/:id/sceneAuthor 3D character

Author 3D character

Session or Bearer token; project owner

Request

pageId, command, expectedRevision, preview (default true). Discover sceneCommands in /api/schema.

Response

Preview or applied revision with compact diagnostics. Apply uses atomic owner/revision validation.
GET/api/projects/:id/thumbnailLoad a persisted project cover

Load a persisted project cover

Session or Bearer token; project owner

Request

Optional query revision: positive saved revision; defaults to current.

Response

200 image/png (maximum 480px per side); 202 {status: rendering, revision} with Retry-After: 2 while another render is active.

Owner-only. Cache misses render once using the isolated server renderer; project summaries expose thumbnailUrl for the current revision and thumbnailRevision for the latest ready cover. Retains two latest completed revisions; older missing covers return 404. Failures preserve the previous cover, with a 30-second retry cooldown. Import external media into the project first. No AI provider call.

GET/api/projects/:id/motionInspect character motion

Inspect character motion

Session or Bearer token; project owner

Request

Optional query: characterId, nodeId, time (seconds).

Response

Revision, rigs, clips, skins, constraints and optional sampled pose.
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", "revision": "<deployed commit> | null" }

revision is the commit stamped into the built site; it is null for local and self-hosted builds that have no release marker.

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": "[email protected]", "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": "[email protected]", "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. Optional expectedBriefRevision guards reviewed proposals against brief changes. 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, motion, png-sequence, spritesheet, scene-angles, editable-scene. scene-angles at start returns four PNGs; adding end and reviewSamples (2–25, default 5) returns four views per sampled time, contact-sheet.png and views.json diagnostics. editable-scene requires nodeId and returns canonical JSON with a hidden original-GLB checkpoint, without saving; project asset references remain. Frame ZIPs accept start/end/fps. 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"