Developers
Agent API (v1)
The Desyn REST API for agents and automation — base URLs, API keys and scopes, errors, pagination, rate limits and the full endpoint index.
On this page
The Agent API lets your own code and agents do what the editor and the built-in agent do: create and read designs, commit transactions, upload assets, run the agent and workflows, and export. Every endpoint is a thin HTTP wrapper over a backend function, so the API behaves exactly like the app.
Base URL#
| Installation | Base URL |
|---|---|
| desyn.app | https://api.desyn.app/api/v1 |
| Self-hosted | https://<CONVEX_SITE_URL host>/api/v1, e.g. https://convex-site.example.org/api/v1 |
Requests and responses are JSON (content-type: application/json) unless an endpoint says otherwise. Timestamps are milliseconds since the Unix epoch.
Authentication#
Create a key in Settings → API keys: give it a name, choose its scopes and, optionally, an expiry between 1 and 730 days. The key is shown once; Desyn only stores a hash of it.
Keys look like dsk_ followed by 43 characters. Send one with every request, either as a bearer token or in x-api-key:
curl https://api.desyn.app/api/v1/me \
-H "Authorization: Bearer $DESYN_API_KEY"A key acts as the member who created it, in the workspace it was created for, limited to its scopes. Write scopes only take effect while that member has at least the editor role in the workspace; otherwise the key is reduced to its read scopes. Revoke keys at any time in the same settings page.
Scopes#
| Scope | Allows |
|---|---|
designs:read | List and read designs, documents, transactions, versions, comments, shares and folders; describe and preview pages. |
designs:write | Create, change and delete designs and folders; commit transactions; comment; manage shares and versions; instantiate templates. |
assets:read | List assets and get signed URLs. |
assets:write | Upload, rename and delete assets. |
templates:read | Search and read templates. |
brand:read | Read brand kits. |
brand:write | Create, change and delete brand kits. |
ai:run | Start and control agent runs, asset tools and workflows, and list models. Spends credits on the hosted Pro plan. |
exports:write | Request exports and read their status. |
mcp | Connect to the MCP server. Requires the MCP feature (Pro or self-hosted). |
Errors#
Failed requests return an HTTP status and a JSON body with a stable, machine-readable code:
{
"error": {
"code": "LIMIT_REACHED",
"message": "You reached your plan limit for designs (20).",
"limit": "designs",
"max": 20,
"current": 20
}
}| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_ARGUMENT | A parameter is missing or invalid; field names it |
| 401 | UNAUTHENTICATED | Missing, malformed, expired or revoked key |
| 403 | FORBIDDEN | The key lacks the scope, or the member lacks the role |
| 403 | FEATURE_UNAVAILABLE | The plan does not include the feature; feature names it |
| 403 | EMAIL_NOT_VERIFIED | The member must verify their email first |
| 404 | NOT_FOUND | No such resource in this workspace |
| 409 | CONFLICT | The request conflicts with the current state |
| 410 | EXPIRED | A link, upload or run has expired |
| 422 | LIMIT_REACHED | A plan limit was reached; limit, max and current explain which |
| 429 | RATE_LIMITED | Too many requests; see rate limits |
| 501 | NOT_CONFIGURED | The installation has not configured what this needs (for example storage or a provider) |
| 500 | INTERNAL | Something failed on our side; safe to retry with backoff |
The message is written for humans and safe to show to users.
Rate limits#
AI endpoints share the account's fair-use limits: per-minute and per-day request caps and a maximum number of concurrent agent runs and workflows (see credits & fair use). When a limit is hit the API responds with 429, a Retry-After header in seconds, and the error fields retryAfterMs and scope (minute, day or concurrency).
On the hosted Pro plan, AI requests beyond the monthly credit pool are not rejected but soft-throttled: they start after a short delay. Requests that run on the member's own provider keys do not use credits.
Pagination#
List endpoints accept limit and cursor and return nextCursor; pass it back to get the next page. nextCursor is null on the last page.
Idempotency#
Transactions are idempotent on their tx.id: retrying a commit after a timeout returns the original result instead of applying the change twice. Generate transaction ids on the client (12 characters, lowercase letters and digits).
Endpoints#
| Method | Path | Endpoint | Scope |
|---|---|---|---|
| GET | /designs | List designs | designs:read |
| POST | /designs | Create a design | designs:write |
| GET | /designs/{designId} | Get a design | designs:read |
| PATCH | /designs/{designId} | Rename or move a design | designs:write |
| POST | /designs/{designId}/duplicate | Duplicate a design | designs:write |
| POST | /designs/{designId}/archive | Move to trash | designs:write |
| POST | /designs/{designId}/restore | Restore from trash | designs:write |
| DELETE | /designs/{designId} | Delete permanently | designs:write |
| GET | /designs/{designId}/document | Load the document | designs:read |
| POST | /designs/{designId}/transactions | Commit a transaction | designs:write |
| GET | /designs/{designId}/transactions | List transactions since a seq | designs:read |
| GET | /designs/{designId}/describe | Describe a page | designs:read |
| POST | /designs/{designId}/preview | Render a preview | designs:read |
| GET | /designs/{designId}/versions | List versions | designs:read |
| POST | /designs/{designId}/versions | Save a named version | designs:write |
| POST | /designs/{designId}/versions/{versionId}/restore | Restore a version | designs:write |
| GET | /designs/{designId}/shares | List share links | designs:read |
| POST | /designs/{designId}/shares | Create or update a share link | designs:write |
| GET | /designs/{designId}/comments | List comments | designs:read |
| POST | /designs/{designId}/comments | Add a comment or reply | designs:write |
| POST | /designs/{designId}/exports | Request an export | exports:write |
| GET | /exports/{exportId} | Get an export | exports:write |
| POST | /assets/uploads | Request an upload | assets:write |
| POST | /assets/{assetId}/finalize | Finalize an upload | assets:write |
| GET | /assets | List assets | assets:read |
| GET | /assets/{assetId} | Get an asset | assets:read |
| PATCH | /assets/{assetId} | Rename an asset | assets:write |
| DELETE | /assets/{assetId} | Delete an asset | assets:write |
| POST | /designs/{designId}/agent-runs | Start an agent run | ai:run |
| GET | /agent-runs/{runId} | Get a run | ai:run |
| GET | /agent-runs/{runId}/events | Follow run events | ai:run |
| POST | /agent-runs/{runId}/answer | Answer a question | ai:run |
| POST | /agent-runs/{runId}/cancel | Cancel a run | ai:run |
| POST | /assets/generate | Generate or transform an asset | ai:run |
| POST | /workflows | Start a workflow | ai:run |
| GET | /workflows/{workflowId} | Get a workflow | ai:run |
| GET | /ai/models | List models | ai:run |
| GET | /templates | Search templates | templates:read |
| GET | /templates/{slug} | Get a template | templates:read |
| POST | /templates/{slug}/instantiate | Instantiate a template | designs:write |
| GET | /brand-kits | List brand kits | brand:read |
| POST | /brand-kits | Create a brand kit | brand:write |
| PATCH | /brand-kits/{brandKitId} | Update a brand kit | brand:write |
| DELETE | /brand-kits/{brandKitId} | Delete a brand kit | brand:write |
| GET | /folders | List folders | designs:read |
| POST | /folders | Create a folder | designs:write |
| GET | /me | Get the current user | any |
| GET | /workspaces | List workspaces | any |
| GET | /credits | Get credit balance | any |
| GET | /usage | Get usage | any |
Working with designs#
The endpoints that matter most for agents:
- Describe a page to understand it, or load the document for full detail.
- Change it either by committing transactions you build yourself, or by starting an agent run with a goal in plain language.
- Render a preview to check the result visually, then export.
Prefer the MCP server if your agent speaks MCP, and the TypeScript SDK for typed access from Node.js, Deno, Bun or the browser.