Skip to main content
Turn a plain-language description of a process into a saved, laid-out diagram and a rendered image. Because generation runs an LLM and then renders the result, it can take many seconds — so the API is asynchronous: you create a generation job, then poll it until it finishes.
All requests are server-to-server only. Never expose jfi_sk_live_... keys in a browser or client app.

Why async?

A single generation involves an LLM call plus a server-side layout and render pass. That can comfortably exceed the lifetime of a normal HTTP request. Rather than hold a connection open (and risk timeouts), POST /v1/diagrams/generate returns immediately with 202 Accepted and a Generation job in queued status. You then poll GET /v1/generations/{id} until the job reaches a terminal state.
Webhooks for generation completion are planned for v2. Until then, poll the generation endpoint with backoff (see the example below).

The flow

1

Create the generation

POST /v1/diagrams/generate with your prompt. You get back 202 Accepted, a Generation with status: "queued", a Location header pointing at the poll URL, and a Retry-After hint.
2

Poll for status

GET the URL from the Location header. While status is queued or processing, wait and try again (respecting Retry-After and backing off).
3

Read the result

When status is succeeded, the diagram (the created, saved diagram) and image_url (the rendered image for the requested theme/format) are populated. When status is failed, error explains why.

Create a generation

Requires the generate scope. Counts against your monthly generation quota (500 generations per rolling 30 days).

Body

string
required
Natural-language description of the process to generate.
string
Theme for the rendered image: "light" (default) or "dark".
string
Image format: "png" (default) or "svg".
string
Optional name for the resulting diagram.
string | null
Optional folder (UUID) to place the diagram in, or null for the root.

Response

202 Accepted
string
Always "generation".
string
The generation job id, prefixed with gen_. Use it to poll.
string
One of "queued", "processing", "succeeded", "failed".
object | null
The created, saved Diagram once status is "succeeded"; otherwise null.
string | null
Path to the rendered image (per the requested theme/format) once status is "succeeded"; otherwise null. It is relative to the API base (https://justflow.it) — prepend the base to fetch it.
object | null
{ "code": string, "message": string } when status is "failed"; otherwise null.
string
ISO-8601 UTC timestamp.

Poll the generation

Requires the generate scope. Poll until status reaches a terminal state (succeeded or failed).

Response — succeeded

200 OK

Response — failed

200 OK
A failed generation returns 200 OK with status: "failed" — the HTTP request to poll succeeded; the job did not. Inspect generation.status and generation.error, not the HTTP status code, to decide outcome.

Full polling example

Poll the Location URL, respecting the initial Retry-After and then backing off, until the job is terminal.
Already have a saved diagram and just want to re-fetch or re-theme its image? Use GET /v1/diagrams/{id}/image with theme and format query params — no regeneration, no quota cost.

Edit an existing diagram

Change a saved diagram’s content with another natural-language instruction. Editing runs an LLM and a render too, so it uses the same asynchronous flow as generation: create an edit job, then poll. Requires the generate scope and counts against the generation quota.

Body

string
required
Natural-language instruction describing the change — e.g. “add a rejection path after the approval gateway” or “rename the first task to ‘Receive invoice’”.
string
Theme for the re-rendered image: "light" (default) or "dark".
string
Image format: "png" (default) or "svg".
Returns 202 Accepted with a Generation (identical shape to generate). Poll GET /v1/generations/{id} exactly as above; on success, diagram is the updated diagram and image_url is the re-rendered image.
Editing applies the instruction to the diagram’s current content and updates it in place (same diagram id). It is the only way to change a diagram’s content — PATCH /v1/diagrams/{id} changes metadata (name, folder) only.

Quota & rate limits

Generation is metered on two axes, both per key:

Generation quota

500 generations per rolling 30 days. Each accepted POST /v1/diagrams/generate (returned as 202 Accepted) counts once — including jobs that later end in failed.

Burst limit

120 requests / 60s across all endpoints, including your poll calls.
Every response carries RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset (seconds). On a 429, a Retry-After (seconds) header tells you how long to wait.
When the monthly generation quota is exhausted, POST /v1/diagrams/generate returns 429 with error.code quota_exceeded. When you’re sending too fast, it returns 429 with rate_limit_exceeded. Back off using Retry-After.

Errors

Every error uses the standard envelope:
Note: when a job’s content is invalid (e.g. it can’t be laid out as valid BPMN), the poll returns 200 with status: "failed" and error.code: "validation_failed" — not an HTTP 422.