[{"data":1,"prerenderedAt":17},["ShallowReactive",2],{"doc-changelog":3},{"blocks":4,"markdown":16},[5,8,14],{"kind":6,"html":7},"html","\u003Cp>New features, improvements and fixes across the API, the oracles and the MCP\nserver, newest first. Each entry says what changed and, when you need to act,\nwhat to do. If something changed and it is not here, tell us — we treat a\nmissing entry as a bug.\u003C\u002Fp>\n",{"kind":9,"tone":10,"blocks":11},"callout","tip",[12],{"kind":6,"html":13},"\u003Cp>\u003Cstrong>Two version numbers, and they never move each other.\u003C\u002Fstrong> The API's major\nversion is in the URL (\u003Ccode>\u002Fv1\u003C\u002Fcode>); each release that changes its endpoints or request\nbodies gets its own version (\u003Ccode>0.x.y\u003C\u002Fcode> while in preview), reported in \u003Ccode>info.version\u003C\u002Fcode>\nof \u003Ccode>GET \u002Fv1\u002Fopenapi.json\u003C\u002Fcode>. The rules an answer was checked against are versioned\nper answer, in \u003Ccode>verified_by\u003C\u002Fcode> — see \u003Ca href=\"\u002Fcitations\">Citations\u003C\u002Fa>. A rules update never\nchanges the API, and an API change never invalidates a citation you already\nhold.\u003C\u002Fp>\n",{"kind":6,"html":15},"\u003Ch2 id=\"where-forma-is-today\">Where Forma is today\u003C\u002Fh2>\n\u003Cp>Forma is in \u003Cstrong>preview\u003C\u002Fstrong>. Until the first general release is dated here, any\npart of the API may still change, so don't pin to it yet.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Six endpoints\u003C\u002Fstrong> — \u003Ccode>GET \u002Fv1\u002Foracles\u003C\u002Fcode>, \u003Ccode>POST \u002Fv1\u002Foracles\u002F{name}\u002Fask\u003C\u002Fcode>,\n\u003Ccode>GET \u002Fv1\u002Fme\u003C\u002Fcode>, \u003Ccode>POST \u002Fv1\u002Ffigures\u002Frender\u003C\u002Fcode>, \u003Ccode>GET \u002Fv1\u002Fnews\u003C\u002Fcode> and\n\u003Ccode>POST \u002Fv1\u002Ffeedback\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Two oracles\u003C\u002Fstrong> — \u003Ccode>chart\u003C\u002Fcode> for Vega-Lite, gnuplot, Plotly, ECharts and\nChart.js, and \u003Ccode>vector-graphics\u003C\u002Fcode> for TikZ, PicTeX and MetaPost.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Published rate limits\u003C\u002Fstrong> — \u003Ccode>requests_per_minute\u003C\u002Fcode> for every plan, in\n\u003Ca href=\"\u002Flimits#requests-per-minute\">Limits and credits\u003C\u002Fa>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Honest figures\u003C\u002Fstrong> — \u003Ccode>vector-graphics\u003C\u002Fcode> says no, with an \u003Ccode class=\"chip chip--invalid\">invalid\u003C\u002Fcode> that names\nthe feature, when a drawing needs something it cannot draw (gradients, images,\nanimation, patterns, transparency, shading) rather than drawing something\nclose. Titles and labels can be up to 60 characters, captions up to 160.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Figures that follow your description\u003C\u002Fstrong> — \u003Ccode>vector-graphics\u003C\u002Fcode> draws the\nrelations you describe (orthogonal, tangent, parallel, perpendicular), lengths\ngiven as distances, and axes. Drawings match your description: points sit on their lines, and descriptive\nsentences become the caption.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"2026-10-02\">2026-10-02\u003C\u002Fh2>\n\u003Ch3 id=\"charts-are-drawn-only-from-values-you-give\">Charts are drawn only from values you give\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>Changed\u003C\u002Fstrong> · A chart request without its values now answers\n\u003Ccode>422 DATA_REQUIRED\u003C\u002Fcode>, and you are not charged, instead of returning a chart of\nmade-up values. Every valid chart says where its numbers came from in \u003Ccode>data\u003C\u002Fcode>\n(\u003Ccode>supplied\u003C\u002Fcode> or \u003Ccode>generated\u003C\u002Fcode>). See \u003Ca href=\"\u002Fask\">Ask an oracle\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>What to do:\u003C\u002Fstrong> send your values, or add \u003Ccode>&quot;allow_generated_data&quot;: true\u003C\u002Fcode> when\nillustrative values are fine. Agents: update the MCP server so it can pass the\nflag.\u003C\u002Fp>\n\u003Ch3 id=\"refusals-say-why-and-the-catalogue-says-what-can-be-drawn\">Refusals say why, and the catalogue says what can be drawn\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>New\u003C\u002Fstrong> · An \u003Ccode class=\"chip chip--invalid\">invalid\u003C\u002Fcode> answer now carries \u003Ccode>reason\u003C\u002Fcode> — \u003Ccode>unsupported_feature\u003C\u002Fcode>,\n\u003Ccode>chart_type_mismatch\u003C\u002Fcode> or \u003Ccode>no_valid_answer\u003C\u002Fcode> — so your code can branch on it; see\n\u003Ca href=\"\u002Fverdicts\">Verdicts\u003C\u002Fa>. A chart of a different kind from the one you asked for is\nnow \u003Ccode class=\"chip chip--invalid\">invalid\u003C\u002Fcode>. Every answer carries a \u003Ccode>request_id\u003C\u002Fcode> to quote when you contact us,\nand \u003Ccode>GET \u002Fv1\u002Foracles\u003C\u002Fcode> lists each oracle's \u003Ccode>drawable_formats\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2 id=\"2026-10-01\">2026-10-01\u003C\u002Fh2>\n\u003Ch3 id=\"every-error-has-a-code\">Every error has a code\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>Fixed\u003C\u002Fstrong> · A request that fails validation now answers \u003Ccode>422\u003C\u002Fcode>\n\u003Ccode>VALIDATION_FAILED\u003C\u002Fcode>, with \u003Ccode>context.parameter\u003C\u002Fcode> naming the field, instead of a\nlist with no code. A figure that cannot be drawn because of a problem on our\nside now answers \u003Ccode>503 UPSTREAM_UNAVAILABLE\u003C\u002Fcode> — wait and send it again — instead of\na \u003Ccode>422\u003C\u002Fcode> that blamed your request. See \u003Ca href=\"\u002Ferrors\">Errors\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"2026-09-29\">2026-09-29\u003C\u002Fh2>\n\u003Ch3 id=\"news-and-feedback-endpoints\">News and feedback endpoints\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>New\u003C\u002Fstrong> · \u003Ccode>GET \u002Fv1\u002Fnews\u003C\u002Fcode> lists what's new, newest first, and \u003Ccode>POST \u002Fv1\u002Ffeedback\u003C\u002Fcode>\ntells us what worked and what didn't. Both are free. See\n\u003Ca href=\"\u002Fnews-feedback\">News and feedback\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"2026-09-28\">2026-09-28\u003C\u002Fh2>\n\u003Ch3 id=\"figures-render-in-the-chat\">Figures render in the chat\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>New\u003C\u002Fstrong> · The MCP \u003Ccode>show_figure\u003C\u002Fcode> tool shows a figure inline in ChatGPT and other\nhosts that support MCP Apps, with the figure and its source on separate tabs.\u003C\u002Fp>\n\u003Ch3 id=\"connect-an-agent-with-oauth\">Connect an agent with OAuth\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>New\u003C\u002Fstrong> · The hosted MCP server signs agents in with OAuth, so connecting one\nneeds no API key. See \u003Ca href=\"\u002Fconnect\">Connect your agent\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch3 id=\"faster-vector-graphics-answers\">Faster vector-graphics answers\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>Improved\u003C\u002Fstrong> · \u003Ccode>vector-graphics\u003C\u002Fcode> answers about a second faster.\u003C\u002Fp>\n\u003Ch2 id=\"our-versioning-promise\">Our versioning promise\u003C\u002Fh2>\n\u003Cp>Every entry is tagged \u003Cstrong>New\u003C\u002Fstrong>, \u003Cstrong>Improved\u003C\u002Fstrong>, \u003Cstrong>Changed\u003C\u002Fstrong>, \u003Cstrong>Fixed\u003C\u002Fstrong>,\n\u003Cstrong>Deprecated\u003C\u002Fstrong> or \u003Cstrong>Removed\u003C\u002Fstrong>, and says what you need to do — usually nothing.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>New\u003C\u002Fstrong> — a new field, oracle or format. Within \u003Ccode>\u002Fv1\u003C\u002Fcode> it is additive: clients\nthat ignore fields they don't recognise need no change.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Improved\u003C\u002Fstrong> — the same behaviour, better: faster, clearer, or more often right.\nWe say what got better and by how much.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Changed\u003C\u002Fstrong> — behaviour that is different but compatible. We describe the old\nbehaviour next to the new one.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Fixed\u003C\u002Fstrong> — something that did not work as documented now does. We say what was\nwrong.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Deprecated\u003C\u002Fstrong> — still works, has an end date, and names what to move to.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Removed\u003C\u002Fstrong> — only ever in a new major version. Within \u003Ccode>\u002Fv1\u003C\u002Fcode> we will not remove a\nfield, change a field's type, or narrow an enum you already receive.\u003C\u002Fp>\n","# Changelog\n\n> What's new in Forma, newest first.\n\nNew features, improvements and fixes across the API, the oracles and the MCP\nserver, newest first. Each entry says what changed and, when you need to act,\nwhat to do. If something changed and it is not here, tell us — we treat a\nmissing entry as a bug.\n\n**Two version numbers, and they never move each other.** The API's major\nversion is in the URL (`\u002Fv1`); each release that changes its endpoints or request\nbodies gets its own version (`0.x.y` while in preview), reported in `info.version`\nof `GET \u002Fv1\u002Fopenapi.json`. The rules an answer was checked against are versioned\nper answer, in `verified_by` — see [Citations](https:\u002F\u002Fdocs.formalogic.io\u002Fcitations). A rules update never\nchanges the API, and an API change never invalidates a citation you already\nhold.\n\n## Where Forma is today\n\nForma is in **preview**. Until the first general release is dated here, any\npart of the API may still change, so don't pin to it yet.\n\n- **Six endpoints** — `GET \u002Fv1\u002Foracles`, `POST \u002Fv1\u002Foracles\u002F{name}\u002Fask`,\n  `GET \u002Fv1\u002Fme`, `POST \u002Fv1\u002Ffigures\u002Frender`, `GET \u002Fv1\u002Fnews` and\n  `POST \u002Fv1\u002Ffeedback`.\n- **Two oracles** — `chart` for Vega-Lite, gnuplot, Plotly, ECharts and\n  Chart.js, and `vector-graphics` for TikZ, PicTeX and MetaPost.\n- **Published rate limits** — `requests_per_minute` for every plan, in\n  [Limits and credits](https:\u002F\u002Fdocs.formalogic.io\u002Flimits#requests-per-minute).\n- **Honest figures** — `vector-graphics` says no, with an `invalid` that names\n  the feature, when a drawing needs something it cannot draw (gradients, images,\n  animation, patterns, transparency, shading) rather than drawing something\n  close. Titles and labels can be up to 60 characters, captions up to 160.\n- **Figures that follow your description** — `vector-graphics` draws the\n  relations you describe (orthogonal, tangent, parallel, perpendicular), lengths\n  given as distances, and axes. Drawings match your description: points sit on their lines, and descriptive\n  sentences become the caption.\n\n## 2026-10-02\n\n### Charts are drawn only from values you give\n\n**Changed** · A chart request without its values now answers\n`422 DATA_REQUIRED`, and you are not charged, instead of returning a chart of\nmade-up values. Every valid chart says where its numbers came from in `data`\n(`supplied` or `generated`). See [Ask an oracle](https:\u002F\u002Fdocs.formalogic.io\u002Fask).\n\n**What to do:** send your values, or add `\"allow_generated_data\": true` when\nillustrative values are fine. Agents: update the MCP server so it can pass the\nflag.\n\n### Refusals say why, and the catalogue says what can be drawn\n\n**New** · An `invalid` answer now carries `reason` — `unsupported_feature`,\n`chart_type_mismatch` or `no_valid_answer` — so your code can branch on it; see\n[Verdicts](https:\u002F\u002Fdocs.formalogic.io\u002Fverdicts). A chart of a different kind from the one you asked for is\nnow `invalid`. Every answer carries a `request_id` to quote when you contact us,\nand `GET \u002Fv1\u002Foracles` lists each oracle's `drawable_formats`.\n\n## 2026-10-01\n\n### Every error has a code\n\n**Fixed** · A request that fails validation now answers `422`\n`VALIDATION_FAILED`, with `context.parameter` naming the field, instead of a\nlist with no code. A figure that cannot be drawn because of a problem on our\nside now answers `503 UPSTREAM_UNAVAILABLE` — wait and send it again — instead of\na `422` that blamed your request. See [Errors](https:\u002F\u002Fdocs.formalogic.io\u002Ferrors).\n\n## 2026-09-29\n\n### News and feedback endpoints\n\n**New** · `GET \u002Fv1\u002Fnews` lists what's new, newest first, and `POST \u002Fv1\u002Ffeedback`\ntells us what worked and what didn't. Both are free. See\n[News and feedback](https:\u002F\u002Fdocs.formalogic.io\u002Fnews-feedback).\n\n## 2026-09-28\n\n### Figures render in the chat\n\n**New** · The MCP `show_figure` tool shows a figure inline in ChatGPT and other\nhosts that support MCP Apps, with the figure and its source on separate tabs.\n\n### Connect an agent with OAuth\n\n**New** · The hosted MCP server signs agents in with OAuth, so connecting one\nneeds no API key. See [Connect your agent](https:\u002F\u002Fdocs.formalogic.io\u002Fconnect).\n\n### Faster vector-graphics answers\n\n**Improved** · `vector-graphics` answers about a second faster.\n\n## Our versioning promise\n\nEvery entry is tagged **New**, **Improved**, **Changed**, **Fixed**,\n**Deprecated** or **Removed**, and says what you need to do — usually nothing.\n\n**New** — a new field, oracle or format. Within `\u002Fv1` it is additive: clients\nthat ignore fields they don't recognise need no change.\n\n**Improved** — the same behaviour, better: faster, clearer, or more often right.\nWe say what got better and by how much.\n\n**Changed** — behaviour that is different but compatible. We describe the old\nbehaviour next to the new one.\n\n**Fixed** — something that did not work as documented now does. We say what was\nwrong.\n\n**Deprecated** — still works, has an end date, and names what to move to.\n\n**Removed** — only ever in a new major version. Within `\u002Fv1` we will not remove a\nfield, change a field's type, or narrow an enum you already receive.\n",1793819974062]