Start here
If you are a model: GET this endpoint with no body. It returns the full catalog, examples, and error hints. Then authenticate.
GET https://ficarra.app/api/metagrid
POST https://ficarra.app/api/metagrid
Content-Type: application/json
Authorization: Bearer mg_live_…
{ "op": "help" }
Machine-readable copy of this page: /metagrid/llms.txt. Keys: signed-in app → Settings → Agent API keys. The secret is shown once.
Mental model for callers
- A sheet is one tree. A new sheet with no
valueis a grid. An object you send is a dictionary of named children. - You send everyday JSON. An array of objects is a table. An object is a dictionary. An array of arrays is a grid.
=SUM(Budget.Total)is a formula string (stored; the app computes it). - You address work with paths of names:
People,People.1.Salary,People.Salary(the column),'Line item'.Q1. A1 only inside a grid (Sheet.B4). - Writes send the
etagfrom the last read. A mismatch is 409 — get again, then retry. - Keys only see sheets you own. This is not the sharing/projection layer.
Operations
Closed set. Synonyms work (read→get, append→insert, ls→outline).
| op | Does |
|---|---|
help | Catalog. No auth. |
whoami | Confirm the key. |
list | Owned sheets (id, title, etag). |
create | New sheet from title + optional value JSON. Omit value for a blank grid. |
outline | Names and kinds, no cell values. Cheap first read. |
get | Everyday JSON at path (omit path for the whole tree). |
set | Write a cell, record, column, or replace a node. Creates missing dictionary keys. |
insert | Append table records. New keys become fields. |
update | where and/or record + set fields. |
delete | Remove matching records. Does not delete the sheet. |
drop | Delete the sheet. confirm must equal the title. |
batch | Several mutations, one save. Stops on the first error. |
identities | Linked emails and phone numbers (From identities). |
identity_add | Link an email or phone. JWT session only. Sends a verification code. |
identity_confirm | Confirm the 6-digit code. |
identity_default / identity_delete | Default From, or unlink. |
send_email | to, subject, body, optional from (linked address or label). Reply-To is that address. |
send_text | SMS when Twilio is configured. from is a linked number or label. |
Example
{ "op": "create", "title": "Team", "value": {
"People": [
{ "Name": "Ada", "Role": "Lead", "Salary": 120000 }
]
}}
{ "op": "insert", "sheet": "<id>", "path": "People", "etag": "<etag>",
"records": [{ "Name": "Bob", "Role": "Eng", "Salary": 90000 }] }
{ "op": "update", "sheet": "<id>", "path": "People", "etag": "<etag>",
"where": { "Name": "Ada" }, "set": { "Salary": 130000 } }
{ "op": "get", "sheet": "<id>", "path": "People.1.Salary" }
Errors look like { "ok": false, "error": "path_not_found", "message": "…", "hint": "…", "nearby": ["People"] }. Read hint and nearby before retrying.
What this is not
- Not a formula evaluator — you store
=…; the app calculates. - Not a confidentiality boundary for shared workbooks. Owner keys see the canonical tree.
- Not the Excel import proxy (
/api/metagrid-importis a different, browser CORS helper).