
Design Tool
Design REST API
Complete REST API for the Efecto Design Tool. Create sessions, execute design tools, upload images, search icons, publish sites, manage sharing, and more.
Prefer MCP?
OpenAPI Specification
On this page
How It Works
Agent → creates session via REST → Server → returns session URL → Browseropens URL → WebSocket connects → Agent executes tools via REST → Server forwards to browser → changes render in real-time
- Your agent creates a session via
POST /sessions - The user opens the returned URL in their browser
- Your agent executes design tools via
POST /sessions/:id/execute - Changes render instantly in the browser via WebSocket
- Optionally subscribe to
GET /sessions/:id/stream(SSE) for real-time updates
Base URL
https://efecto.app/api/v1/designAuthentication
Most design endpoints work without authentication. Sign-in is only required for endpoints that write persistent data or use paid features.
| Endpoints | Auth |
|---|---|
| Sessions, Execute, Stream, Poll, Tools | None |
| Icon Search, Icon SVG, Image Proxy | None |
| Upload Image, Publish, Shares | Required |
| AI Chat, AI Usage | Required + Pro |
Authentication uses Supabase session cookies, which are set automatically when a user signs in via the browser. API calls from the same browser context (e.g. fetch with credentials: "include") send cookies automatically.
Error Responses
All endpoints return errors as JSON with a consistent format:
{
"error": "Human-readable error message"
}| Status | Meaning |
|---|---|
| 400 | Invalid input, missing fields, validation failed |
| 401 | Not authenticated (no valid session) |
| 403 | Insufficient permissions or subscription required |
| 404 | Resource not found |
| 409 | Conflict (e.g. duplicate share) |
| 413 | Payload too large |
| 429 | Rate limited |
| 502 | External API error (e.g. Vercel, upstream image) |
Sessions
Manage the lifecycle of a design session. No authentication required.
Create Session
/api/v1/design/sessionsCreates a new design session. Returns a session ID and a URL for the user to open.
// Request
POST /api/v1/design/sessions
Content-Type: application/json
{
"label": "Landing page design"
}
// Response
{
"sessionId": "abc-123-def",
"designUrl": "https://efecto.app/design?session=abc-123-def",
"expiresAt": "2026-03-01T12:00:00Z"
}Get Session Status
/api/v1/design/sessions/:idCheck if the browser is connected and see pending/completed tool calls.
// Response
{
"session": {
"id": "abc-123-def",
"browserConnected": true,
"label": "Landing page design",
"createdAt": 1709280000000,
"lastActivity": 1709280060000,
"expiresAt": 1709283600000
},
"pendingCalls": 0,
"completedCalls": 12
}Close Session
/api/v1/design/sessions/:idCloses the session, disconnects the browser, and cleans up resources.
Tool Execution
Execute design tools, poll for results, and discover available tools.
Execute Tool
/api/v1/design/sessions/:id/executeExecute any design tool in the connected browser. Add ?wait=true to wait for the browser to process the call and return the result.
// Request
POST /api/v1/design/sessions/abc-123-def/execute?wait=true
Content-Type: application/json
{
"tool": "efecto_create_artboard",
"input": {
"name": "Desktop",
"width": 1440,
"height": 900,
"className": "flex flex-col",
"backgroundColor": "#ffffff"
}
}
// Response (wait=true)
{
"callId": "call-xyz",
"status": "completed",
"result": {
"success": true,
"message": "Artboard created",
"data": { "artboardId": "artboard-1" }
}
}
// Response (wait=false, default)
{
"callId": "call-xyz",
"status": "pending"
}Tool names
efecto_ (e.g. efecto_create_artboard). See the Tool Reference for all available tools.Poll for Result
/api/v1/design/sessions/:id/poll/:callIdPoll for the result of an async tool call (when you used wait=false or omitted it). Use this instead of ?wait=truewhen you don't want to block.
// Response (still processing)
{
"callId": "call-xyz",
"status": "pending",
"result": null
}
// Response (completed)
{
"callId": "call-xyz",
"status": "success",
"result": { "success": true, "message": "Artboard created", "data": {...} }
}
// Response (failed)
{
"callId": "call-xyz",
"status": "error",
"result": { "error": "Node not found" }
}List Tools
/api/v1/design/toolsReturns all available design tools with their input schemas. Useful for tool discovery and building dynamic UIs.
// Response
{
"total": 44,
"tools": [
{
"name": "efecto_create_artboard",
"description": "Creates a new artboard...",
"input_schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"width": { "type": "number" },
...
}
}
},
...
]
}SSE Event Stream
/api/v1/design/sessions/:id/streamSubscribe to real-time updates from the browser via Server-Sent Events.
// Connect
GET /api/v1/design/sessions/abc-123-def/stream
Accept: text/event-stream
// Events (unnamed — use onmessage, not addEventListener)
data: {"type":"connected","sessionId":"abc-123-def"}
data: {"type":"tool_call","callId":"call-xyz","tool":"efecto_create_artboard","input":{...}}
data: {"type":"heartbeat","timestamp":1709280060000}
data: {"type":"session_closed","reason":"Session expired"}Media & Assets
Upload images, search icons, and proxy external media. Icon endpoints are unauthenticated. Image upload requires sign-in.
Upload Image
/api/v1/design/upload-imageUpload an image file or fetch from a URL. Returns a permanent hosted URL. Requires authentication.
| Constraint | Value |
|---|---|
| Max file size | 10 MB |
| Allowed types | PNG, JPEG, GIF, WebP, SVG, AVIF |
| SSRF protection | Blocks localhost, private networks, cloud metadata |
// Option 1: Upload file (from browser)
const form = new FormData()
form.append("file", fileBlob)
const res = await fetch("/api/v1/design/upload-image", {
method: "POST",
credentials: "include",
body: form,
})
// Option 2: Fetch from URL (from browser)
const res = await fetch("/api/v1/design/upload-image", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url: "https://example.com/photo.jpg" }),
})
// Response (201)
{ "url": "https://abc123.public.blob.vercel-storage.com/hero-xyz.png" }Search Icons
/api/v1/design/icons/searchSearch across 4 icon libraries (~9,000+ icons). No authentication required.
| Param | Type | Description |
|---|---|---|
q | string | Search query (e.g. "arrow", "heart") |
library | string | phosphor | lucide | heroicons | radix (default: all) |
limit | number | Max results (default: 50, max: 200) |
// Request
GET /api/v1/design/icons/search?q=arrow&library=phosphor&limit=10
// Response
{
"query": "arrow",
"library": "phosphor",
"count": 10,
"results": ["arrow-right", "arrow-left", "arrow-up", ...],
"libraries": [
{
"id": "phosphor",
"name": "Phosphor",
"iconCount": 7000,
"variants": ["thin", "light", "regular", "bold", "fill", "duotone"]
},
{
"id": "lucide",
"name": "Lucide",
"iconCount": 1500,
"variants": ["regular"]
},
{
"id": "heroicons",
"name": "Heroicons",
"iconCount": 600,
"variants": ["outline", "solid", "mini"]
},
{
"id": "radix",
"name": "Radix",
"iconCount": 300,
"variants": ["regular"]
}
]
}Get Icon SVG
/api/v1/design/icons/svgReturns the raw SVG string for a specific icon. Cached for 1 year (immutable).
| Param | Type | Description |
|---|---|---|
name | string | Icon name (required) |
library | string | phosphor | lucide | heroicons | radix (default: phosphor) |
variant | string | Weight/variant (e.g. bold, fill, duotone, outline, solid) |
size | number | Icon size in pixels (default: 24) |
// Request
GET /api/v1/design/icons/svg?library=phosphor&name=arrow-right&variant=bold&size=32
// Response (Content-Type: image/svg+xml)
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256">...</svg>Image Proxy
/api/v1/design/image-proxyProxy external images server-side to bypass CORS and mixed-content restrictions. Returns the raw image bytes with proper content type. No authentication required.
| Constraint | Value |
|---|---|
| Max size | 10 MB |
| Max redirects | 3 |
| Timeout | 10 seconds |
| Caching | 1 hour |
GET /api/v1/design/image-proxy?url=https%3A%2F%2Fexample.com%2Fphoto.jpg
// Returns raw image bytes with Content-Type headerPublishing
Publish designs as live websites hosted on Vercel. Requires authentication.
Publish Design
/api/v1/design/publishDeploy a design as a static website. Provide the HTML and assets as files.
| Constraint | Value |
|---|---|
| Max files | 50 |
| Max per file | 5 MB |
| Max total payload | 10 MB |
// Request
POST /api/v1/design/publish
Content-Type: application/json
{
"siteName": "my-landing-page",
"files": [
{
"file": "index.html",
"data": "<!DOCTYPE html><html>...</html>",
"encoding": "utf-8"
}
],
"projectId": "prj_abc123" // optional: update existing site
}
// Response
{
"url": "my-landing-page.efecto.app",
"vercelUrl": "efecto-my-landing-page.vercel.app",
"projectId": "prj_abc123",
"projectName": "efecto-my-landing-page",
"deploymentId": "dpl_xyz789",
"status": "QUEUED"
}Check Deployment Status
/api/v1/design/publish?projectId=:idPoll for the status of a published site. You must own the project. The url returned here is the Vercel deployment URL (use the url from the POST response for the efecto.app subdomain).
// Response
{
"url": "efecto-my-landing-page-abc123.vercel.app",
"status": "READY", // QUEUED | BUILDING | READY | ERROR
"createdAt": "2024-01-15T10:30:00Z"
}Sharing & Permissions
Share designs with collaborators via email invites or share links. Requires authentication. Note: PATCH and DELETE identify the share via request body / query param respectively (not as a path segment).
Create Share
/api/v1/design/sharesInvite a collaborator by email or generate a share link. You must own the document.
// Email invite
POST /api/v1/design/shares
{
"documentId": "doc-uuid",
"email": "collaborator@example.com",
"role": "editor" // "viewer" or "editor"
}
// Generate share link
POST /api/v1/design/shares
{
"documentId": "doc-uuid",
"role": "viewer",
"type": "link"
}
// Response (201)
{
"share": {
"id": "share-uuid",
"document_id": "doc-uuid",
"role": "viewer",
"share_token": "abc-def-123",
"created_at": "2024-01-15T10:30:00Z"
}
}List Shares
/api/v1/design/shares?documentId=:idList all shares for a document. Owner only.
// Response
{
"shares": [
{
"id": "share-uuid",
"document_id": "doc-uuid",
"shared_with": "user-uuid",
"email": "collaborator@example.com",
"role": "editor",
"share_token": "abc-def-123",
"created_at": "2024-01-15T10:30:00Z"
}
]
}Update Share Role
/api/v1/design/shares// Request
PATCH /api/v1/design/shares
{ "shareId": "share-uuid", "role": "viewer" }
// Response
{ "success": true }Remove Share
/api/v1/design/shares?shareId=:idRevoke a share. Owner only.
Check Permissions
/api/v1/design/permissionsCheck what permission level the caller has for a document. Works for both authenticated users and unauthenticated users with a share token.
| Param | Type | Description |
|---|---|---|
documentId | string | Document ID (required) |
token | string | Share token for unauthenticated access |
// Response
{
"role": "owner" // "owner" | "editor" | "viewer" | null
}AI Chat
Streaming AI design assistant with tool use. Requires authentication and a Design Pro subscription.
Chat (Streaming)
/api/v1/design/ai/chatSend messages to the AI design assistant. Returns a Server-Sent Event stream with text deltas and tool calls that execute in the browser.
// Request
POST /api/v1/design/ai/chat
Content-Type: application/json
{
"messages": [
{ "role": "user", "content": "Make the heading bigger and bolder" }
],
"documentState": "<artboard data-id=\"ab-1\" ...>...</artboard>",
"selectedIds": ["node-abc"],
"selectedSubtrees": "<h1 data-id=\"node-abc\">Hello</h1>",
"artboards": [
{ "id": "ab-1", "name": "Desktop", "width": 1440, "height": 900 }
],
"activeArtboardId": "ab-1"
}
// Response: Server-Sent Events
data: {"type":"route","model":"sonnet","intent":"modify","reason":"Simple style change"}
data: {"type":"text_delta","text":"I'll make the heading"}
data: {"type":"tool_start","id":"call-1","name":"efecto_update_node"}
data: {"type":"tool_call","id":"call-1","name":"efecto_update_node","input":{"nodeId":"node-abc","className":"text-6xl font-black"}}
data: {"type":"tool_calls_pending","toolCalls":[{"id":"call-1","name":"efecto_update_node","input":{...}}]}
data: {"type":"usage","used":5,"limit":100,"remaining":95,"bonusCredits":0,"totalRemaining":95}
data: {"type":"done","reason":"complete"}Agentic loop
tool_calls_pending, execute the tools in the browser, then send the results back in a follow-up request so the AI can continue.// Follow-up request with tool results
POST /api/v1/design/ai/chat
{
"messages": [
{ "role": "user", "content": "Make the heading bigger and bolder" }
],
"documentState": "<artboard ...>...updated state...</artboard>",
"selectedIds": [],
"artboards": [...],
"pendingAssistantText": "I'll make the heading",
"pendingToolCalls": [
{ "id": "call-1", "name": "efecto_update_node", "input": { "nodeId": "node-abc", "className": "text-6xl font-black" } }
],
"pendingToolResults": [
{ "tool_use_id": "call-1", "result": "{\"success\":true,\"message\":\"Node updated\"}" }
]
}Check AI Usage
/api/v1/design/ai/usageCheck remaining AI message quota for the authenticated user.
// Response
{
"used": 12,
"limit": 100,
"remaining": 88,
"bonusCredits": 0,
"totalRemaining": 88,
"unlimited": false // true for admin users
}Quick Start Example
Create a landing page in 4 API calls:
# 1. Create session
curl -X POST https://efecto.app/api/v1/design/sessions \
-H "Content-Type: application/json" \
-d '{"label":"My landing page"}'
# 2. Create artboard (after user opens the URL)
curl -X POST https://efecto.app/api/v1/design/sessions/SESSION_ID/execute?wait=true \
-H "Content-Type: application/json" \
-d '{"tool":"efecto_create_artboard","input":{"name":"Desktop","width":1440,"height":900,"className":"flex flex-col"}}'
# 3. Add hero section
curl -X POST https://efecto.app/api/v1/design/sessions/SESSION_ID/execute?wait=true \
-H "Content-Type: application/json" \
-d '{"tool":"efecto_add_section","input":{"parentId":"ARTBOARD_ID","jsx":"<section className=\"flex flex-col items-center justify-center py-24 px-8\"><h1 className=\"text-6xl font-bold\">Hello World</h1></section>"}}'
# 4. Close session
curl -X DELETE https://efecto.app/api/v1/design/sessions/SESSION_IDReference
- Tool Reference — all 46 MCP tools with parameters and examples
- MCP integration — connect any AI tool via MCP
- Getting Started — install from scratch