# Venn Diagram Generator > Renders a Venn diagram of 2-6 circles as a PNG and hands back an editable share link. No account, no API key, no rate limit beyond three concurrent renders; the server keeps nothing — the whole diagram lives in the URL. ## Documentation - [API documentation](https://venn.applepig.net/api) - [OpenAPI specification](https://venn.applepig.net/openapi.json) ## Draw one in a single request For a two-circle SVG, fetch this single URL (no encoding of state needed): https://venn.applepig.net/api/venn.svg?a=%E8%97%A5%E5%93%81%E6%BF%AB%E7%94%A8&b=%E7%89%A9%E8%B3%AA%E6%BF%AB%E7%94%A8&ab=%E6%AF%92%E5%93%81&colorA=%23E76F51&colorB=%232A9D8F Query keys: a = A only, b = B only, ab = the intersection, colorA/colorB = #rrggbb colors. Missing or empty text is blank; omitted colors use product defaults. Use URLSearchParams: # must be %23, + must be %2B. Unknown/duplicate parameters, empty colors and mixing s with friendly fields return 400. The SVG has no embedded fonts; use PNG for fixed glyph rendering. Success includes x-venn-url. Friendly SVG is no-cache; GET /api/venn.svg?s= supports the full validated state and uses the same immutable cache policy as GET PNG. SVG does not consume PNG/OG rasterizer workers. POST the diagram as JSON. The response body is the PNG, and the `x-venn-url` response header is the editable share link for that same picture. This request works as written: ```bash curl -sD headers.txt -o venn.png -H 'content-type: application/json' \ --data '{"v":1,"n":2,"style":"translucent","opacity":0.6,"overlap":1.2,"radius":0.3,"colors":["#2e9be6","#e6a92e"],"bg":"#fafafa","size":400,"texts":{"1":{"t":"Coffee"},"2":{"t":"Sleep"},"3":{"t":"Me at 3am"}}}' \ https://venn.applepig.net/api/png grep -i x-venn-url headers.txt ``` ## The diagram There is no partial form: the body is a complete state, and **`v`, `n`, `style`, `opacity`, `overlap`, `radius`, `colors`, `bg`, `size` and `texts` must all be present** — a missing one is a 400, not a default. Copy the request above and change what you need. - `v`: must be `1`. - `n`: how many circles. 2-6 for `ring`, 3-6 for `row`. - `arr`: `"ring"` (default) or `"row"`. The only optional structural field. - `texts`: the words inside each region. **The key is the bitmask of the circles that region belongs to, written as a decimal string** — circle i is bit i, so `"1"` is the first circle alone, `"2"` the second alone, `"3"` their overlap, `"7"` the centre of three. The value is `{"t": "words"}`, optionally with `"fs"` (font size as a fraction of canvas width) and `"fill"` (`#rrggbb`, `flat` style only). 80 characters per region, `\n` breaks a line. `{}` is a legal empty diagram. - `style`: `"translucent"`, `"flat"` or `"outline"`. - `colors`: one `#rrggbb` per circle; the array length must equal `n` exactly. `bg`: background colour. - `opacity`: 0-1, only `translucent` uses it, still required. `overlap`: 0.6-1.6, centre distance over radius. `radius`: fraction of the canvas, 0.2-0.35 for a ring, 0.1-0.35 for a row. - `size`: output pixels, an integer 400-2000. Output is always square. - Optional: `title` (drawn in a band above the diagram) with `title_fill` and `title_fs`; `stroke_width` 0-0.03 and `stroke` `#rrggbb`. Not every overlap exists, and addressing one that does not is an error rather than a silent omission: four circles in a ring means the first and fourth never touch, so `"9"` gets you `400 {"error":"text slot 9 does not exist in ring(4)"}`. Which keys are legal depends on the arrangement *and* the circle count — take them from this table: ``` ring(2) 1 2 3 ring(3) 1 2 4 3 5 6 7 ring(4) 1 2 4 8 3 5 10 12 7 11 13 14 15 ring(5) 1 2 4 8 16 3 6 12 17 24 7 14 19 25 28 15 23 27 29 30 31 ring(6) 1 2 4 8 16 32 3 6 12 24 33 48 7 14 28 35 49 56 row(3) 1 2 4 3 6 row(4) 1 2 4 8 3 6 12 row(5) 1 2 4 8 16 3 6 12 24 row(6) 1 2 4 8 16 32 3 6 12 24 48 ``` Only `ring(2)` and `ring(3)` carry every combination; everywhere else, circles that are not neighbours share no region. If the idea needs a pair that is missing, reorder the circles so those two sit next to each other, or use fewer circles. ## Fetching one that already exists `GET https://venn.applepig.net/api/png?s=` returns the same PNG. `s` is `base64url(deflate-raw())` — the same string the editor puts in a share link, and the one inside `x-venn-url`. It is content-addressed and answered `Cache-Control: public, max-age=31536000, immutable`, so use it for anything fetched more than once; POST is `no-store` and re-rasterizes every time. Use POST to produce a diagram, then pass around the `s` it hands back. ## Errors Always JSON, always English, never localized: `{"error": "..."}`. A missing, undecodable or invalid state is 400; a request body over 32 KB is 413. An `s` longer than 7300 characters is rejected so the share link stays a usable URL. Three renders run at a time. Over that, the answer is `503 {"error":"renderer is busy, retry later"}` with `Retry-After: 2` — a queue signal, not a failure. Wait and resend the same request; if you are producing a batch, keep three in flight rather than firing them all at once. ## Off the web - CLI, no server needed: `npx -y venn-diagram-generator@1 png --set A=Fast --set B=Cheap --set C=Good --text ABC="Pick two" -o out.png`. It takes letters instead of bitmasks (`AB` is the first two circles overlapping) and fills in every field you leave out, so it is the shorter road when you do not want to spell out a whole state. It takes the spec on stdin with `--json -` — the only sane way to pass CJK text, apostrophes and newlines through a shell — and prints the share URL next to the file it wrote. `decode ` turns an existing link back into JSON. - Claude Code plugin: `/plugin marketplace add applepig/venn-diagram-generator` then `/plugin install venn@venn-diagram-generator`. - Source and full documentation: https://github.com/applepig/venn-diagram-generator - Editor: https://venn.applepig.net/