---
name: rombik-api
description: Generates ДСТУ (GOST 19.701-90) algorithm flowcharts from source code (Python, C++, C, Java, C#, Pascal) via the rombik HTTP API. Use it when you need to turn code into a flowchart in docx/typst/excalidraw/svg/png/pdf.
---

# rombik API — skill for agents

rombik turns source code into a ДСТУ 19.701-90 algorithm flowchart over HTTP.
Auth is by API key. 1 chart — 1 credit.

## Base
`https://rombik.app/api/v1` — e.g. the /render endpoint is https://rombik.app/api/v1/render

## Authorization
Header (either of the two):
- `X-API-Key: rk_...`
- `Authorization: Bearer rk_...`

Create a key in your account on the site (shown once).

## CLI (recommended for agents)
Instead of raw HTTP calls with the key in the prompt — install the `rombik` CLI; it keeps the key in a config file (`~/.config/rombik`), so the key never enters the model context:
```bash
curl -fsSL https://rombik.app/install.sh | sh   # macOS/Linux → ~/.local/bin
# Windows (PowerShell): irm https://rombik.app/install.ps1 | iex
rombik auth                                # log in via browser (or: rombik auth rk_…)
```
Then use commands WITHOUT passing the key as an argument (it is read from the config):
- `rombik render main.py -f pdf -o out.pdf` — file/stdin/`--url` → chart
- `rombik batch src/*.py -f pdf -o project.pdf` — many sources at once
- `rombik me` · `rombik products` · `rombik topup` · `rombik gift --email … --qty …`
- `rombik version --json` → `{version,latest,updateAvailable}`; `rombik update` — update the CLI to the latest version
- Engine options — the same flags as the API `options` field: `--locale`, `--for-format`, `--single-end`, `--strip-types`, `--yes/--no`, `--in-word/--out-word`, `--cap-word/--cap-format`, etc. (full list: `rombik render -h`; custom values need Pro).
Commands map 1:1 to the HTTP endpoints below; exit codes follow the error `code`. Download & details: https://rombik.app/developers

## MCP (for clients without a shell)
If you run inside an MCP-capable client (Claude Desktop, Cursor, Cline…), the same binary can act as an MCP server — no need to run shell commands, the tools are available natively. The user installs the CLI once, runs `rombik auth`, and adds to the MCP client config:
```json
{ "mcpServers": { "rombik": { "command": "rombik", "args": ["mcp"] } } }
```
Tools: `render_flowchart` (code|url → PNG image, or svg/typst/excalidraw/pdf), `balance`, `products`, `topup_link`, `gift_credits`. Transport is stdio; API errors with a `code` come back as isError.

## Endpoints

### POST /render — code → flowchart (1 chart — 1 credit)
JSON body: `{ "code": "...", "lang": "python", "format": "svg" }`
- `lang`: python | cpp | c | java | csharp | pascal
- `format`: docx | typst | excalidraw | svg | png | pdf | json (svg by default). `docx` — Word with native shapes; `json` — raw Diagram geometry.
- `split` (default true for docx, PDF & Typst document; for svg/png/excalidraw — with explicit true): split tall charts into parts with А/Б connectors. For docx/pdf/typst these are separate pages (pdf is multi-page); for svg/png/excalidraw — parts on one canvas. `false` — keep continuous (one sheet)
- `url`: instead of `code` — a link to a file (allowlist: raw.githubusercontent.com, gist, gitlab.com, bitbucket.org, codeberg.org; `github.com/.../blob/...` auto→raw). Language is inferred from the extension.
- optional: `fn` (only the function with this name), `scale` (PNG zoom), `fragment` (Typst fragment), `font`, `options` (object — full list in the «Engine options» section below)
- `options` with custom words/caption/for-format require an account with active **Pro** (otherwise 402 `pro_required`). Toggles, `locale`, `font`, `scale`, `figStart` are free.
- `?json=1` → JSON response `{ format, encoding (utf-8|base64), content, creditsLeft }` instead of a file

### POST /render/batch — many sources at once (1 credit per item)
Body: `{ "items": [ {"code":"...","lang":"python"}, {"url":"https://raw.../b.cpp"} ], "format": "pdf" }`
- `items`: 1..100 items, each `{ code|url, lang?, fn?, name? }`.
- Charges 1 credit per chart among successful items; balance ≥ the item count at least.
- `format=pdf` (and not `bundle:"zip"`) → a single multi-page PDF (one page per item); other formats → a zip with one file per item.
- `?json=1` → report `{ count, rendered, creditsLeft, items:[{index,name,ok,error}], encoding:base64, content }`; otherwise a file (pdf|zip) + headers `X-Rombik-Rendered`, `X-Rombik-Failed`.

Example (JSON):
```bash
curl -X POST https://rombik.app/api/v1/render \
  -H "X-API-Key: rk_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"code":"def f(a):\n    return a*2","lang":"python","format":"svg"}' -o out.svg
```
Example (file): `curl -X POST https://rombik.app/api/v1/render -H "X-API-Key: rk_..." -F file=@prog.py -F format=pdf -o out.pdf`

### rombik native format (lang=`rombik`) — chart structure directly (Pro)
When rombik does NOT parse the language (assembler, pseudocode, JS…) or the chart does not
correspond to any code — set `lang:"rombik"` and put the chart TREE into `code` as astJSON
(a JSON string). The parser is skipped. **Pro only** (else 402 `pro_required`). Formats and `options` work as usual.

**Model.** You describe only the LOGIC (sequence of actions, branches, loops) and the node
TEXT. The ДСТУ framing is added by layout ITSELF: Start/End ovals around the function, Yes/No
labels on diamonds, the shapes themselves, the «Рисунок N» numbering. Do NOT write those by hand.

**Top level:** `code` = a JSON ARRAY of functions (each = its own chart):
```json
[ { "name": "name", "main": true, "block": { "kind": "block", "stmts": [ ...nodes... ] } } ]
```
`stmts` is a top-to-bottom sequence of nodes. `main:true` marks the main function.

**Node:** `{ "kind": …, "text"?, "cond"?, "then"?, "else"?, "body"?, "stmts"?, "jump"? }`. Kinds:

| kind | shape | fields |
|------|-------|--------|
| process | rectangle | text |
| io | parallelogram | text (start with «Ввід»/«Вивід») |
| call | subprogram | text (a function call) |
| terminal | oval | text (return/raise) |
| if | diamond | cond + then + else |
| for | hexagon | cond (the spec!) + body |
| while | diamond (pre-cond) | cond + body |
| dowhile | diamond (post-cond) | cond + body |
| infloop | loop | body |
| break / continue | — | only inside a loop |
| connector | circle | text; jump:true — goto |

⚠️ **Key points:**
- `then`/`else`/`body` are BLOCK nodes of the form `{ "stmts": [ … ] }`; an empty branch = `{ "stmts": [] }`.
- In `for` the spec goes in the `cond` field (NOT `text`!), format «var := start, end[, step]», e.g. `i := 1, n`.
- Do NOT add Start/End nodes and do NOT write Yes/No — layout does that.

**Recipes (construct → astJSON).** if / elif / else (elif = a nested if inside else):
```json
{ "kind": "if", "cond": "x > 0",
  "then": { "stmts": [ { "kind": "io", "text": "Вивід: плюс" } ] },
  "else": { "stmts": [
    { "kind": "if", "cond": "x < 0",
      "then": { "stmts": [ { "kind": "io", "text": "Вивід: мінус" } ] },
      "else": { "stmts": [ { "kind": "io", "text": "Вивід: нуль" } ] } } ] } }
```
for (range) loop and while:
```json
{ "kind": "for", "cond": "i := 0, n-1",
  "body": { "stmts": [ { "kind": "call", "text": "обробити(i)" } ] } }

{ "kind": "while", "cond": "b <> 0",
  "body": { "stmts": [ { "kind": "process", "text": "t := b" } ] } }
```

**Full example — find the maximum in an array:**
```json
[
  { "name": "findMax", "main": true, "block": { "kind": "block", "stmts": [
    { "kind": "io", "text": "Ввід a, n" },
    { "kind": "process", "text": "m := a[0]" },
    { "kind": "for", "cond": "i := 1, n-1", "body": { "stmts": [
      { "kind": "if", "cond": "a[i] > m",
        "then": { "stmts": [ { "kind": "process", "text": "m := a[i]" } ] },
        "else": { "stmts": [] } }
    ] } },
    { "kind": "io", "text": "Вивід m" },
    { "kind": "terminal", "text": "Повернути m" }
  ] } }
]
```

**Validation errors** (returned as text — fix and retry): unknown kind; if/while/for without
cond; process/io/call without text; break/continue outside a loop; limits (≤2000 nodes, depth ≤100).

**Call:** `rombik render schema.json --lang rombik -f pdf -o out.pdf`, or MCP `render_flowchart` with `lang:"rombik"`, or POST /render. Pro required.

### GET /me — balance
→ `{ email, name, credits, pro, proUntil }`

### POST /topup — payment link (when out of credits)
- `{ "kind": "credits_unit", "qty": 10 }` — per unit
- `{ "kind": "credits", "id": <packId> }` — a pack (id from /products)
- `{ "kind": "pro", "id": <tierId> }` — Pro
→ `{ jarUrl, comment, label, amountKop, amountUah }`. Open `jarUrl`, pay; credits arrive in ~a minute (poll GET /me).

### GET /products — price catalog
→ `{ credits:[{id,qty,uah}], pro:[{id,bonus,days,uah}], unitUah, available }` (`available:false` → payment temporarily unavailable)

### POST /gift — gift credits to a friend by email
- `{ "email": "friend@example.com", "qty": 5 }` — deducts 5 credits from you, adds them to your friend.
- If the recipient has no account yet — it is created by email (credits wait for first sign-in). They get an email and an in-account notification.
→ `{ ok, credits }` (your new balance). Errors: `gift_failed` (400, e.g. not enough credits), `bad_email`, `bad_qty`.

## Engine options — the `options` object on /render and /render/batch
Powerful tuning of the chart to the requirements (teacher/standard). Use them freely.
Toggles, `locale`, `font`, `scale`, `figStart` are free; custom text values
(your own words) require active Pro on the account (otherwise 402 `pro_required`).
```
# toggles (true/false, default false):
singleEnd            one shared "End" instead of one per exit
mainOnlyTerminators  Start/End only for main; subprograms → Entry/Exit
callAsProcess        a function call as a "Process", not a "Subprogram"
stripTypes           strip type annotations from blocks
returnAsIO           render return as an output block
# text / numeric:
locale                "uk" | "en" — language of chart inserts
forFormat             "comma" | "range" | "verbose" — counting-for look
yes / no              branch labels (Yes/No · Так/Ні · +/−)
inWord / outWord      input/output words (Input/Output)
startText / endText   main terminators (Start/End)
entryText / exitText  subprogram terminators (Entry/Exit)
returnWord            word before return (Return)
forEachWord           foreach separator (∈)
capWord               caption word (Figure)
capFormat             caption template: {word} {num} — {text}
figStart              which number to start figures from (integer)
```
Example: {"code":"…","lang":"python","options":{"locale":"en","yes":"Yes","no":"No","singleEnd":true,"stripTypes":true}}
In the CLI these are flags: --locale, --for-format, --single-end, --yes/--no, --strip-types … (full list: rombik render -h).

## Errors
Body `{ error, code }`. Branch on `code` (stable), not on text:
- `unauthorized` (401) — bad/missing key
- `no_credits` (402) — out of credits → call /topup
- `pro_required` (402) — custom Pro options without active Pro; the `proFeatures` field lists which
- `unknown_format` / `unknown_lang` / `bad_request` (400)
- `bad_source` (400) — could not fetch `url` (host not allowed, unreachable, too large)
- `render_failed` (500) — code parsed but render/rasterization failed (check syntax, language, fn)
- `rate_limited` (429) — free endpoints only; Retry-After header is present
- `payment_unavailable` (503), `server_error` (500)

## Credits & limits
- 1 chart — 1 credit; there is no free tier in the API.
- /render — no limit (bound by credits). /me, /topup, /products, /gift — 60 requests/min per key.

## Machine-readable specification
OpenAPI 3.1: https://rombik.app/api/v1/openapi.json
