REST API
/v1/diagrams does the same work as the MCP tools, through the same code. The full contract, with every field and status code, is in the OpenAPI spec. The first version, /v1/scenes, is retired: every path answers 410 with code: "MOVED" and the method and path that replace it.
Authentication
Send an API key as Authorization: Bearer <key> (or in X-API-Key) on every call except these, which need none: POST /v1/diagrams/validate, POST /v1/diagrams/preview, GET /v1/public/diagrams/{ref} (version links, by a published diagram’s ID or a share link’s token), POST /v1/public/diagrams/{ref}/report, and the signed image links a render returns. Create keys under Dashboard → API keys. A key starts with dsp_sk_ and is shown once, when it is created. It acts in the workspace selected when it was made.
The MCP server also signs people in with their Zindex account (OAuth 2.1), for clients such as claude.ai and ChatGPT that can’t send a key (MCP tools). Those sign-in tokens work only on /mcp.
- Key errors. A key that isn’t accepted gets
401with acode:API_KEY_INVALID(unknown, or its account was closed),API_KEY_REVOKED(revoked, or its person is no longer in its workspace) orAPI_KEY_EXPIRED. A request with no key at all getsAUTH_REQUIRED. Retrying the same key won’t help; use another. - Workspaces. A diagram belongs to a workspace: your personal one, or a team workspace you are in. Each key acts in exactly one workspace, and any key of anyone in that workspace can read its diagrams. A diagram in another workspace answers 404
NOT_FOUND, the same as one that doesn’t exist. No endpoint takes a workspace parameter; to work in two workspaces, use a key for each (Workspaces). - Write and read keys. A key has
scopewriteorread. A read key finds, reads, renders, compares and exports one diagram. Anything that changes or shares a diagram, or reports a problem with one, answers403withcode: "READ_ONLY"andreason:credentialfor a read key,rolewhen the key’s person is a viewer in the workspace, whose keys act read-only whatever their scope. - Email verification. Until the account has verified its email, saving, editing, deleting, restoring, sharing and reporting a diagram, and sending feedback, return
403withcode: "EMAIL_NOT_VERIFIED"; send the person to https://zindex.ai/verify-email. Reads, renders and the endpoints that need no key are never held back.
To create another key with an existing one:
curl -s https://api.zindex.ai/v1/auth/keys \
-H "Authorization: Bearer $ZINDEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Production Key" }'
The response holds the new key, which can’t be retrieved again, with its scope and workspaceId. The new key acts in the same workspace as the key that made it. Add "scope": "read" for a read key; the default is write when the caller can write, and read otherwise. Asking for write with a read key, or as a viewer, answers 403 with code: "READ_ONLY". Add "expiresInDays" (a whole number from 1 to 366) for a key that expires; leave it out, or send null, for one that doesn’t. Any other value returns 400 with code: "INVALID_EXPIRES_IN_DAYS". The number of keys a workspace can have depends on its plan (Limits); a viewer can hold 3 in a workspace.
Endpoints
| Method and path | Does |
|---|---|
POST /v1/diagrams | Save a diagram: { scene or mermaid, key?, brief?, message? } |
GET /v1/diagrams | Find diagrams: query, key, limit, cursor; deleted=true lists the ones deleted in the last 24 hours, which can still be restored |
GET /v1/diagrams/{id} | Read: view (outline, dsp or mermaid), revision, asOf, knownRevision, elements, cursor |
POST /v1/diagrams/{id}/revisions | Change it with ops or edited mermaid, making the next revision |
GET /v1/diagrams/{id}/revisions | History: limit, cursor, asOf |
GET /v1/diagrams/{id}/compare | What changed between from and to (revision numbers or dates) |
GET /v1/diagrams/{id}/render | SVG and PNG links to one version (revision or asOf): permanent for a published diagram, otherwise signed and valid for 7 days |
GET /v1/diagrams/{id}/export | The whole history as JSON Lines, oldest first (see Export) |
GET /v1/workspace/export | Every diagram in the workspace, each with its whole history, in one file (see Export); also at GET /v1/account/export |
GET /v1/images/{id}@{revision}.svg or .png | One version’s image |
POST /v1/diagrams/validate | Check without saving: { scene }, { mermaid }, or the scene document itself as the body (no key needed) |
POST /v1/diagrams/preview | The image of a scene or Mermaid without saving it: SVG, or PNG with format: "png"; theme draws it in clean, dark, blueprint or sketch (no key needed) |
DELETE /v1/diagrams/{id}?confirm=true | Delete, with a 24-hour undo |
POST /v1/diagrams/{id}/undelete | Undo a delete |
PUT /v1/diagrams/{id}/sharing | { "visibility": "public" } or "private"; publishing returns the public link and madePublicAt |
POST /v1/diagrams/{id}/links | Create a share link, on Pro or Team (see Version links) |
GET /v1/diagrams/{id}/links | The diagram’s share links, newest first, each with who made it (createdBy) |
DELETE /v1/diagrams/{id}/links/{linkId} | Revoke a share link |
POST /v1/diagrams/{id}/reports/preview | Preview a problem report (see Report a problem) |
POST /v1/diagrams/{id}/reports | Report a problem with one version |
GET /v1/diagrams/{id}/reports | Your reports on the diagram, newest first |
GET /v1/diagrams/{id}/reports/{reportId} | One report, drawn as Zindex support sees it |
DELETE /v1/diagrams/{id}/reports/{reportId} | Withdraw a report |
POST /v1/feedback | Send Zindex feedback, with or without a diagram (see Feedback) |
GET /v1/feedback | Your feedback, newest first, with its status |
GET /v1/public/diagrams/{ref} | What a version link’s page shows; add .svg or .png for the image (no key needed) |
POST /v1/public/diagrams/{ref}/report | Report a diagram seen at a version link, published or shared with a link, that breaks the content policy (no key needed) |
POST /v1/diagrams/{id}/move | Move a diagram from your personal workspace into a team workspace; the signed-in dashboard only (Workspaces) |
Wherever {id} appears, the diagram’s ID or your key for it works, except under /v1/public, which takes the ID, or a share link’s token, but never a key.
Save
curl -s https://api.zindex.ai/v1/diagrams \
-H "Authorization: Bearer $ZINDEX_API_KEY" -H "Content-Type: application/json" \
-d '{
"key": "payments-architecture",
"brief": "Checkout payment services, left to right.",
"scene": {
"schemaVersion": "0.1",
"scene": { "title": "Payments" },
"layoutStrategy": { "direction": "LR" },
"elements": [
{ "id": "api", "kind": "node", "nodeType": "service", "label": "API" },
{ "id": "db", "kind": "node", "nodeType": "database", "label": "Ledger" },
{ "id": "e1", "kind": "edge", "from": { "elementId": "api" }, "to": { "elementId": "db" }, "label": "writes" }
]
}
}'
{"id":"dgm_7Q2kD9a1B2c3","key":"payments-architecture","revision":1,"hash":"sha256:3f9a…","chain":"sha256:fdac…","warnings":[],"created":true}
Instead of scene you can send Mermaid text as mermaid, for an erDiagram or a flowchart (graph). Element IDs come from the Mermaid IDs, and the same text always gives the same diagram. What Mermaid leaves out is listed in warnings, and other Mermaid types are refused: see Mermaid scope.
warnings lists what checking the scene and drawing it noticed, each with the element when there is one and a one-line fix: for example TEXT_OVERFLOW when text doesn’t fit its element, or NODE_OVERLAP_DETECTED when two nodes sit on top of each other. The diagram is saved either way; an edit fixes it. POST /v1/diagrams/validate reports the same warnings without saving.
Zindex mints the ID; any scene.id you send is ignored. The key is your own name for the diagram, unique among the workspace’s live diagrams. Sending the same create again, with the same key and content, returns the existing diagram with created: false and status 200 (a new diagram answers 201), so retries are safe. The same key with different content, including after an edit, is a 409, KEY_EXISTS, and so is a teammate’s create with a key the team workspace already has, whatever its content: read and edit that diagram instead. Without a key, every create makes a new diagram.
hash is the version’s content hash, the SHA-256 of the scene that view=dsp returns, in RFC 8785 canonical form. chain is its chain hash. It also covers the version’s stored image and the chain hash of the version before it, so it changes if anything up to that version changes. chain is null until Zindex has computed it, normally when the version is saved; a render, an export or the next edit computes a missing one. Reads and the history never compute it. Verifying shows how to check a whole history with them.
Read
A read answers JSON: { id, revision, text }, with nextCursor when a long outline continues. GET /v1/diagrams/payments-architecture returns this outline as its text:
dgm_7Q2kD9a1B2c3 "Payments" r1 2026-10-05T09:12Z sha256:3f9a0c1d2e4b
key: payments-architecture
brief: Checkout payment services, left to right.
recent: r1 curl/8.7.1
outline: 2 nodes, 1 edges
api service "API"
db database "Ledger"
e1: api -> db "writes"
view=dspreturns{ id, key, revision, hash, chain, createdAt, visibility, scene }instead, wheresceneis the scene document with defaults filled in and withoutcomputed, the engine’s drawing output (element boxes, edge routes, label positions). It holds what was written: what the engine infers while drawing, such as an ER edge end’s cardinality from its column, isn’t in it. Thesceneis valid input:POST /v1/diagramswith{ "scene": ... }saves a copy under a new ID. Each node’slayoutholds the position the engine placed it at, which is part of the content and itshash. Later edits keep it unless a node that grows needs the room, a frame added or deleted round it would leave frames overlapping or a frame holding a node that isn’t its member, or anorderconstraint you add finds its two nodes the wrong way round. The edit’schangedlists the nodes that move. SendautoLayoutto have the engine place nodes again. The engine lays sequence diagrams out from their messages, so their nodes stay atx: 0, y: 0, which means not placed.view=mermaidreturns{ id, revision, hash, chain, mermaid, notes }: the diagram as Mermaid you can edit and send back (Edit as Mermaid). Entity-relationship diagrams come back as anerDiagram, every other family as aflowchart, andnotessay what Mermaid can’t show. Sequence diagrams have no Mermaid view yet (VIEW_UNAVAILABLE).revision=3, orasOf=2026-09-26(the end of that day in UTC) or an ISO timestamp with an offset, reads an earlier version.knownRevision=1, on a read of the latest version, returns{ "unchanged": true }, or only what changed since revision 1, one line per element.elements=api,dblimits the outline to those elements and their neighbors.
Change
curl -s https://api.zindex.ai/v1/diagrams/payments-architecture/revisions \
-H "Authorization: Bearer $ZINDEX_API_KEY" -H "Content-Type: application/json" \
-d '{
"baseRevision": 1,
"message": "Add the job queue",
"requestId": "6f1c2e7a-4b0d-4c55-9a51-2f1f8f7c9d10",
"ops": [{ "op": "createNode", "id": "queue", "nodeType": "queue", "label": "Jobs" }]
}'
{"id":"dgm_7Q2kD9a1B2c3","revision":2,"hash":"sha256:9b1c…","chain":"sha256:e665…","warnings":[],"changed":{"added":["queue"],"updated":[],"removed":[]}}
Every edit needs baseRevision, the revision you planned it against. Send exactly one of ops (operations, up to 500), mermaid (below), restoreRevision (a revision number, or { "asOf": "2026-09-26" }), or brief on its own. brief may also go with ops or mermaid; null removes it.
- Every change appends a revision; nothing is overwritten.
- An edit that changes nothing returns
noop: trueand makes no revision. - An edit with an error saves nothing and returns a 422,
VALIDATION_FAILED, witherrors. That includes an op that can’t apply, such asmoveElementon an edge, and a result that breaks a rule the diagram didn’t. - A retry with the same
requestIdreturns the first result withreplayed: true. The samerequestIdwith a different edit is a 422,REQUEST_ID_REUSED. - If the diagram moved on since
baseRevision, the answer is a 409,REVISION_CONFLICT, with the currentrevisionand, when your base is older than it,changes, the elements that changed since your base. A retry whose result is already the current content returnsnoop: trueinstead.
Edit as Mermaid
Send the whole diagram as mermaid instead of ops, usually text you read with view=mermaid and changed. Zindex compares it with the baseRevision version and applies only the differences, as operations, so everything you didn’t change keeps its ID. Nodes and edges missing from the text are deleted, and frames and groups never change this way. It works on architecture and entity-relationship diagrams; Mermaid scope has the rules.
Images
GET /v1/images/[email protected] with your API key returns that version’s SVG; .png returns a PNG. Each version’s image is drawn once, when it is saved, and kept, so it never changes; add ?engine=current to draw it again with today’s engine instead (not stored). Add ?from=1 to draw that version with what changed since revision 1 colored: added in green, removed in red, changed in amber (from must be another revision of the diagram; anything else is a 400). GET /v1/diagrams/{id}/render, like the MCP tool diagram_render, returns links to the same images that a person can open from a chat without a key: a published diagram’s version links, which don’t expire but stop if the diagram is made private or deleted, with url for the version’s page; for any other diagram, signed links that work for 7 days, with expires. Render links draw the plain version: they ignore from, and diagram_render has no from, so an agent connected only through MCP sign-in gets changes as text from diagram_history with compare rather than as a colored image.
Version links
Sharing compares Only you, Anyone with the link and Public. A published diagram, and a diagram shared with a link, has a page and an image for every version that anyone can open without a key:
| Link | Shows |
|---|---|
https://zindex.ai/d/{ref} | The latest version: its image, number and date, and the other versions |
https://zindex.ai/d/{ref}@{revision} | That version, which never changes |
The same with .svg or .png | The image itself |
{ref} is a published diagram’s ID, or a share link’s token. An image is the one Zindex kept for the version, the same picture every other link to it shows. The website answers these links from GET /v1/public/diagrams/{ref}, which you can call directly; add .svg or .png for the image.
Putting a diagram in a doc, issue or README
Pick the link by what the place is for:
| Where | Use | Why |
|---|---|---|
| GitHub issue, pull request or comment | One version, its image linked to its page: [](https://zindex.ai/d/{ref}@3) | The discussion is about that picture, so it shouldn’t change under it |
| README or wiki | The latest version: https://zindex.ai/d/{ref}.svg, linked to https://zindex.ai/d/{ref} | It shows each new version; GitHub’s image proxy follows within minutes |
| Google Docs | A PNG: Insert, Image, By URL with https://zindex.ai/d/{ref}@3.png, or paste the image | Docs doesn’t take SVG, and keeps a copy of the image when it is inserted, so it never updates |
| Notion or Confluence | An image link, https://zindex.ai/d/{ref}@3.png (or .svg), pasted and embedded as an image | Both show the image from its link |
| A web page | HTML: <a href="https://zindex.ai/d/{ref}@3"><img src="https://zindex.ai/d/{ref}@3.png" alt="Checkout flow, version 3"></a> | The image, linked to its page |
| Slack or email | The page link, https://zindex.ai/d/{ref}@3 | Most mail and chat apps don’t show SVG; the page shows the image |
Scope:
- These links need a published diagram (every plan) or a share link (Pro and Team). Neither can be made in a team workspace whose owners turned public sharing off.
- A share link in a public repository is as public as the repository: anyone reading the page can open it. Revoking the link breaks every image that uses it (Caching and taking links down covers what other caches keep).
- The signed links from
GET /v1/diagrams/{id}/renderstop working after 7 days. They suit sending an image to someone, never a page that stays up. - A diagram’s page in the dashboard writes each of these for the version shown or the latest, under Share: pick where it goes (GitHub, Google Docs, Notion or Confluence, a web page, Slack or email), then Copy.
Share links
A share link shows a diagram’s images and the dates of its versions to anyone who has it, until you revoke it. It never returns the scene JSON, the title or the description, and the diagram stays private. Anyone who has it can report the diagram, and Zindex revokes a link whose diagram breaks the content policy. The token is 22 random characters, so a link can’t be guessed, and it opens only its own diagram. Creating one needs Pro or Team: on Free it returns 403 with code: "FEATURE_UNAVAILABLE" (Limits). In a team workspace whose owners turned public sharing off, creating one, and publishing, return 403 with code: "SHARING_DISABLED" (Workspaces). Listing and revoking links work on every plan.
curl -s -X POST https://api.zindex.ai/v1/diagrams/payments-architecture/links \
-H "Authorization: Bearer $ZINDEX_API_KEY"
{"id":"dgm_7Q2kD9a1B2c3","linkId":"lnk_4kP9wXr2TmQa","url":"https://zindex.ai/d/9xWqTk4PmZr7Hb2NcVd8Ls","svg":"https://zindex.ai/d/9xWqTk4PmZr7Hb2NcVd8Ls.svg","png":"https://zindex.ai/d/9xWqTk4PmZr7Hb2NcVd8Ls.png","createdAt":"2026-10-08T09:31:00.000Z"}
The link follows the latest version; add @2 for version 2. Its page’s SVG and PNG links do the same, and so does its link preview in Slack, Teams or iMessage, though an app keeps the preview it made. Anyone with the link can read what its page shows:
curl -s https://api.zindex.ai/v1/public/diagrams/9xWqTk4PmZr7Hb2NcVd8Ls
{"id":"dgm_7Q2kD9a1B2c3","access":"link","revision":2,"latest":2,"at":"2026-10-08T09:14:00.000Z","versions":[{"revision":2,"at":"2026-10-08T09:14:00.000Z"},{"revision":1,"at":"2026-10-08T09:12:00.000Z"}]}
GET /v1/diagrams/{id}/links lists the diagram’s links, newest first. DELETE /v1/diagrams/{id}/links/{linkId} revokes one:
curl -s -X DELETE https://api.zindex.ai/v1/diagrams/payments-architecture/links/lnk_4kP9wXr2TmQa \
-H "Authorization: Bearer $ZINDEX_API_KEY"
{"id":"dgm_7Q2kD9a1B2c3","linkId":"lnk_4kP9wXr2TmQa","revoked":true}
From then on the link opens nothing:
curl -s https://api.zindex.ai/v1/public/diagrams/9xWqTk4PmZr7Hb2NcVd8Ls
{"error":"No public diagram or share link with that ID.","code":"NOT_FOUND"}
Published diagrams
PUT /v1/diagrams/{id}/sharing with { "visibility": "public" } publishes a diagram: anyone can then open its version links by ID, its page also shows its title and description, and GET /v1/public/diagrams/{id} returns its scene JSON.
curl -s -X PUT https://api.zindex.ai/v1/diagrams/payments-architecture/sharing \
-H "Authorization: Bearer $ZINDEX_API_KEY" -H "Content-Type: application/json" \
-d '{ "visibility": "public" }'
{"id":"dgm_7Q2kD9a1B2c3","visibility":"public","url":"https://zindex.ai/d/dgm_7Q2kD9a1B2c3","madePublicAt":"2026-10-08T09:32:00.000Z"}
curl -s -o payments-v1.svg https://api.zindex.ai/v1/public/diagrams/[email protected]
GET /v1/public/diagrams/{id} returns { id, access, title, description, revision, latest, at, madePublicAt, versions, scene, svg }: the version’s scene and its kept image. { "visibility": "private" } takes the diagram’s links by ID down again; its share links keep working until you revoke them.
Caching and taking links down
An exact version’s image never changes, so it is served with Cache-Control: public, max-age=31536000, immutable and an ETag of the version’s chain hash (its content hash while chain is null); send If-None-Match and an unchanged image answers 304. A link that follows the latest version, and every page answer, is served with Cache-Control: public, max-age=60. A share link’s answers are private rather than public: the visitor’s own browser may keep them, but no shared cache (a proxy, an image proxy, a chat preview) may, so a revoked link stops for new viewers.
Making a diagram private stops its links by ID at once, revoking a share link stops that link, and deleting the diagram stops both until it is restored; restoring it within 24 hours brings them back. Zindex’s own servers and edge keep nothing that could still answer. Copies people already fetched stay with them, as with any image once shared: a browser, or for a published diagram another cache, may keep an exact version’s image for up to a year, and a page or latest image for up to a minute. A private, deleted or unknown diagram and a revoked or unknown token all answer the same 404, so the answer doesn’t reveal which exist. The website’s page for that answer says the same for each. For a diagram’s ID it also offers to open the diagram in Zindex at the version the link names, /dashboard/diagram?id={id}&revision={revision}, where the people in its workspace see it once signed in. Every saved version’s image prints this address, zindex.ai/d/{id}@{revision}, in its bottom-right corner (The image’s address).
Reporting a diagram
Anyone, signed in or not, can report a diagram they can see that breaks the hosted-content policy with POST /v1/public/diagrams/{ref}/report and { "reason": "spam", "description": "...", "reporterEmail": "..." }. {ref} is the version link’s own: a published diagram’s ID, or a share link’s token, with @{revision} for the version seen (without it, the latest). The page at zindex.ai/d/{ref} sends its ref with the version it shows. reason is spam, hate, violence, abuse, illegal, copyright or other; description is 50 to 2,000 characters; the email is optional and never shown to the diagram’s owner.
A report is kept only when GET /v1/public/diagrams/{ref} would show that version: one by a private diagram’s ID, a revoked or unknown token, a deleted diagram or a version it doesn’t have is dropped. The answer is the same 200 either way, so it doesn’t reveal which IDs or tokens exist. A report through a share link records the link’s ID, never its token. Moderators see what the ref shows: a published diagram’s page, or, while a report through it is open, a share link’s images and version dates, never the scene.
What happens when a diagram breaks the policy:
- A published diagram is made private, every share link to it is revoked, and its owner is emailed the reason. This applies to a report through a share link too, while the diagram is published.
- A diagram shared only with links keeps every link but the reported one, which is revoked. Nothing else about the diagram changes. The person who made the link is emailed the reason; if they are no longer in the diagram’s workspace, its owners are.
A revoked link can’t be restored; the owner can make a new one, which needs Pro or Team.
Report a problem
When a version draws wrong, send it to Zindex support. A report is its own record of one version, with a one-line problem; the diagram stays as private or public as it was.
POST /v1/diagrams/{id}/reports/previewwith{ "revision": 2, "anonymize": true }(both optional; the default is the latest version, anonymized) returns{ id, revision, anonymized, svg }, plus aseedwhen anonymized: the version drawn as support will see it. Nothing is stored.POST /v1/diagrams/{id}/reportswith{ "problem": "The label sits on the edge", "revision": 2, "anonymize": true, "seed": 123 }returns201with{ reportId, id, revision, reported: true, anonymized }. Pass the preview’sseedand support sees exactly the copy you previewed; without it, a new random substitution is made.problemis one line of up to 500 characters.GET /v1/diagrams/{id}/reports/{reportId}returns{ id, reportId, revision, anonymized, svg }: what support sees, at any time after sending.DELETEon the same path withdraws the report.
An anonymized report keeps that anonymized copy, and staff see only it. With anonymize: false, staff see the version as it is. Deleting the diagram hides its reports from staff at once; they are removed with the diagram 24 hours later.
Feedback
Tell Zindex staff about a bug, a place where the docs and the engine disagree, or something you needed that is missing. Feedback needs an account but no saved diagram. Staff read every item; no model does. An item has:
kind:bug,docs(the docs and the engine disagree),requestorothersummary: one line, up to 200 charactersexpectedandobserved: optional, up to 2,000 characters eachconfidence: optional,seen,likelyorunsure- optionally,
id(withrevision; default the latest) to attach a version of one of the workspace’s diagrams (not with a read key or as a viewer), orsnippet: a scene document or Mermaid text of up to 64 KB. Either is anonymized unlessanonymizeisfalse, as in a problem report.
The person confirms each item before it is sent. The first request stores nothing: it answers 400 with code: "CONFIRMATION_REQUIRED", a confirm token and preview, the item exactly as staff will see it, with the engine version and client Zindex adds.
curl -s -X POST https://api.zindex.ai/v1/feedback \
-H "Authorization: Bearer $ZINDEX_API_KEY" -H "Content-Type: application/json" \
-d '{ "kind": "docs", "summary": "The guide says an edge may end on a frame", "expected": "The edge draws to the frame", "observed": "EDGE_ENDPOINT_KIND_INVALID", "confidence": "seen" }'
{"error":"Nothing was sent. Show the person the preview, and only if they agree, send the same body again with confirm set to the token; it expires in 10 minutes.","code":"CONFIRMATION_REQUIRED","confirm":"1791541440.Qm8rT2vXk9LpZ4nWc7HbYd","preview":{"kind":"docs","summary":"The guide says an edge may end on a frame","expected":"The edge draws to the frame","observed":"EDGE_ENDPOINT_KIND_INVALID","confidence":"seen","engine":"6.0.0+build.1690","client":"curl/8.7.1","diagram":null,"anonymized":null,"snippet":null}}
Show the person the preview. Only if they agree, send the same body again with confirm. The token works for 10 minutes, for that account and that item only:
curl -s -X POST https://api.zindex.ai/v1/feedback \
-H "Authorization: Bearer $ZINDEX_API_KEY" -H "Content-Type: application/json" \
-d '{ "kind": "docs", "summary": "The guide says an edge may end on a frame", "expected": "The edge draws to the frame", "observed": "EDGE_ENDPOINT_KIND_INVALID", "confidence": "seen", "confirm": "1791541440.Qm8rT2vXk9LpZ4nWc7HbYd" }'
{"feedbackId":"fb_6tJ3wNq8KxPa","sent":true,"status":"new"}
GET /v1/feedback lists your items newest first (limit up to 50, default 20, and cursor from nextCursor), each with what staff see and its status: new, accepted, fixed, wont-fix or duplicate. note is from Zindex staff, and a fixed item’s fixedIn names the version that fixed it. The dashboard shows the same list under Your feedback.
curl -s https://api.zindex.ai/v1/feedback \
-H "Authorization: Bearer $ZINDEX_API_KEY"
{"feedback":[{"feedbackId":"fb_6tJ3wNq8KxPa","kind":"docs","summary":"The guide says an edge may end on a frame","expected":"The edge draws to the frame","observed":"EDGE_ENDPOINT_KIND_INVALID","confidence":"seen","engine":"6.0.0+build.1690","client":"curl/8.7.1","diagram":null,"anonymized":null,"snippet":null,"status":"new","note":null,"fixedIn":null,"sentAt":"2026-10-09T10:15:00.000Z","updatedAt":null}]}
An account can send 20 items in any 24 hours; past that, the answer is 429 with code: "RATE_LIMITED" and retryAfter, the seconds until the next can go. Deleting a diagram hides the feedback that carries it from staff at once, and removes it with the diagram 24 hours later; closing the account removes all of it. Over MCP, diagram_share with action: "feedback" takes the same fields and asks the person the same way (MCP tools).
History and compare
GET /v1/diagrams/{id}/revisions lists versions newest first, with the time, who saved each one (by, their name, else their email) and how (credential: session, api_key or oauth, never which key), the client, its message, its chain hash and how many elements it added, changed and removed. GET /v1/diagrams/{id}/compare?from=2026-09-01&to=2026-10-01 returns the element IDs added, changed and removed between two versions, and authors, each distinct { by, client } that saved a version between them.
Export
GET /v1/diagrams/{id}/export downloads one diagram’s whole history as JSON Lines. The first line is a header with the diagram’s id, key, title and revisions. One line per version follows, oldest first, with its scene, its hash and chain, and its stored image. That is all you need to check the history yourself (Verifying).
GET /v1/workspace/export downloads every diagram in the workspace the key acts in, in one file, in the format zindex-account-history/1; GET /v1/account/export is the same download. Settings → Account on zindex.ai downloads the same file for the selected workspace. In a team workspace only its owners can download it, with the dashboard or their own keys; anyone else gets 403 with code: "OWNER_REQUIRED", and can still download each diagram’s history. Its first line names the format and the workspace (kind is personal or team). Each diagram follows in ID order, written exactly as its own export, and the last line counts the diagrams:
{"format":"zindex-account-history/1","workspace":{"id":"0b7e4c1a-…","name":"Personal workspace ([email protected])","kind":"personal"},"exportedAt":"2026-10-13T09:00:00.000Z"}
{"format":"zindex-history/1","chain":"zindex-chain/1","id":"dgm_7Q2kD9a1B2c3","key":"payments-architecture","title":"Payments","revisions":2,"exportedAt":"2026-10-13T09:00:00.004Z"}
{"revision":1,"at":"2026-10-05T09:12:00.000Z","by":"Ana Lima","actor":{"userId":"…","credential":"api_key","credentialId":"…"},"client":"curl/8.7.1","message":null,"hash":"sha256:3f9a…","chain":"sha256:fdac…","scene":{…},"image":{…}}
{"revision":2,…}
{"format":"zindex-history/1","chain":"zindex-chain/1","id":"dgm_Hq3vT8bWm2Xa","key":null,"title":"Orders","revisions":1,"exportedAt":"2026-10-13T09:00:00.019Z"}
{"revision":1,…}
{"end":true,"diagrams":2}
A line with "format": "zindex-history/1" starts the next diagram. A file without the closing line was cut short; download it again. Deleted diagrams are left out, even while they can be restored, and so are share links, problem reports and feedback. Both exports are sent a line at a time as Zindex writes them, so a large workspace starts downloading at once.
Errors
Errors are JSON with error, one sentence, and a code.
| Code | Status | Means |
|---|---|---|
INVALID_REQUEST | 400 | A parameter is wrong; error says which |
CONFIRMATION_REQUIRED | 400 | A delete without ?confirm=true, or feedback without its confirm token; nothing was deleted or sent |
AUTH_REQUIRED | 401 | No API key was sent |
API_KEY_INVALID, API_KEY_REVOKED, API_KEY_EXPIRED | 401 | The key sent is unknown, was revoked or has expired; use another key |
LIMIT_REACHED | 403 | The workspace is at a plan limit (Limits) |
PLAN_LIMIT_EXCEEDED | 403 | A new API key would pass the workspace’s apiKeys limit, or a viewer’s 3 keys; current and maximumAllowed give the numbers |
FEATURE_UNAVAILABLE | 403 | The workspace’s plan doesn’t include the feature (feature): creating a share link needs Pro or Team |
EMAIL_NOT_VERIFIED | 403 | Verify the account’s email before saving |
READ_ONLY | 403 | A read key, or a viewer in the workspace, can read diagrams but not change or share them or report a problem with them; reason is credential or role |
SHARING_DISABLED | 403 | The workspace’s owners turned public sharing off: no publishing and no new share links |
OWNER_REQUIRED | 403 | Only an owner of the team workspace can export all of it |
SESSION_REQUIRED | 403 | Moving a diagram works only from the signed-in dashboard |
LINK_INVALID | 403 | A signed image link is invalid or has expired; render the diagram again for a new link |
NOT_FOUND | 404 | No such diagram or version in this workspace; another workspace’s diagram answers the same way. Also a path with no endpoint |
NO_REVISION_AS_OF | 404 | The diagram had no version yet at that date |
KEY_EXISTS | 409 | The key belongs to another diagram in the workspace, with different content or a teammate’s; id names it |
REVISION_CONFLICT | 409 | The diagram changed since baseRevision; see revision and changes |
MOVED | 410 | A /v1/scenes path; method and path name the request to send instead |
INPUT_TOO_LARGE | 413 | The Mermaid text, or a feedback snippet, is over 64 KB |
VALIDATION_FAILED | 422 | Nothing was saved; errors lists each problem with a code, the element when there is one, and a one-line fix (Validation rules) |
REQUEST_ID_REUSED | 422 | The requestId already made a different revision |
PARSE_ERROR | 422 | The Mermaid has a syntax error; line and column say where |
UNSUPPORTED_DIAGRAM_TYPE | 422 | The Mermaid isn’t an erDiagram or a flowchart |
IMPORT_TIMEOUT, IMPORT_FAILED | 422 | The Mermaid parser took too long or stopped; send shorter text, or a scene |
MERMAID_FAMILY_MISMATCH | 422 | A Mermaid edit doesn’t fit the diagram’s family |
VIEW_UNAVAILABLE | 422 | The diagram can’t be read in that view |
DRAW_TIMEOUT | 422 | Drawing the scene took longer than the drawing budget (5 s without a key or sign-in, 20 s with one and for every save, edit and render), or needed more memory than it allows. A save or edit saved nothing. Split the diagram, or draw fewer edges into one node |
RATE_LIMITED | 429 | Over a rate limit, or 20 feedback items in 24 hours; retryAfter gives the seconds to wait |
INTERNAL_ERROR | 500 | Zindex failed while answering; error doesn’t say how. Retry, with the same requestId for an edit |
UNSUPPORTED | 501 | The server doesn’t offer that feature; api.zindex.ai offers every one |
BUSY | 503 | Every drawing worker is busy; retryAfter and Retry-After give the seconds to wait, half the refused drawing’s budget |
UNAVAILABLE | 503 | Reporting a diagram is unavailable right now; try again later |