Skip to content
Connect an agent
HTTP API

Schemas

Every request and response type of the HTTP API, with its fields. Each endpoint page links the types it uses.

TL;DR

QuestionAnswer
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.

FieldTypeRequiredDescription
status"ok"yes
versionstringyesPackage version of the running service.
kindsstring[]yesDiagram kinds this build can render.

Accepted

FieldTypeRequiredDescription
acceptedtrueyes

ErrorResponse

Standard error envelope used by every failing response.

FieldTypeRequiredDescription
errortrueyesAlways true, so clients can branch without reading the status.
errorCodestringyesStable snake_case key such as validation.failed or diagram.invalid.
messagestringyesSafe, human-readable summary.
detailsanynoValidation issues or diagnostics, JSON-safe.
requestIdstringnoTrace id for correlating with logs.

RequestCodeBody

FieldTypeRequiredDescription
emailstringyesat least 3 characters; at most 254 characters.

SignInResponse

FieldTypeRequiredDescription
userAccountyes
user.idstringyes
user.emailstringyes

Account

FieldTypeRequiredDescription
idstringyes
emailstringyes

VerifyCodeBody

FieldTypeRequiredDescription
emailstringyesat least 3 characters; at most 254 characters.
codestringyespattern ^\d{6}$.

SsoDiscover

FieldTypeRequiredDescription
ssobooleanyesTrue when the address's domain signs in through an organisation's identity provider. Names no organisation.

SsoDiscoverBody

FieldTypeRequiredDescription
emailstringyesat least 3 characters; at most 254 characters.

SsoStart

FieldTypeRequiredDescription
urlstringyesThe identity provider's authorization address to send the browser to.

SsoStartBody

FieldTypeRequiredDescription
emailstringyesat least 3 characters; at most 254 characters.
returnTostringnoWhere 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

FieldTypeRequiredDescription
itemsApiKeySummary[]yes
items[].idstringyes
items[].namestringyes
items[].prefixstringyes
items[].last4stringyes
items[].createdAtintegeryesMilliseconds since the epoch.
items[].lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if never used.
items[].revealablebooleanyesTrue 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

FieldTypeRequiredDescription
idstringyes
namestringyes
prefixstringyes
last4stringyes
createdAtintegeryesMilliseconds since the epoch.
lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if never used.
revealablebooleanyesTrue 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

FieldTypeRequiredDescription
idstringyes
namestringyes
prefixstringyes
last4stringyes
createdAtintegeryesMilliseconds since the epoch.
lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if never used.
revealablebooleanyesTrue 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.
keystringyesThe full key. When revealable is false this is the only time it is shown, so store it now.

CreateApiKeyBody

FieldTypeRequiredDescription
namestringyesat least 1 character; at most 60 characters; pattern \S.

RevealedApiKey

FieldTypeRequiredDescription
idstringyes
keystringyesThe full key.

Approval

FieldTypeRequiredDescription
approvalstringyesThe signed approval. It carries the connection key sealed, so it is safe in an address.
expiresInintegeryesSeconds the approval stays usable.
redirectTostringyesWhere to send the browser: the MCP server callback with the request and the approval already attached.

ApproveConnectionBody

FieldTypeRequiredDescription
requeststringyesThe signed authorization request, exactly as the MCP server put it in the address. at least 1 character; at most 6144 characters.

ConnectionList

FieldTypeRequiredDescription
itemsConnection[]yes
items[].idstringyes
items[].clientIdstringyesThe OAuth client id the agent registered with.
items[].clientNamestringyesThe name the agent gave itself when it registered. It is a claim, not a fact.
items[].connectedAtintegeryesMilliseconds since the epoch.
items[].lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if the agent has not made a call.

Connection

FieldTypeRequiredDescription
idstringyes
clientIdstringyesThe OAuth client id the agent registered with.
clientNamestringyesThe name the agent gave itself when it registered. It is a claim, not a fact.
connectedAtintegeryesMilliseconds since the epoch.
lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if the agent has not made a call.

Usage

FieldTypeRequiredDescription
plan"free" | "pro"yesThe plan the account is on, which decides the limit.
limitintegeryesMetered calls the account may make per UTC day, across every key and connected agent.
usedintegeryesMetered calls made today. minimum 0.
remainingintegeryesCalls left today. Zero when the limit is used up. minimum 0.
resetsAtintegeryesWhen the count goes back to zero (00:00 UTC), in milliseconds since the epoch.
todayobjectyesToday's calls, split by how they reached the service.
today.apiintegeryesminimum 0.
today.mcpintegeryesminimum 0.
daysUsageDay[]yesThe last 30 days, oldest first, ending today. A day with no calls is present with zeros.
days[].daystringyesThe UTC date, as YYYY-MM-DD.
days[].apiintegeryesREST API calls that day. minimum 0.
days[].mcpintegeryesMCP tool calls that day. minimum 0.

UsageDay

FieldTypeRequiredDescription
daystringyesThe UTC date, as YYYY-MM-DD.
apiintegeryesREST API calls that day. minimum 0.
mcpintegeryesMCP tool calls that day. minimum 0.

BillingState

FieldTypeRequiredDescription
plan"free" | "pro"yesThe plan the account gets right now. It is the free plan whenever the subscription is not paying, whatever plan was bought.
statusstringyesStripe's status for the subscription (active, trialing, past_due, canceled, unpaid, incomplete, and so on), or none when the account never started one.
currentPeriodEndinteger | nullyesWhen the period paid for ends, in milliseconds since the epoch, or null when there is no subscription.
cancelAtPeriodEndbooleanyesTrue while the subscription is scheduled to end at the close of the period already paid for.
hasCustomerbooleanyesTrue once the account has billing details at Stripe, which is when the billing portal can be opened.

BillingUrl

FieldTypeRequiredDescription
urlstringyesAn address on Stripe's own site. Send the browser there; it expires, so do not store it.

CheckoutBody

FieldTypeRequiredDescription
plan"pro"yesThe plan to subscribe to. pro is the only paid plan.

VerifyCheckoutBody

FieldTypeRequiredDescription
sessionIdstringyesThe Checkout Session id Stripe put in the return address. pattern ^cs_[A-Za-z0-9_]{8,200}$.

CancelBody

FieldTypeRequiredDescription
reasonstringnoWhy 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

FieldTypeRequiredDescription
itemsBillingDocument[]yes
items[].idstringyesThe id to ask for the document and its PDF with.
items[].kind"invoice" | "receipt"yesA receipt is an invoice that has been paid; anything else is an invoice.
items[].numberstringyesThe number printed on the document, which an accounts department quotes back.
items[].descriptionstringyesWhat it was for, such as the plan. Empty when Stripe names nothing.
items[].currencystringyesThe three-letter currency, in capitals. at least 3 characters; at most 3 characters.
items[].totalCentsintegeryesThe total in whole cents (the currency's minor unit).
items[].statusstringyesThe invoice's own word: paid, open, void, or uncollectible. A draft is never listed.
items[].issuedAtintegeryesWhen it was issued, in milliseconds since the epoch.
items[].paidAtinteger | nullyesWhen it was paid, in milliseconds since the epoch, or null while it is not.
items[].downloadablebooleanyesFalse when there is no PDF to fetch, so the PDF route would answer 404.

BillingDocument

FieldTypeRequiredDescription
idstringyesThe id to ask for the document and its PDF with.
kind"invoice" | "receipt"yesA receipt is an invoice that has been paid; anything else is an invoice.
numberstringyesThe number printed on the document, which an accounts department quotes back.
descriptionstringyesWhat it was for, such as the plan. Empty when Stripe names nothing.
currencystringyesThe three-letter currency, in capitals. at least 3 characters; at most 3 characters.
totalCentsintegeryesThe total in whole cents (the currency's minor unit).
statusstringyesThe invoice's own word: paid, open, void, or uncollectible. A draft is never listed.
issuedAtintegeryesWhen it was issued, in milliseconds since the epoch.
paidAtinteger | nullyesWhen it was paid, in milliseconds since the epoch, or null while it is not.
downloadablebooleanyesFalse when there is no PDF to fetch, so the PDF route would answer 404.

BillingDocumentDetail

FieldTypeRequiredDescription
idstringyesThe id to ask for the document and its PDF with.
kind"invoice" | "receipt"yesA receipt is an invoice that has been paid; anything else is an invoice.
numberstringyesThe number printed on the document, which an accounts department quotes back.
descriptionstringyesWhat it was for, such as the plan. Empty when Stripe names nothing.
currencystringyesThe three-letter currency, in capitals. at least 3 characters; at most 3 characters.
totalCentsintegeryesThe total in whole cents (the currency's minor unit).
statusstringyesThe invoice's own word: paid, open, void, or uncollectible. A draft is never listed.
issuedAtintegeryesWhen it was issued, in milliseconds since the epoch.
paidAtinteger | nullyesWhen it was paid, in milliseconds since the epoch, or null while it is not.
downloadablebooleanyesFalse when there is no PDF to fetch, so the PDF route would answer 404.
linesDocumentLine[]yes
lines[].descriptionstringyes
lines[].quantityintegeryesminimum 1.
lines[].amountCentsintegeryes
lines[].periodStartinteger | nullyesThe start of the service period, in milliseconds since the epoch, or null.
lines[].periodEndinteger | nullyesThe end of the service period, in milliseconds since the epoch, or null.
subtotalCentsinteger | nullyes
taxCentsinteger | nullyesThe tax, or null when Stripe names none.
amountPaidCentsinteger | nullyes
billedToobjectyes
billedTo.namestring | nullyes
billedTo.emailstring | nullyes
issuerobject | nullyesThe 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.namestringyes
issuer.linesstring[]yes
paidWithobject | nullyesThe 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.brandstringyes
paidWith.last4stringyespattern ^\d{4}$.

DocumentLine

FieldTypeRequiredDescription
descriptionstringyes
quantityintegeryesminimum 1.
amountCentsintegeryes
periodStartinteger | nullyesThe start of the service period, in milliseconds since the epoch, or null.
periodEndinteger | nullyesThe end of the service period, in milliseconds since the epoch, or null.

WebhookAck

FieldTypeRequiredDescription
receivedtrueyes
outcome"handled" | "duplicate" | "ignored"yeshandled 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.

FieldTypeRequiredDescription
validbooleanyesTrue when the source has no errors. When false, nothing was drawn: fix the errors and call again.
kindstring | nullyesThe diagram kind, or null when the header could not be read.
errorsDiagnostic[]yesEvery 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
errors[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
errors[].messagestringyesWhat is wrong, in one sentence.
errors[].lineintegeryes1-based line in the submitted source. minimum 1.
errors[].columnintegeryes1-based column in that line. minimum 1.
errors[].lengthintegeryesNumber of characters the problem covers. minimum 1.
errors[].hintstring | nullyesA concrete suggestion for fixing it, or null.
warningsDiagnostic[]yesQuality 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
warnings[].messagestringyesWhat is wrong, in one sentence.
warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
warnings[].columnintegeryes1-based column in that line. minimum 1.
warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
summarystring | nullyesOne-line description of the diagram, usable as alt text; null when invalid.
outlinestring[]yesThe diagram as plain text in reading order, to check it says what you meant; empty when invalid.
outlineTruncatedbooleanyesTrue when the summary level cut the outline short. Call again with detail "full" to read all of it.
sizeobject | nullyesNatural size of the laid-out diagram; null when invalid.
size.widthintegeryesWidth in px. minimum 1.
size.heightintegeryesHeight in px. minimum 1.
qualityobjectnoHow clean the picture looks (score, grade, measures) and up to three changes that would help; read it instead of looking. Absent when invalid.
quality.scoreintegeryes0 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"yesclean is 85 or more, fair 60 or more, cluttered below.
quality.measuresobjectyesWhat 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.hintsstring[]yesUp to three changes, the one worth most first, each naming the statement or option to edit.
quality.linestringyesThe grade, the score, and the first hint in one line.
noticesNote[]noInformation notes, such as an icon alias drawn as the real icon; absent when there is none.
notices[].codestringyesA stable code, such as I122 for an icon alias.
notices[].severity"info"yesA note never stops a drawing and is not a warning.
notices[].messagestringyes
notices[].lineintegeryesminimum 1.
notices[].columnintegeryesminimum 1.
notices[].lengthintegeryesminimum 1.
notices[].hintstring | nullyesThe text to write instead.
rendersobject[]yesOne 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"yesThe color scheme this picture is drawn in.
renders[].svgstringyesSelf-contained SVG markup with an accessible title and description.
renders[].sizeSizeyesNatural size of a rendered diagram in px.
renders[].size.widthintegeryesWidth in px. minimum 1.
renders[].size.heightintegeryesHeight in px. minimum 1.
picturesOmittedobjectnoPresent 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")[]yesThe color schemes whose pictures were left out.
picturesOmitted.charactersintegeryesHow many characters the pictures left out came to.
picturesOmitted.limitintegeryesThe most characters one answer may hold before the pictures are left out.
picturesOmitted.whystringyesWhy they were left out, and what to do.
viewUrlstringnoA 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.
pngUrlstringnoThe 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.
svgUrlstringnoThe viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long.
saveCommandstringnoRun 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.
nextstringyesThe next step in one sentence.

Diagnostic

A located, actionable problem found in diagram source.

FieldTypeRequiredDescription
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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
severity"error" | "warning"yesErrors stop rendering; warnings never do.
messagestringyesWhat is wrong, in one sentence.
lineintegeryes1-based line in the submitted source. minimum 1.
columnintegeryes1-based column in that line. minimum 1.
lengthintegeryesNumber of characters the problem covers. minimum 1.
hintstring | nullyesA concrete suggestion for fixing it, or null.

Note

An information note with its place in the source.

FieldTypeRequiredDescription
codestringyesA stable code, such as I122 for an icon alias.
severity"info"yesA note never stops a drawing and is not a warning.
messagestringyes
lineintegeryesminimum 1.
columnintegeryesminimum 1.
lengthintegeryesminimum 1.
hintstring | nullyesThe text to write instead.

Size

Natural size of a rendered diagram in px.

FieldTypeRequiredDescription
widthintegeryesWidth in px. minimum 1.
heightintegeryesHeight in px. minimum 1.

DrawDiagramInput

Diagram source and what to return: the color schemes to draw and how much detail.

FieldTypeRequiredDescription
sourcestringyesDiagram 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"nolight, dark, or both (the default): the light picture and the dark one a dark page needs. default "both".
detail"summary" | "full"nosummary (the default), or full: the whole outline, and the source embedded in each SVG. default "summary".
svg"auto" | "always" | "never"noauto (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".
embedSourcebooleannoWrite 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.
settingsobjectnoThe 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.

FieldTypeRequiredDescription
sourcestringyesThe edited source. Lines no operation touched are byte for byte as they were, comments included.
changedbooleanyes
resultsobject[]yesOne entry for each operation, in order.
results[].op"rename" | "set" | "add_node" | "remove" | "add_edge" | "remove_edge" | "move" | "replace_text"yes
results[].appliedbooleanyes
results[].linesinteger[]yesLines of the new source this operation wrote, or the lines it removed from.
results[].messagestringyes
results[].hintstring | nullyes
validbooleanyes
kindstring | nullyesA 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.
errorsDiagnostic[]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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
errors[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
errors[].messagestringyesWhat is wrong, in one sentence.
errors[].lineintegeryes1-based line in the submitted source. minimum 1.
errors[].columnintegeryes1-based column in that line. minimum 1.
errors[].lengthintegeryesNumber of characters the problem covers. minimum 1.
errors[].hintstring | nullyesA concrete suggestion for fixing it, or null.
warningsDiagnostic[]yesQuality 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
warnings[].messagestringyesWhat is wrong, in one sentence.
warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
warnings[].columnintegeryes1-based column in that line. minimum 1.
warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
summarystring | nullyes
outlinestring[]yes
outlineTruncatedbooleanyes
sizeanyyes
size.widthintegeryesWidth in px. minimum 1.
size.heightintegeryesHeight in px. minimum 1.
rendersobject[]yes
renders[].theme"light" | "dark"yes
renders[].svgstringyes
renders[].sizeSizeyesNatural size of a rendered diagram in px.
renders[].size.widthintegeryesWidth in px. minimum 1.
renders[].size.heightintegeryesHeight in px. minimum 1.
picturesOmittedobjectnoPresent 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")[]yesThe color schemes whose pictures were left out.
picturesOmitted.charactersintegeryesHow many characters the pictures left out came to.
picturesOmitted.limitintegeryesThe most characters one answer may hold before the pictures are left out.
picturesOmitted.whystringyesWhy they were left out, and what to do.
viewUrlstringnoA 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.
svgUrlstringnoThe viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long.
saveCommandstringnoRun 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.
nextstringyes

EditDiagramInput

Diagram source and the edits to make to it.

FieldTypeRequiredDescription
sourcestringyesDiagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters.
operationsobject[]yesApplied in order.
operations[].op"rename" | "set" | "add_node" | "remove" | "add_edge" | "remove_edge" | "move" | "replace_text"yes
operations[].targetstringnoId, label, table.column, or "header". at most 2000 characters.
operations[].tostringnorename: the new name. Edges: the end. at most 2000 characters.
operations[].fromstringnoEdges: the start. at most 2000 characters.
operations[].optionstringnoat most 40 characters; pattern ^[a-z][A-Za-z0-9_-]*$.
operations[].valuestring | nullnoset: null removes the option. at most 2000 characters.
operations[].idstringnoat most 2000 characters.
operations[].labelstringnoadd_edge on sankey: the amount. at most 2000 characters.
operations[].typestringnoadd_node: node type, or statement word (c4 person, tree dir). at most 2000 characters.
operations[].optionsobjectno
operations[].statementstringnoadd_node: the whole line, for a kind with no plain node statement. at most 2000 characters.
operations[].intostring | nullnoA block; null is the top level. at most 2000 characters.
operations[].afterstringnoat most 2000 characters.
operations[].arrow"<-->" | "-->" | "<->" | "..>" | "->" | "--"no
operations[].findstringnoat most 2000 characters.
operations[].replacestringnoat most 2000 characters.
operations[].allbooleanno
svg"auto" | "always" | "never"nonever (the default) draws nothing; auto or always draws like draw_diagram. default "never".
themes"light" | "dark" | "both"nolight, dark, or both (the default): the light picture and the dark one a dark page needs. default "both".
settingsobjectnoThe 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.

FieldTypeRequiredDescription
okbooleanyesTrue when source is valid Plotwork source. False means nothing was converted and source is empty: read diagnostics.
kindstring | nullyesThe Plotwork kind the diagram became, or null when it could not be converted.
mermaidTypestring | nullyesThe Mermaid diagram type read from the first line, such as flowchart or sequenceDiagram; null when none was found.
sourcestringyesThe Plotwork source, or an empty string when nothing could be converted.
diagnosticsDiagnostic[]yesEverything 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
diagnostics[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
diagnostics[].messagestringyesWhat is wrong, in one sentence.
diagnostics[].lineintegeryes1-based line in the submitted source. minimum 1.
diagnostics[].columnintegeryes1-based column in that line. minimum 1.
diagnostics[].lengthintegeryesNumber of characters the problem covers. minimum 1.
diagnostics[].hintstring | nullyesA concrete suggestion for fixing it, or null.
statsobjectyes
stats.nodesintegeryesFlow nodes written.
stats.edgesintegeryesFlow edges written.
stats.groupsintegeryesFlow groups written.
stats.actorsintegeryesSequence participants written.
stats.messagesintegeryesSequence messages written.
stats.tablesintegeryesSchema tables written.
stats.columnsintegeryesSchema columns written.
stats.relationsintegeryesSchema relations written.
stats.droppedintegeryesWarnings about constructs that were dropped: styling, links, activations, and so on.
stats.renamedintegeryesIds that were not valid Plotwork ids and were renamed.
validationobject | nullyesThe Plotwork validator run on source; null when nothing was converted.
validation.validbooleanyesTrue when the converted source has no Plotwork errors. It always is when ok is true.
validation.errorsDiagnostic[]yesPlotwork 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
validation.errors[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
validation.errors[].messagestringyesWhat is wrong, in one sentence.
validation.errors[].lineintegeryes1-based line in the submitted source. minimum 1.
validation.errors[].columnintegeryes1-based column in that line. minimum 1.
validation.errors[].lengthintegeryesNumber of characters the problem covers. minimum 1.
validation.errors[].hintstring | nullyesA concrete suggestion for fixing it, or null.
validation.warningsDiagnostic[]yesPlotwork 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
validation.warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
validation.warnings[].messagestringyesWhat is wrong, in one sentence.
validation.warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
validation.warnings[].columnintegeryes1-based column in that line. minimum 1.
validation.warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
validation.warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
validation.summarystring | nullyesOne-line description of the converted diagram, usable as alt text.
validation.sizeobject | nullyesNatural size of the laid-out diagram.
validation.size.widthintegeryesWidth in px. minimum 1.
validation.size.heightintegeryesHeight in px. minimum 1.
qualityobjectnoHow clean the converted diagram looks and up to three changes that would help (see draw_diagram); absent when it is not valid.
quality.scoreintegeryes0 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"yesclean is 85 or more, fair 60 or more, cluttered below.
quality.measuresobjectyesWhat 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.hintsstring[]yesUp to three changes, the one worth most first, each naming the statement or option to edit.
quality.linestringyesThe grade, the score, and the first hint in one line.
outlinestring[]yesThe converted diagram as plain text, to check it says what the Mermaid said; empty when nothing was converted.
outlineTruncatedbooleanyesTrue when the summary level cut the outline short. Call again with detail "full" to read all of it.
rendersobject[]yesOne 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"yesThe color scheme this picture is drawn in.
renders[].svgstringyesSelf-contained SVG markup with an accessible title and description.
renders[].sizeSizeyesNatural size of a rendered diagram in px.
renders[].size.widthintegeryesWidth in px. minimum 1.
renders[].size.heightintegeryesHeight in px. minimum 1.
picturesOmittedobjectnoPresent 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")[]yesThe color schemes whose pictures were left out.
picturesOmitted.charactersintegeryesHow many characters the pictures left out came to.
picturesOmitted.limitintegeryesThe most characters one answer may hold before the pictures are left out.
picturesOmitted.whystringyesWhy they were left out, and what to do.
viewUrlstringnoA 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.
pngUrlstringnoThe 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.
svgUrlstringnoThe viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long.
saveCommandstringnoRun 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.
nextstringyesThe next step in one sentence.

ConvertMermaidInput

Mermaid source and what to return with the converted Plotwork source.

FieldTypeRequiredDescription
sourcestringyesOne 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.
lenientbooleannofalse (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.
renderbooleannoAlso draw the converted diagram, in the color schemes themes names. default false.
themes"light" | "dark" | "both"nolight, dark, or both (the default): the light picture and the dark one a dark page needs. default "both".
detail"summary" | "full"nosummary (the default), or full: the whole outline, and the source embedded in each SVG. default "summary".
svg"auto" | "always" | "never"noauto (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".
embedSourcebooleannoWrite 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.
settingsobjectnoThe 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.

FieldTypeRequiredDescription
validbooleanyesTrue when there are no errors; warnings do not make a diagram invalid.
kindstring | nullyesThe diagram kind, or null when the header could not be read.
errorsDiagnostic[]yesEvery 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
errors[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
errors[].messagestringyesWhat is wrong, in one sentence.
errors[].lineintegeryes1-based line in the submitted source. minimum 1.
errors[].columnintegeryes1-based column in that line. minimum 1.
errors[].lengthintegeryesNumber of characters the problem covers. minimum 1.
errors[].hintstring | nullyesA concrete suggestion for fixing it, or null.
warningsDiagnostic[]yesQuality 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
warnings[].messagestringyesWhat is wrong, in one sentence.
warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
warnings[].columnintegeryes1-based column in that line. minimum 1.
warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
summarystring | nullyesOne-line description of the diagram, or null when invalid.
sizeobject | nullyesNatural rendered size, or null when invalid.
size.widthintegeryesWidth in px. minimum 1.
size.heightintegeryesHeight in px. minimum 1.
qualityobjectnoHow clean the laid-out diagram looks, with up to three changes; absent when invalid.
quality.scoreintegeryes0 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"yesclean is 85 or more, fair 60 or more, cluttered below.
quality.measuresobjectyesWhat 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.hintsstring[]yesUp to three changes, the one worth most first, each naming the statement or option to edit.
quality.linestringyesThe grade, the score, and the first hint in one line.
noticesNote[]noInformation notes, such as an icon alias resolved to a real icon; absent when there is none.
notices[].codestringyesA stable code, such as I122 for an icon alias.
notices[].severity"info"yesA note never stops a drawing and is not a warning.
notices[].messagestringyes
notices[].lineintegeryesminimum 1.
notices[].columnintegeryesminimum 1.
notices[].lengthintegeryesminimum 1.
notices[].hintstring | nullyesThe text to write instead.

DiagramSourceInput

Request body carrying diagram source.

FieldTypeRequiredDescription
sourcestringyesDiagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters.
settingsobjectnoThe 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.

FieldTypeRequiredDescription
svgstringyesSelf-contained SVG markup with an accessible title and description.
theme"light" | "dark" | "auto"yesThe color scheme used.
sizeSizeyesNatural size of a rendered diagram in px.
size.widthintegeryesWidth in px. minimum 1.
size.heightintegeryesHeight in px. minimum 1.
warningsDiagnostic[]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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
warnings[].messagestringyesWhat is wrong, in one sentence.
warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
warnings[].columnintegeryes1-based column in that line. minimum 1.
warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.

RenderInput

Diagram source and rendering options.

FieldTypeRequiredDescription
sourcestringyesDiagram 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"noColor scheme to paint with: light, dark, or auto for one picture that follows the reader's light or dark setting. default "light".
idPrefixstringnoPrefix for element ids; set it when inlining several diagrams into one page. at most 32 characters; pattern ^[A-Za-z][A-Za-z0-9_-]*$.
embedSourcebooleannoWrite 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.
settingsobjectnoThe 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.

FieldTypeRequiredDescription
kindstringyesA 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.
summarystringyesOne-line description.
outlinestring[]yesLines in reading order: participants, steps, tables, and connections.

ReadDiagramResponse

The source of a Plotwork SVG, or why there is none and what to do.

FieldTypeRequiredDescription
status"read" | "no-source" | "damaged" | "not-a-picture" | "refused" | "unreachable"yesread: 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.
hasSourcebooleanyesTrue when source is set.
sourcestring | nullyesThe exact source the picture was drawn from, ready to edit and send to draw_diagram; null when there is none.
kindstring | nullyesThe diagram kind of the source, or null.
idstring | nullyesThe id of the stored diagram when the picture was published (data-plotwork-id), or null.
from"text" | "url"yesWhere the picture came from: the text that was sent, or the link that was fetched.
validationobject | nullyesThe check of the source, or null when there is none. It parses the source; draw_diagram also lays it out and returns warnings.
validation.validbooleanyesTrue when the source has no errors.
validation.errorsDiagnostic[]yesEvery 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
validation.errors[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
validation.errors[].messagestringyesWhat is wrong, in one sentence.
validation.errors[].lineintegeryes1-based line in the submitted source. minimum 1.
validation.errors[].columnintegeryes1-based column in that line. minimum 1.
validation.errors[].lengthintegeryesNumber of characters the problem covers. minimum 1.
validation.errors[].hintstring | nullyesA concrete suggestion for fixing it, or null.
validation.summarystring | nullyesOne-line description of the diagram, or null when invalid.
pictureobject | nullyesWhat the picture says about itself, or null when the text is not an SVG.
picture.titlestring | nullyesThe diagram title, or null.
picture.summarystring | nullyesThe one-line summary the picture carries, or null.
picture.themestring | nullyesThe color scheme it was drawn in, or null.
picture.sizeobject | nullyesIts size in px, or null.
picture.size.widthintegeryesWidth in px. minimum 1.
picture.size.heightintegeryesHeight in px. minimum 1.
picture.outlinestring[]yesThe plain-language outline the picture carries, one entry for each line. Empty when the source was read: the source says more.
picture.labelsstring[]yesThe text painted on the picture, each distinct label once, in painted order. Empty when the source was read.
messagestringyesWhat happened, in one sentence.
nextstringyesThe next step in one sentence.

ReadDiagramInput

The text of a Plotwork SVG, or the link of a hosted one.

FieldTypeRequiredDescription
svgstringnoThe 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.
urlstringnoThe 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.

FieldTypeRequiredDescription
samebooleanyes
beforeobjectyes
before.from"source" | "svg" | "url"yes
before.readbooleanyesFalse when no source could be read from it; message says why.
before.kindstring | nullyesA 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.validbooleanyes
before.messagestring | nullyes
afterobjectyes
after.from"source" | "svg" | "url"yes
after.readbooleanyesFalse when no source could be read from it; message says why.
after.kindstring | nullyesA 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.validbooleanyes
after.messagestring | nullyes
countsobjectyes
counts.addedintegeryes
counts.removedintegeryes
counts.renamedintegeryes
counts.movedintegeryes
counts.changedintegeryes
changesobject[]yes
changes[].change"added" | "removed" | "renamed" | "moved" | "changed"yes
changes[].subject"header" | "node" | "group" | "edge" | "row" | "series" | "line"yes
changes[].namestringyesThe id, the label in quotes, or for an edge its ends.
changes[].lineinteger | nullyesThe line in after, or in before for a removal.
changes[].detailstringyes
truncatedbooleanyesTrue when more changes were found than are listed; counts covers all of them.
summarystringyesThe changes in plain words, for a pull request review.
markdownstring | nullyes
nextstringyes

CompareDiagramsInput

Two versions of a diagram to compare.

FieldTypeRequiredDescription
beforestringyesThe 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.
afterstringyesThe new diagram, in any of the same three forms. at least 1 character; at most 1000000 characters.
markdownbooleannoAlso 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.

FieldTypeRequiredDescription
requeststringyesThe request that was read.
suggestionsobject[]yesUp to 3, best first, one for each kind and style.
suggestions[].kindstringyesA 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[].stylestring | nullyesThe 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[].whystringyesOne sentence: why this kind fits.
suggestions[].confidence"high" | "medium" | "low"yeshigh: the text names this kind of picture or its shape fits it exactly. medium: it leans toward it. low: a fallback worth considering.
suggestions[].starterstringyesA 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[].tailoredbooleanyesTrue when the starter uses names or numbers from the text; false when it is the kind's small example.
suggestions[].statementsstring[]yesThe few statements of this kind to write, as syntax. get_diagram_syntax with this kind has them all.
importFormatstringnoPresent 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.
nextstringyesThe next step in one sentence.

SuggestDiagramInput

A request in plain words and optional data to draw from.

FieldTypeRequiredDescription
requeststringyesWhat 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.
datastringnoOptional 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

FieldTypeRequiredDescription
receivedtrueyesAlways true. The enquiry was received.

EnquiryBody

FieldTypeRequiredDescription
namestringyesThe name of the person asking. at least 1 character; at most 120 characters.
emailstringyesTheir work email address. The reply goes here.
companystringyesThe company. at least 1 character; at most 120 characters.
companySize"1-49" | "50-249" | "250-999" | "1000-4999" | "5000+"yesHow many people the company has.
repos"1-9" | "10-49" | "50-199" | "200-999" | "1000+"yesHow many repositories the team would run diagrams in.
useCasestringyesWhat 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")[]noWhat the company needs, as the boxes ticked on the form. Left out, nothing was ticked; a box named twice counts once.
contextEnquiryContextnoSent by the portal: where the form was opened. The site sends none.
context.page"contact" | "plan" | "sso" | "integrations" | "support" | "audit"yesThe place in the portal the form was opened from, such as sso for the Single sign-on panel.
context.orgstringnoThe 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])$.
websitestringnoLeave 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.
elapsedMsintegeryesMilliseconds 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.

FieldTypeRequiredDescription
page"contact" | "plan" | "sso" | "integrations" | "support" | "audit"yesThe place in the portal the form was opened from, such as sso for the Single sign-on panel.
orgstringnoThe 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

FieldTypeRequiredDescription

PublishedDiagram

FieldTypeRequiredDescription
idstringyesThe handle for managing the diagram (delete). It is not in the link.
urlstringyesThe public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed.
namestring | nullyesThe label given at publish, or null.
folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
bytesintegeryesSize of the stored SVG in bytes.
createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them.
lockedbooleanyesTrue 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.
lockedAtinteger | nullyesWhen it was locked, in milliseconds since the epoch, or null when it is not locked.
createdbooleanyesTrue when this call stored a new diagram; false when the same diagram was already hosted and its link was kept.
stableLinkStableLinknoPresent only when the publish named an alias: the stable link, now pointing at this diagram.
stableLink.idstringyesThe handle for managing the stable link (delete). It is not in its address.
stableLink.aliasstringyesThe name you gave it. Only you see it.
stableLink.urlstringyesThe 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.diagramIdstring | nullyesThe 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.createdAtintegeryesWhen it was made, in milliseconds since the epoch.
stableLink.updatedAtintegeryesWhen it was last pointed at a diagram, in milliseconds since the epoch.

Present only when the publish named an alias: the stable link, now pointing at this diagram.

FieldTypeRequiredDescription
idstringyesThe handle for managing the stable link (delete). It is not in its address.
aliasstringyesThe name you gave it. Only you see it.
urlstringyesThe 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.
diagramIdstring | nullyesThe 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.
createdAtintegeryesWhen it was made, in milliseconds since the epoch.
updatedAtintegeryesWhen it was last pointed at a diagram, in milliseconds since the epoch.

HostedDiagram

FieldTypeRequiredDescription
idstringyesThe handle for managing the diagram (delete). It is not in the link.
urlstringyesThe public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed.
namestring | nullyesThe label given at publish, or null.
folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
bytesintegeryesSize of the stored SVG in bytes.
createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them.
lockedbooleanyesTrue 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.
lockedAtinteger | nullyesWhen it was locked, in milliseconds since the epoch, or null when it is not locked.

RoutedPublish

FieldTypeRequiredDescription
idstringyesThe handle for the diagram in the routes below.
namestring | nullyesThe label given at publish, or null.
folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
bytesintegeryesSize of the stored SVG in bytes.
createdBystring | nullyesThe account that published it, or null when that account has left or an organisation key published it.
createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted.
viewUrlstringyesA 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.
lockedbooleanyesTrue 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.
lockedAtinteger | nullyesWhen the owner locked it, in milliseconds since the epoch, or null when it is not locked.
restrictedtruenoPresent, 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.
createdbooleanyesTrue when this call stored a new diagram; false when the same diagram was already in the library and was kept.
sourceEmbeddedbooleanyesTrue when the stored picture carries the diagram source: the call sent embedSource true, or left it out while the organisation's keepEditable is on.
privatetrueyesThe diagram is in an organisation's private library and has no public link.
organizationPublishOrganizationyesThe organisation whose private library holds the diagram.
organization.idstringyes
organization.slugstringyes
organization.namestringyes
routedBy"organisation-default" | "organisation-required"noPresent 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.

FieldTypeRequiredDescription
idstringyes
slugstringyes
namestringyes

PublishedOrganisationDiagram

FieldTypeRequiredDescription
idstringyesThe handle for the diagram in the routes below.
namestring | nullyesThe label given at publish, or null.
folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
bytesintegeryesSize of the stored SVG in bytes.
createdBystring | nullyesThe account that published it, or null when that account has left or an organisation key published it.
createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted.
viewUrlstringyesA 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.
lockedbooleanyesTrue 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.
lockedAtinteger | nullyesWhen the owner locked it, in milliseconds since the epoch, or null when it is not locked.
restrictedtruenoPresent, 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.
createdbooleanyesTrue when this call stored a new diagram; false when the same diagram was already in the library and was kept.
sourceEmbeddedbooleanyesTrue 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

FieldTypeRequiredDescription
idstringyesThe handle for the diagram in the routes below.
namestring | nullyesThe label given at publish, or null.
folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
bytesintegeryesSize of the stored SVG in bytes.
createdBystring | nullyesThe account that published it, or null when that account has left or an organisation key published it.
createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted.
viewUrlstringyesA 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.
lockedbooleanyesTrue 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.
lockedAtinteger | nullyesWhen the owner locked it, in milliseconds since the epoch, or null when it is not locked.
restrictedtruenoPresent, 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

FieldTypeRequiredDescription
sourcestringyesDiagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters.
settingsobjectnoThe 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"noThe color scheme to draw it in: light, dark, or auto (one picture that follows the viewer's light or dark setting). default "light".
embedSourcebooleannoWrite 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.
namestringnoA 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.
folderstring | nullnoThe 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.
aliasstringnoPoint 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]+)*$.
organizationstringnoAn 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.
personalbooleannoTrue 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

FieldTypeRequiredDescription
itemsHostedDiagram[]yesAt most 200, newest published first.
items[].idstringyesThe handle for managing the diagram (delete). It is not in the link.
items[].urlstringyesThe public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed.
items[].namestring | nullyesThe label given at publish, or null.
items[].folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
items[].theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
items[].bytesintegeryesSize of the stored SVG in bytes.
items[].createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
items[].publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
items[].expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them.
items[].lockedbooleanyesTrue 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[].lockedAtinteger | nullyesWhen it was locked, in milliseconds since the epoch, or null when it is not locked.
stableLinksStableLink[]yesEvery stable link the account keeps, by alias, including any whose diagram is gone.
stableLinks[].idstringyesThe handle for managing the stable link (delete). It is not in its address.
stableLinks[].aliasstringyesThe name you gave it. Only you see it.
stableLinks[].urlstringyesThe 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[].diagramIdstring | nullyesThe 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[].createdAtintegeryesWhen it was made, in milliseconds since the epoch.
stableLinks[].updatedAtintegeryesWhen it was last pointed at a diagram, in milliseconds since the epoch.
usageHostingUsageyes
usage.plan"free" | "pro"yesThe plan the account is on, which decides the limits.
usage.countintegeryesHosted diagrams the account holds. This is the total, even when the list is shorter. minimum 0.
usage.bytesintegeryesTotal size of the hosted diagrams in bytes. minimum 0.
usage.stableLinksintegeryesStable links the account keeps. minimum 0.
usage.limitsHostingPlanLimitsyes
usage.limits.dailyCallsintegeryes
usage.limits.hostedDiagramsintegeryes
usage.limits.hostedBytesintegeryes
usage.limits.retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until you delete it.
usage.limits.maxDiagramBytesintegeryes
usage.limits.stableLinksintegeryesStable links the account may keep at once.

HostingUsage

FieldTypeRequiredDescription
plan"free" | "pro"yesThe plan the account is on, which decides the limits.
countintegeryesHosted diagrams the account holds. This is the total, even when the list is shorter. minimum 0.
bytesintegeryesTotal size of the hosted diagrams in bytes. minimum 0.
stableLinksintegeryesStable links the account keeps. minimum 0.
limitsHostingPlanLimitsyes
limits.dailyCallsintegeryes
limits.hostedDiagramsintegeryes
limits.hostedBytesintegeryes
limits.retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until you delete it.
limits.maxDiagramBytesintegeryes
limits.stableLinksintegeryesStable links the account may keep at once.

HostingPlanLimits

FieldTypeRequiredDescription
dailyCallsintegeryes
hostedDiagramsintegeryes
hostedBytesintegeryes
retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until you delete it.
maxDiagramBytesintegeryes
stableLinksintegeryesStable links the account may keep at once.

MoveDiagramBody

FieldTypeRequiredDescription
folderstring | nullyesThe folder to file the diagram in, or null for the top level.

EditedDiagram

FieldTypeRequiredDescription
idstringyesThe handle for managing the diagram (delete). It is not in the link.
urlstringyesThe public address of the SVG. Anyone with the link can see it; the token in it cannot be guessed.
namestring | nullyesThe label given at publish, or null.
folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
bytesintegeryesSize of the stored SVG in bytes.
createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the plan keeps diagrams until you delete them.
lockedbooleanyesTrue 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.
lockedAtinteger | nullyesWhen it was locked, in milliseconds since the epoch, or null when it is not locked.
warningsDiagnostic[]yesQuality 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
warnings[].messagestringyesWhat is wrong, in one sentence.
warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
warnings[].columnintegeryes1-based column in that line. minimum 1.
warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
changedbooleanyesFalse when the source draws the picture the diagram already has: nothing was stored and no version was kept.

SaveDiagramSourceBody

FieldTypeRequiredDescription
sourcestringyesDiagram 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"noThe color scheme to draw it in: light, dark, or auto. Left out, the theme the diagram has.
baseVersionintegeryesThe 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

FieldTypeRequiredDescription
itemsDiagramVersion[]yesNewest first. A diagram keeps at most ten.
items[].idstringyesThe handle for restoring it.
items[].savedAtintegeryesWhen it stopped being the current picture, in milliseconds since the epoch.
items[].bytesintegeryesSize of the stored SVG in bytes. Versions do not count toward the plan.
items[].theme"light" | "dark" | "auto"yes

DiagramVersion

FieldTypeRequiredDescription
idstringyesThe handle for restoring it.
savedAtintegeryesWhen it stopped being the current picture, in milliseconds since the epoch.
bytesintegeryesSize of the stored SVG in bytes. Versions do not count toward the plan.
theme"light" | "dark" | "auto"yes

RestoreDiagramVersionBody

FieldTypeRequiredDescription
baseVersionintegeryesThe 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

FieldTypeRequiredDescription
aliasstringyesThe 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]+)*$.
diagramIdstringyesOne of your hosted diagrams, by its id.

OEmbedPhoto

FieldTypeRequiredDescription
version"1.0"yes
type"photo"yes
provider_namestringyes
provider_urlstringyes
titlestringyesAlways "Diagram": the diagram's own name is shown only to its owner.
urlstringyesThe picture. For a stable link, the stable link itself, so the embed keeps showing the latest version.
widthintegeryes
heightintegeryes
cache_ageintegeryesSeconds 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.

FieldTypeRequiredDescription
provider"aws" | "gcp" | "azure" | "alibaba" | "oci" | "ibm" | "cloudflare" | "digitalocean" | "vercel" | nullyesThe provider hint that was used, or null.
resultsobject[]yesOne entry per name that matched something, in the order sent.
results[].namestringyesThe name exactly as it was sent.
results[].resolvedbooleanyesTrue 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[].iconstring | nullyesThe icon to write as icon=, such as aws:lambda; null when resolved is false.
results[].confidence"exact" | "strong" | "ambiguous"yesexact: 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[].alternativesstring[]yesUp to 3 other icons that also fit a resolved name, best first. Empty when none.
results[].candidatesstring[]yesWhen resolved is false, the icons that fit, best first (up to 4). Empty when resolved.
gapsobject[]yesNames that matched nothing, in the order sent.
gaps[].namestringyesThe name that matched no icon.
gaps[].fallbackstringyesA neutral icon to use instead, or leave icon= out so the node type draws its own.
gaps[].reasonstringyesWhy there is no match, and what to try.
resolvedCountintegeryesHow many names have one icon to use.
ambiguousCountintegeryesHow many names need a choice from candidates.
gapCountintegeryesHow many names matched nothing.

MapIconsInput

Names to find icons for, and an optional provider to look in first.

FieldTypeRequiredDescription
namesstring[]yesServices, 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"noThe 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.

FieldTypeRequiredDescription
querystringyesThe query that was searched.
itemsstring[]yesMatching icon references as set:name, best match first.

ImportSourceResponse

The result of turning a file of another format into Plotwork source.

FieldTypeRequiredDescription
okbooleanyesTrue when source is valid Plotwork source. False means nothing was imported and source is empty: read diagnostics.
kindstring | nullyesThe kind of diagram the file became, or null when nothing was imported.
formatstringyesThe format the text was read as.
sourcestringyesThe Plotwork source, or an empty string when nothing could be imported.
diagnosticsDiagnostic[]yesEverything 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
diagnostics[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
diagnostics[].messagestringyesWhat is wrong, in one sentence.
diagnostics[].lineintegeryes1-based line in the submitted source. minimum 1.
diagnostics[].columnintegeryes1-based column in that line. minimum 1.
diagnostics[].lengthintegeryesNumber of characters the problem covers. minimum 1.
diagnostics[].hintstring | nullyesA concrete suggestion for fixing it, or null.
statsobjectyes
stats.itemsintegeryesBoxes, tables, rows, slices, places, entries, or commits written.
stats.linksintegeryesArrows, relations, messages, flows, or merges written.
stats.groupsintegeryesFrames, sections, or folders written.
stats.droppedintegeryesThings in the file left out by a cap or because the picture has no place for them; each is in diagnostics.
coverageobject | nullyesHow 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.nounstringyesWhat was counted, such as resources, services, tables, or endpoints.
coverage.totalintegeryesEverything of that kind in the file.
coverage.drawnintegeryesDrawn as a box, frame, table, row, or entry of its own.
coverage.summarisedintegeryesNot drawn on their own but counted on the box they belong to, such as "3 role assignments".
coverage.omittedintegeryesNot in the picture at all; the diagnostics say which and why.
coverage.completebooleanyesTrue when nothing was omitted.
coverage.linestringyesThe 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.".
validationobject | nullyesThe Plotwork validator run on source; null when nothing was imported.
validation.validbooleanyesTrue when the source has no Plotwork errors. It always is when ok is true.
validation.errorsDiagnostic[]yesPlotwork 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
validation.errors[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
validation.errors[].messagestringyesWhat is wrong, in one sentence.
validation.errors[].lineintegeryes1-based line in the submitted source. minimum 1.
validation.errors[].columnintegeryes1-based column in that line. minimum 1.
validation.errors[].lengthintegeryesNumber of characters the problem covers. minimum 1.
validation.errors[].hintstring | nullyesA concrete suggestion for fixing it, or null.
validation.warningsDiagnostic[]yesPlotwork 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
validation.warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
validation.warnings[].messagestringyesWhat is wrong, in one sentence.
validation.warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
validation.warnings[].columnintegeryes1-based column in that line. minimum 1.
validation.warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
validation.warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
validation.summarystring | nullyesOne-line description of the diagram, usable as alt text.
validation.sizeobject | nullyesNatural size of the laid-out diagram.
validation.size.widthintegeryesWidth in px. minimum 1.
validation.size.heightintegeryesHeight in px. minimum 1.
partsobject[]yesWhen 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[].titlestringyesWhat this diagram shows, such as one resource group or one tag of an API.
parts[].kindstringyesThe kind of diagram.
parts[].sourcestringyesThe Plotwork source of this diagram; draw it with draw_diagram.
parts[].itemsintegeryesThe boxes, rows, or entries it draws.
parts[].validbooleanyesTrue when the source has no Plotwork errors.
parts[].warningsDiagnostic[]yesPlotwork 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
parts[].warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
parts[].warnings[].messagestringyesWhat is wrong, in one sentence.
parts[].warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
parts[].warnings[].columnintegeryes1-based column in that line. minimum 1.
parts[].warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
parts[].warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
partsTotalintegeryesHow many diagrams the import was split into in all; 0 when it is one diagram.
partsPageintegeryesThe page of parts this answer holds, from 1.
partsPagesintegeryesHow many pages of parts there are; call again with partsPage for the next one.
outlinestring[]yesThe diagram as plain text, to check it says what the file says; empty when nothing was imported.
outlineTruncatedbooleanyesTrue when the outline was cut short at its summary length.
viewUrlstringnoA 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.
pngUrlstringnoThe 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.
svgUrlstringnoThe viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long.
saveCommandstringnoRun 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.
nextstringyesThe next step in one sentence.

ImportSourceInput

A file of another format to turn into Plotwork source.

FieldTypeRequiredDescription
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"yesWhat the text is; get_diagram_syntax with topic import-formats describes each.
textstringnoThe file content, as text. Send text or files, not both.
filesobject[]noThe files of a folder, for a format that spans files; the others read the first.
files[].pathstringyesThe file path, such as infra/network.tf; diagnostics name it. at least 1 character; at most 300 characters.
files[].textstringyesThe file content, as text.
titlestringnoThe diagram title; taken from the file when left out. at most 200 characters.
partsPageintegernoWhich page of parts to return when a split import has more than 24 diagrams: 1 (default) is the first 24. minimum 1; maximum 100000.
optionsobjectnodefault {}.
options.view"endpoints" | "map" | "sequence" | "git" | "timeline" | "context" | "container" | "component"noThe picture of a format drawn several ways.
options.operationIdstringnoopenapi sequence: the operation. at most 200 characters.
options.chart"auto" | "xychart" | "pie" | "sankey" | "treemap" | "matrix"nocsv, json: the chart; auto picks.
options.tablesstring[]noTables to draw, by name or prefix*.
options.pathsstring[]noopenapi: path prefixes to read.
options.tagsstring[]noopenapi: tags to read.
options.varFilesstring[]noVariables files to apply.
options.groupBy"module" | "network" | "file" | "owner"noHow things are framed; module is the default.
options.rootstringnoThe root, stack, or template of several to draw. at most 300 characters.

SyncMarkdownResponse

The result of turning a document's diagram fences into pictures.

FieldTypeRequiredDescription
mode"sync" | "check"yesThe mode that ran.
markdownstringyesThe 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.
changedbooleanyesTrue 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.
filesobject[]yesThe 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[].pathstringyesWhere to write the file, relative to the repository root.
files[].contentstringnoThe file contents; absent when files is none.
files[].encoding"utf8"yesHow content is encoded. Always utf8: the files are SVG text.
files[].bytesintegernoOnly when files is none: the size of the file in bytes.
files[].sha256stringnoOnly when files is none: the SHA-256 of the content, in hex, to check a file fetched later.
files[].viewUrlstringnoOnly when files is none: a link that shows this diagram in a browser.
reportobject[]yesOne entry per fence handled, in document order.
report[].idstring | nullyesThe 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"yesdiagram for a fence that was already Plotwork, mermaid for one that came from Mermaid.
report[].kindstring | nullyesThe diagram kind, or null when it could not be read.
report[].lineintegeryesThe 1-based line of the opening fence in the document that was sent. minimum 1.
report[].status"synced" | "converted" | "unchanged" | "skipped" | "failed"yessynced: 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[].diagnosticsDiagnostic[]yesErrors 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
report[].diagnostics[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
report[].diagnostics[].messagestringyesWhat is wrong, in one sentence.
report[].diagnostics[].lineintegeryes1-based line in the submitted source. minimum 1.
report[].diagnostics[].columnintegeryes1-based column in that line. minimum 1.
report[].diagnostics[].lengthintegeryesNumber of characters the problem covers. minimum 1.
report[].diagnostics[].hintstring | nullyesA concrete suggestion for fixing it, or null.
report[].messagestring | nullyesA plain sentence when something needs saying, such as why a fence was skipped; otherwise null.
summaryobjectyes
summary.diagramsintegeryesFences handled: synced, converted, unchanged, skipped, and failed together.
summary.syncedintegeryes
summary.convertedintegeryes
summary.unchangedintegeryes
summary.skippedintegeryes
summary.failedintegeryes
summary.mermaidIgnoredintegeryesMermaid fences left alone because convertMermaid was false.
summary.filesintegeryesFiles to write.
summary.outputBytesintegeryesBytes in the returned document and files together.
capsobjectyes
caps.hitbooleanyesTrue when a cap stopped some of the work. Nothing is cut silently: see messages.
caps.messagesstring[]yesOne plain sentence per cap that was hit, saying what was skipped and what to do.
caps.maxDiagramsintegeryesMost fences handled in one call.
caps.maxOutputBytesintegeryesMost bytes in the returned document and files together.
pagesobjectnoPresent when page or pageSize was sent: which pictures files holds, and the next page.
pages.pageintegeryes
pages.pageSizeintegeryes
pages.pagesintegeryesPages in all.
pages.picturesintegeryesPictures in all, each a light and a dark file.
pages.nextPageinteger | nullyesThe page to ask for next, or null on the last one.
nextstringyesThe next step in one sentence.

SyncMarkdownInput

A Markdown document and how to turn its diagram fences into pictures.

FieldTypeRequiredDescription
markdownstringyesThe 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.
documentPathstringyesWhere 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.
assetsDirstringnoThe 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.
prefixstringnoText 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.
convertMermaidbooleannoWhen 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"nosync (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"noinline (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".
pageintegernoWhich page of files to return, from 1; pictures are paged in document order, light and dark together. minimum 1.
pageSizeintegernoPictures per page, at most 30. Setting page or pageSize turns paging on. minimum 1; maximum 30.
settingsobjectnoThe 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.

FieldTypeRequiredDescription
summarystringyesOne sentence: how many sections were read and how many would gain a picture.
format"markdown" | "html" | "text"yesHow the document was read: Markdown headings, HTML h1 to h6, or plain text with heading-like lines.
sectionsReadintegeryesSections read, up to the cap.
suggestionsobject[]yesIn document order. Sections that read well as text, or already have a diagram, are not listed.
suggestions[].headingstringyesThe heading of the section, as written.
suggestions[].lineintegeryesThe 1-based line of the heading in the document that was sent. minimum 1.
suggestions[].kindstringyesA 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[].stylestring | nullyesThe 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[].whystringyesOne sentence: what in the section points to this kind.
suggestions[].confidence"high" | "medium" | "low"yeshigh: the text names this kind of picture or its shape fits it exactly. medium: it leans toward it. low: a fallback worth considering.
suggestions[].starterstringyesA 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[].tailoredbooleanyesTrue when the starter uses names or numbers from the text; false when it is the kind's small example.
capsobjectyes
caps.hitbooleanyesTrue when a cap left something out; messages says what.
caps.messagesstring[]yes
caps.maxSectionsintegeryes
caps.maxSuggestionsintegeryes
nextstringyesThe next step in one sentence.

PlanDocumentInput

A document to read for the sections a picture would help.

FieldTypeRequiredDescription
documentstringyesThe 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.
maxSuggestionsintegernoMost 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

FieldTypeRequiredDescription
itemsOrganisation[]yesBy name, at most 100.
items[].idstringyes
items[].slugstringyes
items[].namestringyes
items[].role"owner" | "admin" | "member" | "reader"yesWhat the caller is in this organisation.
items[].createdAtintegeryesMilliseconds since the epoch.
items[].memberCountintegeryesPeople who have joined, the owner included. The same number as usage.members. minimum 0.
items[].plan"free" | "pro" | "enterprise"yesThe organisation's plan: enterprise under a contract, otherwise its owner's.
items[].contractEndsOnstring | nullyesThe 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[].usageOrganisationUsageyes
items[].usage.diagramsintegeryesminimum 0.
items[].usage.bytesintegeryesminimum 0.
items[].usage.membersintegeryesPeople who have joined, the owner included. minimum 0.
items[].usage.invitesintegeryesInvitations that can still be accepted. They count toward the member limit. minimum 0.
items[].limitsOrganisationLimitsyes
items[].limits.dailyCallsintegeryes
items[].limits.hostedDiagramsintegeryesDiagrams the organisation may hold.
items[].limits.hostedBytesintegeryesTotal bytes of diagrams the organisation may hold.
items[].limits.retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until it is deleted.
items[].limits.maxDiagramBytesintegeryes
items[].limits.stableLinksintegeryesStable links the owner may keep for their own diagrams. An organisation's diagrams have none.
items[].limits.organisationsintegeryesOrganisations an account on this plan may own.
items[].limits.orgMembersintegeryesPeople one organisation may have, the owner included and pending invitations counted.
items[].limits.orgIconsintegeryesCustom icons one organisation may keep; zero on a plan without custom icons. minimum 0.
items[].limits.driftHistoryDaysintegeryesDays the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0.
items[].limits.auditRetentionDaysintegeryesDays the organisation's audit log keeps an event; zero on a plan that records none. minimum 0.
items[].avatarOrgAvataryesThe organisation's uploaded avatar, or null when it has none and a mark made from its id stands in.
items[].avatar.versionstringyesChanges 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.animatedbooleanyesTrue when it moves, so a page can hold it still for a person who asked for less motion.
items[].keepEditablebooleanyesThe 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[].publishingOrganisationPublishingyes
items[].publishing.policy"personal" | "organisation-default" | "organisation-required"yesWhat 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"yesWhat is enforced now: the choice, except organisation-required on a plan that no longer includes it, which acts as organisation-default.
items[].publishing.hideViewLinksbooleanyesWhether hosted answers leave view links out for members and the organisation's keys. Honoured only while effective is organisation-required.
items[].publishing.requiredAvailablebooleanyesWhether the organisation's plan includes organisation-required (Pro and Enterprise).

Organisation

FieldTypeRequiredDescription
idstringyes
slugstringyes
namestringyes
role"owner" | "admin" | "member" | "reader"yesWhat the caller is in this organisation.
createdAtintegeryesMilliseconds since the epoch.
memberCountintegeryesPeople who have joined, the owner included. The same number as usage.members. minimum 0.
plan"free" | "pro" | "enterprise"yesThe organisation's plan: enterprise under a contract, otherwise its owner's.
contractEndsOnstring | nullyesThe 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.
usageOrganisationUsageyes
usage.diagramsintegeryesminimum 0.
usage.bytesintegeryesminimum 0.
usage.membersintegeryesPeople who have joined, the owner included. minimum 0.
usage.invitesintegeryesInvitations that can still be accepted. They count toward the member limit. minimum 0.
limitsOrganisationLimitsyes
limits.dailyCallsintegeryes
limits.hostedDiagramsintegeryesDiagrams the organisation may hold.
limits.hostedBytesintegeryesTotal bytes of diagrams the organisation may hold.
limits.retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until it is deleted.
limits.maxDiagramBytesintegeryes
limits.stableLinksintegeryesStable links the owner may keep for their own diagrams. An organisation's diagrams have none.
limits.organisationsintegeryesOrganisations an account on this plan may own.
limits.orgMembersintegeryesPeople one organisation may have, the owner included and pending invitations counted.
limits.orgIconsintegeryesCustom icons one organisation may keep; zero on a plan without custom icons. minimum 0.
limits.driftHistoryDaysintegeryesDays the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0.
limits.auditRetentionDaysintegeryesDays the organisation's audit log keeps an event; zero on a plan that records none. minimum 0.
avatarOrgAvataryesThe organisation's uploaded avatar, or null when it has none and a mark made from its id stands in.
avatar.versionstringyesChanges 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.animatedbooleanyesTrue when it moves, so a page can hold it still for a person who asked for less motion.
keepEditablebooleanyesThe 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.
publishingOrganisationPublishingyes
publishing.policy"personal" | "organisation-default" | "organisation-required"yesWhat 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"yesWhat is enforced now: the choice, except organisation-required on a plan that no longer includes it, which acts as organisation-default.
publishing.hideViewLinksbooleanyesWhether hosted answers leave view links out for members and the organisation's keys. Honoured only while effective is organisation-required.
publishing.requiredAvailablebooleanyesWhether the organisation's plan includes organisation-required (Pro and Enterprise).

OrganisationUsage

FieldTypeRequiredDescription
diagramsintegeryesminimum 0.
bytesintegeryesminimum 0.
membersintegeryesPeople who have joined, the owner included. minimum 0.
invitesintegeryesInvitations that can still be accepted. They count toward the member limit. minimum 0.

OrganisationLimits

FieldTypeRequiredDescription
dailyCallsintegeryes
hostedDiagramsintegeryesDiagrams the organisation may hold.
hostedBytesintegeryesTotal bytes of diagrams the organisation may hold.
retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until it is deleted.
maxDiagramBytesintegeryes
stableLinksintegeryesStable links the owner may keep for their own diagrams. An organisation's diagrams have none.
organisationsintegeryesOrganisations an account on this plan may own.
orgMembersintegeryesPeople one organisation may have, the owner included and pending invitations counted.
orgIconsintegeryesCustom icons one organisation may keep; zero on a plan without custom icons. minimum 0.
driftHistoryDaysintegeryesDays the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0.
auditRetentionDaysintegeryesDays 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.

FieldTypeRequiredDescription
versionstringyesChanges 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
animatedbooleanyesTrue when it moves, so a page can hold it still for a person who asked for less motion.

OrganisationPublishing

FieldTypeRequiredDescription
policy"personal" | "organisation-default" | "organisation-required"yesWhat 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"yesWhat is enforced now: the choice, except organisation-required on a plan that no longer includes it, which acts as organisation-default.
hideViewLinksbooleanyesWhether hosted answers leave view links out for members and the organisation's keys. Honoured only while effective is organisation-required.
requiredAvailablebooleanyesWhether the organisation's plan includes organisation-required (Pro and Enterprise).

CreateOrganisationBody

FieldTypeRequiredDescription
namestringyesWhat people read. 1 to 60 characters. It can be changed; the slug cannot. at least 1 character; pattern ^[^\p{Cc}]+$/u.
slugstringnoThe 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

FieldTypeRequiredDescription
namestringyesWhat people read. 1 to 60 characters. It can be changed; the slug cannot. at least 1 character; pattern ^[^\p{Cc}]+$/u.

OrganisationMemberList

FieldTypeRequiredDescription
itemsOrganisationMember[]yes
items[].userIdstringyes
items[].emailstringyesShown to every member: a team knows who is in it.
items[].role"owner" | "admin" | "member" | "reader"yes
items[].joinedAtintegeryesMilliseconds since the epoch.

OrganisationMember

FieldTypeRequiredDescription
userIdstringyes
emailstringyesShown to every member: a team knows who is in it.
role"owner" | "admin" | "member" | "reader"yes
joinedAtintegeryesMilliseconds since the epoch.

ChangeMemberRoleBody

FieldTypeRequiredDescription
role"admin" | "member" | "reader"yesadmin, 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

FieldTypeRequiredDescription
itemsOrganisationInvite[]yes
items[].idstringyes
items[].emailstringyes
items[].role"admin" | "member" | "reader"yes
items[].createdAtintegeryesMilliseconds since the epoch.
items[].expiresAtintegeryesMilliseconds since the epoch. Seven days after it was made.

OrganisationInvite

FieldTypeRequiredDescription
idstringyes
emailstringyes
role"admin" | "member" | "reader"yes
createdAtintegeryesMilliseconds since the epoch.
expiresAtintegeryesMilliseconds since the epoch. Seven days after it was made.

CreateInviteBody

FieldTypeRequiredDescription
emailstringyesThe 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"yesadmin, 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

FieldTypeRequiredDescription
tokenstringyesThe token in the invitation link. at least 1 character; at most 200 characters.

OrganisationDiagramList

FieldTypeRequiredDescription
itemsOrganisationDiagram[]yesAt most 200, newest published first.
items[].idstringyesThe handle for the diagram in the routes below.
items[].namestring | nullyesThe label given at publish, or null.
items[].folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
items[].theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
items[].bytesintegeryesSize of the stored SVG in bytes.
items[].createdBystring | nullyesThe account that published it, or null when that account has left or an organisation key published it.
items[].createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
items[].publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
items[].expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted.
items[].viewUrlstringyesA 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[].lockedbooleanyesTrue 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[].lockedAtinteger | nullyesWhen the owner locked it, in milliseconds since the epoch, or null when it is not locked.
items[].restrictedtruenoPresent, 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.
usageOrganisationHostingUsageyes
usage.plan"free" | "pro" | "enterprise"yes
usage.countintegeryesDiagrams the organisation holds. This is the total, even when the list is shorter. minimum 0.
usage.bytesintegeryesminimum 0.
usage.limitsOrganisationLimitsyes
usage.limits.dailyCallsintegeryes
usage.limits.hostedDiagramsintegeryesDiagrams the organisation may hold.
usage.limits.hostedBytesintegeryesTotal bytes of diagrams the organisation may hold.
usage.limits.retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until it is deleted.
usage.limits.maxDiagramBytesintegeryes
usage.limits.stableLinksintegeryesStable links the owner may keep for their own diagrams. An organisation's diagrams have none.
usage.limits.organisationsintegeryesOrganisations an account on this plan may own.
usage.limits.orgMembersintegeryesPeople one organisation may have, the owner included and pending invitations counted.
usage.limits.orgIconsintegeryesCustom icons one organisation may keep; zero on a plan without custom icons. minimum 0.
usage.limits.driftHistoryDaysintegeryesDays the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0.
usage.limits.auditRetentionDaysintegeryesDays the organisation's audit log keeps an event; zero on a plan that records none. minimum 0.

OrganisationHostingUsage

FieldTypeRequiredDescription
plan"free" | "pro" | "enterprise"yes
countintegeryesDiagrams the organisation holds. This is the total, even when the list is shorter. minimum 0.
bytesintegeryesminimum 0.
limitsOrganisationLimitsyes
limits.dailyCallsintegeryes
limits.hostedDiagramsintegeryesDiagrams the organisation may hold.
limits.hostedBytesintegeryesTotal bytes of diagrams the organisation may hold.
limits.retentionDaysinteger | nullyesDays a diagram is kept after it was last published, or null to keep it until it is deleted.
limits.maxDiagramBytesintegeryes
limits.stableLinksintegeryesStable links the owner may keep for their own diagrams. An organisation's diagrams have none.
limits.organisationsintegeryesOrganisations an account on this plan may own.
limits.orgMembersintegeryesPeople one organisation may have, the owner included and pending invitations counted.
limits.orgIconsintegeryesCustom icons one organisation may keep; zero on a plan without custom icons. minimum 0.
limits.driftHistoryDaysintegeryesDays the drift dashboard keeps a run and a status after it was reported; zero on a plan without the dashboard. minimum 0.
limits.auditRetentionDaysintegeryesDays the organisation's audit log keeps an event; zero on a plan that records none. minimum 0.

PublishOrganisationDiagramBody

FieldTypeRequiredDescription
sourcestringyesDiagram source; the first line is the header, such as flow "Title" (draw_diagram lists every kind). at least 1 character; at most 50000 characters.
settingsobjectnoThe 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"noThe color scheme to draw it in: light, dark, or auto (one picture that follows the viewer's light or dark setting). default "light".
embedSourcebooleannoWrite 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.
namestringnoA 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.
folderstring | nullnoThe 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

FieldTypeRequiredDescription
folderstring | nullnoThe folder to file the diagram in, or null for the top level.
namestring | nullnoA new label, or null to clear it. at least 1 character; at most 80 characters; pattern ^[^\p{Cc}]+$/u.

EditedOrganisationDiagram

FieldTypeRequiredDescription
idstringyesThe handle for the diagram in the routes below.
namestring | nullyesThe label given at publish, or null.
folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
bytesintegeryesSize of the stored SVG in bytes.
createdBystring | nullyesThe account that published it, or null when that account has left or an organisation key published it.
createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted.
viewUrlstringyesA 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.
lockedbooleanyesTrue 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.
lockedAtinteger | nullyesWhen the owner locked it, in milliseconds since the epoch, or null when it is not locked.
restrictedtruenoPresent, 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.
warningsDiagnostic[]yesQuality 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
warnings[].messagestringyesWhat is wrong, in one sentence.
warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
warnings[].columnintegeryes1-based column in that line. minimum 1.
warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
changedbooleanyesFalse when the source draws the picture the diagram already has: nothing was stored and no version was kept.

KeepEditable

FieldTypeRequiredDescription
keepEditablebooleanyesTrue 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

FieldTypeRequiredDescription
policy"personal" | "organisation-default" | "organisation-required"yes
hideViewLinksbooleannoLeave view links out of hosted answers for members and keys. Only with organisation-required. default false.

MemberPublicDiagramList

FieldTypeRequiredDescription
itemsMemberPublicDiagram[]yesAt most 200, newest published first.
items[].idstringyesThe personal diagram's id.
items[].namestring | nullyes
items[].urlstringyesIts public link, which anyone who has it can open.
items[].createdAtintegeryes
items[].publishedAtintegeryes
items[].bytesintegeryes
items[].lockedbooleanyesWhether the member locked it. Moving and unpublishing override the member's lock.
items[].stableLinksintegeryesHow many of the member's stable links show it now. minimum 0.
items[].memberobjectyes
items[].member.userIdstringyes
items[].member.emailstringyes
totalintegeryesHow many there are, which may be more than the list holds. minimum 0.

MemberPublicDiagram

FieldTypeRequiredDescription
idstringyesThe personal diagram's id.
namestring | nullyes
urlstringyesIts public link, which anyone who has it can open.
createdAtintegeryes
publishedAtintegeryes
bytesintegeryes
lockedbooleanyesWhether the member locked it. Moving and unpublishing override the member's lock.
stableLinksintegeryesHow many of the member's stable links show it now. minimum 0.
memberobjectyes
member.userIdstringyes
member.emailstringyes

MovedMemberDiagram

FieldTypeRequiredDescription
diagramOrganisationDiagramyes
diagram.idstringyesThe handle for the diagram in the routes below.
diagram.namestring | nullyesThe label given at publish, or null.
diagram.folderstring | nullyesThe folder it is filed in, such as Payments/Checkout, or null for the top level.
diagram.theme"light" | "dark" | "auto"yesThe color scheme it was drawn in: light, dark, or auto.
diagram.bytesintegeryesSize of the stored SVG in bytes.
diagram.createdBystring | nullyesThe account that published it, or null when that account has left or an organisation key published it.
diagram.createdAtintegeryesWhen it was first published, in milliseconds since the epoch.
diagram.publishedAtintegeryesWhen it was last published, in milliseconds since the epoch. Publishing the same diagram again moves it.
diagram.expiresAtinteger | nullyesWhen it will be deleted, in milliseconds since the epoch, or null when the owner's plan keeps diagrams until they are deleted.
diagram.viewUrlstringyesA 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.lockedbooleanyesTrue 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.lockedAtinteger | nullyesWhen the owner locked it, in milliseconds since the epoch, or null when it is not locked.
diagram.restrictedtruenoPresent, 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.
mergedbooleanyesTrue when the library already held exactly this picture, so only the public copy went.

UserPublishing

FieldTypeRequiredDescription
defaultOrganizationanyyes
defaultOrganization.idstringyes
defaultOrganization.slugstringyes
defaultOrganization.namestringyes
organizationsPublishingClaim[]yesThe organisations whose Publishing setting claims the person's publishes, by name.
organizations[].idstringyes
organizations[].slugstringyes
organizations[].namestringyes
organizations[].policy"organisation-default" | "organisation-required"yesWhat it enforces: its library by default, or its library always.
organizations[].via"member" | "domain"yesmember when the person belongs to it; domain when it verified the domain of their address and they have not joined.
organizations[].canPublishbooleanyesWhether the person may publish to its library: a member who is not a reader.
targetPublishTargetyespersonal, the organisation it goes to and why, choose (several claim it and none is the default), or refused.

PublishingClaim

FieldTypeRequiredDescription
idstringyes
slugstringyes
namestringyes
policy"organisation-default" | "organisation-required"yesWhat it enforces: its library by default, or its library always.
via"member" | "domain"yesmember when the person belongs to it; domain when it verified the domain of their address and they have not joined.
canPublishbooleanyesWhether 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.

FieldTypeRequiredDescription

SetUserPublishingBody

FieldTypeRequiredDescription
defaultOrganizationstring | nullyesAn 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

FieldTypeRequiredDescription
itemsFolderRule[]yesBy folder, at most 50.
items[].folderstringyesThe restricted folder, in the form diagrams carry in their folder.
items[].roles("admin" | "member" | "reader" | "key")[]yesThe roles let in, apart from the owner, who is always allowed: admin, member, reader, and key for the organisation's own API keys.
items[].usersFolderRuleUser[]yesThe people let in by name, whatever their role.
items[].users[].userIdstringyesThe member's account id.
items[].users[].emailstringyesThe member's address, as the member list shows it.
items[].createdAtintegeryesMilliseconds since the epoch. When the rule as it now stands was set; replacing a rule sets it again.

FolderRule

FieldTypeRequiredDescription
folderstringyesThe restricted folder, in the form diagrams carry in their folder.
roles("admin" | "member" | "reader" | "key")[]yesThe roles let in, apart from the owner, who is always allowed: admin, member, reader, and key for the organisation's own API keys.
usersFolderRuleUser[]yesThe people let in by name, whatever their role.
users[].userIdstringyesThe member's account id.
users[].emailstringyesThe member's address, as the member list shows it.
createdAtintegeryesMilliseconds since the epoch. When the rule as it now stands was set; replacing a rule sets it again.

FolderRuleUser

FieldTypeRequiredDescription
userIdstringyesThe member's account id.
emailstringyesThe member's address, as the member list shows it.

SetFolderRuleBody

FieldTypeRequiredDescription
folderstringyesThe 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.
rolesstring[]yesAny of admin, member, reader, key. owner is not a choice. An empty list, with no people, lets in the owner alone.
usersstring[]yesAccount ids of current members, at most 100. A person who leaves is taken out of every rule.

OrgApiKeyList

FieldTypeRequiredDescription
itemsOrgApiKeySummary[]yes
items[].idstringyes
items[].namestringyes
items[].prefixstringyes
items[].last4stringyes
items[].createdAtintegeryesMilliseconds since the epoch.
items[].lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if never used.
items[].revealablebooleanyesTrue 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")[]yesdiagrams: 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

FieldTypeRequiredDescription
idstringyes
namestringyes
prefixstringyes
last4stringyes
createdAtintegeryesMilliseconds since the epoch.
lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if never used.
revealablebooleanyesTrue 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")[]yesdiagrams: 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

FieldTypeRequiredDescription
idstringyes
namestringyes
prefixstringyes
last4stringyes
createdAtintegeryesMilliseconds since the epoch.
lastUsedAtinteger | nullyesMilliseconds since the epoch, or null if never used.
revealablebooleanyesTrue 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.
keystringyesThe full key. When revealable is false this is the only time it is shown, so store it now.
scopes("diagrams" | "audit:read")[]yesdiagrams: 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

FieldTypeRequiredDescription
namestringyesat least 1 character; at most 60 characters; pattern \S.
scopes("diagrams" | "audit:read")[]noWhat the key may do. Left out, ["diagrams"]. A key for a SIEM takes ["audit:read"] alone.

OrgBrand

FieldTypeRequiredDescription
brandBrandColorsyesThe saved brand, or null when none is saved.
brand.primarystringyesLowercase #rrggbb.
brand.secondarystringyesLowercase #rrggbb.
brand.accentstringyesLowercase #rrggbb.
chosen("primary" | "secondary" | "accent")[]yesThe colors the person chose. The others are made from the primary.
activebooleanyesTrue when a brand is saved and the owner's plan includes brand themes, so the hosted service paints with it.
canEditbooleanyesTrue when the caller's role may save, remove and preview a brand: the owner and admins.
plan"free" | "pro" | "enterprise"yesThe organisation's plan, which is its owner's.

BrandColors

The saved brand, or null when none is saved.

FieldTypeRequiredDescription
primarystringyesLowercase #rrggbb.
secondarystringyesLowercase #rrggbb.
accentstringyesLowercase #rrggbb.

SavedBrand

FieldTypeRequiredDescription
brandanyyes
brand.primarystringyesLowercase #rrggbb.
brand.secondarystringyesLowercase #rrggbb.
brand.accentstringyesLowercase #rrggbb.
chosen("primary" | "secondary" | "accent")[]yes
checkBrandCheckyes
check.issuesBrandIssue[]yes
check.issues[].role"primary" | "secondary" | "accent"yes
check.issues[].severity"error" | "warning" | "note"yesAn 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[].messagestringyes
check.swatchesobject | nullyesThe color each scheme draws for each role, made darker or lighter where it would not keep 3:1 against the surface.
check.swatches.lightobjectyes
check.swatches.darkobjectyes

BrandCheck

FieldTypeRequiredDescription
issuesBrandIssue[]yes
issues[].role"primary" | "secondary" | "accent"yes
issues[].severity"error" | "warning" | "note"yesAn 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[].messagestringyes
swatchesobject | nullyesThe color each scheme draws for each role, made darker or lighter where it would not keep 3:1 against the surface.
swatches.lightobjectyes
swatches.light.primaryobjectyes
swatches.light.secondaryobjectyes
swatches.light.accentobjectyes
swatches.darkobjectyes
swatches.dark.primaryobjectyes
swatches.dark.secondaryobjectyes
swatches.dark.accentobjectyes

BrandIssue

FieldTypeRequiredDescription
role"primary" | "secondary" | "accent"yes
severity"error" | "warning" | "note"yesAn error stops a save. A warning and a note are advice.
code"not-a-color" | "missing-primary" | "reads-as-status" | "too-similar" | "adjusted"yes
messagestringyes

BrandBody

FieldTypeRequiredDescription
primarystring | nullnoThe 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.
secondarystring | nullnoTakes 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.
accentstring | nullnoTakes 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

FieldTypeRequiredDescription
checkBrandCheckyes
check.issuesBrandIssue[]yes
check.issues[].role"primary" | "secondary" | "accent"yes
check.issues[].severity"error" | "warning" | "note"yesAn 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[].messagestringyes
check.swatchesobject | nullyesThe color each scheme draws for each role, made darker or lighter where it would not keep 3:1 against the surface.
check.swatches.lightobjectyes
check.swatches.darkobjectyes
picturesBrandPreviewPicture[]yes
pictures[].idstringyes
pictures[].titlestringyes
pictures[].lightstringyesThe sample as an SVG in the light scheme.
pictures[].darkstringyesThe sample as an SVG in the dark scheme.

BrandPreviewPicture

FieldTypeRequiredDescription
idstringyes
titlestringyes
lightstringyesThe sample as an SVG in the light scheme.
darkstringyesThe sample as an SVG in the dark scheme.

AccountBrand

FieldTypeRequiredDescription
chosenobject | nullyesThe organisation whose brand and custom icons the account's own calls use, or null.
chosen.idstringyes
chosen.slugstringyes
chosen.namestringyes
availableobject[]yesThe organisations the account belongs to that have a saved brand or custom icons, by name.
available[].idstringyes
available[].slugstringyes
available[].namestringyes
available[].activebooleanyesTrue when the organisation has a saved brand and the owner's plan includes brand themes.
available[].iconsActivebooleanyesTrue when the organisation has custom icons and the owner's plan includes them.

ChooseBrandBody

FieldTypeRequiredDescription
organizationstring | nullyesAn 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

FieldTypeRequiredDescription
rulesStyleRules | nullyesThe saved rules as the engine read them (the format of docs/architecture/repository-settings.md), or null when none are saved.
textstring | nullyesThe saved rules as the person wrote them, or null.
activebooleanyesTrue when rules are saved and the owner's plan includes saved style rules, so CI that reads them applies them.
canEditbooleanyesTrue when the caller's role may save and remove the rules.
plan"free" | "pro" | "enterprise"yesThe organisation's plan, which is its owner's.
updatedAtinteger | nullyesWhen 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.

FieldTypeRequiredDescription
$schemastringnoat most 500 characters.
version1yes
level"error" | "warning"noerror fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error.
requireTitlebooleannoEvery diagram has a title in its header.
requireDescriptionbooleannoEvery diagram has desc= in its header, the text screen readers announce.
maxNodesintegernoThe 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")[]noKinds of diagram the team does not use.
idsobjectnoA pattern every node id must match.
ids.patternstringyesA 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")[]noOnly diagrams of these kinds; every kind when left out.
ids.hintstringnoWhat to tell the author who breaks the rule. at least 1 character; at most 300 characters.
ids.level"error" | "warning"noerror fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error.
labelsobjectnoA pattern every node label must match.
labels.patternstringyesA 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")[]noOnly diagrams of these kinds; every kind when left out.
labels.hintstringnoWhat to tell the author who breaks the rule. at least 1 character; at most 300 characters.
labels.level"error" | "warning"noerror fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error.
iconsobject[]noIcons required by label.
icons[].labelstringyesMatched against each node label with case ignored, such as postgres|mysql. at least 1 character; at most 200 characters.
icons[].usestring[]yes
icons[].kinds("flow" | "sequence" | "schema" | "git" | "gantt" | "class" | "state" | "timeline" | "journey" | "mindmap" | "treemap" | "pie" | "quadrant" | "layers" | "c4" | "matrix" | "sankey" | "xychart" | "tree" | "swimlane")[]noOnly diagrams of these kinds; every kind when left out.
icons[].hintstringnoWhat to tell the author who breaks the rule. at least 1 character; at most 300 characters.
icons[].level"error" | "warning"noerror fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error.
tonesobject[]noTones allowed or forbidden, by node type.
tones[].typesstring[]noOnly 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")[]noOnly diagrams of these kinds; every kind when left out.
tones[].hintstringnoWhat to tell the author who breaks the rule. at least 1 character; at most 300 characters.
tones[].level"error" | "warning"noerror fails a check; warning is reported and passes. Defaults to the file's level, which defaults to error.

StyleRulesBody

FieldTypeRequiredDescription
textstringyesThe 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

FieldTypeRequiredDescription
iconsOrgIcon[]yes
icons[].namestringyes
icons[].refstringyesWhat a diagram writes to use it.
icons[].aliasesstring[]yes
icons[].mediaType"image/svg+xml" | "image/png"yes
icons[].imagestringyesThe checked picture as a data: address, for a preview.
icons[].widthnumberyes
icons[].heightnumberyes
icons[].bytesintegeryes
icons[].updatedAtintegeryesMilliseconds since the epoch.
activebooleanyesTrue when the owner's plan includes custom icons, so the hosted service draws them.
canEditbooleanyesTrue when the caller's role may upload, replace and delete icons.
plan"free" | "pro" | "enterprise"yes
limitintegeryesHow many icons the plan lets the organisation keep.

OrgIcon

FieldTypeRequiredDescription
namestringyes
refstringyesWhat a diagram writes to use it.
aliasesstring[]yes
mediaType"image/svg+xml" | "image/png"yes
imagestringyesThe checked picture as a data: address, for a preview.
widthnumberyes
heightnumberyes
bytesintegeryes
updatedAtintegeryesMilliseconds since the epoch.

SavedIcon

FieldTypeRequiredDescription
iconOrgIconyes
icon.namestringyes
icon.refstringyesWhat a diagram writes to use it.
icon.aliasesstring[]yes
icon.mediaType"image/svg+xml" | "image/png"yes
icon.imagestringyesThe checked picture as a data: address, for a preview.
icon.widthnumberyes
icon.heightnumberyes
icon.bytesintegeryes
icon.updatedAtintegeryesMilliseconds since the epoch.
removedstring[]yesWhat 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.

FieldTypeRequiredDescription
svgstringnoThe SVG file's text, at most 32 KB. It is rewritten from an allowlist before it is stored. at most 49152 characters.
pngstringnoThe PNG file's bytes in base64, at most 32 KB and 1024 pixels on a side. at most 49152 characters.
aliasesstring[]noOther names search and automatic matching find the icon by, at most 10. Left out, the icon has none.

IconPreview

FieldTypeRequiredDescription
refstringyesWhat a diagram writes to use the icon.
sourcestringyesThe diagram source the preview draws, which uses the icon on one box.
lightstringyesThe preview drawn on light, as SVG text.
darkstringyesThe preview drawn on dark, as SVG text.

SavedAvatar

FieldTypeRequiredDescription
avatarOrgAvataryesThe organisation's uploaded avatar, or null when it has none and a mark made from its id stands in.
avatar.versionstringyesChanges 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.animatedbooleanyesTrue when it moves, so a page can hold it still for a person who asked for less motion.
removedstring[]yesWhat the check left out of the file because it draws nothing, such as editor metadata, EXIF or XMP.

AvatarBody

One file: svg, or image.

FieldTypeRequiredDescription
svgstringnoThe 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.
imagestringnoA 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

FieldTypeRequiredDescription
organizationobjectyesThe organisation the run was stored for. With _ in the path, this says which one the key belongs to.
organization.idstringyes
organization.slugstringyes
repositorystringyesThe repository, as sent.
sourcesintegeryesSources stored. minimum 0.
driftedintegeryesSources that drifted. minimum 0.
dashboardUrlstringyesThe organisation's drift dashboard in the portal, for a signed-in member.

DriftRunBody

FieldTypeRequiredDescription
repositorystringyesThe 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}$.
refstring | nullyesThe git ref the run checked, or null. at least 1 character; at most 255 characters; pattern ^[^\p{Cc}]+$/u.
shastring | nullyesThe commit the run checked, or null. pattern ^[0-9a-fA-F]{7,64}$.
eventstring | nullyesThe event that started the run, or null. at least 1 character; at most 64 characters; pattern ^[a-z][a-z0-9_]*$.
runUrlstring | nullyesThe run on GitHub. An https address of at most 500 characters, or null. at most 500 characters.
pullRequestUrlstring | nullyesThe pull request the run opened or checked. An https address of at most 500 characters, or null. at most 500 characters.
sourcesDriftSourceBody[]yesEvery source the run checked, at most 250. A source of the repository that a run leaves out is removed from the dashboard.
sources[].namestringyesThe 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[].outstringyesThe 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"yesWhat 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[].addedintegeryesItems in the files that the diagram does not have. minimum 0; maximum 1000000.
sources[].removedintegeryesItems in the diagram that the files no longer have. minimum 0; maximum 1000000.
sources[].changedintegeryesItems both have that differ. minimum 0; maximum 1000000.
sources[].errorsintegeryesErrors the run met making this diagram. minimum 0; maximum 1000000.
sources[].ownersstring[]yesThe owners CODEOWNERS gives the diagram's path, as it writes them: at most 20, each @user, @org/team or an email address.

DriftSourceBody

FieldTypeRequiredDescription
namestringyesThe 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.
outstringyesThe 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"yesWhat the check found: the diagram matches its files (in-step), differs (drifted), was written by the run (written), or could not be made (failed).
addedintegeryesItems in the files that the diagram does not have. minimum 0; maximum 1000000.
removedintegeryesItems in the diagram that the files no longer have. minimum 0; maximum 1000000.
changedintegeryesItems both have that differ. minimum 0; maximum 1000000.
errorsintegeryesErrors the run met making this diagram. minimum 0; maximum 1000000.
ownersstring[]yesThe owners CODEOWNERS gives the diagram's path, as it writes them: at most 20, each @user, @org/team or an email address.

OrgDrift

FieldTypeRequiredDescription
activebooleanyesTrue when the owner's plan includes the drift dashboard. When false the lists are empty and run reports are refused.
plan"free" | "pro" | "enterprise"yesThe organisation's plan, which is its owner's.
retentionDaysintegeryesDays 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.
repositoriesDriftRepository[]yesEvery repository with a stored status, by name.
repositories[].repositorystringyes
repositories[].sourcesintegeryesminimum 0.
repositories[].inStepintegeryesminimum 0.
repositories[].driftedintegeryesminimum 0.
repositories[].writtenintegeryesminimum 0.
repositories[].failedintegeryesminimum 0.
repositories[].refstring | nullyes
repositories[].shastring | nullyes
repositories[].runUrlstring | nullyesThe run on GitHub, or null.
repositories[].pullRequestUrlstring | nullyesThe pull request, or null.
repositories[].checkedAtintegeryesWhen the run was reported, in milliseconds since the epoch.
sourcesDriftSource[]yesThe latest status of every source: failed first, then drifted, written and in step, each by repository and name.
sources[].repositorystringyes
sources[].namestringyes
sources[].outstringyes
sources[].status"in-step" | "drifted" | "written" | "failed"yes
sources[].addedintegeryesminimum 0.
sources[].removedintegeryesminimum 0.
sources[].changedintegeryesminimum 0.
sources[].errorsintegeryesminimum 0.
sources[].ownersstring[]yesThe owners CODEOWNERS gave the path, as written there.
sources[].refstring | nullyes
sources[].shastring | nullyes
sources[].runUrlstring | nullyesThe run on GitHub, or null.
sources[].pullRequestUrlstring | nullyesThe pull request, or null.
sources[].checkedAtintegeryesWhen the run was reported, in milliseconds since the epoch.
truncatedbooleanyesTrue when there were more sources than one answer carries.
runsDriftRun[]yesThe latest runs, newest first.
runs[].idstringyes
runs[].repositorystringyes
runs[].eventstring | nullyes
runs[].sourcesintegeryesminimum 0.
runs[].driftedintegeryesminimum 0.
runs[].failedintegeryesminimum 0.
runs[].errorsintegeryesminimum 0.
runs[].refstring | nullyes
runs[].shastring | nullyes
runs[].runUrlstring | nullyesThe run on GitHub, or null.
runs[].pullRequestUrlstring | nullyesThe pull request, or null.
runs[].checkedAtintegeryesWhen the run was reported, in milliseconds since the epoch.

DriftRepository

FieldTypeRequiredDescription
repositorystringyes
sourcesintegeryesminimum 0.
inStepintegeryesminimum 0.
driftedintegeryesminimum 0.
writtenintegeryesminimum 0.
failedintegeryesminimum 0.
refstring | nullyes
shastring | nullyes
runUrlstring | nullyesThe run on GitHub, or null.
pullRequestUrlstring | nullyesThe pull request, or null.
checkedAtintegeryesWhen the run was reported, in milliseconds since the epoch.

DriftSource

FieldTypeRequiredDescription
repositorystringyes
namestringyes
outstringyes
status"in-step" | "drifted" | "written" | "failed"yes
addedintegeryesminimum 0.
removedintegeryesminimum 0.
changedintegeryesminimum 0.
errorsintegeryesminimum 0.
ownersstring[]yesThe owners CODEOWNERS gave the path, as written there.
refstring | nullyes
shastring | nullyes
runUrlstring | nullyesThe run on GitHub, or null.
pullRequestUrlstring | nullyesThe pull request, or null.
checkedAtintegeryesWhen the run was reported, in milliseconds since the epoch.

DriftRun

FieldTypeRequiredDescription
idstringyes
repositorystringyes
eventstring | nullyes
sourcesintegeryesminimum 0.
driftedintegeryesminimum 0.
failedintegeryesminimum 0.
errorsintegeryesminimum 0.
refstring | nullyes
shastring | nullyes
runUrlstring | nullyesThe run on GitHub, or null.
pullRequestUrlstring | nullyesThe pull request, or null.
checkedAtintegeryesWhen the run was reported, in milliseconds since the epoch.

OrgAuditPage

FieldTypeRequiredDescription
itemsOrgAuditEvent[]yes
items[].version1yesThe version of this shape. A change that is not only an addition gets a new number.
items[].idstringyes
items[].orgIdstringyes
items[].atstringyesWhen 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"yesWhat happened. Never reused for another meaning.
items[].actorobjectyes
items[].actor.kind"user" | "key" | "ci" | "operator"yes
items[].actor.idstring | nullyesThe account id (user), the key id (key, ci), or null (operator).
items[].actor.namestring | nullyesThe address or key name when it was recorded, "Plotwork support" for the operator, null once a deleted account is forgotten.
items[].targetobjectyes
items[].target.type"org" | "member" | "invite" | "key" | "diagram" | "folder" | "brand" | "icon" | "avatar" | "style_rules" | "settings" | "drift" | "contract" | "sso" | nullyes
items[].target.idstring | nullyes
items[].target.namestring | nullyesA member's address, an invited address, a key's, a diagram's or an icon's name, or a folder.
items[].metadataobjectyesA few facts about the event, such as role or keepEditable. Never a diagram source, a key, a token or a color.
items[].ipstring | nullyesThe network the request came from: the IPv4 /24 or the IPv6 /48, never the full address.
items[].userAgentstring | nullyesThe first 200 characters of the user agent.
items[].requestIdstring | nullyesThe request id, which Plotwork support can look up in the API's logs.
nextCursorstring | nullyesSend as cursor for the next, older page; null on the last.
retentionDaysintegeryesHow many days the organisation's plan keeps an event.
canExportbooleanyesWhether the organisation's plan may export the log.

OrgAuditEvent

FieldTypeRequiredDescription
version1yesThe version of this shape. A change that is not only an addition gets a new number.
idstringyes
orgIdstringyes
atstringyesWhen 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"yesWhat happened. Never reused for another meaning.
actorobjectyes
actor.kind"user" | "key" | "ci" | "operator"yes
actor.idstring | nullyesThe account id (user), the key id (key, ci), or null (operator).
actor.namestring | nullyesThe address or key name when it was recorded, "Plotwork support" for the operator, null once a deleted account is forgotten.
targetobjectyes
target.type"org" | "member" | "invite" | "key" | "diagram" | "folder" | "brand" | "icon" | "avatar" | "style_rules" | "settings" | "drift" | "contract" | "sso" | nullyes
target.idstring | nullyes
target.namestring | nullyesA member's address, an invited address, a key's, a diagram's or an icon's name, or a folder.
metadataobjectyesA few facts about the event, such as role or keepEditable. Never a diagram source, a key, a token or a color.
ipstring | nullyesThe network the request came from: the IPv4 /24 or the IPv6 /48, never the full address.
userAgentstring | nullyesThe first 200 characters of the user agent.
requestIdstring | nullyesThe request id, which Plotwork support can look up in the API's logs.

SsoSettings

FieldTypeRequiredDescription
availablebooleanyesWhether the organisation's plan has single sign-on (Enterprise).
plan"free" | "pro" | "enterprise"yes
redirectUristringyesThe redirect URI to register at the identity provider.
samlSamlServiceProvideryes
saml.entityIdstringyesOur entity id for this organisation: the audience to set at the provider.
saml.acsUrlstringyesOur assertion consumer service for this organisation: the single sign-on URL to set at the provider.
saml.metadataUrlstringyesOur service provider metadata, for a provider that imports it.
samlAvailablebooleanyesWhether this server can check SAML responses.
connectionSsoConnectionyes
connection.protocol"oidc" | "saml"yesOpenID Connect or SAML 2.0. One connection, one protocol.
connection.issuerstringyesThe OpenID Connect issuer, or the SAML provider's entity id.
connection.clientIdstring | nullyesOpenID Connect only.
connection.secretSetbooleanyesTrue when an OpenID Connect client secret is stored. It is never returned. Always false for SAML.
connection.tokenAuthMethod"client_secret_basic" | "client_secret_post" | nullyes
connection.samlSamlConnectionyesSAML only.
connection.saml.entityIdstringyesThe provider's entity id, which every Issuer must equal.
connection.saml.ssoUrlstringyesThe provider's sign-in service on the redirect binding.
connection.saml.certificatesobject[]yes
connection.saml.emailAttributestring | nullyesThe attribute that carries the address, or null when the name identifier does.
connection.saml.metadataUrlstring | nullyesWhere the metadata was fetched from, or null when it was pasted.
connection.enabledbooleanyes
connection.requireSsobooleanyes
connection.jitbooleanyes
connection.jitRole"member" | "reader"yes
connection.updatedAtintegeryes
domainsSsoDomain[]yes
domains[].idstringyes
domains[].domainstringyes
domains[].verifiedbooleanyes
domains[].verifiedAtinteger | nullyes
domains[].checkedAtinteger | nullyes
domains[].createdAtintegeryes
domains[].recordobjectyes
domains[].record.namestringyes
domains[].record.type"TXT"yes
domains[].record.valuestringyes

SamlServiceProvider

FieldTypeRequiredDescription
entityIdstringyesOur entity id for this organisation: the audience to set at the provider.
acsUrlstringyesOur assertion consumer service for this organisation: the single sign-on URL to set at the provider.
metadataUrlstringyesOur service provider metadata, for a provider that imports it.

SsoConnection

FieldTypeRequiredDescription
protocol"oidc" | "saml"yesOpenID Connect or SAML 2.0. One connection, one protocol.
issuerstringyesThe OpenID Connect issuer, or the SAML provider's entity id.
clientIdstring | nullyesOpenID Connect only.
secretSetbooleanyesTrue when an OpenID Connect client secret is stored. It is never returned. Always false for SAML.
tokenAuthMethod"client_secret_basic" | "client_secret_post" | nullyes
samlSamlConnectionyesSAML only.
saml.entityIdstringyesThe provider's entity id, which every Issuer must equal.
saml.ssoUrlstringyesThe provider's sign-in service on the redirect binding.
saml.certificatesobject[]yes
saml.certificates[].fingerprintstringyesSHA-256 of the certificate, as providers show it.
saml.certificates[].notAfterintegeryesWhen the certificate expires, in milliseconds since the epoch. Shown, not enforced.
saml.emailAttributestring | nullyesThe attribute that carries the address, or null when the name identifier does.
saml.metadataUrlstring | nullyesWhere the metadata was fetched from, or null when it was pasted.
enabledbooleanyes
requireSsobooleanyes
jitbooleanyes
jitRole"member" | "reader"yes
updatedAtintegeryes

SamlConnection

SAML only.

FieldTypeRequiredDescription
entityIdstringyesThe provider's entity id, which every Issuer must equal.
ssoUrlstringyesThe provider's sign-in service on the redirect binding.
certificatesobject[]yes
certificates[].fingerprintstringyesSHA-256 of the certificate, as providers show it.
certificates[].notAfterintegeryesWhen the certificate expires, in milliseconds since the epoch. Shown, not enforced.
emailAttributestring | nullyesThe attribute that carries the address, or null when the name identifier does.
metadataUrlstring | nullyesWhere the metadata was fetched from, or null when it was pasted.

SsoDomain

FieldTypeRequiredDescription
idstringyes
domainstringyes
verifiedbooleanyes
verifiedAtinteger | nullyes
checkedAtinteger | nullyes
createdAtintegeryes
recordobjectyes
record.namestringyes
record.type"TXT"yes
record.valuestringyes

SsoConnectionBody

FieldTypeRequiredDescription
issuerstringyesThe issuer URL of your own tenant. at least 9 characters; at most 300 characters.
clientIdstringyesat least 1 character; at most 255 characters.
clientSecretstringnoRequired the first time. Left out later, the stored one is kept. Never returned. at least 1 character; at most 1000 characters.

SsoSwitchesBody

FieldTypeRequiredDescription
enabledbooleanno
requireSsobooleanno
jitbooleanno
jitRole"member" | "reader"no

SamlConnectionBody

FieldTypeRequiredDescription
metadataUrlstringnoThe 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.
metadataXmlstringnoThe provider's metadata XML, pasted. at least 1 character; at most 262144 characters.
emailAttributestring | nullnoThe 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

FieldTypeRequiredDescription
domainstringyesat least 3 characters; at most 253 characters.

SsoDomainVerify

FieldTypeRequiredDescription
domainSsoDomainyes
domain.idstringyes
domain.domainstringyes
domain.verifiedbooleanyes
domain.verifiedAtinteger | nullyes
domain.checkedAtinteger | nullyes
domain.createdAtintegeryes
domain.recordobjectyes
domain.record.namestringyes
domain.record.type"TXT"yes
domain.record.valuestringyes
checkedbooleanyesFalse when the resolver did not answer, so nothing was learned. Try again.

ScimSettings

FieldTypeRequiredDescription
availablebooleanyesWhether the organisation's plan includes SCIM (Enterprise).
baseUrlstringyesThe SCIM base URL to give the identity provider.
tokenScimTokenViewyes
token.prefixstringyesThe first characters of the token, to tell it apart.
token.createdAtintegeryes
token.lastUsedAtinteger | nullyesWhen the provider last used it, to the minute. Null until it has.
usersintegeryesHow many people the provider manages here, active or not.
groupsScimGroupView[]yes
groups[].idstringyes
groups[].displayNamestringyes
groups[].role"admin" | "member" | "reader" | nullyesThe role the group gives its members, or null when it gives none.
groups[].membersintegeryes

ScimTokenView

FieldTypeRequiredDescription
prefixstringyesThe first characters of the token, to tell it apart.
createdAtintegeryes
lastUsedAtinteger | nullyesWhen the provider last used it, to the minute. Null until it has.

ScimGroupView

FieldTypeRequiredDescription
idstringyes
displayNamestringyes
role"admin" | "member" | "reader" | nullyesThe role the group gives its members, or null when it gives none.
membersintegeryes

ScimTokenIssued

FieldTypeRequiredDescription
tokenstringyesThe bearer token for the identity provider. Shown once; only its hash is kept.
viewScimTokenViewyes
view.prefixstringyesThe first characters of the token, to tell it apart.
view.createdAtintegeryes
view.lastUsedAtinteger | nullyesWhen the provider last used it, to the minute. Null until it has.

ScimGroupRoleBody

FieldTypeRequiredDescription
role"admin" | "member" | "reader" | nullyes

SupportSettings

FieldTypeRequiredDescription
availablebooleanyesTrue when the organisation's plan includes priority support (Enterprise).
planstringyesThe organisation's plan.
contactobject | nullyesThe named contact, or null when none is named yet. A request still reaches Plotwork support.
contact.namestringyes
contact.emailstringyes
firstResponseHoursinteger | nullyesThe first response target, in business hours, or null when the contract names none.
hoursstring | nullyesWhen support is staffed, as the contract says it, or null.
uptimeSlabooleanyesTrue when the plan includes an uptime SLA.
contractobject | nullyesThe dates of the contract: for the owner and the admins only, and null for everyone else or a contract set without dates.
contract.startsOnstringyesThe first day of the contract, YYYY-MM-DD (UTC).
contract.endsOnstringyesThe last day of the contract, YYYY-MM-DD (UTC).
contract.autoRenewbooleanyesWhether the contract renews by itself at the end.
contract.noticeDaysintegeryesThe notice either side gives before the end, in days.

SupportAck

FieldTypeRequiredDescription
receivedtrueyes
contactNamestring | nullyesThe name of the contact who will answer, or null when none is named.
firstResponseHoursinteger | nullyesThe first response target, in business hours, or null.

SupportRequestBody

FieldTypeRequiredDescription
subjectstringyesOne line on what it is about. 1 to 160 characters. at least 1 character; at most 160 characters.
messagestringyesWhat 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"yesquestion 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.

FieldTypeRequiredDescription
querystringyesThe query that was searched.
matchesobject[]yesUp to the limit, best match first. Empty when nothing fits.
matches[].idstringyesThe pattern id, as find_pattern returns it, such as three-tier-network. at least 1 character; at most 60 characters.
matches[].titlestringyes
matches[].summarystringyesOne sentence: what the diagram shows.
matches[].kindstringyesA 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[].tagsstring[]yes
matches[].providers("neutral" | "aws" | "azure" | "gcp")[]yesThe flavours the pattern comes in.
matches[].scorenumberyesHow well it matches; only the order of the results is meaningful.
nextstringyesThe next step in one sentence.

FindPatternInput

Words that describe the architecture wanted, and optional filters.

FieldTypeRequiredDescription
querystringyesThe architecture wanted, in plain words, such as "three tier network". at least 1 character; at most 200 characters.
provider"neutral" | "aws" | "azure" | "gcp"noOnly patterns that come in this flavour: neutral, aws, azure, or gcp.
tagsstring[]noTags 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"noOnly 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.
limitintegernoMost results to return, up to 5. minimum 1; maximum 5; default 5.

GetPatternResponse

A pattern filled for one flavour, with its slots and advice.

FieldTypeRequiredDescription
foundbooleanyesTrue when the pattern and flavour exist and the slot values are usable. When false, problems says why and nothing else is filled.
idstringyesThe pattern id that was asked for.
titlestring | nullyes
patternSummarystring | nullyesOne sentence: what the pattern shows.
whenToUsestring | nullyes
kindstring | nullyesA 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" | nullyesThe flavour that was filled.
flavours("neutral" | "aws" | "azure" | "gcp")[]yesEvery flavour this pattern comes in; empty when the pattern was not found.
sourcestring | nullyesPlotwork source, valid and ready to use; null when not found.
slotsobject[]yesEvery slot the source uses, with the value it has.
slots[].idstringyesThe slot id; the key to use in slots.
slots[].valuestringyesThe text the slot has in the source: the value sent, or the default.
slots[].defaultstringyesThe default text.
slots[].meaningstringyesWhat belongs in this slot.
slots[].isDefaultbooleanyesTrue when the slot kept its default.
notesobject | nullyesHow to adapt the pattern: what to keep, what to rename, and when to split.
notes.keepstringyesWhat to leave exactly as it is.
notes.renamestringyesWhat to rename or replace, and how.
notes.splitstringyesWhen the diagram has grown too big, and where to cut it.
problemsobject[]yesMistakes 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[].messagestringyes
problems[].hintstringyesHow to fix it.
treeobject[]yesThe groups, overlays, and nodes as drawn, depth first, so you can see what to rename.
tree[].depthintegeryesHow deep the item sits: 0 for the top level.
tree[].kind"group" | "overlay" | "node" | "actor" | "table"yes
tree[].idstringyesThe id written in the source.
tree[].labelstringyes
tree[].typestring | nullyesThe group type, node type, or actor type; null for a table or an untyped group.
outlinestring[]yesThe text description of the diagram.
nextstringyesThe next step in one sentence.

GetPatternInput

A pattern id, the flavour to draw, and the slot values to use.

FieldTypeRequiredDescription
idstringyesThe 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"noneutral (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".
slotsobjectnoSlot 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.

FieldTypeRequiredDescription
foundbooleanyesTrue when the pattern and flavour exist and the slot values are usable. When false, problems says why and nothing else is filled.
idstringyesThe pattern id that was asked for.
titlestring | nullyes
patternSummarystring | nullyesOne sentence: what the pattern shows.
whenToUsestring | nullyes
kindstring | nullyesA 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" | nullyesThe flavour that was filled.
flavours("neutral" | "aws" | "azure" | "gcp")[]yesEvery flavour this pattern comes in; empty when the pattern was not found.
sourcestring | nullyesPlotwork source, valid and ready to use; null when not found.
slotsobject[]yesEvery slot the source uses, with the value it has.
slots[].idstringyesThe slot id; the key to use in slots.
slots[].valuestringyesThe text the slot has in the source: the value sent, or the default.
slots[].defaultstringyesThe default text.
slots[].meaningstringyesWhat belongs in this slot.
slots[].isDefaultbooleanyesTrue when the slot kept its default.
notesobject | nullyesHow to adapt the pattern: what to keep, what to rename, and when to split.
notes.keepstringyesWhat to leave exactly as it is.
notes.renamestringyesWhat to rename or replace, and how.
notes.splitstringyesWhen the diagram has grown too big, and where to cut it.
problemsobject[]yesMistakes 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[].messagestringyes
problems[].hintstringyesHow to fix it.
validbooleanyesTrue when the source has no errors. When false, nothing was drawn: fix the errors and call again.
errorsDiagnostic[]yesEvery 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
errors[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
errors[].messagestringyesWhat is wrong, in one sentence.
errors[].lineintegeryes1-based line in the submitted source. minimum 1.
errors[].columnintegeryes1-based column in that line. minimum 1.
errors[].lengthintegeryesNumber of characters the problem covers. minimum 1.
errors[].hintstring | nullyesA concrete suggestion for fixing it, or null.
warningsDiagnostic[]yesQuality 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"yesStable code to branch on; E-codes are errors, W-codes are warnings.
warnings[].severity"error" | "warning"yesErrors stop rendering; warnings never do.
warnings[].messagestringyesWhat is wrong, in one sentence.
warnings[].lineintegeryes1-based line in the submitted source. minimum 1.
warnings[].columnintegeryes1-based column in that line. minimum 1.
warnings[].lengthintegeryesNumber of characters the problem covers. minimum 1.
warnings[].hintstring | nullyesA concrete suggestion for fixing it, or null.
summarystring | nullyesOne-line description of the diagram, usable as alt text; null when invalid.
outlinestring[]yesThe diagram as plain text in reading order, to check it says what you meant; empty when invalid.
outlineTruncatedbooleanyesTrue when the summary level cut the outline short. Call again with detail "full" to read all of it.
sizeobject | nullyesNatural size of the laid-out diagram; null when invalid.
size.widthintegeryesWidth in px. minimum 1.
size.heightintegeryesHeight in px. minimum 1.
qualityobjectnoHow clean the picture looks (score, grade, measures) and up to three changes that would help; read it instead of looking. Absent when invalid.
quality.scoreintegeryes0 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"yesclean is 85 or more, fair 60 or more, cluttered below.
quality.measuresobjectyesWhat 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.hintsstring[]yesUp to three changes, the one worth most first, each naming the statement or option to edit.
quality.linestringyesThe grade, the score, and the first hint in one line.
noticesNote[]noInformation notes, such as an icon alias drawn as the real icon; absent when there is none.
notices[].codestringyesA stable code, such as I122 for an icon alias.
notices[].severity"info"yesA note never stops a drawing and is not a warning.
notices[].messagestringyes
notices[].lineintegeryesminimum 1.
notices[].columnintegeryesminimum 1.
notices[].lengthintegeryesminimum 1.
notices[].hintstring | nullyesThe text to write instead.
rendersobject[]yesOne 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"yesThe color scheme this picture is drawn in.
renders[].svgstringyesSelf-contained SVG markup with an accessible title and description.
renders[].sizeSizeyesNatural size of a rendered diagram in px.
renders[].size.widthintegeryesWidth in px. minimum 1.
renders[].size.heightintegeryesHeight in px. minimum 1.
picturesOmittedobjectnoPresent 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")[]yesThe color schemes whose pictures were left out.
picturesOmitted.charactersintegeryesHow many characters the pictures left out came to.
picturesOmitted.limitintegeryesThe most characters one answer may hold before the pictures are left out.
picturesOmitted.whystringyesWhy they were left out, and what to do.
viewUrlstringnoA 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.
pngUrlstringnoThe 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.
svgUrlstringnoThe viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long.
saveCommandstringnoRun 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.
nextstringyesThe next step in one sentence.

DrawFromPatternInput

A pattern id, the flavour and slot values to use, and what to return.

FieldTypeRequiredDescription
idstringyesThe 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"noneutral (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".
slotsobjectnoSlot 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"nolight, dark, or both (the default): the light picture and the dark one a dark page needs. default "both".
detail"summary" | "full"nosummary (the default), or full: the whole outline, and the source embedded in each SVG. default "summary".
svg"auto" | "always" | "never"noauto (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".
embedSourcebooleannoWrite 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.
settingsobjectnoThe repo's plotwork.config.json, if any. Schema: https://docs.plotwork.dev/schemas/plotwork.config.json (opens in a new tab).

LocalUsageAck

FieldTypeRequiredDescription
acceptedintegeryesHow many counts were stored. A count sent again replaces the one stored, so a retry never adds twice. minimum 0.
ignoredintegeryesHow 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

FieldTypeRequiredDescription
schema1yesThe version of this request shape. Always 1.
clientLocalUsageClientyes
client.name"plotwork-mcp"yesAlways plotwork-mcp.
client.versionstringyesThe 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"yesThe operating system family. Anything else is other.
client.nodeintegeryesThe Node major version, a whole number. minimum 18; maximum 99.
daysLocalUsageDay[]yesAt most 31 finished days.
days[].daystringyesA UTC date from 40 days ago to yesterday. Nothing is accepted for today. pattern ^\d{4}-\d{2}-\d{2}$.
days[].idstringyesA 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[].countsLocalUsageCount[]yesAt most 400 counts. A tool, kind, and outcome may appear once a day.
days[].counts[].toolstringyesThe 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[].kindstringyesThe 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"yesok produced its answer, rejected was refused because of its input, error failed inside the tool.
days[].counts[].countintegeryesA whole number from 1 to 1,000,000. minimum 1; maximum 1000000.

LocalUsageClient

FieldTypeRequiredDescription
name"plotwork-mcp"yesAlways plotwork-mcp.
versionstringyesThe 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"yesThe operating system family. Anything else is other.
nodeintegeryesThe Node major version, a whole number. minimum 18; maximum 99.

LocalUsageDay

FieldTypeRequiredDescription
daystringyesA UTC date from 40 days ago to yesterday. Nothing is accepted for today. pattern ^\d{4}-\d{2}-\d{2}$.
idstringyesA 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}$.
countsLocalUsageCount[]yesAt most 400 counts. A tool, kind, and outcome may appear once a day.
counts[].toolstringyesThe 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[].kindstringyesThe 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"yesok produced its answer, rejected was refused because of its input, error failed inside the tool.
counts[].countintegeryesA whole number from 1 to 1,000,000. minimum 1; maximum 1000000.

LocalUsageCount

FieldTypeRequiredDescription
toolstringyesThe 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}$.
kindstringyesThe 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"yesok produced its answer, rejected was refused because of its input, error failed inside the tool.
countintegeryesA 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.

FieldTypeRequiredDescription
answerstringyesWhat 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).
howToGetAKindstringyesIn plain words: what this answer holds and how to get the rest.
kindsstring[]yesHeader keywords: the first line names the kind.
kindDetailsobject[]yesThe 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[].kindstringyesA 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[].headerstringyesThe header line, such as flow "Title".
kindDetails[].nounstringyesWhat the kind's diagrams are called in a sentence, such as flow or database schema.
kindDetails[].summarystringyesOne sentence: what the kind draws.
kindDetails[].statementsobject[]noThe statements the kind adds to the header. Empty for a kind whose language the shared tables of this reference already describe.
kindDetails[].statements[].syntaxstringyesThe statement with its parts named, such as: task "Name" days=.
kindDetails[].statements[].meaningstringyesWhat the statement does, and what it needs.
kindDetails[].statements[].examplestringyesOne line that parses.
kindDetails[].limitsobject[]noThe quality thresholds the kind adds. Empty for a kind whose limits are in the limits table of this reference.
kindDetails[].limits[].namestringyesWhat is counted, such as tasks.
kindDetails[].limits[].valueintegeryesMore than this in one diagram draws a quality warning.
kindDetails[].limits[].meaningstringyesWhy the limit exists and what to do past it.
kindDetails[].morestringnoOnly 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.
nodeTypesobject[]no
nodeTypes[].type"person" | "agent" | "client" | "service" | "gateway" | "function" | "database" | "cache" | "queue" | "storage" | "identity" | "secret" | "external" | "step" | "decision" | "terminal"yes
nodeTypes[].shape"card" | "pill"yesHow the node is drawn.
nodeTypes[].isTintedbooleanyesTrue when the card is filled and outlined in its tone, as for decisions.
nodeTypes[].defaultTone"neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red"yesColor family used when tone= is not set.
nodeTypes[].defaultIconstring | nullyesIcon used when icon= is not set, or null for none.
nodeTypes[].isDashedbooleanyesTrue when the outline is dashed, as for external systems.
nodeTypes[].usableAsActorbooleanyesTrue 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")[]noValues for direction= on a flow header.
arrowsobject[]no
arrows[].tokenstringyesThe arrow as written in source.
arrows[].line"solid" | "dashed" | "dotted"yesHow the line is drawn.
arrows[].heads"end" | "both" | "none"yesWhich ends carry an arrowhead.
arrows[].meaningstringyesWhat the arrow says, so the right one is chosen.
blockTypes("alt" | "opt" | "loop" | "par")[]noFrames a sequence diagram can wrap around messages.
columnFlags("pk" | "fk" | "unique" | "nullable")[]noFlags a schema column row may carry.
themes("light" | "dark")[]no
iconSets("lucide" | "simple" | "status" | "aws" | "gcp" | "azure" | "alibaba" | "oci" | "ibm" | "cloudflare" | "digitalocean" | "vercel")[]no
iconCountintegernoNumber of bundled icons; use search_icons to find names.
iconProvidersobject[]noCloud 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"yesIcon set prefix, as in aws:lambda.
iconProviders[].titlestringyesThe provider the set stands for.
iconProviders[].iconCountintegeryesIcons in the set: the provider itself (set:cloud) and its products.
iconProviders[].examplestringyesOne icon of the set that is bundled, for example aws:lambda.
overlayobjectnoA dashed frame around members that may sit in different groups; it owns none of them.
overlay.optionsstring[]yesOptions an overlay statement takes after its name, as in: overlay id "Name" members=a,b type=scale-group.
overlay.frame"solid" | "dashed" | "dotted"yesHow an overlay is always drawn.
overlay.meaningstringyesWhat an overlay is for, so it is used where a group would be wrong.
groupobjectnoHow a flow group looks and what it accepts; its corner tab shows its icon and name.
group.optionsstring[]yesOptions 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"yesColor family of a group with no type when tone= is not set.
group.exampleobjectyesA 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.kindstringyesA 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.titlestringyes
group.example.sourcestringyesA complete diagram that is checked by the build; copy and edit it.
group.typesobject[]yesEvery 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"yesValue for type= on a group.
group.types[].titlestringyesWhat the frame is called in the text description.
group.types[].meaningstringyesWhat the author means by this type, so the right one is chosen.
group.types[].tone"neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red"yesColor family the frame and tab get when tone= is not set.
group.types[].frame"solid" | "dashed" | "dotted"yesHow the outline is drawn.
group.types[].iconstringyesIcon in the corner tab when the group has no provider.
group.types[].providerIconsobjectyesIcon in the corner tab for each provider whose icon differs from the generic one, keyed by provider set.
lineOptionsobject[]noOptions 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[].keystringyesThe option as written, such as animate or step.
lineOptions[].scope"header" | "line"yesheader: on the flow or sequence header line. line: on an edge or a message.
lineOptions[].valuesstringyesWhat the option takes.
lineOptions[].meaningstringyesWhat it does, and the cases where it is refused.
lineOptions[].examplestringyesOne line that parses.
labelIconsobject[]noEdge labels that get a tick or cross automatically; icon=none on the edge removes it.
labelIcons[].labelstringyesAn edge label that gets an icon automatically, matched whole and ignoring case.
labelIcons[].iconstringyesThe icon the label gets.
verbIconsobject[]noThe 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[].iconstringyesThe icon drawn in the label.
verbIcons[].wordsstring[]yesPhrases that draw it: the whole label, or its first words followed by what is acted on ("reads orders").
stylestring[]noHow to make a flow diagram look finished: verbs on arrows, role= on lines that mean something, typed groups, product names.
autoIconsobjectnoItems 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.keystringyesThe header option: icons.
autoIcons.valuesstringyesWhat it takes.
autoIcons.meaningstringyesWhat it does, and how one item opts out.
autoIcons.examplestringyesOne header line that parses.
roleIconsobject[]noThe 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[].iconstringyesThe icon drawn.
roleIcons[].wordsstring[]yesWhole words of a label of three words or fewer that draw it.
statusIconsobject[]noColored status and outcome icons: a green check, a red X, and so on.
statusIcons[].refstringyesValue for icon=, such as status:success.
statusIcons[].tone"neutral" | "blue" | "violet" | "aqua" | "orange" | "green" | "amber" | "red"yesColor the icon is always drawn in, whatever tone its owner has.
statusIcons[].meaningstringyesWhat the icon says, so the right one is chosen.
limitsobjectnoBounds and quality thresholds.
limits.maxSourceLengthintegeryes
limits.maxFlowNodesintegeryesQuality lint: more nodes than this warns, for a diagram with no groups.
limits.nodesPerGroupintegeryesEach group of a flow diagram raises the node limit by this many.
limits.maxFlowNodesCeilingintegeryesThe node limit never rises above this, whatever the groups.
limits.maxSchemaTablesintegeryes
limits.maxSequenceActorsintegeryes
limits.maxNumberedStepsintegeryesMore numbered steps than this in one diagram warns (W200).
limits.maxStackMarksintegeryesMost technology marks a node carries in stack=.
limits.targetWidthintegeryesColumn width in px that diagrams are checked against.
editingobjectnoHow to edit an existing Plotwork SVG: read it back with read_diagram, change the source, draw it, and save or publish it again.
editing.stepsstring[]yesIn order: how to change a diagram that already exists as a Plotwork SVG, a hosted link or a file in the repository.
editing.embedSourcestringyesWhen to set embedSource true on draw_diagram, render_diagram, or publish_diagram, and what it means for who can read the source.
diagnosticCodesobject[]no
diagnosticCodes[].namestringyesIdentifier of the code.
diagnosticCodes[].codestringyesThe code to branch on, such as E120.
diagnosticCodes[].severity"error" | "warning"yes
examplesobject[]yesTested examples: the overview holds the ones for the kinds the shared tables describe in full, a kind answer holds its own.
examples[].kindstringyesA 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[].titlestringyes
examples[].sourcestringyesA complete diagram that is checked by the build; copy and edit it.
importFormatsobject[]noOnly for topic import-formats: every format import_source reads, a line each.
importFormats[].formatstringyesThe format, as import_source takes it.
importFormats[].readsstringyesWhat it reads.
importFormats[].drawsstringyesThe diagram it draws.
importFormats[].optionsstringyesThe options it takes.

See also

DocWhy
API referenceEvery endpoint, and the error envelope
Tool referenceThe same operations as callable tools
Language referenceWhat the diagram source may contain