← Back to Agent Handoff Brief

Agent API Reference

Complete reference for the Agent Sheet JSON API.

The Agent API is a stateless JSON API for creating and updating sheets. It is the agent-facing surface of Agent Sheet: an agent creates a sheet, gets back share links, then appends rows and updates cells over time. Humans review the result in the browser via the share link.

All endpoints live under /api and accept/return application/json.

Authentication

Authentication is by capability token: a per-sheet secret carried as a bearer token.

Authorization: Bearer <token>

Tokens are share links scoped to a single sheet. Each token grants exactly one ability:

AbilityCan do
ReadView the sheet and its human share/export URLs.
EditView and update existing cells, rows, and comments.
ManageFull control: append rows, upsert rows, add columns, update rows.

Creating a sheet mints two links. The Manage token is returned once, as manage_token, in the create response. Treat it as a secret. The Read link is surfaced as the human share_url. The Manage token is the agent's write credential; the Read share_url is what you hand to a human reviewer.

A token is rejected when it is missing (401), invalid/expired/revoked (401), belongs to a different sheet than the one in the URL (403), or lacks the ability the endpoint requires (403).

Sheet creation is the one exception: it is anonymous (no token) but rate-limited.

Column types

Cell values are always stored as text (lossless). There is no type inference. A column's type only governs how that text is interpreted on read. Supported types:

text (default), number, boolean, date, datetime, url.

When you create a sheet you may declare columns explicitly (type defaults to text when omitted). If you omit columns entirely, columns are derived as text from the union of cell keys across your rows, in first-seen order.

In responses, every cell is an object:

{
  "value": "184000",
  "typed": 184000,
  "metadata": null
}

Endpoints

MethodPathAbilityPurpose
POST/api/sheetsnoneCreate a sheet (rate-limited).
GET/api/sheets/{sheet}anyShow a sheet with a page of rows.
POST/api/sheets/{sheet}/rowsManageAppend new rows.
PUT/api/sheets/{sheet}/rowsManageUpsert rows by key.
PATCH/api/sheets/{sheet}/rows/{row}Edit/ManageUpdate one row by id.
POST/api/sheets/{sheet}/columnsManageAdd columns.

Human (browser) URLs, resolved by the Read/Edit share token in the path:

MethodPathPurpose
GET/s/{token}The review workspace (grid).
GET/s/{token}/export/{format}Download csv or xlsx.

Create a sheet

POST /api/sheets is anonymous and rate-limited. It creates the sheet, columns, rows, and cells, then mints the Manage + Read links. Returns 201.

curl -X POST https://agent-sheet.com/api/sheets \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "title": "Prospect Research",
    "description": "Accounts gathered by a research agent.",
    "columns": [
      { "key": "company", "name": "Company", "type": "text" },
      { "key": "arr", "name": "ARR (USD)", "type": "number" },
      { "key": "renews", "name": "Renews", "type": "date" }
    ],
    "rows": [
      { "cells": { "company": "Northwind Logistics", "arr": "184000", "renews": "2026-08-15" } },
      { "cells": { "company": "Acme Robotics", "arr": "92000", "renews": "2026-07-30" } }
    ]
  }'

Request fields

FieldTypeNotes
titlestring, requiredMax 255.
descriptionstring, nullableMax 2000.
metadataobject, nullableSheet-level provenance.
columns[]array, nullableMax 200. Omit to derive text columns from row cell keys.
columns[].namestring, requiredColumn header.
columns[].keystring, nullableStable cell key; defaults to a slug of name.
columns[].typestring, nullableOne of the column types above; defaults to text.
columns[].metadataobject, nullableColumn-level metadata.
rows[]array, nullableMax 1000.
rows[].keystring, nullableCaller-defined stable key (used by upsert).
rows[].cellsobject, nullableMap of column key → scalar value. Max 500 cells.
rows[].metadataobject, nullableRow-level provenance.

Response 201

{
  "data": {
    "id": "01JZ8Q9X4F0K3M2N6P7R8S9T0V",
    "title": "Prospect Research",
    "description": "Accounts gathered by a research agent.",
    "metadata": null,
    "columns": [
      { "id": "01JZ8Q9X...", "key": "company", "name": "Company", "type": "text", "position": 0, "metadata": null },
      { "id": "01JZ8Q9Y...", "key": "arr", "name": "ARR (USD)", "type": "number", "position": 1, "metadata": null },
      { "id": "01JZ8Q9Z...", "key": "renews", "name": "Renews", "type": "date", "position": 2, "metadata": null }
    ],
    "counts": { "columns": 3, "rows": 2 },
    "share_url": "https://agent-sheet.com/s/Hb3...48charToken",
    "web_url": "https://agent-sheet.com/sheets/01JZ8Q9X4F0K3M2N6P7R8S9T0V",
    "manage_token": "******************",
    "created_at": "2026-06-21T10:00:00.000000Z",
    "updated_at": "2026-06-21T10:00:00.000000Z"
  }
}

Validation failures return 422 with errors (e.g. a missing title, an unsupported column type, a duplicate column key, or a cell key referencing an unknown column).

Show a sheet

GET /api/sheets/{sheet} accepts any active token. Returns the sheet, its columns, and a page of rows (200 rows per page).

curl https://agent-sheet.com/api/sheets/01JZ8Q9X4F0K3M2N6P7R8S9T0V \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <token>'

share_url / web_url appear only when the sheet has an active Read link. manage_token is never returned on read. A read/edit holder can't escalate.

Append rows

POST /api/sheets/{sheet}/rows requires the Manage ability. It adds new rows; existing rows are never touched. Cell keys must reference existing columns (unknown keys → 422). Returns 201 with the created rows.

curl -X POST https://agent-sheet.com/api/sheets/01JZ8Q9X4F0K3M2N6P7R8S9T0V/rows \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <manage_token>' \
  -d '{
    "rows": [
      { "cells": { "company": "Helios Energy", "arr": "256000", "renews": "2026-09-01" } }
    ]
  }'

Upsert rows by key

PUT /api/sheets/{sheet}/rows requires the Manage ability. Same body as append, but rows are matched by their caller-provided key: an existing key updates that row's cells, a new key creates a row. Returns 200 (the batch may mix creates and updates) with the affected rows.

curl -X PUT https://agent-sheet.com/api/sheets/01JZ8Q9X4F0K3M2N6P7R8S9T0V/rows \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <manage_token>' \
  -d '{
    "rows": [
      { "key": "acme-robotics", "cells": { "arr": "98000" } }
    ]
  }'

The response shape matches the append response (a data array of row objects), returned with status 200.

Update one row

PATCH /api/sheets/{sheet}/rows/{row} requires the Edit or Manage ability. It updates the cells (and/or metadata) of a single row by its ULID id. A row that does not belong to the sheet returns 404. Returns 200 with the updated row.

curl -X PATCH https://agent-sheet.com/api/sheets/01JZ8Q9X4F0K3M2N6P7R8S9T0V/rows/01JZ8QA0... \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{ "cells": { "arr": "190000" } }'

Response 200: a single row object (same shape as one element of the append response's data array).

Add columns

POST /api/sheets/{sheet}/columns requires the Manage ability. It appends new columns. A duplicate key returns 422. Returns 201 with the created columns.

curl -X POST https://agent-sheet.com/api/sheets/01JZ8Q9X4F0K3M2N6P7R8S9T0V/columns \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <manage_token>' \
  -d '{
    "columns": [
      { "key": "status", "name": "Status", "type": "text" }
    ]
  }'

Response 201:

{
  "data": [
    { "id": "01JZ8QC2...", "key": "status", "name": "Status", "type": "text", "position": 3, "metadata": null }
  ]
}

Human share and export URLs

These are browser URLs (not JSON), resolved by the share token in the path. No Authorization header is needed. Any active token (Read included) may open and export.

# Download the sheet as CSV using a share token:
curl -L -o sheet.csv https://agent-sheet.com/s/<token>/export/csv

Errors

StatusMeaning
401Missing, invalid, expired, or revoked capability token.
403Token is for another sheet, or lacks the required ability.
404Sheet or row not found (or not in the token's sheet).
422Validation failed. See the errors object.
429Rate limit exceeded (sheet creation).