# Import source

> Page: https://docs.plotwork.dev/api/post-v1-import. Index of every page: https://docs.plotwork.dev/llms.txt

Turn a file of another format into a diagram.

`POST /v1/import`

## TL;DR

| Question | Answer |
|---|---|
| What does it do? | Turn a file of another format into a diagram. |
| Which tool does the same? | [`import_source`](https://docs.plotwork.dev/mcp/tools/import-source.md) |
| What does it take? | A JSON body of type [`ImportSourceInput`](https://docs.plotwork.dev/api/schemas.md#importsourceinput). |
| What does it return? | Status 200 with a body of type [`ImportSourceResponse`](https://docs.plotwork.dev/api/schemas.md#importsourceresponse). |
| 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 the text of a file and its format: SQL DDL, Prisma, or Drizzle becomes a schema; an OpenAPI 3 document becomes a matrix of who may call each endpoint, or one operation as a sequence; Terraform, Bicep, an ARM template, Pulumi, CloudFormation, the AWS CDK, Docker Compose, Kubernetes manifests, Helm, Kustomize, a Backstage catalog, AsyncAPI documents, or a GitHub Actions, GitLab CI/CD, or Azure Pipelines pipeline becomes a flow with icons and frames; a Structurizr workspace becomes a C4 diagram of one view; CSV or JSON data becomes the chart its shape suits; tree output or a list of paths becomes a tree; a git log becomes a git graph or a timeline. Answers with the Plotwork source, a diagnostic for everything left out with its line and column in the file, the validation, and an outline. A file that cannot be read is a normal 200 result with ok false. It runs no code and fetches nothing, and the text is not stored.

## Request body

The body has the type [`ImportSourceInput`](https://docs.plotwork.dev/api/schemas.md#importsourceinput).

| Field | Type | Required | Description |
|---|---|---|---|
| `format` | `"sql" \| "prisma" \| "drizzle" \| "openapi" \| "terraform" \| "terraform-plan" \| "bicep" \| "arm" \| "pulumi" \| "cloudformation" \| "cdk" \| "compose" \| "kubernetes" \| "helm" \| "kustomize" \| "backstage" \| "structurizr" \| "asyncapi" \| "github-actions" \| "gitlab-ci" \| "azure-pipelines" \| "csv" \| "json" \| "tree" \| "git-log"` | yes | What the text is; get_diagram_syntax with topic import-formats describes each. |
| `text` | `string` | no | The file content, as text. Send text or files, not both. |
| `files` | `object[]` | no | The files of a folder, for a format that spans files; the others read the first. |
| `files[].path` | `string` | yes | The file path, such as infra/network.tf; diagnostics name it. at least 1 character; at most 300 characters. |
| `files[].text` | `string` | yes | The file content, as text. |
| `title` | `string` | no | The diagram title; taken from the file when left out. at most 200 characters. |
| `partsPage` | `integer` | no | Which page of parts to return when a split import has more than 24 diagrams: 1 (default) is the first 24. minimum 1; maximum 100000. |
| `options` | `object` | no | default {}. |
| `options.view` | `"endpoints" \| "map" \| "sequence" \| "git" \| "timeline" \| "context" \| "container" \| "component"` | no | The picture of a format drawn several ways. |
| `options.operationId` | `string` | no | openapi sequence: the operation. at most 200 characters. |
| `options.chart` | `"auto" \| "xychart" \| "pie" \| "sankey" \| "treemap" \| "matrix"` | no | csv, json: the chart; auto picks. |
| `options.tables` | `string[]` | no | Tables to draw, by name or prefix*. |
| `options.paths` | `string[]` | no | openapi: path prefixes to read. |
| `options.tags` | `string[]` | no | openapi: tags to read. |
| `options.varFiles` | `string[]` | no | Variables files to apply. |
| `options.groupBy` | `"module" \| "network" \| "file" \| "owner"` | no | How things are framed; module is the default. |
| `options.root` | `string` | no | The root, stack, or template of several to draw. at most 300 characters. |

## Responses

| Status | Meaning | Body |
|---|---|---|
| 200 | The imported source, its diagnostics, its check, and its outline. | [`ImportSourceResponse`](https://docs.plotwork.dev/api/schemas.md#importsourceresponse) |
| 400 | The body failed schema validation. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 401 | The API key is missing or not valid. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 403 | The account is on the Free plan, which does not include the REST drawing and checking routes (plan.rest_not_included). | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 413 | The body is larger than the size cap. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |
| 429 | Too many requests. | [`ErrorResponse`](https://docs.plotwork.dev/api/schemas.md#errorresponse) |

## Response body

A 200 answer has the type [`ImportSourceResponse`](https://docs.plotwork.dev/api/schemas.md#importsourceresponse).

| Field | Type | Required | Description |
|---|---|---|---|
| `ok` | `boolean` | yes | True when `source` is valid Plotwork source. False means nothing was imported and `source` is empty: read `diagnostics`. |
| `kind` | `string \| null` | yes | The kind of diagram the file became, or null when nothing was imported. |
| `format` | `string` | yes | The format the text was read as. |
| `source` | `string` | yes | The Plotwork source, or an empty string when nothing could be imported. |
| `diagnostics` | `Diagnostic[]` | yes | Everything left out, changed, or wrong, with a hint. Codes start with I and point into the text you sent: I1xx errors stopped the import, I2xx warnings did not. |
| `diagnostics[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `diagnostics[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `diagnostics[].message` | `string` | yes | What is wrong, in one sentence. |
| `diagnostics[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `diagnostics[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `diagnostics[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `diagnostics[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `stats` | `object` | yes |  |
| `stats.items` | `integer` | yes | Boxes, tables, rows, slices, places, entries, or commits written. |
| `stats.links` | `integer` | yes | Arrows, relations, messages, flows, or merges written. |
| `stats.groups` | `integer` | yes | Frames, sections, or folders written. |
| `stats.dropped` | `integer` | yes | Things in the file left out by a cap or because the picture has no place for them; each is in diagnostics. |
| `coverage` | `object \| null` | yes | How much of the file the picture shows; null when nothing was imported. When complete is false, the picture is not the whole file: say so. |
| `coverage.noun` | `string` | yes | What was counted, such as resources, services, tables, or endpoints. |
| `coverage.total` | `integer` | yes | Everything of that kind in the file. |
| `coverage.drawn` | `integer` | yes | Drawn as a box, frame, table, row, or entry of its own. |
| `coverage.summarised` | `integer` | yes | Not drawn on their own but counted on the box they belong to, such as "3 role assignments". |
| `coverage.omitted` | `integer` | yes | Not in the picture at all; the diagnostics say which and why. |
| `coverage.complete` | `boolean` | yes | True when nothing was omitted. |
| `coverage.line` | `string` | yes | The coverage in one sentence, such as "Drawn 12 of 85 resources; 60 are counted on the boxes they belong to and 13 are left out.". |
| `validation` | `object \| null` | yes | The Plotwork validator run on `source`; null when nothing was imported. |
| `validation.valid` | `boolean` | yes | True when the source has no Plotwork errors. It always is when `ok` is true. |
| `validation.errors` | `Diagnostic[]` | yes | Plotwork errors. Lines and columns point into `source`. |
| `validation.errors[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `validation.errors[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `validation.errors[].message` | `string` | yes | What is wrong, in one sentence. |
| `validation.errors[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `validation.errors[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `validation.errors[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `validation.errors[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `validation.warnings` | `Diagnostic[]` | yes | Plotwork quality warnings, with the exact fix in each hint. Lines and columns point into `source`. |
| `validation.warnings[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `validation.warnings[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `validation.warnings[].message` | `string` | yes | What is wrong, in one sentence. |
| `validation.warnings[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `validation.warnings[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `validation.warnings[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `validation.warnings[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `validation.summary` | `string \| null` | yes | One-line description of the diagram, usable as alt text. |
| `validation.size` | `object \| null` | yes | Natural size of the laid-out diagram. |
| `validation.size.width` | `integer` | yes | Width in px. minimum 1. |
| `validation.size.height` | `integer` | yes | Height in px. minimum 1. |
| `parts` | `object[]` | yes | When the file is too big for one readable picture, the diagrams it was split into, in order, at most 24 a page; `source` is the first diagram of all. Show or draw each of them. Empty when the import is one diagram. |
| `parts[].title` | `string` | yes | What this diagram shows, such as one resource group or one tag of an API. |
| `parts[].kind` | `string` | yes | The kind of diagram. |
| `parts[].source` | `string` | yes | The Plotwork source of this diagram; draw it with draw_diagram. |
| `parts[].items` | `integer` | yes | The boxes, rows, or entries it draws. |
| `parts[].valid` | `boolean` | yes | True when the source has no Plotwork errors. |
| `parts[].warnings` | `Diagnostic[]` | yes | Plotwork quality warnings of this diagram. Lines and columns point into its source. |
| `parts[].warnings[].code` | `"E100" \| "E101" \| "E110" \| "E111" \| "E120" \| "E121" \| "E122" \| "E123" \| "E124" \| "E125" \| "E130" \| "E131" \| "E132" \| "E133" \| "E134" \| "E135" \| "E136" \| "E137" \| "E138" \| "E139" \| "E140" \| "W200" \| "W201" \| "W202" \| "W203" \| "W204" \| "W205" \| "W206" \| "W207" \| "W500" \| "M100" \| "M101" \| "M102" \| "M103" \| "M104" \| "M110" \| "M200" \| "M201" \| "M202" \| "M203" \| "M204" \| "M205" \| "M206" \| "M207" \| "M208" \| "M209" \| "M210" \| "M211" \| "M212" \| "M213" \| "M214" \| "M215" \| "M216" \| "M217" \| "M218" \| "E300" \| "E301" \| "E302" \| "E303" \| "E304" \| "W300" \| "W301" \| "W302" \| "W303" \| "M120" \| "M220" \| "M221" \| "M222" \| "E340" \| "E341" \| "E342" \| "E343" \| "E344" \| "E345" \| "W320" \| "W321" \| "W322" \| "W323" \| "M240" \| "M241" \| "M242" \| "E360" \| "E361" \| "E362" \| "E363" \| "E364" \| "E365" \| "E366" \| "E367" \| "W330" \| "W331" \| "W332" \| "W333" \| "W334" \| "M250" \| "M251" \| "E400" \| "E401" \| "E402" \| "E403" \| "W350" \| "W351" \| "W352" \| "W353" \| "M270" \| "M271" \| "E420" \| "E421" \| "E422" \| "E423" \| "E424" \| "W360" \| "W361" \| "W362" \| "W363" \| "W364" \| "M180" \| "M280" \| "M281" \| "M282" \| "E320" \| "E321" \| "E322" \| "E323" \| "E324" \| "E325" \| "E326" \| "E327" \| "E328" \| "E329" \| "E330" \| "W310" \| "W311" \| "W312" \| "W313" \| "W314" \| "M130" \| "M131" \| "M132" \| "M230" \| "M231" \| "M232" \| "M233" \| "M234" \| "M235" \| "M236" \| "M237" \| "M238" \| "E380" \| "E381" \| "E382" \| "E383" \| "W340" \| "W341" \| "W342" \| "W343" \| "M260" \| "I100" \| "I101" \| "I102" \| "I103" \| "I104" \| "I105" \| "I200" \| "I201" \| "I202" \| "I203" \| "I204" \| "I206" \| "R100" \| "R101" \| "R200" \| "R201" \| "R202" \| "R203" \| "R204" \| "R205" \| "R206" \| "R207" \| "S100" \| "S200" \| "S101" \| "S102" \| "S103" \| "S104" \| "S201" \| "S202" \| "S203"` | yes | Stable code to branch on; E-codes are errors, W-codes are warnings. |
| `parts[].warnings[].severity` | `"error" \| "warning"` | yes | Errors stop rendering; warnings never do. |
| `parts[].warnings[].message` | `string` | yes | What is wrong, in one sentence. |
| `parts[].warnings[].line` | `integer` | yes | 1-based line in the submitted source. minimum 1. |
| `parts[].warnings[].column` | `integer` | yes | 1-based column in that line. minimum 1. |
| `parts[].warnings[].length` | `integer` | yes | Number of characters the problem covers. minimum 1. |
| `parts[].warnings[].hint` | `string \| null` | yes | A concrete suggestion for fixing it, or null. |
| `partsTotal` | `integer` | yes | How many diagrams the import was split into in all; 0 when it is one diagram. |
| `partsPage` | `integer` | yes | The page of parts this answer holds, from 1. |
| `partsPages` | `integer` | yes | How many pages of parts there are; call again with partsPage for the next one. |
| `outline` | `string[]` | yes | The diagram as plain text, to check it says what the file says; empty when nothing was imported. |
| `outlineTruncated` | `boolean` | yes | True when the outline was cut short at its summary length. |
| `viewUrl` | `string` | no | A link that shows a valid diagram in a browser; give it to the person who wants to look. The source is in the part after #, never sent to a server, but anyone with the link can read it. Absent when too long; next says so. |
| `pngUrl` | `string` | no | The viewUrl with &download=png: opening it in a browser saves the diagram as a PNG for Slack, email, or a wiki. The PNG is drawn in the person's browser, not on a server, so it is a link to open, not an image address to embed. Absent when too long. |
| `svgUrl` | `string` | no | The viewUrl with &download=svg: a person opens it to download the SVG. Not a file address for curl; use saveCommand. Absent when too long. |
| `saveCommand` | `string` | no | Run in a shell to save the SVG into the repository: the CLI decodes the link locally, fetches nothing, and embeds the source. Set --out to the path; add --theme dark for dark. Absent when too long. |
| `next` | `string` | yes | The next step in one sentence. |

## See also

| Doc | Why |
|---|---|
| [API reference](https://docs.plotwork.dev/api/reference.md) | Every endpoint, and the error envelope |
| [Schemas](https://docs.plotwork.dev/api/schemas.md) | Every request and response type |
| [`import_source`](https://docs.plotwork.dev/mcp/tools/import-source.md) | The same operation as an MCP tool |
| [Tool reference](https://docs.plotwork.dev/mcp/tools.md) | The operations as callable tools |
