Skip to content
Connect an agent
Markdown

Sync Markdown

Turn a document's diagram fences into pictures.

POST/v1/markdown/sync

TL;DR

QuestionAnswer
What does it do?Turn a document's diagram fences into pictures.
Which tool does the same?sync_markdown
What does it take?A JSON body of type SyncMarkdownInput.
What does it return?Status 200 with a body of type SyncMarkdownResponse.
What can go wrong?400 the body failed schema validation; 401 the api key is missing or not valid; 403 the account is on the free plan, which does not include the rest drawing and checking routes (plan.rest_not_included); 413 the body is larger than the size cap; 429 too many requests. Every failure uses the one error envelope.

What it does

Takes a whole Markdown document and its path and answers with the rewritten document (every diagram fence wrapped in a collapsed source section with its picture and a text description), the SVG files to write, and a report per fence with errors that carry line numbers counted in the document sent. With convertMermaid set, every Mermaid fence that can be converted becomes a diagram fence first; the others are left exactly as they were and reported. The route reads and writes no file: the caller writes the returned document and files. A fence with errors is a normal 200 result with status failed in the report. Mode check changes nothing and only reports. Prefer this route over converting, validating, and rendering each fence yourself.

Request body

The body has the type SyncMarkdownInput.

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

Responses

StatusMeaningBody
200The rewritten document, the files to write, and the report.SyncMarkdownResponse
400The body failed schema validation.ErrorResponse
401The API key is missing or not valid.ErrorResponse
403The account is on the Free plan, which does not include the REST drawing and checking routes (plan.rest_not_included).ErrorResponse
413The body is larger than the size cap.ErrorResponse
429Too many requests.ErrorResponse

Response body

A 200 answer has the type SyncMarkdownResponse.

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.

See also

DocWhy
API referenceEvery endpoint, and the error envelope
SchemasEvery request and response type
sync_markdownThe same operation as an MCP tool
Tool referenceThe operations as callable tools