diagrams-so — Python SDK
A thin, typed, dependency-free client for the Diagrams.so public API (/api/v2). Generate, edit, and manage cloud-architecture diagrams (draw.io / SVG) with AI.
- Covers all 27
/api/v2operations · one method per endpoint - No hard dependencies — uses
requestsif installed, else stdliburllib - Typed, ships
py.typed· raises a singleDiagramsAPIErrorwithcode/status/request_id - Safe retries: every AI call auto-attaches an
Idempotency-Keyand retries ambiguous failures (timeout / 5xx / in-progress) with the same key, so a response lost to a gateway timeout is replayed: one diagram, never two - Built-in
429/503backoff (honorsRetry-After), SSE streaming, async re-layout helper, and an in-process task tally (session_charges)
Install
pip install diagrams-so
Then connect. This puts a diagrams-so command on your PATH, so there is no key
to copy and nothing to paste:
diagrams-so login # a browser opens, press Approve
diagrams-so whoami # check which account this machine is connected as
In code, DiagramsClient() then needs no arguments. For CI, set
DIAGRAMS_API_KEY instead; it always takes priority over a stored login.
(Uses requests if present, otherwise the stdlib urllib — no hard dependency.)
Quickstart
from diagrams_so import DiagramsClient
client = DiagramsClient(api_key="dgz_live_…") # or dgz_test_… (test mode: same account, lower rate limits)
d = client.generate("AWS 3-tier web app: ALB, EC2, RDS", cloud_provider="aws")
print(d["id"], d["score"]["score"], len(d["warnings"]))
# fix the first Well-Architected warning
w = client.warnings(d["id"])
if w:
client.fix(d["id"], w[0]["message"], component=w[0].get("component"), warning_type=w[0]["type"])
open("diagram.drawio", "w").write(client.export(d["id"], "drawio")) # Paid plan
open("diagram.svg", "w").write(client.export(d["id"], "svg")) # every plan; watermarked on Free
Free plan: watermarked images, Paid: the draw.io file
On the Free plan the API leaves xml out: d["xml"] is None, d["xml_withheld"] is True, and d["export_url"] points at the watermarked SVG. client.image_url(d) gives the absolute URL (fetch it with the same key), or call client.export(d["id"], "svg"). export(id, "drawio") raises DiagramsAPIError with code UPGRADE_REQUIRED on Free. On the Paid plan d["xml"] is the draw.io XML, as before.
Diagram type
diagram_type is optional. Leave it out and the SDK does not send it, so the server picks the kind of diagram for your prompt. Pass a value to choose: diagram_type="architecture" or diagram_type="auto" is sent as given. Up to 1.3.0 the SDK always sent "architecture"; to keep that exact behaviour, pass it explicitly. client.meta("diagram-types") lists the values the API accepts.
Authentication & plans
Pass your key (from Settings → API Keys in your account). Every plan has unlimited diagrams and edits; nothing is metered, there is only a per-minute rate limit. Paid adds no watermark and draw.io export; Free diagrams can be private. dgz_test_ keys are test mode: they work on your real account, like a live key, at lower test rate limits. See your plan with client.usage().
Errors
Every non-2xx raises DiagramsAPIError:
from diagrams_so import DiagramsAPIError
try:
client.generate("…")
except DiagramsAPIError as e:
print(e.code, e.status, e.request_id) # e.g. QUOTA_EXCEEDED 402 req_abc
if e.status == 402:
... # needs the Paid plan → send the user to upgrade
Idempotency (safe retries)
Every AI call (generate, edit, fix, relayout) auto-attaches a fresh
Idempotency-Key and retries ambiguous failures with that same key, so a timeout
never makes a second diagram. Pass your own key to make the safety window explicit or
to dedupe across processes:
client.generate("…", idempotency_key="order-42") # server replays the stored result for 24h
Definite rejections (401/402/404/422) are never retried; a call whose outcome
is lost is recorded in session_charges as status="unknown" — reconcile with
client.usage_history(). Streamed generations tally a confirmed entry on their
terminal event; an applied re-layout tallies unknown (the server records it
asynchronously, so check usage_history).
Streaming
for event, data in client.generate_stream("AWS event-driven pipeline"):
if event == "progress":
print(data["progress"], data["message"])
elif event == "complete":
print(data["id"])
elif event == "error":
raise RuntimeError(data["error"]["message"])
The diagram XML arrives only in the terminal complete event.
Async re-layout
Re-layout replaces the current layout, so it asks first. The first call returns
confirmation_required; re-call with confirm=True to go ahead:
job = client.relayout_and_wait(d["id"]) # starts + polls to completion
if job.get("status") == "confirmation_required": # re-layout always needs confirmation
job = client.relayout_and_wait(d["id"], confirm=True)
Pagination
List / gallery / versions return {items, next_cursor, has_more}:
cursor = None
while True:
page = client.list(limit=50, cursor=cursor)
for item in page["items"]:
...
if not page.get("has_more"):
break
cursor = page["next_cursor"]
Config, retries & timeouts
DiagramsClient(api_key, base_url="https://api.diagrams.so/api/v2",
timeout=450.0, max_retries=3, backoff=0.5,
retry_delays=(5.0, 15.0, 30.0), retry_budget=600.0)
timeout defaults to 450s, above the server-side timeout ladder, so the client
never aborts work the server would still deliver. Reads retry 429/503 (honoring
Retry-After). Billable calls retry 429 the same way and every ambiguous failure
(timeout / 502/503/504 / in-progress) through the same-key idempotent ladder
(retry_delays between attempts, capped at retry_budget seconds) — a single retry
layer, so a busy server is never poked twice. Point base_url at
http://localhost:8000/api/v2 for local development.
Full method list
generate · generate_stream · list · get · update · delete · edit · fix · warnings · relayout · relayout_status · relayout_and_wait · export · versions · get_version · revert · import_diagram · search_gallery · fork · enhance_prompt · clarify_prompt · usage · usage_history · iter_usage_history · me · meta — each maps 1:1 to an endpoint.
License
Apache-2.0 · docs at diagrams.so/developers
Metadata
Release files for diagrams-so 1.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| diagrams_so-1.4.0.tar.gz | 31.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| diagrams_so-1.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 56.2 kB
Release files / diagrams_so-1.4.0.tar.gz
| Download URL | diagrams_so-1.4.0.tar.gz |
|---|---|
| Size | 31.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7233197527dae33d1388c9687b5cf7358ccdb3baa1ac41195e47bd9c4c6263a5
|
|
BLAKE2b-256 checksum How to use checksums |
cf8bca987d821214297015cdf3e69ca7aee6f843d86b7e8bc61cf75bea62ad49
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / diagrams_so-1.4.0-py3-none-any.whl
| Download URL | diagrams_so-1.4.0-py3-none-any.whl |
|---|---|
| Size | 24.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4932f1ecbaeae0a715118c619163909110b8c3365de5d681cdc598016c95dbf9
|
|
BLAKE2b-256 checksum How to use checksums |
27e2b0e6f4ed807d3350c48c96e28163baf09b6af865f45889a67ba80e43c912
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|