Schemas
Every request and response type of the HTTP API, with its fields. Each endpoint page links the types it uses.
TL;DR
| Question | Answer |
|---|---|
| What is a schema? | The shape of a JSON body: its fields, their types, and which are required. |
| Where do I find the one an endpoint uses? | On the endpoint page, whose request and response types link here. |
| Where is the machine-readable form? | GET /openapi.json returns every schema as OpenAPI 3.1 JSON Schema. |
| How many are there? | 180. |
HealthResponse
Liveness answer.
| Field | Type | Required | Description |
|---|---|---|---|
status | "ok" | yes | |
version | string | yes | Package version of the running service. |
kinds | string[] | yes | Diagram kinds this build can render. |
Accepted
| Field | Type | Required | Description |
|---|---|---|---|
accepted | true | yes |
ErrorResponse
Standard error envelope used by every failing response.
| Field | Type | Required | Description |
|---|---|---|---|
error | true | yes | Always true, so clients can branch without reading the status. |
errorCode | string | yes | Stable snake_case key such as validation.failed or diagram.invalid. |
message | string | yes | Safe, human-readable summary. |
details | any | no | Validation issues or diagnostics, JSON-safe. |
requestId | string | no | Trace id for correlating with logs. |
RequestCodeBody
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | at least 3 characters; at most 254 characters. |
SignInResponse
| Field | Type | Required | Description |
|---|---|---|---|
user | Account | yes | |
user.id | string | yes | |
user.email | string | yes |
Account
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
email | string | yes |
VerifyCodeBody
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | at least 3 characters; at most 254 characters. |
code | string | yes | pattern ^\d{6}$. |
SsoDiscover
| Field | Type | Required | Description |
|---|---|---|---|
sso | boolean | yes | True when the address's domain signs in through an organisation's identity provider. Names no organisation. |
SsoDiscoverBody
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | at least 3 characters; at most 254 characters. |
SsoStart
| Field | Type | Required | Description |
|---|---|---|---|
url | string | yes | The identity provider's authorization address to send the browser to. |
SsoStartBody
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | at least 3 characters; at most 254 characters. |
returnTo | string | no | Where to send the browser after signing in. Kept only when its origin is one of Plotwork's; otherwise the portal. at most 2000 characters. |
ApiKeyList
| Field | Type | Required | Description |
|---|---|---|---|
items | ApiKeySummary[] | yes | |
items[].id | string | yes | |
items[].name | string | yes | |
items[].prefix | string | yes | |
items[].last4 | string | yes | |
items[].createdAt | integer | yes | Milliseconds since the epoch. |
items[].lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if never used. |
items[].revealable | boolean | yes | True when the full key can be shown again with the reveal route. False for a key made before that was possible, or on a server that cannot seal keys. |
ApiKeySummary
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
name | string | yes | |
prefix | string | yes | |
last4 | string | yes | |
createdAt | integer | yes | Milliseconds since the epoch. |
lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if never used. |
revealable | boolean | yes | True when the full key can be shown again with the reveal route. False for a key made before that was possible, or on a server that cannot seal keys. |
CreatedApiKey
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
name | string | yes | |
prefix | string | yes | |
last4 | string | yes | |
createdAt | integer | yes | Milliseconds since the epoch. |
lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if never used. |
revealable | boolean | yes | True when the full key can be shown again with the reveal route. False for a key made before that was possible, or on a server that cannot seal keys. |
key | string | yes | The full key. When revealable is false this is the only time it is shown, so store it now. |
CreateApiKeyBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | at least 1 character; at most 60 characters; pattern \S. |
RevealedApiKey
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
key | string | yes | The full key. |
Approval
| Field | Type | Required | Description |
|---|---|---|---|
approval | string | yes | The signed approval. It carries the connection key sealed, so it is safe in an address. |
expiresIn | integer | yes | Seconds the approval stays usable. |
redirectTo | string | yes | Where to send the browser: the MCP server callback with the request and the approval already attached. |
ApproveConnectionBody
| Field | Type | Required | Description |
|---|---|---|---|
request | string | yes | The signed authorization request, exactly as the MCP server put it in the address. at least 1 character; at most 6144 characters. |
ConnectionList
| Field | Type | Required | Description |
|---|---|---|---|
items | Connection[] | yes | |
items[].id | string | yes | |
items[].clientId | string | yes | The OAuth client id the agent registered with. |
items[].clientName | string | yes | The name the agent gave itself when it registered. It is a claim, not a fact. |
items[].connectedAt | integer | yes | Milliseconds since the epoch. |
items[].lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if the agent has not made a call. |
Connection
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
clientId | string | yes | The OAuth client id the agent registered with. |
clientName | string | yes | The name the agent gave itself when it registered. It is a claim, not a fact. |
connectedAt | integer | yes | Milliseconds since the epoch. |
lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if the agent has not made a call. |
Usage
| Field | Type | Required | Description |
|---|---|---|---|
plan | "free" | "pro" | yes | The plan the account is on, which decides the limit. |
limit | integer | yes | Metered calls the account may make per UTC day, across every key and connected agent. |
used | integer | yes | Metered calls made today. minimum 0. |
remaining | integer | yes | Calls left today. Zero when the limit is used up. minimum 0. |
resetsAt | integer | yes | When the count goes back to zero (00:00 UTC), in milliseconds since the epoch. |
today | object | yes | Today's calls, split by how they reached the service. |
today.api | integer | yes | minimum 0. |
today.mcp | integer | yes | minimum 0. |
days | UsageDay[] | yes | The last 30 days, oldest first, ending today. A day with no calls is present with zeros. |
days[].day | string | yes | The UTC date, as YYYY-MM-DD. |
days[].api | integer | yes | REST API calls that day. minimum 0. |
days[].mcp | integer | yes | MCP tool calls that day. minimum 0. |
UsageDay
| Field | Type | Required | Description |
|---|---|---|---|
day | string | yes | The UTC date, as YYYY-MM-DD. |
api | integer | yes | REST API calls that day. minimum 0. |
mcp | integer | yes | MCP tool calls that day. minimum 0. |
BillingState
| Field | Type | Required | Description |
|---|---|---|---|
plan | "free" | "pro" | yes | The plan the account gets right now. It is the free plan whenever the subscription is not paying, whatever plan was bought. |
status | string | yes | Stripe's status for the subscription (active, trialing, past_due, canceled, unpaid, incomplete, and so on), or none when the account never started one. |
currentPeriodEnd | integer | null | yes | When the period paid for ends, in milliseconds since the epoch, or null when there is no subscription. |
cancelAtPeriodEnd | boolean | yes | True while the subscription is scheduled to end at the close of the period already paid for. |
hasCustomer | boolean | yes | True once the account has billing details at Stripe, which is when the billing portal can be opened. |
BillingUrl
| Field | Type | Required | Description |
|---|---|---|---|
url | string | yes | An address on Stripe's own site. Send the browser there; it expires, so do not store it. |
CheckoutBody
| Field | Type | Required | Description |
|---|---|---|---|
plan | "pro" | yes | The plan to subscribe to. pro is the only paid plan. |
VerifyCheckoutBody
| Field | Type | Required | Description |
|---|---|---|---|
sessionId | string | yes | The Checkout Session id Stripe put in the return address. pattern ^cs_[A-Za-z0-9_]{8,200}$. |
CancelBody
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | no | Why the person is cancelling, in their own words. Optional. Sent to Stripe as the cancellation comment; Plotwork does not store it. at most 500 characters. |
BillingDocumentList
| Field | Type | Required | Description |
|---|---|---|---|
items | BillingDocument[] | yes | |
items[].id | string | yes | The id to ask for the document and its PDF with. |
items[].kind | "invoice" | "receipt" | yes | A receipt is an invoice that has been paid; anything else is an invoice. |
items[].number | string | yes | The number printed on the document, which an accounts department quotes back. |
items[].description | string | yes | What it was for, such as the plan. Empty when Stripe names nothing. |
items[].currency | string | yes | The three-letter currency, in capitals. at least 3 characters; at most 3 characters. |
items[].totalCents | integer | yes | The total in whole cents (the currency's minor unit). |
items[].status | string | yes | The invoice's own word: paid, open, void, or uncollectible. A draft is never listed. |
items[].issuedAt | integer | yes | When it was issued, in milliseconds since the epoch. |
items[].paidAt | integer | null | yes | When it was paid, in milliseconds since the epoch, or null while it is not. |
items[].downloadable | boolean | yes | False when there is no PDF to fetch, so the PDF route would answer 404. |
BillingDocument
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The id to ask for the document and its PDF with. |
kind | "invoice" | "receipt" | yes | A receipt is an invoice that has been paid; anything else is an invoice. |
number | string | yes | The number printed on the document, which an accounts department quotes back. |
description | string | yes | What it was for, such as the plan. Empty when Stripe names nothing. |
currency | string | yes | The three-letter currency, in capitals. at least 3 characters; at most 3 characters. |
totalCents | integer | yes | The total in whole cents (the currency's minor unit). |
status | string | yes | The invoice's own word: paid, open, void, or uncollectible. A draft is never listed. |
issuedAt | integer | yes | When it was issued, in milliseconds since the epoch. |
paidAt | integer | null | yes | When it was paid, in milliseconds since the epoch, or null while it is not. |
downloadable | boolean | yes | False when there is no PDF to fetch, so the PDF route would answer 404. |
BillingDocumentDetail
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The id to ask for the document and its PDF with. |
kind | "invoice" | "receipt" | yes | A receipt is an invoice that has been paid; anything else is an invoice. |
number | string | yes | The number printed on the document, which an accounts department quotes back. |
description | string | yes | What it was for, such as the plan. Empty when Stripe names nothing. |
currency | string | yes | The three-letter currency, in capitals. at least 3 characters; at most 3 characters. |
totalCents | integer | yes | The total in whole cents (the currency's minor unit). |
status | string | yes | The invoice's own word: paid, open, void, or uncollectible. A draft is never listed. |
issuedAt | integer | yes | When it was issued, in milliseconds since the epoch. |
paidAt | integer | null | yes | When it was paid, in milliseconds since the epoch, or null while it is not. |
downloadable | boolean | yes | False when there is no PDF to fetch, so the PDF route would answer 404. |
lines | DocumentLine[] | yes | |
lines[].description | string | yes | |
lines[].quantity | integer | yes | minimum 1. |
lines[].amountCents | integer | yes | |
lines[].periodStart | integer | null | yes | The start of the service period, in milliseconds since the epoch, or null. |
lines[].periodEnd | integer | null | yes | The end of the service period, in milliseconds since the epoch, or null. |
subtotalCents | integer | null | yes | |
taxCents | integer | null | yes | The tax, or null when Stripe names none. |
amountPaidCents | integer | null | yes | |
billedTo | object | yes | |
billedTo.name | string | null | yes | |
billedTo.email | string | null | yes | |
issuer | object | null | yes | The Stripe account's business name and its tax numbers, from the invoice. There is no address: Stripe does not put one on an invoice. |
issuer.name | string | yes | |
issuer.lines | string[] | yes | |
paidWith | object | null | yes | The card the payment was taken from: its brand and last four digits, and nothing more of it. Null when it was not paid by card. |
paidWith.brand | string | yes | |
paidWith.last4 | string | yes | pattern ^\d{4}$. |
DocumentLine
| Field | Type | Required | Description |
|---|---|---|---|
description | string | yes | |
quantity | integer | yes | minimum 1. |
amountCents | integer | yes | |
periodStart | integer | null | yes | The start of the service period, in milliseconds since the epoch, or null. |
periodEnd | integer | null | yes | The end of the service period, in milliseconds since the epoch, or null. |
WebhookAck
| Field | Type | Required | Description |
|---|---|---|---|
received | true | yes | |
outcome | "handled" | "duplicate" | "ignored" | yes | handled when the event changed or confirmed an account, duplicate when it had been handled before, ignored when it is not about a Plotwork subscription. |
DrawDiagramResponse
The result of checking, describing, and drawing a diagram in one call.
| Field | Type | Required | Description |
|---|---|---|---|
valid | boolean | yes | True when the source has no errors. When false, nothing was drawn: fix the errors and call again. |
kind | string | null | yes | The diagram kind, or null when the header could not be read. |
errors | Diagnostic[] | yes | Every error found in one pass, each with line, column, and a hint. Empty when valid. |
errors[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
errors[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
errors[].message | string | yes | What is wrong, in one sentence. |
errors[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
errors[].column | integer | yes | 1-based column in that line. minimum 1. |
errors[].length | integer | yes | Number of characters the problem covers. minimum 1. |
errors[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
warnings | Diagnostic[] | yes | Quality warnings for a valid diagram: too dense, too wide, text cut, unconnected nodes, and suggestions for an icon or a group type. Empty when invalid. |
warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
warnings[].message | string | yes | What is wrong, in one sentence. |
warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
summary | string | null | yes | One-line description of the diagram, usable as alt text; null when invalid. |
outline | string[] | yes | The diagram as plain text in reading order, to check it says what you meant; empty when invalid. |
outlineTruncated | boolean | yes | True when the summary level cut the outline short. Call again with detail "full" to read all of it. |
size | object | null | yes | Natural size of the laid-out diagram; null when invalid. |
size.width | integer | yes | Width in px. minimum 1. |
size.height | integer | yes | Height in px. minimum 1. |
quality | object | no | How clean the picture looks (score, grade, measures) and up to three changes that would help; read it instead of looking. Absent when invalid. |
quality.score | integer | yes | 0 to 100; 100 is a picture with nothing to fix. The same diagram always gets the same score. minimum 0; maximum 100. |
quality.grade | "clean" | "fair" | "cluttered" | yes | clean is 85 or more, fair 60 or more, cluttered below. |
quality.measures | object | yes | What the score is made from: crossings, lineOverBox, labelOverlaps, smallestTextPx (in an 880px column), aspectRatio, emptySpace (0 to 1), longestLine (px), detour (1 is straight), the counts of boxes, lines, labels, series, and slices, and any measure the kind adds. |
quality.hints | string[] | yes | Up to three changes, the one worth most first, each naming the statement or option to edit. |
quality.line | string | yes | The grade, the score, and the first hint in one line. |
notices | Note[] | no | Information notes, such as an icon alias drawn as the real icon; absent when there is none. |
notices[].code | string | yes | A stable code, such as I122 for an icon alias. |
notices[].severity | "info" | yes | A note never stops a drawing and is not a warning. |
notices[].message | string | yes | |
notices[].line | integer | yes | minimum 1. |
notices[].column | integer | yes | minimum 1. |
notices[].length | integer | yes | minimum 1. |
notices[].hint | string | null | yes | The text to write instead. |
renders | object[] | yes | One picture per requested color scheme, light first; empty when invalid, when svg is never, and when every picture was left out (see picturesOmitted). |
renders[].theme | "light" | "dark" | yes | The color scheme this picture is drawn in. |
renders[].svg | string | yes | Self-contained SVG markup with an accessible title and description. |
renders[].size | Size | yes | Natural size of a rendered diagram in px. |
renders[].size.width | integer | yes | Width in px. minimum 1. |
renders[].size.height | integer | yes | Height in px. minimum 1. |
picturesOmitted | object | no | Present only when pictures were left out because the answer would have been too big for an AI client to read in one piece. |
picturesOmitted.themes | ("light" | "dark")[] | yes | The color schemes whose pictures were left out. |
picturesOmitted.characters | integer | yes | How many characters the pictures left out came to. |
picturesOmitted.limit | integer | yes | The most characters one answer may hold before the pictures are left out. |
picturesOmitted.why | string | yes | Why they were left out, and what to do. |
viewUrl | string | no | A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so. |
pngUrl | string | no | The viewUrl with &download=png: opening it in a browser saves the diagram as a PNG for Slack, email, or a wiki. The PNG is drawn in the person's browser, not on a server, so it is a link to open, not an image address to embed. Absent when too long. |
svgUrl | string | no | The viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long. |
saveCommand | string | no | Run in a shell to save the SVG into the repository: the CLI decodes the link locally, fetches nothing, and embeds the source. Set --out to the path; add --theme dark for dark. Absent when too long. |
next | string | yes | The next step in one sentence. |
Diagnostic
A located, actionable problem found in diagram source.
| Field | Type | Required | Description |
|---|---|---|---|
code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
message | string | yes | What is wrong, in one sentence. |
line | integer | yes | 1-based line in the submitted source. minimum 1. |
column | integer | yes | 1-based column in that line. minimum 1. |
length | integer | yes | Number of characters the problem covers. minimum 1. |
hint | string | null | yes | A concrete suggestion for fixing it, or null. |
Note
An information note with its place in the source.
| Field | Type | Required | Description |
|---|---|---|---|
code | string | yes | A stable code, such as I122 for an icon alias. |
severity | "info" | yes | A note never stops a drawing and is not a warning. |
message | string | yes | |
line | integer | yes | minimum 1. |
column | integer | yes | minimum 1. |
length | integer | yes | minimum 1. |
hint | string | null | yes | The text to write instead. |
Size
Natural size of a rendered diagram in px.
| Field | Type | Required | Description |
|---|---|---|---|
width | integer | yes | Width in px. minimum 1. |
height | integer | yes | Height in px. minimum 1. |
DrawDiagramInput
Diagram source and what to return: the color schemes to draw and how much detail.
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Diagram source. The first line is the header: flow "Title", sequence "Title", schema "Title", git "Title", gantt "Title", class "Title", state "Title", timeline "Title", journey "Title", mindmap "Title", treemap "Title", pie "Title", quadrant "Title", layers "Title", c4 "Title", matrix "Title", sankey "Title", xychart "Title", tree "Title", or swimlane "Title". at least 1 character; at most 50000 characters. |
themes | "light" | "dark" | "both" | no | light, dark, or both (the default): the light picture and the dark one a dark page needs. default "both". |
detail | "summary" | "full" | no | summary (the default), or full: the whole outline, and the source embedded in each SVG. default "summary". |
svg | "auto" | "always" | "never" | no | auto (the default) returns the SVGs, but over MCP leaves them out when the answer would be too big for a client (picturesOmitted). always returns them at any size. never draws nothing, which is cheaper. The HTTP API treats auto as always. default "auto". |
embedSource | boolean | no | Write the source into each SVG so read_diagram can give it back. Set it when you save the SVG in a repository or publish it to edit later; anyone with the file or link can then read the source. default false. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
EditDiagramResponse
The edited source, a result for each operation, and the check of the result.
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | The edited source. Lines no operation touched are byte for byte as they were, comments included. |
changed | boolean | yes | |
results | object[] | yes | One entry for each operation, in order. |
results[].op | "rename" | "set" | "add_node" | "remove" | "add_edge" | "remove_edge" | "move" | "replace_text" | yes | |
results[].applied | boolean | yes | |
results[].lines | integer[] | yes | Lines of the new source this operation wrote, or the lines it removed from. |
results[].message | string | yes | |
results[].hint | string | null | yes | |
valid | boolean | yes | |
kind | string | null | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
errors | Diagnostic[] | yes | |
errors[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
errors[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
errors[].message | string | yes | What is wrong, in one sentence. |
errors[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
errors[].column | integer | yes | 1-based column in that line. minimum 1. |
errors[].length | integer | yes | Number of characters the problem covers. minimum 1. |
errors[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
warnings | Diagnostic[] | yes | Quality warnings; only when the result is drawn. |
warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
warnings[].message | string | yes | What is wrong, in one sentence. |
warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
summary | string | null | yes | |
outline | string[] | yes | |
outlineTruncated | boolean | yes | |
size | any | yes | |
size.width | integer | yes | Width in px. minimum 1. |
size.height | integer | yes | Height in px. minimum 1. |
renders | object[] | yes | |
renders[].theme | "light" | "dark" | yes | |
renders[].svg | string | yes | |
renders[].size | Size | yes | Natural size of a rendered diagram in px. |
renders[].size.width | integer | yes | Width in px. minimum 1. |
renders[].size.height | integer | yes | Height in px. minimum 1. |
picturesOmitted | object | no | Present only when pictures were left out because the answer would have been too big for an AI client to read in one piece. |
picturesOmitted.themes | ("light" | "dark")[] | yes | The color schemes whose pictures were left out. |
picturesOmitted.characters | integer | yes | How many characters the pictures left out came to. |
picturesOmitted.limit | integer | yes | The most characters one answer may hold before the pictures are left out. |
picturesOmitted.why | string | yes | Why they were left out, and what to do. |
viewUrl | string | no | A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so. |
svgUrl | string | no | The viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long. |
saveCommand | string | no | Run in a shell to save the SVG into the repository: the CLI decodes the link locally, fetches nothing, and embeds the source. Set --out to the path; add --theme dark for dark. Absent when too long. |
next | string | yes |
EditDiagramInput
Diagram source and the edits to make to it.
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Diagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters. |
operations | object[] | yes | Applied in order. |
operations[].op | "rename" | "set" | "add_node" | "remove" | "add_edge" | "remove_edge" | "move" | "replace_text" | yes | |
operations[].target | string | no | Id, label, table.column, or "header". at most 2000 characters. |
operations[].to | string | no | rename: the new name. Edges: the end. at most 2000 characters. |
operations[].from | string | no | Edges: the start. at most 2000 characters. |
operations[].option | string | no | at most 40 characters; pattern ^[a-z][A-Za-z0-9_-]*$. |
operations[].value | string | null | no | set: null removes the option. at most 2000 characters. |
operations[].id | string | no | at most 2000 characters. |
operations[].label | string | no | add_edge on sankey: the amount. at most 2000 characters. |
operations[].type | string | no | add_node: node type, or statement word (c4 person, tree dir). at most 2000 characters. |
operations[].options | object | no | |
operations[].statement | string | no | add_node: the whole line, for a kind with no plain node statement. at most 2000 characters. |
operations[].into | string | null | no | A block; null is the top level. at most 2000 characters. |
operations[].after | string | no | at most 2000 characters. |
operations[].arrow | "<-->" | "-->" | "<->" | "..>" | "->" | "--" | no | |
operations[].find | string | no | at most 2000 characters. |
operations[].replace | string | no | at most 2000 characters. |
operations[].all | boolean | no | |
svg | "auto" | "always" | "never" | no | never (the default) draws nothing; auto or always draws like draw_diagram. default "never". |
themes | "light" | "dark" | "both" | no | light, dark, or both (the default): the light picture and the dark one a dark page needs. default "both". |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
ConvertMermaidResponse
The result of converting one Mermaid diagram to Plotwork.
| Field | Type | Required | Description |
|---|---|---|---|
ok | boolean | yes | True when source is valid Plotwork source. False means nothing was converted and source is empty: read diagnostics. |
kind | string | null | yes | The Plotwork kind the diagram became, or null when it could not be converted. |
mermaidType | string | null | yes | The Mermaid diagram type read from the first line, such as flowchart or sequenceDiagram; null when none was found. |
source | string | yes | The Plotwork source, or an empty string when nothing could be converted. |
diagnostics | Diagnostic[] | yes | Everything dropped, changed, or wrong, with a hint that says what to do. Codes start with M. Lines and columns point into the Mermaid you sent. M1xx codes are errors that stop the conversion; M2xx codes are warnings and the conversion went on. |
diagnostics[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
diagnostics[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
diagnostics[].message | string | yes | What is wrong, in one sentence. |
diagnostics[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
diagnostics[].column | integer | yes | 1-based column in that line. minimum 1. |
diagnostics[].length | integer | yes | Number of characters the problem covers. minimum 1. |
diagnostics[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
stats | object | yes | |
stats.nodes | integer | yes | Flow nodes written. |
stats.edges | integer | yes | Flow edges written. |
stats.groups | integer | yes | Flow groups written. |
stats.actors | integer | yes | Sequence participants written. |
stats.messages | integer | yes | Sequence messages written. |
stats.tables | integer | yes | Schema tables written. |
stats.columns | integer | yes | Schema columns written. |
stats.relations | integer | yes | Schema relations written. |
stats.dropped | integer | yes | Warnings about constructs that were dropped: styling, links, activations, and so on. |
stats.renamed | integer | yes | Ids that were not valid Plotwork ids and were renamed. |
validation | object | null | yes | The Plotwork validator run on source; null when nothing was converted. |
validation.valid | boolean | yes | True when the converted source has no Plotwork errors. It always is when ok is true. |
validation.errors | Diagnostic[] | yes | Plotwork errors in the converted source. Lines and columns point into source, not into the Mermaid. |
validation.errors[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
validation.errors[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
validation.errors[].message | string | yes | What is wrong, in one sentence. |
validation.errors[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
validation.errors[].column | integer | yes | 1-based column in that line. minimum 1. |
validation.errors[].length | integer | yes | Number of characters the problem covers. minimum 1. |
validation.errors[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
validation.warnings | Diagnostic[] | yes | Plotwork quality warnings, including icon and group-type suggestions with the exact icon= to write. Lines and columns point into source, not into the Mermaid. |
validation.warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
validation.warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
validation.warnings[].message | string | yes | What is wrong, in one sentence. |
validation.warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
validation.warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
validation.warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
validation.warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
validation.summary | string | null | yes | One-line description of the converted diagram, usable as alt text. |
validation.size | object | null | yes | Natural size of the laid-out diagram. |
validation.size.width | integer | yes | Width in px. minimum 1. |
validation.size.height | integer | yes | Height in px. minimum 1. |
quality | object | no | How clean the converted diagram looks and up to three changes that would help (see draw_diagram); absent when it is not valid. |
quality.score | integer | yes | 0 to 100; 100 is a picture with nothing to fix. The same diagram always gets the same score. minimum 0; maximum 100. |
quality.grade | "clean" | "fair" | "cluttered" | yes | clean is 85 or more, fair 60 or more, cluttered below. |
quality.measures | object | yes | What the score is made from: crossings, lineOverBox, labelOverlaps, smallestTextPx (in an 880px column), aspectRatio, emptySpace (0 to 1), longestLine (px), detour (1 is straight), the counts of boxes, lines, labels, series, and slices, and any measure the kind adds. |
quality.hints | string[] | yes | Up to three changes, the one worth most first, each naming the statement or option to edit. |
quality.line | string | yes | The grade, the score, and the first hint in one line. |
outline | string[] | yes | The converted diagram as plain text, to check it says what the Mermaid said; empty when nothing was converted. |
outlineTruncated | boolean | yes | True when the summary level cut the outline short. Call again with detail "full" to read all of it. |
renders | object[] | yes | One picture per requested color scheme, light first; empty unless render was true and the conversion is valid, when svg is never, and when every picture was left out (see picturesOmitted). |
renders[].theme | "light" | "dark" | yes | The color scheme this picture is drawn in. |
renders[].svg | string | yes | Self-contained SVG markup with an accessible title and description. |
renders[].size | Size | yes | Natural size of a rendered diagram in px. |
renders[].size.width | integer | yes | Width in px. minimum 1. |
renders[].size.height | integer | yes | Height in px. minimum 1. |
picturesOmitted | object | no | Present only when pictures were left out because the answer would have been too big for an AI client to read in one piece. |
picturesOmitted.themes | ("light" | "dark")[] | yes | The color schemes whose pictures were left out. |
picturesOmitted.characters | integer | yes | How many characters the pictures left out came to. |
picturesOmitted.limit | integer | yes | The most characters one answer may hold before the pictures are left out. |
picturesOmitted.why | string | yes | Why they were left out, and what to do. |
viewUrl | string | no | A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so. |
pngUrl | string | no | The viewUrl with &download=png: opening it in a browser saves the diagram as a PNG for Slack, email, or a wiki. The PNG is drawn in the person's browser, not on a server, so it is a link to open, not an image address to embed. Absent when too long. |
svgUrl | string | no | The viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long. |
saveCommand | string | no | Run in a shell to save the SVG into the repository: the CLI decodes the link locally, fetches nothing, and embeds the source. Set --out to the path; add --theme dark for dark. Absent when too long. |
next | string | yes | The next step in one sentence. |
ConvertMermaidInput
Mermaid source and what to return with the converted Plotwork source.
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | One Mermaid diagram: a flowchart or graph, sequenceDiagram, erDiagram, gitGraph, gantt, classDiagram, stateDiagram, timeline, journey, mindmap, treemap-beta or treemap, pie, quadrantChart, C4Context or C4Container or C4Component or C4Dynamic or C4Deployment, sankey-beta or sankey, xychart-beta or xychart, or treeView-beta or treeView. Front matter and %%{init}%% directives are allowed and are dropped. Send the text inside a mermaid fence, without the fence. at least 1 character; at most 50000 characters. |
lenient | boolean | no | false (the default): a line that cannot be read stops the conversion, so nothing is converted with a line missing. true: such a line is skipped with a warning and the rest is converted. default false. |
render | boolean | no | Also draw the converted diagram, in the color schemes themes names. default false. |
themes | "light" | "dark" | "both" | no | light, dark, or both (the default): the light picture and the dark one a dark page needs. default "both". |
detail | "summary" | "full" | no | summary (the default), or full: the whole outline, and the source embedded in each SVG. default "summary". |
svg | "auto" | "always" | "never" | no | auto (the default) returns the SVGs, but over MCP leaves them out when the answer would be too big for a client (picturesOmitted). always returns them at any size. never draws nothing, which is cheaper. The HTTP API treats auto as always. default "auto". |
embedSource | boolean | no | Write the source into each SVG so read_diagram can give it back. Set it when you save the SVG in a repository or publish it to edit later; anyone with the file or link can then read the source. default false. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
ValidateResponse
Result of checking diagram source.
| Field | Type | Required | Description |
|---|---|---|---|
valid | boolean | yes | True when there are no errors; warnings do not make a diagram invalid. |
kind | string | null | yes | The diagram kind, or null when the header could not be read. |
errors | Diagnostic[] | yes | Every error found in one pass, so they can be fixed together. |
errors[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
errors[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
errors[].message | string | yes | What is wrong, in one sentence. |
errors[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
errors[].column | integer | yes | 1-based column in that line. minimum 1. |
errors[].length | integer | yes | Number of characters the problem covers. minimum 1. |
errors[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
warnings | Diagnostic[] | yes | Quality warnings for a valid diagram, such as too dense or too wide. |
warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
warnings[].message | string | yes | What is wrong, in one sentence. |
warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
summary | string | null | yes | One-line description of the diagram, or null when invalid. |
size | object | null | yes | Natural rendered size, or null when invalid. |
size.width | integer | yes | Width in px. minimum 1. |
size.height | integer | yes | Height in px. minimum 1. |
quality | object | no | How clean the laid-out diagram looks, with up to three changes; absent when invalid. |
quality.score | integer | yes | 0 to 100; 100 is a picture with nothing to fix. The same diagram always gets the same score. minimum 0; maximum 100. |
quality.grade | "clean" | "fair" | "cluttered" | yes | clean is 85 or more, fair 60 or more, cluttered below. |
quality.measures | object | yes | What the score is made from: crossings, lineOverBox, labelOverlaps, smallestTextPx (in an 880px column), aspectRatio, emptySpace (0 to 1), longestLine (px), detour (1 is straight), the counts of boxes, lines, labels, series, and slices, and any measure the kind adds. |
quality.hints | string[] | yes | Up to three changes, the one worth most first, each naming the statement or option to edit. |
quality.line | string | yes | The grade, the score, and the first hint in one line. |
notices | Note[] | no | Information notes, such as an icon alias resolved to a real icon; absent when there is none. |
notices[].code | string | yes | A stable code, such as I122 for an icon alias. |
notices[].severity | "info" | yes | A note never stops a drawing and is not a warning. |
notices[].message | string | yes | |
notices[].line | integer | yes | minimum 1. |
notices[].column | integer | yes | minimum 1. |
notices[].length | integer | yes | minimum 1. |
notices[].hint | string | null | yes | The text to write instead. |
DiagramSourceInput
Request body carrying diagram source.
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Diagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
RenderResponse
A rendered diagram.
| Field | Type | Required | Description |
|---|---|---|---|
svg | string | yes | Self-contained SVG markup with an accessible title and description. |
theme | "light" | "dark" | "auto" | yes | The color scheme used. |
size | Size | yes | Natural size of a rendered diagram in px. |
size.width | integer | yes | Width in px. minimum 1. |
size.height | integer | yes | Height in px. minimum 1. |
warnings | Diagnostic[] | yes | |
warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
warnings[].message | string | yes | What is wrong, in one sentence. |
warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
RenderInput
Diagram source and rendering options.
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Diagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters. |
theme | "light" | "dark" | "auto" | no | Color scheme to paint with: light, dark, or auto for one picture that follows the reader's light or dark setting. default "light". |
idPrefix | string | no | Prefix for element ids; set it when inlining several diagrams into one page. at most 32 characters; pattern ^[A-Za-z][A-Za-z0-9_-]*$. |
embedSource | boolean | no | Write the source into the SVG metadata so read_diagram can give it back. Set it true when you save the SVG into a repository; anyone with the file can then read the source. Default false. default false. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
OutlineResponse
A plain-text description of a diagram, usable as alt text.
| Field | Type | Required | Description |
|---|---|---|---|
kind | string | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
summary | string | yes | One-line description. |
outline | string[] | yes | Lines in reading order: participants, steps, tables, and connections. |
ReadDiagramResponse
The source of a Plotwork SVG, or why there is none and what to do.
| Field | Type | Required | Description |
|---|---|---|---|
status | "read" | "no-source" | "damaged" | "not-a-picture" | "refused" | "unreachable" | yes | read: the source was found. no-source: the picture carries none. damaged: it carries one that cannot be read back. not-a-picture: the text is not an SVG. refused: the link is not one this tool fetches. unreachable: the link could not be fetched. |
hasSource | boolean | yes | True when source is set. |
source | string | null | yes | The exact source the picture was drawn from, ready to edit and send to draw_diagram; null when there is none. |
kind | string | null | yes | The diagram kind of the source, or null. |
id | string | null | yes | The id of the stored diagram when the picture was published (data-plotwork-id), or null. |
from | "text" | "url" | yes | Where the picture came from: the text that was sent, or the link that was fetched. |
validation | object | null | yes | The check of the source, or null when there is none. It parses the source; draw_diagram also lays it out and returns warnings. |
validation.valid | boolean | yes | True when the source has no errors. |
validation.errors | Diagnostic[] | yes | Every error, each with line, column, and a hint; empty when valid. |
validation.errors[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
validation.errors[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
validation.errors[].message | string | yes | What is wrong, in one sentence. |
validation.errors[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
validation.errors[].column | integer | yes | 1-based column in that line. minimum 1. |
validation.errors[].length | integer | yes | Number of characters the problem covers. minimum 1. |
validation.errors[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
validation.summary | string | null | yes | One-line description of the diagram, or null when invalid. |
picture | object | null | yes | What the picture says about itself, or null when the text is not an SVG. |
picture.title | string | null | yes | The diagram title, or null. |
picture.summary | string | null | yes | The one-line summary the picture carries, or null. |
picture.theme | string | null | yes | The color scheme it was drawn in, or null. |
picture.size | object | null | yes | Its size in px, or null. |
picture.size.width | integer | yes | Width in px. minimum 1. |
picture.size.height | integer | yes | Height in px. minimum 1. |
picture.outline | string[] | yes | The plain-language outline the picture carries, one entry for each line. Empty when the source was read: the source says more. |
picture.labels | string[] | yes | The text painted on the picture, each distinct label once, in painted order. Empty when the source was read. |
message | string | yes | What happened, in one sentence. |
next | string | yes | The next step in one sentence. |
ReadDiagramInput
The text of a Plotwork SVG, or the link of a hosted one.
| Field | Type | Required | Description |
|---|---|---|---|
svg | string | no | The text of a Plotwork SVG: the content of an .svg file in the repository. Send this or url, not both. at least 1 character; at most 1000000 characters. |
url | string | no | The link of a hosted Plotwork picture, https://cdn.plotwork.dev/d/ (opens in a new tab)<22 characters>.svg. Only Plotwork's own picture hosts are fetched. Send this or svg, not both. at least 1 character; at most 200 characters. |
CompareDiagramsResponse
What changed between two versions of a diagram.
| Field | Type | Required | Description |
|---|---|---|---|
same | boolean | yes | |
before | object | yes | |
before.from | "source" | "svg" | "url" | yes | |
before.read | boolean | yes | False when no source could be read from it; message says why. |
before.kind | string | null | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
before.valid | boolean | yes | |
before.message | string | null | yes | |
after | object | yes | |
after.from | "source" | "svg" | "url" | yes | |
after.read | boolean | yes | False when no source could be read from it; message says why. |
after.kind | string | null | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
after.valid | boolean | yes | |
after.message | string | null | yes | |
counts | object | yes | |
counts.added | integer | yes | |
counts.removed | integer | yes | |
counts.renamed | integer | yes | |
counts.moved | integer | yes | |
counts.changed | integer | yes | |
changes | object[] | yes | |
changes[].change | "added" | "removed" | "renamed" | "moved" | "changed" | yes | |
changes[].subject | "header" | "node" | "group" | "edge" | "row" | "series" | "line" | yes | |
changes[].name | string | yes | The id, the label in quotes, or for an edge its ends. |
changes[].line | integer | null | yes | The line in after, or in before for a removal. |
changes[].detail | string | yes | |
truncated | boolean | yes | True when more changes were found than are listed; counts covers all of them. |
summary | string | yes | The changes in plain words, for a pull request review. |
markdown | string | null | yes | |
next | string | yes |
CompareDiagramsInput
Two versions of a diagram to compare.
| Field | Type | Required | Description |
|---|---|---|---|
before | string | yes | The old diagram: source, the text of a Plotwork SVG that carries its source, or a cdn.plotwork.dev link. at least 1 character; at most 1000000 characters. |
after | string | yes | The new diagram, in any of the same three forms. at least 1 character; at most 1000000 characters. |
markdown | boolean | no | Also return a Markdown block ready to paste as a pull request comment. default false. |
SuggestDiagramResponse
The diagram kinds that fit a request, best first, each with a starter source.
| Field | Type | Required | Description |
|---|---|---|---|
request | string | yes | The request that was read. |
suggestions | object[] | yes | Up to 3, best first, one for each kind and style. |
suggestions[].kind | string | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
suggestions[].style | string | null | yes | The style the starter uses: compare, score, raci, or risk for a matrix, files or org for a tree; null for the kind's only style. |
suggestions[].why | string | yes | One sentence: why this kind fits. |
suggestions[].confidence | "high" | "medium" | "low" | yes | high: the text names this kind of picture or its shape fits it exactly. medium: it leans toward it. low: a fallback worth considering. |
suggestions[].starter | string | yes | A short Plotwork source of this kind that parses without errors: built from the names and numbers in the text where it could find them, otherwise a small example to edit. Replace every placeholder before you draw it. |
suggestions[].tailored | boolean | yes | True when the starter uses names or numbers from the text; false when it is the kind's small example. |
suggestions[].statements | string[] | yes | The few statements of this kind to write, as syntax. get_diagram_syntax with this kind has them all. |
importFormat | string | no | Present when the data is, or the request names, a file import_source reads (sql, openapi, compose, terraform, and so on): call import_source with this format and the file's text instead of editing a starter. |
next | string | yes | The next step in one sentence. |
SuggestDiagramInput
A request in plain words and optional data to draw from.
| Field | Type | Required | Description |
|---|---|---|---|
request | string | yes | What the picture is for, in plain words, such as "permission matrix for these endpoints and roles" or "how a refund moves between support and billing". at least 1 character; at most 1000 characters. |
data | string | no | Optional text to draw from: a pasted table, a list, numbers by period, or notes. Names and numbers in it are used in the starters. at most 20000 characters. |
EnquiryAck
| Field | Type | Required | Description |
|---|---|---|---|
received | true | yes | Always true. The enquiry was received. |
EnquiryBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | The name of the person asking. at least 1 character; at most 120 characters. |
email | string | yes | Their work email address. The reply goes here. |
company | string | yes | The company. at least 1 character; at most 120 characters. |
companySize | "1-49" | "50-249" | "250-999" | "1000-4999" | "5000+" | yes | How many people the company has. |
repos | "1-9" | "10-49" | "50-199" | "200-999" | "1000+" | yes | How many repositories the team would run diagrams in. |
useCase | string | yes | What the team wants to do, in their words. at least 10 characters; at most 2000 characters. |
interests | ("sso-scim" | "audit-siem" | "support-sla" | "limits" | "self-hosting" | "invoicing")[] | no | What the company needs, as the boxes ticked on the form. Left out, nothing was ticked; a box named twice counts once. |
context | EnquiryContext | no | Sent by the portal: where the form was opened. The site sends none. |
context.page | "contact" | "plan" | "sso" | "integrations" | "support" | "audit" | yes | The place in the portal the form was opened from, such as sso for the Single sign-on panel. |
context.org | string | no | The slug of the organisation the form was opened from. Kept only when the signed-in account is a member. pattern ^[a-z0-9](?:[a-z0-9-]{1,38}[a-z0-9])$. |
website | string | no | Leave empty. A field people do not see: an enquiry that fills it is taken for a script and dropped, with the same answer. at most 200 characters. |
elapsedMs | integer | yes | Milliseconds between the form being shown and being sent. An enquiry sent faster than a person can type is dropped, with the same answer. minimum 0. |
EnquiryContext
Sent by the portal: where the form was opened. The site sends none.
| Field | Type | Required | Description |
|---|---|---|---|
page | "contact" | "plan" | "sso" | "integrations" | "support" | "audit" | yes | The place in the portal the form was opened from, such as sso for the Single sign-on panel. |
org | string | no | The slug of the organisation the form was opened from. Kept only when the signed-in account is a member. pattern ^[a-z0-9](?:[a-z0-9-]{1,38}[a-z0-9])$. |
PublishAnswer
| Field | Type | Required | Description |
|---|
PublishedDiagram
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for managing the diagram (delete). It is not in the link. |
url | string | yes | The public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed. |
name | string | null | yes | The label given at publish, or null. |
folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
bytes | integer | yes | Size of the stored SVG in bytes. |
createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them. |
locked | boolean | yes | True while the diagram is locked: it cannot be deleted, renamed or moved until you unlock it. A lock does not stop it expiring on a plan that expires diagrams. |
lockedAt | integer | null | yes | When it was locked, in milliseconds since the epoch, or null when it is not locked. |
created | boolean | yes | True when this call stored a new diagram; false when the same diagram was already hosted and its link was kept. |
stableLink | StableLink | no | Present only when the publish named an alias: the stable link, now pointing at this diagram. |
stableLink.id | string | yes | The handle for managing the stable link (delete). It is not in its address. |
stableLink.alias | string | yes | The name you gave it. Only you see it. |
stableLink.url | string | yes | The public address, on the CDN host. It shows the diagram the stable link points at now (cached for up to 60 seconds) and never changes. Anyone with it can see the picture. |
stableLink.diagramId | string | null | yes | The diagram it shows now, or null when that diagram was deleted or expired; the address then answers 404 until you point the link at a diagram again. |
stableLink.createdAt | integer | yes | When it was made, in milliseconds since the epoch. |
stableLink.updatedAt | integer | yes | When it was last pointed at a diagram, in milliseconds since the epoch. |
StableLink
Present only when the publish named an alias: the stable link, now pointing at this diagram.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for managing the stable link (delete). It is not in its address. |
alias | string | yes | The name you gave it. Only you see it. |
url | string | yes | The public address, on the CDN host. It shows the diagram the stable link points at now (cached for up to 60 seconds) and never changes. Anyone with it can see the picture. |
diagramId | string | null | yes | The diagram it shows now, or null when that diagram was deleted or expired; the address then answers 404 until you point the link at a diagram again. |
createdAt | integer | yes | When it was made, in milliseconds since the epoch. |
updatedAt | integer | yes | When it was last pointed at a diagram, in milliseconds since the epoch. |
HostedDiagram
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for managing the diagram (delete). It is not in the link. |
url | string | yes | The public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed. |
name | string | null | yes | The label given at publish, or null. |
folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
bytes | integer | yes | Size of the stored SVG in bytes. |
createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them. |
locked | boolean | yes | True while the diagram is locked: it cannot be deleted, renamed or moved until you unlock it. A lock does not stop it expiring on a plan that expires diagrams. |
lockedAt | integer | null | yes | When it was locked, in milliseconds since the epoch, or null when it is not locked. |
RoutedPublish
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for the diagram in the routes below. |
name | string | null | yes | The label given at publish, or null. |
folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
bytes | integer | yes | Size of the stored SVG in bytes. |
createdBy | string | null | yes | The account that published it, or null when that account has left or an organisation key published it. |
createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted. |
viewUrl | string | yes | A page in the portal that shows the diagram to a signed-in member. It is not a link anyone can open: an organisation's diagrams have no public address. |
locked | boolean | yes | True while the owner has the diagram locked: nobody can delete, rename or move it, its publisher and the owner included, until the owner unlocks it. A lock does not stop it expiring on a plan that expires diagrams. |
lockedAt | integer | null | yes | When the owner locked it, in milliseconds since the epoch, or null when it is not locked. |
restricted | true | no | Present, and true, when the owner has restricted this diagram's folder and the caller is allowed in it, so the portal can show it as locked. Absent otherwise. A diagram in a folder the caller may not use is not listed at all. |
created | boolean | yes | True when this call stored a new diagram; false when the same diagram was already in the library and was kept. |
sourceEmbedded | boolean | yes | True when the stored picture carries the diagram source: the call sent embedSource true, or left it out while the organisation's keepEditable is on. |
private | true | yes | The diagram is in an organisation's private library and has no public link. |
organization | PublishOrganization | yes | The organisation whose private library holds the diagram. |
organization.id | string | yes | |
organization.slug | string | yes | |
organization.name | string | yes | |
routedBy | "organisation-default" | "organisation-required" | no | Present when the organisation's Publishing setting chose its library for a publish that named no organisation: organisation-default (its members publish there unless they ask for a personal link) or organisation-required (they always do). |
PublishOrganization
The organisation whose private library holds the diagram.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
slug | string | yes | |
name | string | yes |
PublishedOrganisationDiagram
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for the diagram in the routes below. |
name | string | null | yes | The label given at publish, or null. |
folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
bytes | integer | yes | Size of the stored SVG in bytes. |
createdBy | string | null | yes | The account that published it, or null when that account has left or an organisation key published it. |
createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted. |
viewUrl | string | yes | A page in the portal that shows the diagram to a signed-in member. It is not a link anyone can open: an organisation's diagrams have no public address. |
locked | boolean | yes | True while the owner has the diagram locked: nobody can delete, rename or move it, its publisher and the owner included, until the owner unlocks it. A lock does not stop it expiring on a plan that expires diagrams. |
lockedAt | integer | null | yes | When the owner locked it, in milliseconds since the epoch, or null when it is not locked. |
restricted | true | no | Present, and true, when the owner has restricted this diagram's folder and the caller is allowed in it, so the portal can show it as locked. Absent otherwise. A diagram in a folder the caller may not use is not listed at all. |
created | boolean | yes | True when this call stored a new diagram; false when the same diagram was already in the library and was kept. |
sourceEmbedded | boolean | yes | True when the stored picture carries the diagram source: the call sent embedSource true, or left it out while the organisation's keepEditable is on. |
OrganisationDiagram
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for the diagram in the routes below. |
name | string | null | yes | The label given at publish, or null. |
folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
bytes | integer | yes | Size of the stored SVG in bytes. |
createdBy | string | null | yes | The account that published it, or null when that account has left or an organisation key published it. |
createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted. |
viewUrl | string | yes | A page in the portal that shows the diagram to a signed-in member. It is not a link anyone can open: an organisation's diagrams have no public address. |
locked | boolean | yes | True while the owner has the diagram locked: nobody can delete, rename or move it, its publisher and the owner included, until the owner unlocks it. A lock does not stop it expiring on a plan that expires diagrams. |
lockedAt | integer | null | yes | When the owner locked it, in milliseconds since the epoch, or null when it is not locked. |
restricted | true | no | Present, and true, when the owner has restricted this diagram's folder and the caller is allowed in it, so the portal can show it as locked. Absent otherwise. A diagram in a folder the caller may not use is not listed at all. |
PublishDiagramBody
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Diagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
theme | "light" | "dark" | "auto" | no | The color scheme to draw it in: light, dark, or auto (one picture that follows the viewer's light or dark setting). default "light". |
embedSource | boolean | no | Write the diagram source into the stored SVG, in its metadata, so the picture can be edited later: read_diagram gives the source back from the link. The source then becomes part of the picture, which anyone who has the link can read (for a diagram in an organisation, every member who can open it). The same diagram published with and without it is two pictures with two links. Left out, a personal diagram does not store the source, and a diagram that lands in an organisation follows its keepEditable setting. |
name | string | no | A label for the diagram in your list and in the Markdown snippet. Optional. at least 1 character; at most 80 characters; pattern ^[^\p{Cc}]+$/u. |
folder | string | null | no | The folder to file the diagram in. Left out, a new diagram goes to the top level and a diagram that is already hosted stays where it is. A path files a new diagram there, or moves the one that is already hosted and keeps its link. null puts it at the top level. |
alias | string | no | Point a stable link with this name at the diagram, so one address always shows the latest version. The first publish with a name makes the stable link (the answer's stableLink.url) and every later publish with the same name moves it to the new diagram; the address never changes. How many stable links an account keeps depends on its plan. An alias asks for a personal link, so an organisation that requires its library refuses it (orgs.publish_required). Optional. at least 1 character; at most 60 characters; pattern ^[a-z0-9]+(?:-[a-z0-9]+)*$. |
organization | string | no | An organisation's slug or id: the diagram goes to that organisation's private library, and the answer has private true and a viewUrl in place of a public link. The account must be a member who may publish there. Left out, the diagram goes to your own library, unless an organisation you belong to publishes its members' diagrams to its library. at least 1 character; at most 64 characters. |
personal | boolean | no | True asks for a public link in your own library even though an organisation you belong to publishes its members' diagrams to its library by default. An organisation that requires its library refuses it (403 orgs.publish_required). Not with organization. |
HostedDiagramList
| Field | Type | Required | Description |
|---|---|---|---|
items | HostedDiagram[] | yes | At most 200, newest published first. |
items[].id | string | yes | The handle for managing the diagram (delete). It is not in the link. |
items[].url | string | yes | The public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed. |
items[].name | string | null | yes | The label given at publish, or null. |
items[].folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
items[].theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
items[].bytes | integer | yes | Size of the stored SVG in bytes. |
items[].createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
items[].publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
items[].expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them. |
items[].locked | boolean | yes | True while the diagram is locked: it cannot be deleted, renamed or moved until you unlock it. A lock does not stop it expiring on a plan that expires diagrams. |
items[].lockedAt | integer | null | yes | When it was locked, in milliseconds since the epoch, or null when it is not locked. |
stableLinks | StableLink[] | yes | Every stable link the account keeps, by alias, including any whose diagram is gone. |
stableLinks[].id | string | yes | The handle for managing the stable link (delete). It is not in its address. |
stableLinks[].alias | string | yes | The name you gave it. Only you see it. |
stableLinks[].url | string | yes | The public address, on the CDN host. It shows the diagram the stable link points at now (cached for up to 60 seconds) and never changes. Anyone with it can see the picture. |
stableLinks[].diagramId | string | null | yes | The diagram it shows now, or null when that diagram was deleted or expired; the address then answers 404 until you point the link at a diagram again. |
stableLinks[].createdAt | integer | yes | When it was made, in milliseconds since the epoch. |
stableLinks[].updatedAt | integer | yes | When it was last pointed at a diagram, in milliseconds since the epoch. |
usage | HostingUsage | yes | |
usage.plan | "free" | "pro" | yes | The plan the account is on, which decides the limits. |
usage.count | integer | yes | Hosted diagrams the account holds. This is the total, even when the list is shorter. minimum 0. |
usage.bytes | integer | yes | Total size of the hosted diagrams in bytes. minimum 0. |
usage.stableLinks | integer | yes | Stable links the account keeps. minimum 0. |
usage.limits | HostingPlanLimits | yes | |
usage.limits.dailyCalls | integer | yes | |
usage.limits.hostedDiagrams | integer | yes | |
usage.limits.hostedBytes | integer | yes | |
usage.limits.retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until you delete it. |
usage.limits.maxDiagramBytes | integer | yes | |
usage.limits.stableLinks | integer | yes | Stable links the account may keep at once. |
HostingUsage
| Field | Type | Required | Description |
|---|---|---|---|
plan | "free" | "pro" | yes | The plan the account is on, which decides the limits. |
count | integer | yes | Hosted diagrams the account holds. This is the total, even when the list is shorter. minimum 0. |
bytes | integer | yes | Total size of the hosted diagrams in bytes. minimum 0. |
stableLinks | integer | yes | Stable links the account keeps. minimum 0. |
limits | HostingPlanLimits | yes | |
limits.dailyCalls | integer | yes | |
limits.hostedDiagrams | integer | yes | |
limits.hostedBytes | integer | yes | |
limits.retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until you delete it. |
limits.maxDiagramBytes | integer | yes | |
limits.stableLinks | integer | yes | Stable links the account may keep at once. |
HostingPlanLimits
| Field | Type | Required | Description |
|---|---|---|---|
dailyCalls | integer | yes | |
hostedDiagrams | integer | yes | |
hostedBytes | integer | yes | |
retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until you delete it. |
maxDiagramBytes | integer | yes | |
stableLinks | integer | yes | Stable links the account may keep at once. |
MoveDiagramBody
| Field | Type | Required | Description |
|---|---|---|---|
folder | string | null | yes | The folder to file the diagram in, or null for the top level. |
EditedDiagram
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for managing the diagram (delete). It is not in the link. |
url | string | yes | The public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed. |
name | string | null | yes | The label given at publish, or null. |
folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
bytes | integer | yes | Size of the stored SVG in bytes. |
createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them. |
locked | boolean | yes | True while the diagram is locked: it cannot be deleted, renamed or moved until you unlock it. A lock does not stop it expiring on a plan that expires diagrams. |
lockedAt | integer | null | yes | When it was locked, in milliseconds since the epoch, or null when it is not locked. |
warnings | Diagnostic[] | yes | Quality warnings from drawing the source, as draw_diagram gives them. Empty for a restore. |
warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
warnings[].message | string | yes | What is wrong, in one sentence. |
warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
changed | boolean | yes | False when the source draws the picture the diagram already has: nothing was stored and no version was kept. |
SaveDiagramSourceBody
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Diagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters. |
theme | "light" | "dark" | "auto" | no | The color scheme to draw it in: light, dark, or auto. Left out, the theme the diagram has. |
baseVersion | integer | yes | The diagram's publishedAt (milliseconds since the epoch) when the editor loaded it. If the diagram was saved since, the answer is 409 diagram.version_conflict with details.currentVersion. minimum 0. |
DiagramVersionList
| Field | Type | Required | Description |
|---|---|---|---|
items | DiagramVersion[] | yes | Newest first. A diagram keeps at most ten. |
items[].id | string | yes | The handle for restoring it. |
items[].savedAt | integer | yes | When it stopped being the current picture, in milliseconds since the epoch. |
items[].bytes | integer | yes | Size of the stored SVG in bytes. Versions do not count toward the plan. |
items[].theme | "light" | "dark" | "auto" | yes |
DiagramVersion
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for restoring it. |
savedAt | integer | yes | When it stopped being the current picture, in milliseconds since the epoch. |
bytes | integer | yes | Size of the stored SVG in bytes. Versions do not count toward the plan. |
theme | "light" | "dark" | "auto" | yes |
RestoreDiagramVersionBody
| Field | Type | Required | Description |
|---|---|---|---|
baseVersion | integer | yes | The diagram's publishedAt (milliseconds since the epoch) when the editor loaded it. If the diagram was saved since, the answer is 409 diagram.version_conflict with details.currentVersion. minimum 0. |
SetStableLinkBody
| Field | Type | Required | Description |
|---|---|---|---|
alias | string | yes | The name of a stable link: lower-case letters and digits in words joined by single hyphens, up to 60 characters. Only you see it; the public address carries a random token instead. at least 1 character; at most 60 characters; pattern ^[a-z0-9]+(?:-[a-z0-9]+)*$. |
diagramId | string | yes | One of your hosted diagrams, by its id. |
OEmbedPhoto
| Field | Type | Required | Description |
|---|---|---|---|
version | "1.0" | yes | |
type | "photo" | yes | |
provider_name | string | yes | |
provider_url | string | yes | |
title | string | yes | Always "Diagram": the diagram's own name is shown only to its owner. |
url | string | yes | The picture. For a stable link, the stable link itself, so the embed keeps showing the latest version. |
width | integer | yes | |
height | integer | yes | |
cache_age | integer | yes | Seconds the answer may be kept: 60 for a stable link, 3600 for a picture. |
MapIconsResponse
An icon, or candidates, for each name sent, and the names that found no icon.
| Field | Type | Required | Description |
|---|---|---|---|
provider | "aws" | "gcp" | "azure" | "alibaba" | "oci" | "ibm" | "cloudflare" | "digitalocean" | "vercel" | null | yes | The provider hint that was used, or null. |
results | object[] | yes | One entry per name that matched something, in the order sent. |
results[].name | string | yes | The name exactly as it was sent. |
results[].resolved | boolean | yes | True when icon holds the one icon to use. False when the name could mean more than one: choose from candidates, or ask the user. |
results[].icon | string | null | yes | The icon to write as icon=, such as aws:lambda; null when resolved is false. |
results[].confidence | "exact" | "strong" | "ambiguous" | yes | exact: the name is the icon or product name. strong: the name clearly points at this icon and no other provider competes. ambiguous: several icons fit, or the match is by idea only. |
results[].alternatives | string[] | yes | Up to 3 other icons that also fit a resolved name, best first. Empty when none. |
results[].candidates | string[] | yes | When resolved is false, the icons that fit, best first (up to 4). Empty when resolved. |
gaps | object[] | yes | Names that matched nothing, in the order sent. |
gaps[].name | string | yes | The name that matched no icon. |
gaps[].fallback | string | yes | A neutral icon to use instead, or leave icon= out so the node type draws its own. |
gaps[].reason | string | yes | Why there is no match, and what to try. |
resolvedCount | integer | yes | How many names have one icon to use. |
ambiguousCount | integer | yes | How many names need a choice from candidates. |
gapCount | integer | yes | How many names matched nothing. |
MapIconsInput
Names to find icons for, and an optional provider to look in first.
| Field | Type | Required | Description |
|---|---|---|---|
names | string[] | yes | Services, products, or ideas to find icons for, written as the user wrote them ("S3", "Postgres", "load balancer"). Up to 40 names of up to 80 characters. |
provider | "aws" | "gcp" | "azure" | "alibaba" | "oci" | "ibm" | "cloudflare" | "digitalocean" | "vercel" | no | The cloud the architecture runs on. A name is looked up there first, so "queue" finds aws:sqs for aws. Omit it when the names are not tied to one provider. |
IconSearchResponse
Matching bundled icon names.
| Field | Type | Required | Description |
|---|---|---|---|
query | string | yes | The query that was searched. |
items | string[] | yes | Matching icon references as set:name, best match first. |
ImportSourceResponse
The result of turning a file of another format into Plotwork source.
| Field | Type | Required | Description |
|---|---|---|---|
ok | boolean | yes | True when source is valid Plotwork source. False means nothing was imported and source is empty: read diagnostics. |
kind | string | null | yes | The kind of diagram the file became, or null when nothing was imported. |
format | string | yes | The format the text was read as. |
source | string | yes | The Plotwork source, or an empty string when nothing could be imported. |
diagnostics | Diagnostic[] | yes | Everything left out, changed, or wrong, with a hint. Codes start with I and point into the text you sent: I1xx errors stopped the import, I2xx warnings did not. |
diagnostics[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
diagnostics[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
diagnostics[].message | string | yes | What is wrong, in one sentence. |
diagnostics[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
diagnostics[].column | integer | yes | 1-based column in that line. minimum 1. |
diagnostics[].length | integer | yes | Number of characters the problem covers. minimum 1. |
diagnostics[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
stats | object | yes | |
stats.items | integer | yes | Boxes, tables, rows, slices, places, entries, or commits written. |
stats.links | integer | yes | Arrows, relations, messages, flows, or merges written. |
stats.groups | integer | yes | Frames, sections, or folders written. |
stats.dropped | integer | yes | Things in the file left out by a cap or because the picture has no place for them; each is in diagnostics. |
coverage | object | null | yes | How much of the file the picture shows; null when nothing was imported. When complete is false, the picture is not the whole file: say so. |
coverage.noun | string | yes | What was counted, such as resources, services, tables, or endpoints. |
coverage.total | integer | yes | Everything of that kind in the file. |
coverage.drawn | integer | yes | Drawn as a box, frame, table, row, or entry of its own. |
coverage.summarised | integer | yes | Not drawn on their own but counted on the box they belong to, such as "3 role assignments". |
coverage.omitted | integer | yes | Not in the picture at all; the diagnostics say which and why. |
coverage.complete | boolean | yes | True when nothing was omitted. |
coverage.line | string | yes | The coverage in one sentence, such as "Drawn 12 of 85 resources; 60 are counted on the boxes they belong to and 13 are left out.". |
validation | object | null | yes | The Plotwork validator run on source; null when nothing was imported. |
validation.valid | boolean | yes | True when the source has no Plotwork errors. It always is when ok is true. |
validation.errors | Diagnostic[] | yes | Plotwork errors. Lines and columns point into source. |
validation.errors[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
validation.errors[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
validation.errors[].message | string | yes | What is wrong, in one sentence. |
validation.errors[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
validation.errors[].column | integer | yes | 1-based column in that line. minimum 1. |
validation.errors[].length | integer | yes | Number of characters the problem covers. minimum 1. |
validation.errors[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
validation.warnings | Diagnostic[] | yes | Plotwork quality warnings, with the exact fix in each hint. Lines and columns point into source. |
validation.warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
validation.warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
validation.warnings[].message | string | yes | What is wrong, in one sentence. |
validation.warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
validation.warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
validation.warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
validation.warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
validation.summary | string | null | yes | One-line description of the diagram, usable as alt text. |
validation.size | object | null | yes | Natural size of the laid-out diagram. |
validation.size.width | integer | yes | Width in px. minimum 1. |
validation.size.height | integer | yes | Height in px. minimum 1. |
parts | object[] | yes | When the file is too big for one readable picture, the diagrams it was split into, in order, at most 24 a page; source is the first diagram of all. Show or draw each of them. Empty when the import is one diagram. |
parts[].title | string | yes | What this diagram shows, such as one resource group or one tag of an API. |
parts[].kind | string | yes | The kind of diagram. |
parts[].source | string | yes | The Plotwork source of this diagram; draw it with draw_diagram. |
parts[].items | integer | yes | The boxes, rows, or entries it draws. |
parts[].valid | boolean | yes | True when the source has no Plotwork errors. |
parts[].warnings | Diagnostic[] | yes | Plotwork quality warnings of this diagram. Lines and columns point into its source. |
parts[].warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
parts[].warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
parts[].warnings[].message | string | yes | What is wrong, in one sentence. |
parts[].warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
parts[].warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
parts[].warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
parts[].warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
partsTotal | integer | yes | How many diagrams the import was split into in all; 0 when it is one diagram. |
partsPage | integer | yes | The page of parts this answer holds, from 1. |
partsPages | integer | yes | How many pages of parts there are; call again with partsPage for the next one. |
outline | string[] | yes | The diagram as plain text, to check it says what the file says; empty when nothing was imported. |
outlineTruncated | boolean | yes | True when the outline was cut short at its summary length. |
viewUrl | string | no | A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so. |
pngUrl | string | no | The viewUrl with &download=png: opening it in a browser saves the diagram as a PNG for Slack, email, or a wiki. The PNG is drawn in the person's browser, not on a server, so it is a link to open, not an image address to embed. Absent when too long. |
svgUrl | string | no | The viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long. |
saveCommand | string | no | Run in a shell to save the SVG into the repository: the CLI decodes the link locally, fetches nothing, and embeds the source. Set --out to the path; add --theme dark for dark. Absent when too long. |
next | string | yes | The next step in one sentence. |
ImportSourceInput
A file of another format to turn into Plotwork source.
| Field | Type | Required | Description |
|---|---|---|---|
format | "sql" | "prisma" | "drizzle" | "openapi" | "terraform" | "terraform-plan" | "bicep" | "arm" | "pulumi" | "cloudformation" | "cdk" | "compose" | "kubernetes" | "helm" | "kustomize" | "backstage" | "structurizr" | "asyncapi" | "github-actions" | "gitlab-ci" | "azure-pipelines" | "csv" | "json" | "tree" | "git-log" | yes | What the text is; get_diagram_syntax with topic import-formats describes each. |
text | string | no | The file content, as text. Send text or files, not both. |
files | object[] | no | The files of a folder, for a format that spans files; the others read the first. |
files[].path | string | yes | The file path, such as infra/network.tf; diagnostics name it. at least 1 character; at most 300 characters. |
files[].text | string | yes | The file content, as text. |
title | string | no | The diagram title; taken from the file when left out. at most 200 characters. |
partsPage | integer | no | Which page of parts to return when a split import has more than 24 diagrams: 1 (default) is the first 24. minimum 1; maximum 100000. |
options | object | no | default {}. |
options.view | "endpoints" | "map" | "sequence" | "git" | "timeline" | "context" | "container" | "component" | no | The picture of a format drawn several ways. |
options.operationId | string | no | openapi sequence: the operation. at most 200 characters. |
options.chart | "auto" | "xychart" | "pie" | "sankey" | "treemap" | "matrix" | no | csv, json: the chart; auto picks. |
options.tables | string[] | no | Tables to draw, by name or prefix*. |
options.paths | string[] | no | openapi: path prefixes to read. |
options.tags | string[] | no | openapi: tags to read. |
options.varFiles | string[] | no | Variables files to apply. |
options.groupBy | "module" | "network" | "file" | "owner" | no | How things are framed; module is the default. |
options.root | string | no | The root, stack, or template of several to draw. at most 300 characters. |
SyncMarkdownResponse
The result of turning a document's diagram fences into pictures.
| Field | Type | Required | Description |
|---|---|---|---|
mode | "sync" | "check" | yes | The mode that ran. |
markdown | string | yes | The document to write back: every diagram fence wrapped in its collapsed source section, with the picture block and text description under it, and everything else unchanged. In check mode this is the document that was sent. |
changed | boolean | yes | True when the document or a file differs from what was sent. In check mode this says the pictures are stale or a fence would convert. |
files | object[] | yes | The SVG files to write, light and dark for each picture that was refreshed, with paths relative to the repository root. Empty in check mode. A picture that was already current has no files. |
files[].path | string | yes | Where to write the file, relative to the repository root. |
files[].content | string | no | The file contents; absent when files is none. |
files[].encoding | "utf8" | yes | How content is encoded. Always utf8: the files are SVG text. |
files[].bytes | integer | no | Only when files is none: the size of the file in bytes. |
files[].sha256 | string | no | Only when files is none: the SHA-256 of the content, in hex, to check a file fetched later. |
files[].viewUrl | string | no | Only when files is none: a link that shows this diagram in a browser. |
report | object[] | yes | One entry per fence handled, in document order. |
report[].id | string | null | yes | The picture id, which names the SVG files; null for a fence that has none (a mermaid fence that was not converted). |
report[].source | "diagram" | "mermaid" | yes | diagram for a fence that was already Plotwork, mermaid for one that came from Mermaid. |
report[].kind | string | null | yes | The diagram kind, or null when it could not be read. |
report[].line | integer | yes | The 1-based line of the opening fence in the document that was sent. minimum 1. |
report[].status | "synced" | "converted" | "unchanged" | "skipped" | "failed" | yes | synced: the picture was written or refreshed. converted: a mermaid fence became a diagram fence and was drawn. unchanged: the picture was already current. skipped: a cap stopped it, see message. failed: it has errors, the fence is left as it was. |
report[].diagnostics | Diagnostic[] | yes | Errors and warnings, with line numbers counted in the document that was sent. For a converted fence they point at the Mermaid lines. |
report[].diagnostics[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
report[].diagnostics[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
report[].diagnostics[].message | string | yes | What is wrong, in one sentence. |
report[].diagnostics[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
report[].diagnostics[].column | integer | yes | 1-based column in that line. minimum 1. |
report[].diagnostics[].length | integer | yes | Number of characters the problem covers. minimum 1. |
report[].diagnostics[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
report[].message | string | null | yes | A plain sentence when something needs saying, such as why a fence was skipped; otherwise null. |
summary | object | yes | |
summary.diagrams | integer | yes | Fences handled: synced, converted, unchanged, skipped, and failed together. |
summary.synced | integer | yes | |
summary.converted | integer | yes | |
summary.unchanged | integer | yes | |
summary.skipped | integer | yes | |
summary.failed | integer | yes | |
summary.mermaidIgnored | integer | yes | Mermaid fences left alone because convertMermaid was false. |
summary.files | integer | yes | Files to write. |
summary.outputBytes | integer | yes | Bytes in the returned document and files together. |
caps | object | yes | |
caps.hit | boolean | yes | True when a cap stopped some of the work. Nothing is cut silently: see messages. |
caps.messages | string[] | yes | One plain sentence per cap that was hit, saying what was skipped and what to do. |
caps.maxDiagrams | integer | yes | Most fences handled in one call. |
caps.maxOutputBytes | integer | yes | Most bytes in the returned document and files together. |
pages | object | no | Present when page or pageSize was sent: which pictures files holds, and the next page. |
pages.page | integer | yes | |
pages.pageSize | integer | yes | |
pages.pages | integer | yes | Pages in all. |
pages.pictures | integer | yes | Pictures in all, each a light and a dark file. |
pages.nextPage | integer | null | yes | The page to ask for next, or null on the last one. |
next | string | yes | The next step in one sentence. |
SyncMarkdownInput
A Markdown document and how to turn its diagram fences into pictures.
| Field | Type | Required | Description |
|---|---|---|---|
markdown | string | yes | The whole Markdown document, exactly as it is on disk, with its line endings. Up to 10000000 characters. at least 1 character; at most 10000000 characters. |
documentPath | string | yes | Where the document lives, relative to the repository root, with forward slashes, for example docs/guide.md. Picture links and file paths are worked out from it. at least 1 character; at most 300 characters. |
assetsDir | string | no | The directory for the SVG files, relative to the repository root. The default is assets/diagrams next to the document. at least 1 character; at most 300 characters. |
prefix | string | no | Text put in front of every picture file name, for documents that share one assets directory. By default a titled diagram is named from its title and an untitled one from the document name. at least 1 character; at most 32 characters. |
convertMermaid | boolean | no | When true, every mermaid fence that can be converted is replaced by a diagram fence first, then drawn. Fences that cannot be converted are left exactly as they were and reported. default false. |
mode | "sync" | "check" | no | sync (the default) returns the rewritten document and the files to write. check changes nothing: it only reports whether a picture is stale or a fence would convert. default "sync". |
files | "inline" | "none" | no | inline (the default) returns each SVG file with its content. none returns each with path, bytes, sha256, and viewUrl instead, so the answer stays small. default "inline". |
page | integer | no | Which page of files to return, from 1; pictures are paged in document order, light and dark together. minimum 1. |
pageSize | integer | no | Pictures per page, at most 30. Setting page or pageSize turns paging on. minimum 1; maximum 30. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
PlanDocumentResponse
The sections of a document a picture would help, each with a kind, a reason, and a starter.
| Field | Type | Required | Description |
|---|---|---|---|
summary | string | yes | One sentence: how many sections were read and how many would gain a picture. |
format | "markdown" | "html" | "text" | yes | How the document was read: Markdown headings, HTML h1 to h6, or plain text with heading-like lines. |
sectionsRead | integer | yes | Sections read, up to the cap. |
suggestions | object[] | yes | In document order. Sections that read well as text, or already have a diagram, are not listed. |
suggestions[].heading | string | yes | The heading of the section, as written. |
suggestions[].line | integer | yes | The 1-based line of the heading in the document that was sent. minimum 1. |
suggestions[].kind | string | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
suggestions[].style | string | null | yes | The style the starter uses: compare, score, raci, or risk for a matrix, files or org for a tree; null for the kind's only style. |
suggestions[].why | string | yes | One sentence: what in the section points to this kind. |
suggestions[].confidence | "high" | "medium" | "low" | yes | high: the text names this kind of picture or its shape fits it exactly. medium: it leans toward it. low: a fallback worth considering. |
suggestions[].starter | string | yes | A short Plotwork source of this kind that parses without errors: built from the names and numbers in the text where it could find them, otherwise a small example to edit. Replace every placeholder before you draw it. |
suggestions[].tailored | boolean | yes | True when the starter uses names or numbers from the text; false when it is the kind's small example. |
caps | object | yes | |
caps.hit | boolean | yes | True when a cap left something out; messages says what. |
caps.messages | string[] | yes | |
caps.maxSections | integer | yes | |
caps.maxSuggestions | integer | yes | |
next | string | yes | The next step in one sentence. |
PlanDocumentInput
A document to read for the sections a picture would help.
| Field | Type | Required | Description |
|---|---|---|---|
document | string | yes | The whole document: Markdown, plain text pasted from Confluence, Notion, or Google Docs, or HTML. Up to 10000000 characters. at least 1 character; at most 10000000 characters. |
maxSuggestions | integer | no | Most sections to suggest a picture for, up to 12. The strongest are kept, in document order. The default is 8. minimum 1; maximum 12; default 8. |
OrganisationList
| Field | Type | Required | Description |
|---|---|---|---|
items | Organisation[] | yes | By name, at most 100. |
items[].id | string | yes | |
items[].slug | string | yes | |
items[].name | string | yes | |
items[].role | "owner" | "admin" | "member" | "reader" | yes | What the caller is in this organisation. |
items[].createdAt | integer | yes | Milliseconds since the epoch. |
items[].memberCount | integer | yes | People who have joined, the owner included. The same number as usage.members. minimum 0. |
items[].plan | "free" | "pro" | "enterprise" | yes | The organisation's plan: enterprise under a contract, otherwise its owner's. |
items[].contractEndsOn | string | null | yes | The last day of the Enterprise contract, YYYY-MM-DD, or null when there is none or it has no end date written. The terms of a contract are not shown to members. |
items[].usage | OrganisationUsage | yes | |
items[].usage.diagrams | integer | yes | minimum 0. |
items[].usage.bytes | integer | yes | minimum 0. |
items[].usage.members | integer | yes | People who have joined, the owner included. minimum 0. |
items[].usage.invites | integer | yes | Invitations that can still be accepted. They count toward the member limit. minimum 0. |
items[].limits | OrganisationLimits | yes | |
items[].limits.dailyCalls | integer | yes | |
items[].limits.hostedDiagrams | integer | yes | Diagrams the organisation may hold. |
items[].limits.hostedBytes | integer | yes | Total bytes of diagrams the organisation may hold. |
items[].limits.retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until it is deleted. |
items[].limits.maxDiagramBytes | integer | yes | |
items[].limits.stableLinks | integer | yes | Stable links the owner may keep for their own diagrams. An organisation's diagrams have none. |
items[].limits.organisations | integer | yes | Organisations an account on this plan may own. |
items[].limits.orgMembers | integer | yes | People one organisation may have, the owner included and pending invitations counted. |
items[].limits.orgIcons | integer | yes | Custom icons one organisation may keep; zero on a plan without custom icons. minimum 0. |
items[].limits.driftHistoryDays | integer | yes | Days the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0. |
items[].limits.auditRetentionDays | integer | yes | Days the organisation's audit log keeps an event; zero on a plan that records none. minimum 0. |
items[].avatar | OrgAvatar | yes | The organisation's uploaded avatar, or null when it has none and a mark made from its id stands in. |
items[].avatar.version | string | yes | Changes with every upload. Put it in the address (?v=) so a new picture is a new address. |
items[].avatar.contentType | "image/svg+xml" | "image/png" | "image/gif" | "image/webp" | yes | |
items[].avatar.animated | boolean | yes | True when it moves, so a page can hold it still for a person who asked for less motion. |
items[].keepEditable | boolean | yes | The owner's setting "Keep diagrams editable": true when a publish to the organisation that does not send embedSource writes the diagram source into the picture, so members can edit it in the portal later. Every member can open such a picture and read its source. |
items[].publishing | OrganisationPublishing | yes | |
items[].publishing.policy | "personal" | "organisation-default" | "organisation-required" | yes | What the owner or an admin chose: personal (members publish where they choose), organisation-default (a member's publish that names no organisation goes to this library), or organisation-required (nothing a member publishes reaches a public link). |
items[].publishing.effective | "personal" | "organisation-default" | "organisation-required" | yes | What is enforced now: the choice, except organisation-required on a plan that no longer includes it, which acts as organisation-default. |
items[].publishing.hideViewLinks | boolean | yes | Whether hosted answers leave view links out for members and the organisation's keys. Honoured only while effective is organisation-required. |
items[].publishing.requiredAvailable | boolean | yes | Whether the organisation's plan includes organisation-required (Pro and Enterprise). |
Organisation
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
slug | string | yes | |
name | string | yes | |
role | "owner" | "admin" | "member" | "reader" | yes | What the caller is in this organisation. |
createdAt | integer | yes | Milliseconds since the epoch. |
memberCount | integer | yes | People who have joined, the owner included. The same number as usage.members. minimum 0. |
plan | "free" | "pro" | "enterprise" | yes | The organisation's plan: enterprise under a contract, otherwise its owner's. |
contractEndsOn | string | null | yes | The last day of the Enterprise contract, YYYY-MM-DD, or null when there is none or it has no end date written. The terms of a contract are not shown to members. |
usage | OrganisationUsage | yes | |
usage.diagrams | integer | yes | minimum 0. |
usage.bytes | integer | yes | minimum 0. |
usage.members | integer | yes | People who have joined, the owner included. minimum 0. |
usage.invites | integer | yes | Invitations that can still be accepted. They count toward the member limit. minimum 0. |
limits | OrganisationLimits | yes | |
limits.dailyCalls | integer | yes | |
limits.hostedDiagrams | integer | yes | Diagrams the organisation may hold. |
limits.hostedBytes | integer | yes | Total bytes of diagrams the organisation may hold. |
limits.retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until it is deleted. |
limits.maxDiagramBytes | integer | yes | |
limits.stableLinks | integer | yes | Stable links the owner may keep for their own diagrams. An organisation's diagrams have none. |
limits.organisations | integer | yes | Organisations an account on this plan may own. |
limits.orgMembers | integer | yes | People one organisation may have, the owner included and pending invitations counted. |
limits.orgIcons | integer | yes | Custom icons one organisation may keep; zero on a plan without custom icons. minimum 0. |
limits.driftHistoryDays | integer | yes | Days the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0. |
limits.auditRetentionDays | integer | yes | Days the organisation's audit log keeps an event; zero on a plan that records none. minimum 0. |
avatar | OrgAvatar | yes | The organisation's uploaded avatar, or null when it has none and a mark made from its id stands in. |
avatar.version | string | yes | Changes with every upload. Put it in the address (?v=) so a new picture is a new address. |
avatar.contentType | "image/svg+xml" | "image/png" | "image/gif" | "image/webp" | yes | |
avatar.animated | boolean | yes | True when it moves, so a page can hold it still for a person who asked for less motion. |
keepEditable | boolean | yes | The owner's setting "Keep diagrams editable": true when a publish to the organisation that does not send embedSource writes the diagram source into the picture, so members can edit it in the portal later. Every member can open such a picture and read its source. |
publishing | OrganisationPublishing | yes | |
publishing.policy | "personal" | "organisation-default" | "organisation-required" | yes | What the owner or an admin chose: personal (members publish where they choose), organisation-default (a member's publish that names no organisation goes to this library), or organisation-required (nothing a member publishes reaches a public link). |
publishing.effective | "personal" | "organisation-default" | "organisation-required" | yes | What is enforced now: the choice, except organisation-required on a plan that no longer includes it, which acts as organisation-default. |
publishing.hideViewLinks | boolean | yes | Whether hosted answers leave view links out for members and the organisation's keys. Honoured only while effective is organisation-required. |
publishing.requiredAvailable | boolean | yes | Whether the organisation's plan includes organisation-required (Pro and Enterprise). |
OrganisationUsage
| Field | Type | Required | Description |
|---|---|---|---|
diagrams | integer | yes | minimum 0. |
bytes | integer | yes | minimum 0. |
members | integer | yes | People who have joined, the owner included. minimum 0. |
invites | integer | yes | Invitations that can still be accepted. They count toward the member limit. minimum 0. |
OrganisationLimits
| Field | Type | Required | Description |
|---|---|---|---|
dailyCalls | integer | yes | |
hostedDiagrams | integer | yes | Diagrams the organisation may hold. |
hostedBytes | integer | yes | Total bytes of diagrams the organisation may hold. |
retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until it is deleted. |
maxDiagramBytes | integer | yes | |
stableLinks | integer | yes | Stable links the owner may keep for their own diagrams. An organisation's diagrams have none. |
organisations | integer | yes | Organisations an account on this plan may own. |
orgMembers | integer | yes | People one organisation may have, the owner included and pending invitations counted. |
orgIcons | integer | yes | Custom icons one organisation may keep; zero on a plan without custom icons. minimum 0. |
driftHistoryDays | integer | yes | Days the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0. |
auditRetentionDays | integer | yes | Days the organisation's audit log keeps an event; zero on a plan that records none. minimum 0. |
OrgAvatar
The organisation's uploaded avatar, or null when it has none and a mark made from its id stands in.
| Field | Type | Required | Description |
|---|---|---|---|
version | string | yes | Changes with every upload. Put it in the address (?v=) so a new picture is a new address. |
contentType | "image/svg+xml" | "image/png" | "image/gif" | "image/webp" | yes | |
animated | boolean | yes | True when it moves, so a page can hold it still for a person who asked for less motion. |
OrganisationPublishing
| Field | Type | Required | Description |
|---|---|---|---|
policy | "personal" | "organisation-default" | "organisation-required" | yes | What the owner or an admin chose: personal (members publish where they choose), organisation-default (a member's publish that names no organisation goes to this library), or organisation-required (nothing a member publishes reaches a public link). |
effective | "personal" | "organisation-default" | "organisation-required" | yes | What is enforced now: the choice, except organisation-required on a plan that no longer includes it, which acts as organisation-default. |
hideViewLinks | boolean | yes | Whether hosted answers leave view links out for members and the organisation's keys. Honoured only while effective is organisation-required. |
requiredAvailable | boolean | yes | Whether the organisation's plan includes organisation-required (Pro and Enterprise). |
CreateOrganisationBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | What people read. 1 to 60 characters. It can be changed; the slug cannot. at least 1 character; pattern ^[^\p{Cc}]+$/u. |
slug | string | no | The handle. Left out, it is made from the name, with a short suffix when that is taken. at least 3 characters; at most 40 characters; pattern ^[a-z0-9][a-z0-9-]*[a-z0-9]$. |
RenameOrganisationBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | What people read. 1 to 60 characters. It can be changed; the slug cannot. at least 1 character; pattern ^[^\p{Cc}]+$/u. |
OrganisationMemberList
| Field | Type | Required | Description |
|---|---|---|---|
items | OrganisationMember[] | yes | |
items[].userId | string | yes | |
items[].email | string | yes | Shown to every member: a team knows who is in it. |
items[].role | "owner" | "admin" | "member" | "reader" | yes | |
items[].joinedAt | integer | yes | Milliseconds since the epoch. |
OrganisationMember
| Field | Type | Required | Description |
|---|---|---|---|
userId | string | yes | |
email | string | yes | Shown to every member: a team knows who is in it. |
role | "owner" | "admin" | "member" | "reader" | yes | |
joinedAt | integer | yes | Milliseconds since the epoch. |
ChangeMemberRoleBody
| Field | Type | Required | Description |
|---|---|---|---|
role | "admin" | "member" | "reader" | yes | admin, member or reader. An admin can invite and remove members and readers, rename the organisation and manage its keys; a member can publish and change their own diagrams; a reader can view and download and change nothing. Only the owner offers admin or changes a role. |
OrganisationInviteList
| Field | Type | Required | Description |
|---|---|---|---|
items | OrganisationInvite[] | yes | |
items[].id | string | yes | |
items[].email | string | yes | |
items[].role | "admin" | "member" | "reader" | yes | |
items[].createdAt | integer | yes | Milliseconds since the epoch. |
items[].expiresAt | integer | yes | Milliseconds since the epoch. Seven days after it was made. |
OrganisationInvite
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
email | string | yes | |
role | "admin" | "member" | "reader" | yes | |
createdAt | integer | yes | Milliseconds since the epoch. |
expiresAt | integer | yes | Milliseconds since the epoch. Seven days after it was made. |
CreateInviteBody
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | The address to invite. The person must sign in with this address to accept. at least 3 characters; at most 254 characters. |
role | "admin" | "member" | "reader" | yes | admin, member or reader. An admin can invite and remove members and readers, rename the organisation and manage its keys; a member can publish and change their own diagrams; a reader can view and download and change nothing. Only the owner offers admin or changes a role. |
AcceptInviteBody
| Field | Type | Required | Description |
|---|---|---|---|
token | string | yes | The token in the invitation link. at least 1 character; at most 200 characters. |
OrganisationDiagramList
| Field | Type | Required | Description |
|---|---|---|---|
items | OrganisationDiagram[] | yes | At most 200, newest published first. |
items[].id | string | yes | The handle for the diagram in the routes below. |
items[].name | string | null | yes | The label given at publish, or null. |
items[].folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
items[].theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
items[].bytes | integer | yes | Size of the stored SVG in bytes. |
items[].createdBy | string | null | yes | The account that published it, or null when that account has left or an organisation key published it. |
items[].createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
items[].publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
items[].expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted. |
items[].viewUrl | string | yes | A page in the portal that shows the diagram to a signed-in member. It is not a link anyone can open: an organisation's diagrams have no public address. |
items[].locked | boolean | yes | True while the owner has the diagram locked: nobody can delete, rename or move it, its publisher and the owner included, until the owner unlocks it. A lock does not stop it expiring on a plan that expires diagrams. |
items[].lockedAt | integer | null | yes | When the owner locked it, in milliseconds since the epoch, or null when it is not locked. |
items[].restricted | true | no | Present, and true, when the owner has restricted this diagram's folder and the caller is allowed in it, so the portal can show it as locked. Absent otherwise. A diagram in a folder the caller may not use is not listed at all. |
usage | OrganisationHostingUsage | yes | |
usage.plan | "free" | "pro" | "enterprise" | yes | |
usage.count | integer | yes | Diagrams the organisation holds. This is the total, even when the list is shorter. minimum 0. |
usage.bytes | integer | yes | minimum 0. |
usage.limits | OrganisationLimits | yes | |
usage.limits.dailyCalls | integer | yes | |
usage.limits.hostedDiagrams | integer | yes | Diagrams the organisation may hold. |
usage.limits.hostedBytes | integer | yes | Total bytes of diagrams the organisation may hold. |
usage.limits.retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until it is deleted. |
usage.limits.maxDiagramBytes | integer | yes | |
usage.limits.stableLinks | integer | yes | Stable links the owner may keep for their own diagrams. An organisation's diagrams have none. |
usage.limits.organisations | integer | yes | Organisations an account on this plan may own. |
usage.limits.orgMembers | integer | yes | People one organisation may have, the owner included and pending invitations counted. |
usage.limits.orgIcons | integer | yes | Custom icons one organisation may keep; zero on a plan without custom icons. minimum 0. |
usage.limits.driftHistoryDays | integer | yes | Days the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0. |
usage.limits.auditRetentionDays | integer | yes | Days the organisation's audit log keeps an event; zero on a plan that records none. minimum 0. |
OrganisationHostingUsage
| Field | Type | Required | Description |
|---|---|---|---|
plan | "free" | "pro" | "enterprise" | yes | |
count | integer | yes | Diagrams the organisation holds. This is the total, even when the list is shorter. minimum 0. |
bytes | integer | yes | minimum 0. |
limits | OrganisationLimits | yes | |
limits.dailyCalls | integer | yes | |
limits.hostedDiagrams | integer | yes | Diagrams the organisation may hold. |
limits.hostedBytes | integer | yes | Total bytes of diagrams the organisation may hold. |
limits.retentionDays | integer | null | yes | Days a diagram is kept after it was last published, or null to keep it until it is deleted. |
limits.maxDiagramBytes | integer | yes | |
limits.stableLinks | integer | yes | Stable links the owner may keep for their own diagrams. An organisation's diagrams have none. |
limits.organisations | integer | yes | Organisations an account on this plan may own. |
limits.orgMembers | integer | yes | People one organisation may have, the owner included and pending invitations counted. |
limits.orgIcons | integer | yes | Custom icons one organisation may keep; zero on a plan without custom icons. minimum 0. |
limits.driftHistoryDays | integer | yes | Days the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0. |
limits.auditRetentionDays | integer | yes | Days the organisation's audit log keeps an event; zero on a plan that records none. minimum 0. |
PublishOrganisationDiagramBody
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Diagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
theme | "light" | "dark" | "auto" | no | The color scheme to draw it in: light, dark, or auto (one picture that follows the viewer's light or dark setting). default "light". |
embedSource | boolean | no | Write the diagram source into the stored SVG, in its metadata, so the diagram can be edited later; every member who can open it can then read the source. The same diagram published with and without it is two pictures. Left out, the organisation's keepEditable setting decides (false unless the owner turned it on); false always leaves the source out. |
name | string | no | A label for the diagram in your list and in the Markdown snippet. Optional. at least 1 character; at most 80 characters; pattern ^[^\p{Cc}]+$/u. |
folder | string | null | no | The folder to file the diagram in. Left out, a new diagram goes to the top level and a diagram that is already hosted stays where it is. A path files a new diagram there, or moves the one that is already hosted and keeps its link. null puts it at the top level. |
UpdateOrganisationDiagramBody
| Field | Type | Required | Description |
|---|---|---|---|
folder | string | null | no | The folder to file the diagram in, or null for the top level. |
name | string | null | no | A new label, or null to clear it. at least 1 character; at most 80 characters; pattern ^[^\p{Cc}]+$/u. |
EditedOrganisationDiagram
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The handle for the diagram in the routes below. |
name | string | null | yes | The label given at publish, or null. |
folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
bytes | integer | yes | Size of the stored SVG in bytes. |
createdBy | string | null | yes | The account that published it, or null when that account has left or an organisation key published it. |
createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted. |
viewUrl | string | yes | A page in the portal that shows the diagram to a signed-in member. It is not a link anyone can open: an organisation's diagrams have no public address. |
locked | boolean | yes | True while the owner has the diagram locked: nobody can delete, rename or move it, its publisher and the owner included, until the owner unlocks it. A lock does not stop it expiring on a plan that expires diagrams. |
lockedAt | integer | null | yes | When the owner locked it, in milliseconds since the epoch, or null when it is not locked. |
restricted | true | no | Present, and true, when the owner has restricted this diagram's folder and the caller is allowed in it, so the portal can show it as locked. Absent otherwise. A diagram in a folder the caller may not use is not listed at all. |
warnings | Diagnostic[] | yes | Quality warnings from drawing the source, as draw_diagram gives them. Empty for a restore. |
warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
warnings[].message | string | yes | What is wrong, in one sentence. |
warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
changed | boolean | yes | False when the source draws the picture the diagram already has: nothing was stored and no version was kept. |
KeepEditable
| Field | Type | Required | Description |
|---|---|---|---|
keepEditable | boolean | yes | True to write the diagram source into every picture published to the organisation that does not say otherwise, so members can edit it in the portal later. A publish that sends embedSource false still leaves it out. |
SetOrganisationPublishingBody
| Field | Type | Required | Description |
|---|---|---|---|
policy | "personal" | "organisation-default" | "organisation-required" | yes | |
hideViewLinks | boolean | no | Leave view links out of hosted answers for members and keys. Only with organisation-required. default false. |
MemberPublicDiagramList
| Field | Type | Required | Description |
|---|---|---|---|
items | MemberPublicDiagram[] | yes | At most 200, newest published first. |
items[].id | string | yes | The personal diagram's id. |
items[].name | string | null | yes | |
items[].url | string | yes | Its public link, which anyone who has it can open. |
items[].createdAt | integer | yes | |
items[].publishedAt | integer | yes | |
items[].bytes | integer | yes | |
items[].locked | boolean | yes | Whether the member locked it. Moving and unpublishing override the member's lock. |
items[].stableLinks | integer | yes | How many of the member's stable links show it now. minimum 0. |
items[].member | object | yes | |
items[].member.userId | string | yes | |
items[].member.email | string | yes | |
total | integer | yes | How many there are, which may be more than the list holds. minimum 0. |
MemberPublicDiagram
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The personal diagram's id. |
name | string | null | yes | |
url | string | yes | Its public link, which anyone who has it can open. |
createdAt | integer | yes | |
publishedAt | integer | yes | |
bytes | integer | yes | |
locked | boolean | yes | Whether the member locked it. Moving and unpublishing override the member's lock. |
stableLinks | integer | yes | How many of the member's stable links show it now. minimum 0. |
member | object | yes | |
member.userId | string | yes | |
member.email | string | yes |
MovedMemberDiagram
| Field | Type | Required | Description |
|---|---|---|---|
diagram | OrganisationDiagram | yes | |
diagram.id | string | yes | The handle for the diagram in the routes below. |
diagram.name | string | null | yes | The label given at publish, or null. |
diagram.folder | string | null | yes | The folder it is filed in, such as Payments/Checkout, or null for the top level. |
diagram.theme | "light" | "dark" | "auto" | yes | The color scheme it was drawn in: light, dark, or auto. |
diagram.bytes | integer | yes | Size of the stored SVG in bytes. |
diagram.createdBy | string | null | yes | The account that published it, or null when that account has left or an organisation key published it. |
diagram.createdAt | integer | yes | When it was first published, in milliseconds since the epoch. |
diagram.publishedAt | integer | yes | When it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it. |
diagram.expiresAt | integer | null | yes | When it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted. |
diagram.viewUrl | string | yes | A page in the portal that shows the diagram to a signed-in member. It is not a link anyone can open: an organisation's diagrams have no public address. |
diagram.locked | boolean | yes | True while the owner has the diagram locked: nobody can delete, rename or move it, its publisher and the owner included, until the owner unlocks it. A lock does not stop it expiring on a plan that expires diagrams. |
diagram.lockedAt | integer | null | yes | When the owner locked it, in milliseconds since the epoch, or null when it is not locked. |
diagram.restricted | true | no | Present, and true, when the owner has restricted this diagram's folder and the caller is allowed in it, so the portal can show it as locked. Absent otherwise. A diagram in a folder the caller may not use is not listed at all. |
merged | boolean | yes | True when the library already held exactly this picture, so only the public copy went. |
UserPublishing
| Field | Type | Required | Description |
|---|---|---|---|
defaultOrganization | any | yes | |
defaultOrganization.id | string | yes | |
defaultOrganization.slug | string | yes | |
defaultOrganization.name | string | yes | |
organizations | PublishingClaim[] | yes | The organisations whose Publishing setting claims the person's publishes, by name. |
organizations[].id | string | yes | |
organizations[].slug | string | yes | |
organizations[].name | string | yes | |
organizations[].policy | "organisation-default" | "organisation-required" | yes | What it enforces: its library by default, or its library always. |
organizations[].via | "member" | "domain" | yes | member when the person belongs to it; domain when it verified the domain of their address and they have not joined. |
organizations[].canPublish | boolean | yes | Whether the person may publish to its library: a member who is not a reader. |
target | PublishTarget | yes | personal, the organisation it goes to and why, choose (several claim it and none is the default), or refused. |
PublishingClaim
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
slug | string | yes | |
name | string | yes | |
policy | "organisation-default" | "organisation-required" | yes | What it enforces: its library by default, or its library always. |
via | "member" | "domain" | yes | member when the person belongs to it; domain when it verified the domain of their address and they have not joined. |
canPublish | boolean | yes | Whether the person may publish to its library: a member who is not a reader. |
PublishTarget
personal, the organisation it goes to and why, choose (several claim it and none is the default), or refused.
| Field | Type | Required | Description |
|---|
SetUserPublishingBody
| Field | Type | Required | Description |
|---|---|---|---|
defaultOrganization | string | null | yes | An organisation's slug or id, or null for none. The person must be a member who may publish there. at least 1 character; at most 64 characters. |
FolderRuleList
| Field | Type | Required | Description |
|---|---|---|---|
items | FolderRule[] | yes | By folder, at most 50. |
items[].folder | string | yes | The restricted folder, in the form diagrams carry in their folder. |
items[].roles | ("admin" | "member" | "reader" | "key")[] | yes | The roles let in, apart from the owner, who is always allowed: admin, member, reader, and key for the organisation's own API keys. |
items[].users | FolderRuleUser[] | yes | The people let in by name, whatever their role. |
items[].users[].userId | string | yes | The member's account id. |
items[].users[].email | string | yes | The member's address, as the member list shows it. |
items[].createdAt | integer | yes | Milliseconds since the epoch. When the rule as it now stands was set; replacing a rule sets it again. |
FolderRule
| Field | Type | Required | Description |
|---|---|---|---|
folder | string | yes | The restricted folder, in the form diagrams carry in their folder. |
roles | ("admin" | "member" | "reader" | "key")[] | yes | The roles let in, apart from the owner, who is always allowed: admin, member, reader, and key for the organisation's own API keys. |
users | FolderRuleUser[] | yes | The people let in by name, whatever their role. |
users[].userId | string | yes | The member's account id. |
users[].email | string | yes | The member's address, as the member list shows it. |
createdAt | integer | yes | Milliseconds since the epoch. When the rule as it now stands was set; replacing a rule sets it again. |
FolderRuleUser
| Field | Type | Required | Description |
|---|---|---|---|
userId | string | yes | The member's account id. |
email | string | yes | The member's address, as the member list shows it. |
SetFolderRuleBody
| Field | Type | Required | Description |
|---|---|---|---|
folder | string | yes | The folder the rule restricts, with every folder inside it: names from the outermost in, joined with a slash, with no slash at either end. at least 1 character; at most 405 characters. |
roles | string[] | yes | Any of admin, member, reader, key. owner is not a choice. An empty list, with no people, lets in the owner alone. |
users | string[] | yes | Account ids of current members, at most 100. A person who leaves is taken out of every rule. |
OrgApiKeyList
| Field | Type | Required | Description |
|---|---|---|---|
items | OrgApiKeySummary[] | yes | |
items[].id | string | yes | |
items[].name | string | yes | |
items[].prefix | string | yes | |
items[].last4 | string | yes | |
items[].createdAt | integer | yes | Milliseconds since the epoch. |
items[].lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if never used. |
items[].revealable | boolean | yes | True when the full key can be shown again with the reveal route. False for a key made before that was possible, or on a server that cannot seal keys. |
items[].scopes | ("diagrams" | "audit:read")[] | yes | diagrams: read the library, publish, and change its diagrams, which every key made before scopes holds. audit:read: read and export the audit log, and nothing else unless diagrams is also given. |
OrgApiKeySummary
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
name | string | yes | |
prefix | string | yes | |
last4 | string | yes | |
createdAt | integer | yes | Milliseconds since the epoch. |
lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if never used. |
revealable | boolean | yes | True when the full key can be shown again with the reveal route. False for a key made before that was possible, or on a server that cannot seal keys. |
scopes | ("diagrams" | "audit:read")[] | yes | diagrams: read the library, publish, and change its diagrams, which every key made before scopes holds. audit:read: read and export the audit log, and nothing else unless diagrams is also given. |
CreatedOrgApiKey
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
name | string | yes | |
prefix | string | yes | |
last4 | string | yes | |
createdAt | integer | yes | Milliseconds since the epoch. |
lastUsedAt | integer | null | yes | Milliseconds since the epoch, or null if never used. |
revealable | boolean | yes | True when the full key can be shown again with the reveal route. False for a key made before that was possible, or on a server that cannot seal keys. |
key | string | yes | The full key. When revealable is false this is the only time it is shown, so store it now. |
scopes | ("diagrams" | "audit:read")[] | yes | diagrams: read the library, publish, and change its diagrams, which every key made before scopes holds. audit:read: read and export the audit log, and nothing else unless diagrams is also given. |
CreateOrgApiKeyBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | at least 1 character; at most 60 characters; pattern \S. |
scopes | ("diagrams" | "audit:read")[] | no | What the key may do. Left out, ["diagrams"]. A key for a SIEM takes ["audit:read"] alone. |
OrgBrand
| Field | Type | Required | Description |
|---|---|---|---|
brand | BrandColors | yes | The saved brand, or null when none is saved. |
brand.primary | string | yes | Lowercase #rrggbb. |
brand.secondary | string | yes | Lowercase #rrggbb. |
brand.accent | string | yes | Lowercase #rrggbb. |
chosen | ("primary" | "secondary" | "accent")[] | yes | The colors the person chose. The others are made from the primary. |
active | boolean | yes | True when a brand is saved and the owner's plan includes brand themes, so the hosted service paints with it. |
canEdit | boolean | yes | True when the caller's role may save, remove and preview a brand: the owner and admins. |
plan | "free" | "pro" | "enterprise" | yes | The organisation's plan, which is its owner's. |
BrandColors
The saved brand, or null when none is saved.
| Field | Type | Required | Description |
|---|---|---|---|
primary | string | yes | Lowercase #rrggbb. |
secondary | string | yes | Lowercase #rrggbb. |
accent | string | yes | Lowercase #rrggbb. |
SavedBrand
| Field | Type | Required | Description |
|---|---|---|---|
brand | any | yes | |
brand.primary | string | yes | Lowercase #rrggbb. |
brand.secondary | string | yes | Lowercase #rrggbb. |
brand.accent | string | yes | Lowercase #rrggbb. |
chosen | ("primary" | "secondary" | "accent")[] | yes | |
check | BrandCheck | yes | |
check.issues | BrandIssue[] | yes | |
check.issues[].role | "primary" | "secondary" | "accent" | yes | |
check.issues[].severity | "error" | "warning" | "note" | yes | An error stops a save. A warning and a note are advice. |
check.issues[].code | "not-a-color" | "missing-primary" | "reads-as-status" | "too-similar" | "adjusted" | yes | |
check.issues[].message | string | yes | |
check.swatches | object | null | yes | The color each scheme draws for each role, made darker or lighter where it would not keep 3:1 against the surface. |
check.swatches.light | object | yes | |
check.swatches.dark | object | yes |
BrandCheck
| Field | Type | Required | Description |
|---|---|---|---|
issues | BrandIssue[] | yes | |
issues[].role | "primary" | "secondary" | "accent" | yes | |
issues[].severity | "error" | "warning" | "note" | yes | An error stops a save. A warning and a note are advice. |
issues[].code | "not-a-color" | "missing-primary" | "reads-as-status" | "too-similar" | "adjusted" | yes | |
issues[].message | string | yes | |
swatches | object | null | yes | The color each scheme draws for each role, made darker or lighter where it would not keep 3:1 against the surface. |
swatches.light | object | yes | |
swatches.light.primary | object | yes | |
swatches.light.secondary | object | yes | |
swatches.light.accent | object | yes | |
swatches.dark | object | yes | |
swatches.dark.primary | object | yes | |
swatches.dark.secondary | object | yes | |
swatches.dark.accent | object | yes |
BrandIssue
| Field | Type | Required | Description |
|---|---|---|---|
role | "primary" | "secondary" | "accent" | yes | |
severity | "error" | "warning" | "note" | yes | An error stops a save. A warning and a note are advice. |
code | "not-a-color" | "missing-primary" | "reads-as-status" | "too-similar" | "adjusted" | yes | |
message | string | yes |
BrandBody
| Field | Type | Required | Description |
|---|---|---|---|
primary | string | null | no | The main brand color, as #rrggbb or #rgb in any case. Takes the place of the blue tone. A brand needs one. at most 32 characters. |
secondary | string | null | no | Takes the place of the violet tone. Left out or null, it is made from the primary by turning its hue, and follows the primary. at most 32 characters. |
accent | string | null | no | Takes the place of the aqua tone. Left out or null, it is made from the primary by turning its hue, and follows the primary. at most 32 characters. |
BrandPreview
| Field | Type | Required | Description |
|---|---|---|---|
check | BrandCheck | yes | |
check.issues | BrandIssue[] | yes | |
check.issues[].role | "primary" | "secondary" | "accent" | yes | |
check.issues[].severity | "error" | "warning" | "note" | yes | An error stops a save. A warning and a note are advice. |
check.issues[].code | "not-a-color" | "missing-primary" | "reads-as-status" | "too-similar" | "adjusted" | yes | |
check.issues[].message | string | yes | |
check.swatches | object | null | yes | The color each scheme draws for each role, made darker or lighter where it would not keep 3:1 against the surface. |
check.swatches.light | object | yes | |
check.swatches.dark | object | yes | |
pictures | BrandPreviewPicture[] | yes | |
pictures[].id | string | yes | |
pictures[].title | string | yes | |
pictures[].light | string | yes | The sample as an SVG in the light scheme. |
pictures[].dark | string | yes | The sample as an SVG in the dark scheme. |
BrandPreviewPicture
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
title | string | yes | |
light | string | yes | The sample as an SVG in the light scheme. |
dark | string | yes | The sample as an SVG in the dark scheme. |
AccountBrand
| Field | Type | Required | Description |
|---|---|---|---|
chosen | object | null | yes | The organisation whose brand and custom icons the account's own calls use, or null. |
chosen.id | string | yes | |
chosen.slug | string | yes | |
chosen.name | string | yes | |
available | object[] | yes | The organisations the account belongs to that have a saved brand or custom icons, by name. |
available[].id | string | yes | |
available[].slug | string | yes | |
available[].name | string | yes | |
available[].active | boolean | yes | True when the organisation has a saved brand and the owner's plan includes brand themes. |
available[].iconsActive | boolean | yes | True when the organisation has custom icons and the owner's plan includes them. |
ChooseBrandBody
| Field | Type | Required | Description |
|---|---|---|---|
organization | string | null | yes | An organisation's id or slug, or null for no brand. The account must be a member and the organisation must have a saved brand. at least 1 character; at most 64 characters. |
OrgStyleRules
| Field | Type | Required | Description |
|---|---|---|---|
rules | StyleRules | null | yes | The saved rules as the engine read them (the format of docs/architecture/repository-settings.md), or null when none are saved. |
text | string | null | yes | The saved rules as the person wrote them, or null. |
active | boolean | yes | True when rules are saved and the owner's plan includes saved style rules, so CI that reads them applies them. |
canEdit | boolean | yes | True when the caller's role may save and remove the rules. |
plan | "free" | "pro" | "enterprise" | yes | The organisation's plan, which is its owner's. |
updatedAt | integer | null | yes | When the rules were last saved, in milliseconds since the epoch, or null. |
StyleRules
A team's style rules for its Plotwork diagrams, with the version of the format.
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | no | at most 500 characters. |
version | 1 | yes | |
level | "error" | "warning" | no | error fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error. |
requireTitle | boolean | no | Every diagram has a title in its header. |
requireDescription | boolean | no | Every diagram has desc= in its header, the text screen readers announce. |
maxNodes | integer | no | The most nodes one diagram may hold. minimum 1; maximum 10000. |
forbidKinds | ("flow" | "sequence" | "schema" | "git" | "gantt" | "class" | "state" | "timeline" | "journey" | "mindmap" | "treemap" | "pie" | "quadrant" | "layers" | "c4" | "matrix" | "sankey" | "xychart" | "tree" | "swimlane")[] | no | Kinds of diagram the team does not use. |
ids | object | no | A pattern every node id must match. |
ids.pattern | string | yes | A JavaScript regular expression, without slashes, such as ^[a-z][a-z0-9_]*$. No nested repeats and no back references. at least 1 character; at most 200 characters. |
ids.kinds | ("flow" | "sequence" | "schema" | "git" | "gantt" | "class" | "state" | "timeline" | "journey" | "mindmap" | "treemap" | "pie" | "quadrant" | "layers" | "c4" | "matrix" | "sankey" | "xychart" | "tree" | "swimlane")[] | no | Only diagrams of these kinds; every kind when left out. |
ids.hint | string | no | What to tell the author who breaks the rule. at least 1 character; at most 300 characters. |
ids.level | "error" | "warning" | no | error fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error. |
labels | object | no | A pattern every node label must match. |
labels.pattern | string | yes | A JavaScript regular expression, without slashes, such as ^[a-z][a-z0-9_]*$. No nested repeats and no back references. at least 1 character; at most 200 characters. |
labels.kinds | ("flow" | "sequence" | "schema" | "git" | "gantt" | "class" | "state" | "timeline" | "journey" | "mindmap" | "treemap" | "pie" | "quadrant" | "layers" | "c4" | "matrix" | "sankey" | "xychart" | "tree" | "swimlane")[] | no | Only diagrams of these kinds; every kind when left out. |
labels.hint | string | no | What to tell the author who breaks the rule. at least 1 character; at most 300 characters. |
labels.level | "error" | "warning" | no | error fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error. |
icons | object[] | no | Icons required by label. |
icons[].label | string | yes | Matched against each node label with case ignored, such as postgres|mysql. at least 1 character; at most 200 characters. |
icons[].use | string[] | yes | |
icons[].kinds | ("flow" | "sequence" | "schema" | "git" | "gantt" | "class" | "state" | "timeline" | "journey" | "mindmap" | "treemap" | "pie" | "quadrant" | "layers" | "c4" | "matrix" | "sankey" | "xychart" | "tree" | "swimlane")[] | no | Only diagrams of these kinds; every kind when left out. |
icons[].hint | string | no | What to tell the author who breaks the rule. at least 1 character; at most 300 characters. |
icons[].level | "error" | "warning" | no | error fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error. |
tones | object[] | no | Tones allowed or forbidden, by node type. |
tones[].types | string[] | no | Only nodes of these types, as the kind names them (database, service, person, table, container); every node when left out. |
tones[].allow | ("neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red")[] | no | |
tones[].forbid | ("neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red")[] | no | |
tones[].kinds | ("flow" | "sequence" | "schema" | "git" | "gantt" | "class" | "state" | "timeline" | "journey" | "mindmap" | "treemap" | "pie" | "quadrant" | "layers" | "c4" | "matrix" | "sankey" | "xychart" | "tree" | "swimlane")[] | no | Only diagrams of these kinds; every kind when left out. |
tones[].hint | string | no | What to tell the author who breaks the rule. at least 1 character; at most 300 characters. |
tones[].level | "error" | "warning" | no | error fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error. |
StyleRulesBody
| Field | Type | Required | Description |
|---|---|---|---|
text | string | yes | The rules file as JSON text, at most 32768 characters. The style rules guide lists its fields. at least 1 character; at most 32768 characters. |
OrgIcons
| Field | Type | Required | Description |
|---|---|---|---|
icons | OrgIcon[] | yes | |
icons[].name | string | yes | |
icons[].ref | string | yes | What a diagram writes to use it. |
icons[].aliases | string[] | yes | |
icons[].mediaType | "image/svg+xml" | "image/png" | yes | |
icons[].image | string | yes | The checked picture as a data: address, for a preview. |
icons[].width | number | yes | |
icons[].height | number | yes | |
icons[].bytes | integer | yes | |
icons[].updatedAt | integer | yes | Milliseconds since the epoch. |
active | boolean | yes | True when the owner's plan includes custom icons, so the hosted service draws them. |
canEdit | boolean | yes | True when the caller's role may upload, replace and delete icons. |
plan | "free" | "pro" | "enterprise" | yes | |
limit | integer | yes | How many icons the plan lets the organisation keep. |
OrgIcon
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
ref | string | yes | What a diagram writes to use it. |
aliases | string[] | yes | |
mediaType | "image/svg+xml" | "image/png" | yes | |
image | string | yes | The checked picture as a data: address, for a preview. |
width | number | yes | |
height | number | yes | |
bytes | integer | yes | |
updatedAt | integer | yes | Milliseconds since the epoch. |
SavedIcon
| Field | Type | Required | Description |
|---|---|---|---|
icon | OrgIcon | yes | |
icon.name | string | yes | |
icon.ref | string | yes | What a diagram writes to use it. |
icon.aliases | string[] | yes | |
icon.mediaType | "image/svg+xml" | "image/png" | yes | |
icon.image | string | yes | The checked picture as a data: address, for a preview. |
icon.width | number | yes | |
icon.height | number | yes | |
icon.bytes | integer | yes | |
icon.updatedAt | integer | yes | Milliseconds since the epoch. |
removed | string[] | yes | What the check left out of the file because it draws nothing, such as editor metadata. |
IconBody
One file (svg or png), or neither to change only the aliases of an icon that exists.
| Field | Type | Required | Description |
|---|---|---|---|
svg | string | no | The SVG file's text, at most 32 KB. It is rewritten from an allowlist before it is stored. at most 49152 characters. |
png | string | no | The PNG file's bytes in base64, at most 32 KB and 1024 pixels on a side. at most 49152 characters. |
aliases | string[] | no | Other names search and automatic matching find the icon by, at most 10. Left out, the icon has none. |
IconPreview
| Field | Type | Required | Description |
|---|---|---|---|
ref | string | yes | What a diagram writes to use the icon. |
source | string | yes | The diagram source the preview draws, which uses the icon on one box. |
light | string | yes | The preview drawn on light, as SVG text. |
dark | string | yes | The preview drawn on dark, as SVG text. |
SavedAvatar
| Field | Type | Required | Description |
|---|---|---|---|
avatar | OrgAvatar | yes | The organisation's uploaded avatar, or null when it has none and a mark made from its id stands in. |
avatar.version | string | yes | Changes with every upload. Put it in the address (?v=) so a new picture is a new address. |
avatar.contentType | "image/svg+xml" | "image/png" | "image/gif" | "image/webp" | yes | |
avatar.animated | boolean | yes | True when it moves, so a page can hold it still for a person who asked for less motion. |
removed | string[] | yes | What the check left out of the file because it draws nothing, such as editor metadata, EXIF or XMP. |
AvatarBody
One file: svg, or image.
| Field | Type | Required | Description |
|---|---|---|---|
svg | string | no | The SVG file's text, at most 256 KB, still or animated with SMIL. It is rewritten from an allowlist before it is stored. at most 368640 characters. |
image | string | no | A PNG (APNG included), GIF or WebP file's bytes in base64, still or animated: at most 256 KB, 512 pixels on a side, and 200 frames. The format is read from the bytes. at most 368640 characters. |
DriftRunReceipt
| Field | Type | Required | Description |
|---|---|---|---|
organization | object | yes | The organisation the run was stored for. With _ in the path, this says which one the key belongs to. |
organization.id | string | yes | |
organization.slug | string | yes | |
repository | string | yes | The repository, as sent. |
sources | integer | yes | Sources stored. minimum 0. |
drifted | integer | yes | Sources that drifted. minimum 0. |
dashboardUrl | string | yes | The organisation's drift dashboard in the portal, for a signed-in member. |
DriftRunBody
| Field | Type | Required | Description |
|---|---|---|---|
repository | string | yes | The repository the run checked, as owner/name. at most 140 characters; pattern ^[A-Za-z0-9][A-Za-z0-9-]{0,38}\/[A-Za-z0-9._-]{1,100}$. |
ref | string | null | yes | The git ref the run checked, or null. at least 1 character; at most 255 characters; pattern ^[^\p{Cc}]+$/u. |
sha | string | null | yes | The commit the run checked, or null. pattern ^[0-9a-fA-F]{7,64}$. |
event | string | null | yes | The event that started the run, or null. at least 1 character; at most 64 characters; pattern ^[a-z][a-z0-9_]*$. |
runUrl | string | null | yes | The run on GitHub. An https address of at most 500 characters, or null. at most 500 characters. |
pullRequestUrl | string | null | yes | The pull request the run opened or checked. An https address of at most 500 characters, or null. at most 500 characters. |
sources | DriftSourceBody[] | yes | Every source the run checked, at most 250. A source of the repository that a run leaves out is removed from the dashboard. |
sources[].name | string | yes | The source's name as the repository's settings write it, 1 to 120 characters. Unique within a run. at least 1 character; at most 120 characters; pattern ^[^\p{Cc}]+$/u. |
sources[].out | string | yes | The diagram's path in the repository, 1 to 300 characters. at least 1 character; at most 300 characters; pattern ^[^\p{Cc}]+$/u. |
sources[].status | "in-step" | "drifted" | "written" | "failed" | yes | What the check found: the diagram matches its files (in-step), differs (drifted), was written by the run (written), or could not be made (failed). |
sources[].added | integer | yes | Items in the files that the diagram does not have. minimum 0; maximum 1000000. |
sources[].removed | integer | yes | Items in the diagram that the files no longer have. minimum 0; maximum 1000000. |
sources[].changed | integer | yes | Items both have that differ. minimum 0; maximum 1000000. |
sources[].errors | integer | yes | Errors the run met making this diagram. minimum 0; maximum 1000000. |
sources[].owners | string[] | yes | The owners CODEOWNERS gives the diagram's path, as it writes them: at most 20, each @user, @org/team or an email address. |
DriftSourceBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | The source's name as the repository's settings write it, 1 to 120 characters. Unique within a run. at least 1 character; at most 120 characters; pattern ^[^\p{Cc}]+$/u. |
out | string | yes | The diagram's path in the repository, 1 to 300 characters. at least 1 character; at most 300 characters; pattern ^[^\p{Cc}]+$/u. |
status | "in-step" | "drifted" | "written" | "failed" | yes | What the check found: the diagram matches its files (in-step), differs (drifted), was written by the run (written), or could not be made (failed). |
added | integer | yes | Items in the files that the diagram does not have. minimum 0; maximum 1000000. |
removed | integer | yes | Items in the diagram that the files no longer have. minimum 0; maximum 1000000. |
changed | integer | yes | Items both have that differ. minimum 0; maximum 1000000. |
errors | integer | yes | Errors the run met making this diagram. minimum 0; maximum 1000000. |
owners | string[] | yes | The owners CODEOWNERS gives the diagram's path, as it writes them: at most 20, each @user, @org/team or an email address. |
OrgDrift
| Field | Type | Required | Description |
|---|---|---|---|
active | boolean | yes | True when the owner's plan includes the drift dashboard. When false the lists are empty and run reports are refused. |
plan | "free" | "pro" | "enterprise" | yes | The organisation's plan, which is its owner's. |
retentionDays | integer | yes | Days a run and a status are kept after they were reported, from the owner's plan. Zero on a plan without the dashboard. minimum 0. |
repositories | DriftRepository[] | yes | Every repository with a stored status, by name. |
repositories[].repository | string | yes | |
repositories[].sources | integer | yes | minimum 0. |
repositories[].inStep | integer | yes | minimum 0. |
repositories[].drifted | integer | yes | minimum 0. |
repositories[].written | integer | yes | minimum 0. |
repositories[].failed | integer | yes | minimum 0. |
repositories[].ref | string | null | yes | |
repositories[].sha | string | null | yes | |
repositories[].runUrl | string | null | yes | The run on GitHub, or null. |
repositories[].pullRequestUrl | string | null | yes | The pull request, or null. |
repositories[].checkedAt | integer | yes | When the run was reported, in milliseconds since the epoch. |
sources | DriftSource[] | yes | The latest status of every source: failed first, then drifted, written and in step, each by repository and name. |
sources[].repository | string | yes | |
sources[].name | string | yes | |
sources[].out | string | yes | |
sources[].status | "in-step" | "drifted" | "written" | "failed" | yes | |
sources[].added | integer | yes | minimum 0. |
sources[].removed | integer | yes | minimum 0. |
sources[].changed | integer | yes | minimum 0. |
sources[].errors | integer | yes | minimum 0. |
sources[].owners | string[] | yes | The owners CODEOWNERS gave the path, as written there. |
sources[].ref | string | null | yes | |
sources[].sha | string | null | yes | |
sources[].runUrl | string | null | yes | The run on GitHub, or null. |
sources[].pullRequestUrl | string | null | yes | The pull request, or null. |
sources[].checkedAt | integer | yes | When the run was reported, in milliseconds since the epoch. |
truncated | boolean | yes | True when there were more sources than one answer carries. |
runs | DriftRun[] | yes | The latest runs, newest first. |
runs[].id | string | yes | |
runs[].repository | string | yes | |
runs[].event | string | null | yes | |
runs[].sources | integer | yes | minimum 0. |
runs[].drifted | integer | yes | minimum 0. |
runs[].failed | integer | yes | minimum 0. |
runs[].errors | integer | yes | minimum 0. |
runs[].ref | string | null | yes | |
runs[].sha | string | null | yes | |
runs[].runUrl | string | null | yes | The run on GitHub, or null. |
runs[].pullRequestUrl | string | null | yes | The pull request, or null. |
runs[].checkedAt | integer | yes | When the run was reported, in milliseconds since the epoch. |
DriftRepository
| Field | Type | Required | Description |
|---|---|---|---|
repository | string | yes | |
sources | integer | yes | minimum 0. |
inStep | integer | yes | minimum 0. |
drifted | integer | yes | minimum 0. |
written | integer | yes | minimum 0. |
failed | integer | yes | minimum 0. |
ref | string | null | yes | |
sha | string | null | yes | |
runUrl | string | null | yes | The run on GitHub, or null. |
pullRequestUrl | string | null | yes | The pull request, or null. |
checkedAt | integer | yes | When the run was reported, in milliseconds since the epoch. |
DriftSource
| Field | Type | Required | Description |
|---|---|---|---|
repository | string | yes | |
name | string | yes | |
out | string | yes | |
status | "in-step" | "drifted" | "written" | "failed" | yes | |
added | integer | yes | minimum 0. |
removed | integer | yes | minimum 0. |
changed | integer | yes | minimum 0. |
errors | integer | yes | minimum 0. |
owners | string[] | yes | The owners CODEOWNERS gave the path, as written there. |
ref | string | null | yes | |
sha | string | null | yes | |
runUrl | string | null | yes | The run on GitHub, or null. |
pullRequestUrl | string | null | yes | The pull request, or null. |
checkedAt | integer | yes | When the run was reported, in milliseconds since the epoch. |
DriftRun
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
repository | string | yes | |
event | string | null | yes | |
sources | integer | yes | minimum 0. |
drifted | integer | yes | minimum 0. |
failed | integer | yes | minimum 0. |
errors | integer | yes | minimum 0. |
ref | string | null | yes | |
sha | string | null | yes | |
runUrl | string | null | yes | The run on GitHub, or null. |
pullRequestUrl | string | null | yes | The pull request, or null. |
checkedAt | integer | yes | When the run was reported, in milliseconds since the epoch. |
OrgAuditPage
| Field | Type | Required | Description |
|---|---|---|---|
items | OrgAuditEvent[] | yes | |
items[].version | 1 | yes | The version of this shape. A change that is not only an addition gets a new number. |
items[].id | string | yes | |
items[].orgId | string | yes | |
items[].at | string | yes | When it happened: an ISO 8601 time in UTC with milliseconds. |
items[].action | "orgs.org.create" | "orgs.org.rename" | "orgs.member.add" | "orgs.member.remove" | "orgs.member.leave" | "orgs.member.role" | "orgs.owner.transfer" | "orgs.invite.create" | "orgs.invite.revoke" | "orgs.invite.accept" | "orgs.key.create" | "orgs.key.reveal" | "orgs.key.revoke" | "orgs.diagram.publish" | "orgs.diagram.update" | "orgs.diagram.edit" | "orgs.diagram.restore" | "orgs.diagram.lock" | "orgs.diagram.unlock" | "orgs.diagram.delete" | "orgs.folder_rule.set" | "orgs.folder_rule.clear" | "orgs.brand.set" | "orgs.brand.clear" | "orgs.icon.set" | "orgs.icon.delete" | "orgs.avatar.set" | "orgs.avatar.clear" | "orgs.style_rules.set" | "orgs.style_rules.clear" | "orgs.settings.editable" | "orgs.settings.publishing" | "orgs.publishing.move" | "orgs.publishing.unpublish" | "orgs.drift.report" | "orgs.drift.settings" | "orgs.integration.create" | "orgs.integration.update" | "orgs.integration.delete" | "orgs.contract.set" | "orgs.contract.end" | "orgs.audit.export" | "orgs.sso.signin" | "orgs.sso.config" | "orgs.sso.domain_add" | "orgs.sso.domain_verify" | "orgs.sso.domain_remove" | "orgs.sso.signin_failed" | "orgs.sso.jit" | "orgs.sso.break_glass" | "orgs.scim.token" | "orgs.scim.user_create" | "orgs.scim.user_update" | "orgs.scim.user_deactivate" | "orgs.scim.user_delete" | "orgs.scim.group" | "orgs.scim.role" | yes | What happened. Never reused for another meaning. |
items[].actor | object | yes | |
items[].actor.kind | "user" | "key" | "ci" | "operator" | yes | |
items[].actor.id | string | null | yes | The account id (user), the key id (key, ci), or null (operator). |
items[].actor.name | string | null | yes | The address or key name when it was recorded, "Plotwork support" for the operator, null once a deleted account is forgotten. |
items[].target | object | yes | |
items[].target.type | "org" | "member" | "invite" | "key" | "diagram" | "folder" | "brand" | "icon" | "avatar" | "style_rules" | "settings" | "drift" | "contract" | "sso" | null | yes | |
items[].target.id | string | null | yes | |
items[].target.name | string | null | yes | A member's address, an invited address, a key's, a diagram's or an icon's name, or a folder. |
items[].metadata | object | yes | A few facts about the event, such as role or keepEditable. Never a diagram source, a key, a token or a color. |
items[].ip | string | null | yes | The network the request came from: the IPv4 /24 or the IPv6 /48, never the full address. |
items[].userAgent | string | null | yes | The first 200 characters of the user agent. |
items[].requestId | string | null | yes | The request id, which Plotwork support can look up in the API's logs. |
nextCursor | string | null | yes | Send as cursor for the next, older page; null on the last. |
retentionDays | integer | yes | How many days the organisation's plan keeps an event. |
canExport | boolean | yes | Whether the organisation's plan may export the log. |
OrgAuditEvent
| Field | Type | Required | Description |
|---|---|---|---|
version | 1 | yes | The version of this shape. A change that is not only an addition gets a new number. |
id | string | yes | |
orgId | string | yes | |
at | string | yes | When it happened: an ISO 8601 time in UTC with milliseconds. |
action | "orgs.org.create" | "orgs.org.rename" | "orgs.member.add" | "orgs.member.remove" | "orgs.member.leave" | "orgs.member.role" | "orgs.owner.transfer" | "orgs.invite.create" | "orgs.invite.revoke" | "orgs.invite.accept" | "orgs.key.create" | "orgs.key.reveal" | "orgs.key.revoke" | "orgs.diagram.publish" | "orgs.diagram.update" | "orgs.diagram.edit" | "orgs.diagram.restore" | "orgs.diagram.lock" | "orgs.diagram.unlock" | "orgs.diagram.delete" | "orgs.folder_rule.set" | "orgs.folder_rule.clear" | "orgs.brand.set" | "orgs.brand.clear" | "orgs.icon.set" | "orgs.icon.delete" | "orgs.avatar.set" | "orgs.avatar.clear" | "orgs.style_rules.set" | "orgs.style_rules.clear" | "orgs.settings.editable" | "orgs.settings.publishing" | "orgs.publishing.move" | "orgs.publishing.unpublish" | "orgs.drift.report" | "orgs.drift.settings" | "orgs.integration.create" | "orgs.integration.update" | "orgs.integration.delete" | "orgs.contract.set" | "orgs.contract.end" | "orgs.audit.export" | "orgs.sso.signin" | "orgs.sso.config" | "orgs.sso.domain_add" | "orgs.sso.domain_verify" | "orgs.sso.domain_remove" | "orgs.sso.signin_failed" | "orgs.sso.jit" | "orgs.sso.break_glass" | "orgs.scim.token" | "orgs.scim.user_create" | "orgs.scim.user_update" | "orgs.scim.user_deactivate" | "orgs.scim.user_delete" | "orgs.scim.group" | "orgs.scim.role" | yes | What happened. Never reused for another meaning. |
actor | object | yes | |
actor.kind | "user" | "key" | "ci" | "operator" | yes | |
actor.id | string | null | yes | The account id (user), the key id (key, ci), or null (operator). |
actor.name | string | null | yes | The address or key name when it was recorded, "Plotwork support" for the operator, null once a deleted account is forgotten. |
target | object | yes | |
target.type | "org" | "member" | "invite" | "key" | "diagram" | "folder" | "brand" | "icon" | "avatar" | "style_rules" | "settings" | "drift" | "contract" | "sso" | null | yes | |
target.id | string | null | yes | |
target.name | string | null | yes | A member's address, an invited address, a key's, a diagram's or an icon's name, or a folder. |
metadata | object | yes | A few facts about the event, such as role or keepEditable. Never a diagram source, a key, a token or a color. |
ip | string | null | yes | The network the request came from: the IPv4 /24 or the IPv6 /48, never the full address. |
userAgent | string | null | yes | The first 200 characters of the user agent. |
requestId | string | null | yes | The request id, which Plotwork support can look up in the API's logs. |
SsoSettings
| Field | Type | Required | Description |
|---|---|---|---|
available | boolean | yes | Whether the organisation's plan has single sign-on (Enterprise). |
plan | "free" | "pro" | "enterprise" | yes | |
redirectUri | string | yes | The redirect URI to register at the identity provider. |
saml | SamlServiceProvider | yes | |
saml.entityId | string | yes | Our entity id for this organisation: the audience to set at the provider. |
saml.acsUrl | string | yes | Our assertion consumer service for this organisation: the single sign-on URL to set at the provider. |
saml.metadataUrl | string | yes | Our service provider metadata, for a provider that imports it. |
samlAvailable | boolean | yes | Whether this server can check SAML responses. |
connection | SsoConnection | yes | |
connection.protocol | "oidc" | "saml" | yes | OpenID Connect or SAML 2.0. One connection, one protocol. |
connection.issuer | string | yes | The OpenID Connect issuer, or the SAML provider's entity id. |
connection.clientId | string | null | yes | OpenID Connect only. |
connection.secretSet | boolean | yes | True when an OpenID Connect client secret is stored. It is never returned. Always false for SAML. |
connection.tokenAuthMethod | "client_secret_basic" | "client_secret_post" | null | yes | |
connection.saml | SamlConnection | yes | SAML only. |
connection.saml.entityId | string | yes | The provider's entity id, which every Issuer must equal. |
connection.saml.ssoUrl | string | yes | The provider's sign-in service on the redirect binding. |
connection.saml.certificates | object[] | yes | |
connection.saml.emailAttribute | string | null | yes | The attribute that carries the address, or null when the name identifier does. |
connection.saml.metadataUrl | string | null | yes | Where the metadata was fetched from, or null when it was pasted. |
connection.enabled | boolean | yes | |
connection.requireSso | boolean | yes | |
connection.jit | boolean | yes | |
connection.jitRole | "member" | "reader" | yes | |
connection.updatedAt | integer | yes | |
domains | SsoDomain[] | yes | |
domains[].id | string | yes | |
domains[].domain | string | yes | |
domains[].verified | boolean | yes | |
domains[].verifiedAt | integer | null | yes | |
domains[].checkedAt | integer | null | yes | |
domains[].createdAt | integer | yes | |
domains[].record | object | yes | |
domains[].record.name | string | yes | |
domains[].record.type | "TXT" | yes | |
domains[].record.value | string | yes |
SamlServiceProvider
| Field | Type | Required | Description |
|---|---|---|---|
entityId | string | yes | Our entity id for this organisation: the audience to set at the provider. |
acsUrl | string | yes | Our assertion consumer service for this organisation: the single sign-on URL to set at the provider. |
metadataUrl | string | yes | Our service provider metadata, for a provider that imports it. |
SsoConnection
| Field | Type | Required | Description |
|---|---|---|---|
protocol | "oidc" | "saml" | yes | OpenID Connect or SAML 2.0. One connection, one protocol. |
issuer | string | yes | The OpenID Connect issuer, or the SAML provider's entity id. |
clientId | string | null | yes | OpenID Connect only. |
secretSet | boolean | yes | True when an OpenID Connect client secret is stored. It is never returned. Always false for SAML. |
tokenAuthMethod | "client_secret_basic" | "client_secret_post" | null | yes | |
saml | SamlConnection | yes | SAML only. |
saml.entityId | string | yes | The provider's entity id, which every Issuer must equal. |
saml.ssoUrl | string | yes | The provider's sign-in service on the redirect binding. |
saml.certificates | object[] | yes | |
saml.certificates[].fingerprint | string | yes | SHA-256 of the certificate, as providers show it. |
saml.certificates[].notAfter | integer | yes | When the certificate expires, in milliseconds since the epoch. Shown, not enforced. |
saml.emailAttribute | string | null | yes | The attribute that carries the address, or null when the name identifier does. |
saml.metadataUrl | string | null | yes | Where the metadata was fetched from, or null when it was pasted. |
enabled | boolean | yes | |
requireSso | boolean | yes | |
jit | boolean | yes | |
jitRole | "member" | "reader" | yes | |
updatedAt | integer | yes |
SamlConnection
SAML only.
| Field | Type | Required | Description |
|---|---|---|---|
entityId | string | yes | The provider's entity id, which every Issuer must equal. |
ssoUrl | string | yes | The provider's sign-in service on the redirect binding. |
certificates | object[] | yes | |
certificates[].fingerprint | string | yes | SHA-256 of the certificate, as providers show it. |
certificates[].notAfter | integer | yes | When the certificate expires, in milliseconds since the epoch. Shown, not enforced. |
emailAttribute | string | null | yes | The attribute that carries the address, or null when the name identifier does. |
metadataUrl | string | null | yes | Where the metadata was fetched from, or null when it was pasted. |
SsoDomain
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
domain | string | yes | |
verified | boolean | yes | |
verifiedAt | integer | null | yes | |
checkedAt | integer | null | yes | |
createdAt | integer | yes | |
record | object | yes | |
record.name | string | yes | |
record.type | "TXT" | yes | |
record.value | string | yes |
SsoConnectionBody
| Field | Type | Required | Description |
|---|---|---|---|
issuer | string | yes | The issuer URL of your own tenant. at least 9 characters; at most 300 characters. |
clientId | string | yes | at least 1 character; at most 255 characters. |
clientSecret | string | no | Required the first time. Left out later, the stored one is kept. Never returned. at least 1 character; at most 1000 characters. |
SsoSwitchesBody
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | no | |
requireSso | boolean | no | |
jit | boolean | no | |
jitRole | "member" | "reader" | no |
SamlConnectionBody
| Field | Type | Required | Description |
|---|---|---|---|
metadataUrl | string | no | The address of the provider's metadata, fetched over HTTPS. Give this or metadataXml, or neither to keep the stored metadata. at least 9 characters; at most 500 characters. |
metadataXml | string | no | The provider's metadata XML, pasted. at least 1 character; at most 262144 characters. |
emailAttribute | string | null | no | The attribute that carries the address. Null reads the name identifier; left out keeps the stored choice. at least 1 character; at most 200 characters. |
SsoDomainBody
| Field | Type | Required | Description |
|---|---|---|---|
domain | string | yes | at least 3 characters; at most 253 characters. |
SsoDomainVerify
| Field | Type | Required | Description |
|---|---|---|---|
domain | SsoDomain | yes | |
domain.id | string | yes | |
domain.domain | string | yes | |
domain.verified | boolean | yes | |
domain.verifiedAt | integer | null | yes | |
domain.checkedAt | integer | null | yes | |
domain.createdAt | integer | yes | |
domain.record | object | yes | |
domain.record.name | string | yes | |
domain.record.type | "TXT" | yes | |
domain.record.value | string | yes | |
checked | boolean | yes | False when the resolver did not answer, so nothing was learned. Try again. |
ScimSettings
| Field | Type | Required | Description |
|---|---|---|---|
available | boolean | yes | Whether the organisation's plan includes SCIM (Enterprise). |
baseUrl | string | yes | The SCIM base URL to give the identity provider. |
token | ScimTokenView | yes | |
token.prefix | string | yes | The first characters of the token, to tell it apart. |
token.createdAt | integer | yes | |
token.lastUsedAt | integer | null | yes | When the provider last used it, to the minute. Null until it has. |
users | integer | yes | How many people the provider manages here, active or not. |
groups | ScimGroupView[] | yes | |
groups[].id | string | yes | |
groups[].displayName | string | yes | |
groups[].role | "admin" | "member" | "reader" | null | yes | The role the group gives its members, or null when it gives none. |
groups[].members | integer | yes |
ScimTokenView
| Field | Type | Required | Description |
|---|---|---|---|
prefix | string | yes | The first characters of the token, to tell it apart. |
createdAt | integer | yes | |
lastUsedAt | integer | null | yes | When the provider last used it, to the minute. Null until it has. |
ScimGroupView
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
displayName | string | yes | |
role | "admin" | "member" | "reader" | null | yes | The role the group gives its members, or null when it gives none. |
members | integer | yes |
ScimTokenIssued
| Field | Type | Required | Description |
|---|---|---|---|
token | string | yes | The bearer token for the identity provider. Shown once; only its hash is kept. |
view | ScimTokenView | yes | |
view.prefix | string | yes | The first characters of the token, to tell it apart. |
view.createdAt | integer | yes | |
view.lastUsedAt | integer | null | yes | When the provider last used it, to the minute. Null until it has. |
ScimGroupRoleBody
| Field | Type | Required | Description |
|---|---|---|---|
role | "admin" | "member" | "reader" | null | yes |
SupportSettings
| Field | Type | Required | Description |
|---|---|---|---|
available | boolean | yes | True when the organisation's plan includes priority support (Enterprise). |
plan | string | yes | The organisation's plan. |
contact | object | null | yes | The named contact, or null when none is named yet. A request still reaches Plotwork support. |
contact.name | string | yes | |
contact.email | string | yes | |
firstResponseHours | integer | null | yes | The first response target, in business hours, or null when the contract names none. |
hours | string | null | yes | When support is staffed, as the contract says it, or null. |
uptimeSla | boolean | yes | True when the plan includes an uptime SLA. |
contract | object | null | yes | The dates of the contract: for the owner and the admins only, and null for everyone else or a contract set without dates. |
contract.startsOn | string | yes | The first day of the contract, YYYY-MM-DD (UTC). |
contract.endsOn | string | yes | The last day of the contract, YYYY-MM-DD (UTC). |
contract.autoRenew | boolean | yes | Whether the contract renews by itself at the end. |
contract.noticeDays | integer | yes | The notice either side gives before the end, in days. |
SupportAck
| Field | Type | Required | Description |
|---|---|---|---|
received | true | yes | |
contactName | string | null | yes | The name of the contact who will answer, or null when none is named. |
firstResponseHours | integer | null | yes | The first response target, in business hours, or null. |
SupportRequestBody
| Field | Type | Required | Description |
|---|---|---|---|
subject | string | yes | One line on what it is about. 1 to 160 characters. at least 1 character; at most 160 characters. |
message | string | yes | What happened, what was expected, and anything that helps reproduce it. 1 to 5000 characters; line breaks are kept. at least 1 character; at most 5000 characters. |
severity | "question" | "broken" | "urgent" | yes | question for a question, broken when something does not work, urgent when production is affected. The contact reads the urgent ones first. |
FindPatternResponse
Patterns that match a request, best first, with summaries and no source.
| Field | Type | Required | Description |
|---|---|---|---|
query | string | yes | The query that was searched. |
matches | object[] | yes | Up to the limit, best match first. Empty when nothing fits. |
matches[].id | string | yes | The pattern id, as find_pattern returns it, such as three-tier-network. at least 1 character; at most 60 characters. |
matches[].title | string | yes | |
matches[].summary | string | yes | One sentence: what the diagram shows. |
matches[].kind | string | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
matches[].tags | string[] | yes | |
matches[].providers | ("neutral" | "aws" | "azure" | "gcp")[] | yes | The flavours the pattern comes in. |
matches[].score | number | yes | How well it matches; only the order of the results is meaningful. |
next | string | yes | The next step in one sentence. |
FindPatternInput
Words that describe the architecture wanted, and optional filters.
| Field | Type | Required | Description |
|---|---|---|---|
query | string | yes | The architecture wanted, in plain words, such as "three tier network". at least 1 character; at most 200 characters. |
provider | "neutral" | "aws" | "azure" | "gcp" | no | Only patterns that come in this flavour: neutral, aws, azure, or gcp. |
tags | string[] | no | Tags every result must have, such as "load balancer". Up to 5. |
kind | "flow" | "sequence" | "schema" | "git" | "gantt" | "class" | "state" | "timeline" | "journey" | "mindmap" | "treemap" | "pie" | "quadrant" | "layers" | "c4" | "matrix" | "sankey" | "xychart" | "tree" | "swimlane" | no | Only patterns of this diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane. |
limit | integer | no | Most results to return, up to 5. minimum 1; maximum 5; default 5. |
GetPatternResponse
A pattern filled for one flavour, with its slots and advice.
| Field | Type | Required | Description |
|---|---|---|---|
found | boolean | yes | True when the pattern and flavour exist and the slot values are usable. When false, problems says why and nothing else is filled. |
id | string | yes | The pattern id that was asked for. |
title | string | null | yes | |
patternSummary | string | null | yes | One sentence: what the pattern shows. |
whenToUse | string | null | yes | |
kind | string | null | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
flavour | "neutral" | "aws" | "azure" | "gcp" | null | yes | The flavour that was filled. |
flavours | ("neutral" | "aws" | "azure" | "gcp")[] | yes | Every flavour this pattern comes in; empty when the pattern was not found. |
source | string | null | yes | Plotwork source, valid and ready to use; null when not found. |
slots | object[] | yes | Every slot the source uses, with the value it has. |
slots[].id | string | yes | The slot id; the key to use in slots. |
slots[].value | string | yes | The text the slot has in the source: the value sent, or the default. |
slots[].default | string | yes | The default text. |
slots[].meaning | string | yes | What belongs in this slot. |
slots[].isDefault | boolean | yes | True when the slot kept its default. |
notes | object | null | yes | How to adapt the pattern: what to keep, what to rename, and when to split. |
notes.keep | string | yes | What to leave exactly as it is. |
notes.rename | string | yes | What to rename or replace, and how. |
notes.split | string | yes | When the diagram has grown too big, and where to cut it. |
problems | object[] | yes | Mistakes in the id, the flavour, or the slot values, each with a fix. Empty when found. |
problems[].code | "unknown-pattern" | "unknown-flavour" | "unknown-slot" | "bad-slot-value" | "bad-source" | yes | |
problems[].message | string | yes | |
problems[].hint | string | yes | How to fix it. |
tree | object[] | yes | The groups, overlays, and nodes as drawn, depth first, so you can see what to rename. |
tree[].depth | integer | yes | How deep the item sits: 0 for the top level. |
tree[].kind | "group" | "overlay" | "node" | "actor" | "table" | yes | |
tree[].id | string | yes | The id written in the source. |
tree[].label | string | yes | |
tree[].type | string | null | yes | The group type, node type, or actor type; null for a table or an untyped group. |
outline | string[] | yes | The text description of the diagram. |
next | string | yes | The next step in one sentence. |
GetPatternInput
A pattern id, the flavour to draw, and the slot values to use.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The pattern id, as find_pattern returns it, such as three-tier-network. at least 1 character; at most 60 characters. |
provider | "neutral" | "aws" | "azure" | "gcp" | no | neutral (generic glyphs, no vendor names; the default), or aws, azure, or gcp for that provider's icons. Not every pattern comes in every flavour; the answer lists the ones it has. default "neutral". |
slots | object | no | Slot values keyed by slot id, such as {"office": "Branch office"}: plain text of up to 60 characters, no quotes or line breaks. Omit a slot to keep its default. get_pattern lists the slots and what they mean. |
DrawFromPatternResponse
A pattern filled, checked, and drawn in one call.
| Field | Type | Required | Description |
|---|---|---|---|
found | boolean | yes | True when the pattern and flavour exist and the slot values are usable. When false, problems says why and nothing else is filled. |
id | string | yes | The pattern id that was asked for. |
title | string | null | yes | |
patternSummary | string | null | yes | One sentence: what the pattern shows. |
whenToUse | string | null | yes | |
kind | string | null | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
flavour | "neutral" | "aws" | "azure" | "gcp" | null | yes | The flavour that was filled. |
flavours | ("neutral" | "aws" | "azure" | "gcp")[] | yes | Every flavour this pattern comes in; empty when the pattern was not found. |
source | string | null | yes | Plotwork source, valid and ready to use; null when not found. |
slots | object[] | yes | Every slot the source uses, with the value it has. |
slots[].id | string | yes | The slot id; the key to use in slots. |
slots[].value | string | yes | The text the slot has in the source: the value sent, or the default. |
slots[].default | string | yes | The default text. |
slots[].meaning | string | yes | What belongs in this slot. |
slots[].isDefault | boolean | yes | True when the slot kept its default. |
notes | object | null | yes | How to adapt the pattern: what to keep, what to rename, and when to split. |
notes.keep | string | yes | What to leave exactly as it is. |
notes.rename | string | yes | What to rename or replace, and how. |
notes.split | string | yes | When the diagram has grown too big, and where to cut it. |
problems | object[] | yes | Mistakes in the id, the flavour, or the slot values, each with a fix. Empty when found. |
problems[].code | "unknown-pattern" | "unknown-flavour" | "unknown-slot" | "bad-slot-value" | "bad-source" | yes | |
problems[].message | string | yes | |
problems[].hint | string | yes | How to fix it. |
valid | boolean | yes | True when the source has no errors. When false, nothing was drawn: fix the errors and call again. |
errors | Diagnostic[] | yes | Every error found in one pass, each with line, column, and a hint. Empty when valid. |
errors[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
errors[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
errors[].message | string | yes | What is wrong, in one sentence. |
errors[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
errors[].column | integer | yes | 1-based column in that line. minimum 1. |
errors[].length | integer | yes | Number of characters the problem covers. minimum 1. |
errors[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
warnings | Diagnostic[] | yes | Quality warnings for a valid diagram: too dense, too wide, text cut, unconnected nodes, and suggestions for an icon or a group type. Empty when invalid. |
warnings[].code | "E100" | "E101" | "E110" | "E111" | "E120" | "E121" | "E122" | "E123" | "E124" | "E125" | "E130" | "E131" | "E132" | "E133" | "E134" | "E135" | "E136" | "E137" | "E138" | "E139" | "E140" | "W200" | "W201" | "W202" | "W203" | "W204" | "W205" | "W206" | "W207" | "W500" | "M100" | "M101" | "M102" | "M103" | "M104" | "M110" | "M200" | "M201" | "M202" | "M203" | "M204" | "M205" | "M206" | "M207" | "M208" | "M209" | "M210" | "M211" | "M212" | "M213" | "M214" | "M215" | "M216" | "M217" | "M218" | "E300" | "E301" | "E302" | "E303" | "E304" | "W300" | "W301" | "W302" | "W303" | "M120" | "M220" | "M221" | "M222" | "E340" | "E341" | "E342" | "E343" | "E344" | "E345" | "W320" | "W321" | "W322" | "W323" | "M240" | "M241" | "M242" | "E360" | "E361" | "E362" | "E363" | "E364" | "E365" | "E366" | "E367" | "W330" | "W331" | "W332" | "W333" | "W334" | "M250" | "M251" | "E400" | "E401" | "E402" | "E403" | "W350" | "W351" | "W352" | "W353" | "M270" | "M271" | "E420" | "E421" | "E422" | "E423" | "E424" | "W360" | "W361" | "W362" | "W363" | "W364" | "M180" | "M280" | "M281" | "M282" | "E320" | "E321" | "E322" | "E323" | "E324" | "E325" | "E326" | "E327" | "E328" | "E329" | "E330" | "W310" | "W311" | "W312" | "W313" | "W314" | "M130" | "M131" | "M132" | "M230" | "M231" | "M232" | "M233" | "M234" | "M235" | "M236" | "M237" | "M238" | "E380" | "E381" | "E382" | "E383" | "W340" | "W341" | "W342" | "W343" | "M260" | "I100" | "I101" | "I102" | "I103" | "I104" | "I105" | "I200" | "I201" | "I202" | "I203" | "I204" | "I206" | "R100" | "R101" | "R200" | "R201" | "R202" | "R203" | "R204" | "R205" | "R206" | "R207" | "S100" | "S200" | "S101" | "S102" | "S103" | "S104" | "S201" | "S202" | "S203" | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
warnings[].severity | "error" | "warning" | yes | Errors stop rendering; warnings never do. |
warnings[].message | string | yes | What is wrong, in one sentence. |
warnings[].line | integer | yes | 1-based line in the submitted source. minimum 1. |
warnings[].column | integer | yes | 1-based column in that line. minimum 1. |
warnings[].length | integer | yes | Number of characters the problem covers. minimum 1. |
warnings[].hint | string | null | yes | A concrete suggestion for fixing it, or null. |
summary | string | null | yes | One-line description of the diagram, usable as alt text; null when invalid. |
outline | string[] | yes | The diagram as plain text in reading order, to check it says what you meant; empty when invalid. |
outlineTruncated | boolean | yes | True when the summary level cut the outline short. Call again with detail "full" to read all of it. |
size | object | null | yes | Natural size of the laid-out diagram; null when invalid. |
size.width | integer | yes | Width in px. minimum 1. |
size.height | integer | yes | Height in px. minimum 1. |
quality | object | no | How clean the picture looks (score, grade, measures) and up to three changes that would help; read it instead of looking. Absent when invalid. |
quality.score | integer | yes | 0 to 100; 100 is a picture with nothing to fix. The same diagram always gets the same score. minimum 0; maximum 100. |
quality.grade | "clean" | "fair" | "cluttered" | yes | clean is 85 or more, fair 60 or more, cluttered below. |
quality.measures | object | yes | What the score is made from: crossings, lineOverBox, labelOverlaps, smallestTextPx (in an 880px column), aspectRatio, emptySpace (0 to 1), longestLine (px), detour (1 is straight), the counts of boxes, lines, labels, series, and slices, and any measure the kind adds. |
quality.hints | string[] | yes | Up to three changes, the one worth most first, each naming the statement or option to edit. |
quality.line | string | yes | The grade, the score, and the first hint in one line. |
notices | Note[] | no | Information notes, such as an icon alias drawn as the real icon; absent when there is none. |
notices[].code | string | yes | A stable code, such as I122 for an icon alias. |
notices[].severity | "info" | yes | A note never stops a drawing and is not a warning. |
notices[].message | string | yes | |
notices[].line | integer | yes | minimum 1. |
notices[].column | integer | yes | minimum 1. |
notices[].length | integer | yes | minimum 1. |
notices[].hint | string | null | yes | The text to write instead. |
renders | object[] | yes | One picture per requested color scheme, light first; empty when invalid, when svg is never, and when every picture was left out (see picturesOmitted). |
renders[].theme | "light" | "dark" | yes | The color scheme this picture is drawn in. |
renders[].svg | string | yes | Self-contained SVG markup with an accessible title and description. |
renders[].size | Size | yes | Natural size of a rendered diagram in px. |
renders[].size.width | integer | yes | Width in px. minimum 1. |
renders[].size.height | integer | yes | Height in px. minimum 1. |
picturesOmitted | object | no | Present only when pictures were left out because the answer would have been too big for an AI client to read in one piece. |
picturesOmitted.themes | ("light" | "dark")[] | yes | The color schemes whose pictures were left out. |
picturesOmitted.characters | integer | yes | How many characters the pictures left out came to. |
picturesOmitted.limit | integer | yes | The most characters one answer may hold before the pictures are left out. |
picturesOmitted.why | string | yes | Why they were left out, and what to do. |
viewUrl | string | no | A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so. |
pngUrl | string | no | The viewUrl with &download=png: opening it in a browser saves the diagram as a PNG for Slack, email, or a wiki. The PNG is drawn in the person's browser, not on a server, so it is a link to open, not an image address to embed. Absent when too long. |
svgUrl | string | no | The viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long. |
saveCommand | string | no | Run in a shell to save the SVG into the repository: the CLI decodes the link locally, fetches nothing, and embeds the source. Set --out to the path; add --theme dark for dark. Absent when too long. |
next | string | yes | The next step in one sentence. |
DrawFromPatternInput
A pattern id, the flavour and slot values to use, and what to return.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | The pattern id, as find_pattern returns it, such as three-tier-network. at least 1 character; at most 60 characters. |
provider | "neutral" | "aws" | "azure" | "gcp" | no | neutral (generic glyphs, no vendor names; the default), or aws, azure, or gcp for that provider's icons. Not every pattern comes in every flavour; the answer lists the ones it has. default "neutral". |
slots | object | no | Slot values keyed by slot id, such as {"office": "Branch office"}: plain text of up to 60 characters, no quotes or line breaks. Omit a slot to keep its default. get_pattern lists the slots and what they mean. |
themes | "light" | "dark" | "both" | no | light, dark, or both (the default): the light picture and the dark one a dark page needs. default "both". |
detail | "summary" | "full" | no | summary (the default), or full: the whole outline, and the source embedded in each SVG. default "summary". |
svg | "auto" | "always" | "never" | no | auto (the default) returns the SVGs, but over MCP leaves them out when the answer would be too big for a client (picturesOmitted). always returns them at any size. never draws nothing, which is cheaper. The HTTP API treats auto as always. default "auto". |
embedSource | boolean | no | Write the source into each SVG so read_diagram can give it back. Set it when you save the SVG in a repository or publish it to edit later; anyone with the file or link can then read the source. default false. |
settings | object | no | The repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab). |
LocalUsageAck
| Field | Type | Required | Description |
|---|---|---|---|
accepted | integer | yes | How many counts were stored. A count sent again replaces the one stored, so a retry never adds twice. minimum 0. |
ignored | integer | yes | How many counts were dropped because their tool or kind is not one this server knows. A 200 means the client may treat the days as sent. minimum 0. |
LocalUsageBody
| Field | Type | Required | Description |
|---|---|---|---|
schema | 1 | yes | The version of this request shape. Always 1. |
client | LocalUsageClient | yes | |
client.name | "plotwork-mcp" | yes | Always plotwork-mcp. |
client.version | string | yes | The package version, in semver form. at most 40 characters; pattern ^\d{1,6}\.\d{1,6}\.\d{1,6}(?:-[0-9A-Za-z.-]{1,32})?(?:\+[0-9A-Za-z.-]{1,32})?$. |
client.os | "linux" | "darwin" | "win32" | "other" | yes | The operating system family. Anything else is other. |
client.node | integer | yes | The Node major version, a whole number. minimum 18; maximum 99. |
days | LocalUsageDay[] | yes | At most 31 finished days. |
days[].day | string | yes | A UTC date from 40 days ago to yesterday. Nothing is accepted for today. pattern ^\d{4}-\d{2}-\d{2}$. |
days[].id | string | yes | A pseudonym for one install for one month: the first 128 bits of an HMAC-SHA-256 of plotwork-usage: and the month, keyed with a secret that never leaves the device. It changes every month, so installs can be counted within a month and cannot be followed from one month to the next. pattern ^[0-9a-f]{32}$. |
days[].counts | LocalUsageCount[] | yes | At most 400 counts. A tool, kind, and outcome may appear once a day. |
days[].counts[].tool | string | yes | The name of the local MCP tool, such as draw_diagram. A name this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9_]{0,63}$. |
days[].counts[].kind | string | yes | The diagram kind the source declared, such as flow, or none for a call with no source or one that names no kind. A kind this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9]{0,31}$. |
days[].counts[].outcome | "ok" | "rejected" | "error" | yes | ok produced its answer, rejected was refused because of its input, error failed inside the tool. |
days[].counts[].count | integer | yes | A whole number from 1 to 1,000,000. minimum 1; maximum 1000000. |
LocalUsageClient
| Field | Type | Required | Description |
|---|---|---|---|
name | "plotwork-mcp" | yes | Always plotwork-mcp. |
version | string | yes | The package version, in semver form. at most 40 characters; pattern ^\d{1,6}\.\d{1,6}\.\d{1,6}(?:-[0-9A-Za-z.-]{1,32})?(?:\+[0-9A-Za-z.-]{1,32})?$. |
os | "linux" | "darwin" | "win32" | "other" | yes | The operating system family. Anything else is other. |
node | integer | yes | The Node major version, a whole number. minimum 18; maximum 99. |
LocalUsageDay
| Field | Type | Required | Description |
|---|---|---|---|
day | string | yes | A UTC date from 40 days ago to yesterday. Nothing is accepted for today. pattern ^\d{4}-\d{2}-\d{2}$. |
id | string | yes | A pseudonym for one install for one month: the first 128 bits of an HMAC-SHA-256 of plotwork-usage: and the month, keyed with a secret that never leaves the device. It changes every month, so installs can be counted within a month and cannot be followed from one month to the next. pattern ^[0-9a-f]{32}$. |
counts | LocalUsageCount[] | yes | At most 400 counts. A tool, kind, and outcome may appear once a day. |
counts[].tool | string | yes | The name of the local MCP tool, such as draw_diagram. A name this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9_]{0,63}$. |
counts[].kind | string | yes | The diagram kind the source declared, such as flow, or none for a call with no source or one that names no kind. A kind this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9]{0,31}$. |
counts[].outcome | "ok" | "rejected" | "error" | yes | ok produced its answer, rejected was refused because of its input, error failed inside the tool. |
counts[].count | integer | yes | A whole number from 1 to 1,000,000. minimum 1; maximum 1000000. |
LocalUsageCount
| Field | Type | Required | Description |
|---|---|---|---|
tool | string | yes | The name of the local MCP tool, such as draw_diagram. A name this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9_]{0,63}$. |
kind | string | yes | The diagram kind the source declared, such as flow, or none for a call with no source or one that names no kind. A kind this server does not know is ignored, not refused, so an older server accepts a newer package. pattern ^[a-z][a-z0-9]{0,31}$. |
outcome | "ok" | "rejected" | "error" | yes | ok produced its answer, rejected was refused because of its input, error failed inside the tool. |
count | integer | yes | A whole number from 1 to 1,000,000. minimum 1; maximum 1000000. |
SyntaxResponse
The diagram language for one scope: the overview, or one kind in full.
| Field | Type | Required | Description |
|---|---|---|---|
answer | string | yes | What this answer is: overview, a topic (import-formats), or the kind it describes in full (flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today; later versions add kinds, so expect others). |
howToGetAKind | string | yes | In plain words: what this answer holds and how to get the rest. |
kinds | string[] | yes | Header keywords: the first line names the kind. |
kindDetails | object[] | yes | The overview lists every kind in the order of kinds, with its header, noun, and summary, and a pointer in more. A kind answer holds that kind alone, in full. |
kindDetails[].kind | string | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
kindDetails[].header | string | yes | The header line, such as flow "Title". |
kindDetails[].noun | string | yes | What the kind's diagrams are called in a sentence, such as flow or database schema. |
kindDetails[].summary | string | yes | One sentence: what the kind draws. |
kindDetails[].statements | object[] | no | The statements the kind adds to the header. Empty for a kind whose language the shared tables of this reference already describe. |
kindDetails[].statements[].syntax | string | yes | The statement with its parts named, such as: task |
kindDetails[].statements[].meaning | string | yes | What the statement does, and what it needs. |
kindDetails[].statements[].example | string | yes | One line that parses. |
kindDetails[].limits | object[] | no | The quality thresholds the kind adds. Empty for a kind whose limits are in the limits table of this reference. |
kindDetails[].limits[].name | string | yes | What is counted, such as tasks. |
kindDetails[].limits[].value | integer | yes | More than this in one diagram draws a quality warning. |
kindDetails[].limits[].meaning | string | yes | Why the limit exists and what to do past it. |
kindDetails[].more | string | no | Only in the overview, where statements and limits are left out: what a call with this kind returns that the overview does not, and how to ask for it. |
nodeTypes | object[] | no | |
nodeTypes[].type | "person" | "agent" | "client" | "service" | "gateway" | "function" | "database" | "cache" | "queue" | "storage" | "identity" | "secret" | "external" | "step" | "decision" | "terminal" | yes | |
nodeTypes[].shape | "card" | "pill" | yes | How the node is drawn. |
nodeTypes[].isTinted | boolean | yes | True when the card is filled and outlined in its tone, as for decisions. |
nodeTypes[].defaultTone | "neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red" | yes | Color family used when tone= is not set. |
nodeTypes[].defaultIcon | string | null | yes | Icon used when icon= is not set, or null for none. |
nodeTypes[].isDashed | boolean | yes | True when the outline is dashed, as for external systems. |
nodeTypes[].usableAsActor | boolean | yes | True when a sequence diagram actor may use this type. |
tones | ("neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red")[] | no | |
directions | ("auto" | "right" | "down" | "left" | "up")[] | no | Values for direction= on a flow header. |
arrows | object[] | no | |
arrows[].token | string | yes | The arrow as written in source. |
arrows[].line | "solid" | "dashed" | "dotted" | yes | How the line is drawn. |
arrows[].heads | "end" | "both" | "none" | yes | Which ends carry an arrowhead. |
arrows[].meaning | string | yes | What the arrow says, so the right one is chosen. |
blockTypes | ("alt" | "opt" | "loop" | "par")[] | no | Frames a sequence diagram can wrap around messages. |
columnFlags | ("pk" | "fk" | "unique" | "nullable")[] | no | Flags a schema column row may carry. |
themes | ("light" | "dark")[] | no | |
iconSets | ("lucide" | "simple" | "status" | "aws" | "gcp" | "azure" | "alibaba" | "oci" | "ibm" | "cloudflare" | "digitalocean" | "vercel")[] | no | |
iconCount | integer | no | Number of bundled icons; use search_icons to find names. |
iconProviders | object[] | no | Cloud and platform providers, each an icon set holding the provider (set:cloud) and its products. |
iconProviders[].set | "aws" | "gcp" | "azure" | "alibaba" | "oci" | "ibm" | "cloudflare" | "digitalocean" | "vercel" | yes | Icon set prefix, as in aws:lambda. |
iconProviders[].title | string | yes | The provider the set stands for. |
iconProviders[].iconCount | integer | yes | Icons in the set: the provider itself (set:cloud) and its products. |
iconProviders[].example | string | yes | One icon of the set that is bundled, for example aws:lambda. |
overlay | object | no | A dashed frame around members that may sit in different groups; it owns none of them. |
overlay.options | string[] | yes | Options an overlay statement takes after its name, as in: overlay id "Name" members=a,b type=scale-group. |
overlay.frame | "solid" | "dashed" | "dotted" | yes | How an overlay is always drawn. |
overlay.meaning | string | yes | What an overlay is for, so it is used where a group would be wrong. |
group | object | no | How a flow group looks and what it accepts; its corner tab shows its icon and name. |
group.options | string[] | yes | Options a group statement takes after its name, as in: group id "Name" type=region provider=aws {. |
group.defaultTone | "neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red" | yes | Color family of a group with no type when tone= is not set. |
group.example | object | yes | A complete architecture diagram: typed groups nested by provider, a provider icon on every node, stack marks, and a dotted edge. Copy and edit it. |
group.example.kind | string | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
group.example.title | string | yes | |
group.example.source | string | yes | A complete diagram that is checked by the build; copy and edit it. |
group.types | object[] | yes | Every group type. A type gives the group a default icon, tone, frame style, and a shade that deepens with nesting; icon= and tone= override them. |
group.types[].type | "cloud" | "account" | "region" | "zone" | "network" | "subnet" | "public-subnet" | "private-subnet" | "management-subnet" | "isolated-subnet" | "resource-group" | "cluster" | "scale-group" | "service-plan" | "web-tier" | "app-tier" | "data-tier" | "storage-account" | "messaging" | "edge" | "security" | "identity-boundary" | "trust-boundary" | "observability" | "ci-cd" | "environment" | "cloud-boundary" | "on-premises" | "client-side" | "external-systems" | yes | Value for type= on a group. |
group.types[].title | string | yes | What the frame is called in the text description. |
group.types[].meaning | string | yes | What the author means by this type, so the right one is chosen. |
group.types[].tone | "neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red" | yes | Color family the frame and tab get when tone= is not set. |
group.types[].frame | "solid" | "dashed" | "dotted" | yes | How the outline is drawn. |
group.types[].icon | string | yes | Icon in the corner tab when the group has no provider. |
group.types[].providerIcons | object | yes | Icon in the corner tab for each provider whose icon differs from the generic one, keyed by provider set. |
lineOptions | object[] | no | Options that animate a line (animate=on makes dashes travel toward the arrowhead) or number the steps of a flow or sequence (numbered=on, start=, and step= on a line). All are off by default. |
lineOptions[].key | string | yes | The option as written, such as animate or step. |
lineOptions[].scope | "header" | "line" | yes | header: on the flow or sequence header line. line: on an edge or a message. |
lineOptions[].values | string | yes | What the option takes. |
lineOptions[].meaning | string | yes | What it does, and the cases where it is refused. |
lineOptions[].example | string | yes | One line that parses. |
labelIcons | object[] | no | Edge labels that get a tick or cross automatically; icon=none on the edge removes it. |
labelIcons[].label | string | yes | An edge label that gets an icon automatically, matched whole and ignoring case. |
labelIcons[].icon | string | yes | The icon the label gets. |
verbIcons | object[] | no | The icons a flow edge label draws when it names a relationship with a verb. icon= on the edge wins, icon=none removes it, and icons=off on the header turns them all off. |
verbIcons[].icon | string | yes | The icon drawn in the label. |
verbIcons[].words | string[] | yes | Phrases that draw it: the whole label, or its first words followed by what is acted on ("reads orders"). |
style | string[] | no | How to make a flow diagram look finished: verbs on arrows, role= on lines that mean something, typed groups, product names. |
autoIcons | object | no | Items with no icon= get the icon their label names for certain (a brand, a cloud product, a common role). icon=none keeps one item plain; icons=off on the header keeps them all plain. |
autoIcons.key | string | yes | The header option: icons. |
autoIcons.values | string | yes | What it takes. |
autoIcons.meaning | string | yes | What it does, and how one item opts out. |
autoIcons.example | string | yes | One header line that parses. |
roleIcons | object[] | no | The plain icons for common roles, drawn on flow and sequence service and external items, C4 elements, layers blocks, mind map topics, and swimlane lanes. The last role word of the label wins. |
roleIcons[].icon | string | yes | The icon drawn. |
roleIcons[].words | string[] | yes | Whole words of a label of three words or fewer that draw it. |
statusIcons | object[] | no | Colored status and outcome icons: a green check, a red X, and so on. |
statusIcons[].ref | string | yes | Value for icon=, such as status:success. |
statusIcons[].tone | "neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red" | yes | Color the icon is always drawn in, whatever tone its owner has. |
statusIcons[].meaning | string | yes | What the icon says, so the right one is chosen. |
limits | object | no | Bounds and quality thresholds. |
limits.maxSourceLength | integer | yes | |
limits.maxFlowNodes | integer | yes | Quality lint: more nodes than this warns, for a diagram with no groups. |
limits.nodesPerGroup | integer | yes | Each group of a flow diagram raises the node limit by this many. |
limits.maxFlowNodesCeiling | integer | yes | The node limit never rises above this, whatever the groups. |
limits.maxSchemaTables | integer | yes | |
limits.maxSequenceActors | integer | yes | |
limits.maxNumberedSteps | integer | yes | More numbered steps than this in one diagram warns (W200). |
limits.maxStackMarks | integer | yes | Most technology marks a node carries in stack=. |
limits.targetWidth | integer | yes | Column width in px that diagrams are checked against. |
editing | object | no | How to edit an existing Plotwork SVG: read it back with read_diagram, change the source, draw it, and save or publish it again. |
editing.steps | string[] | yes | In order: how to change a diagram that already exists as a Plotwork SVG, a hosted link or a file in the repository. |
editing.embedSource | string | yes | When to set embedSource true on draw_diagram, render_diagram, or publish_diagram, and what it means for who can read the source. |
diagnosticCodes | object[] | no | |
diagnosticCodes[].name | string | yes | Identifier of the code. |
diagnosticCodes[].code | string | yes | The code to branch on, such as E120. |
diagnosticCodes[].severity | "error" | "warning" | yes | |
examples | object[] | yes | Tested examples: the overview holds the ones for the kinds the shared tables describe in full, a kind answer holds its own. |
examples[].kind | string | yes | A diagram kind: flow, sequence, schema, git, gantt, class, state, timeline, journey, mindmap, treemap, pie, quadrant, layers, c4, matrix, sankey, xychart, tree, or swimlane today. Later versions add kinds, so expect others. |
examples[].title | string | yes | |
examples[].source | string | yes | A complete diagram that is checked by the build; copy and edit it. |
importFormats | object[] | no | Only for topic import-formats: every format import_source reads, a line each. |
importFormats[].format | string | yes | The format, as import_source takes it. |
importFormats[].reads | string | yes | What it reads. |
importFormats[].draws | string | yes | The diagram it draws. |
importFormats[].options | string | yes | The options it takes. |
See also
| Doc | Why |
|---|---|
| API reference | Every endpoint, and the error envelope |
| Tool reference | The same operations as callable tools |
| Language reference | What the diagram source may contain |