# Metagrid Agent API Metagrid is a nested spreadsheet: one tree of dictionaries, tables, lists, and grids. This API is for language models and scripts. ## Endpoint GET or POST https://ficarra.app/api/metagrid (Production: https://ficarra.app/api/metagrid) Legacy alias: /api/subsheet (same handler). GET with no body returns this catalog as JSON (op=help). Always start there. Authorization: Bearer mg_live_ Create keys in the signed-in app: Settings → Agent API keys. Secret shown once. A Supabase user JWT is also accepted. Keys only access sheets the owner owns. ## JSON mapping - array of objects → table (keys = fields, items = records) - object → dictionary (named children) - array of arrays → grid - array of scalars → numbered list - string starting with "=" → formula (stored, not evaluated) - boolean / number / null → cell ## Paths (names, not A1) People People.1 record 1 (1-based) as an object People.1.Salary one cell People.Salary whole column (array) People.Salary.1 same cell, field then record 'Line item'.Q1 quote names with spaces Grid.B4 A1 only inside a grid ## Ops (POST JSON { "op": "…" }) help catalog, no auth whoami confirm the key list owned sheets {id,title,etag,updated_at} create { title, value } new sheet from JSON outline { sheet, path? } names/kinds, no values — cheap first read get { sheet, path? } everyday JSON at path (omit path = whole tree) set { sheet, path, value, etag } write cell/record/column/node; creates missing dict keys insert { sheet, path, records:[…], etag } append table rows; new keys become fields update { sheet, path, where and/or record, set, etag } patch matching records delete { sheet, path, where|record|records, etag } remove records (not the sheet) drop { sheet, confirm: "" } delete the sheet batch { sheet, etag, ops:[…] } several mutations, one save; stops on first error identities linked emails/phones (From for send_email / send_text) identity_add { kind:"email"|"phone", value, label? } JWT only; sends a code identity_confirm { id, code } 6-digit code identity_default { id } identity_delete { id } send_email { to, subject, body, from? } from = linked verified email or label; Reply-To is that address send_text { to, body, from? } needs Twilio; from = linked verified phone or label Synonyms: read=get, write/put=set, append/add=insert, ls/tree=outline, rm=delete. ## Envelope In: { "op":"get", "sheet":"", "path":"People" } Out: { "ok":true, "op":"get", "sheet":{"id","title","etag"}, "path":"People", "kind":"table", "value":[…] } Err: { "ok":false, "error":"path_not_found", "message":"…", "hint":"…", "nearby":["People"] } Writes must send etag from the last get. 409 = reload and retry. Prefer outline before get on an unknown sheet. Prefer batch to cut round trips. ## Example {"op":"create","title":"Team","value":{"People":[{"Name":"Ada","Role":"Lead"}]}} {"op":"insert","sheet":"","path":"People","etag":"","records":[{"Name":"Bob","Role":"Eng"}]} {"op":"update","sheet":"","path":"People","etag":"","where":{"Name":"Ada"},"set":{"Salary":130000}} Human docs: /metagrid/docs/api App: /metagrid/app