1. Documentation
  2. Boards
  3. Read and write
Open Specter
  • Introduction
  • Quickstart
  • Authentication
  • Errors
  • Rate limits
  • Best practices
  • Overview
  • Best practices
  • Create a key
  • Read and write
  • Overview
  • Best practices
  • Hosted page
  • Submit from your code
  • Drafts, files and corrections

Read and write

Read a board and add rows to it with a board key.

Loading documentation…

Create a key< PreviousOverviewNext >

On this page

Read the boardWhat a row takesAdd a rowAdd many rowsCell formatsRetrying safely

Read the board

GET /v1/ingest/board · scope read

bash
curl "https://neo-app-api-prod-836053680024.us-central1.run.app/v1/ingest/board?limit=100" \  -H "Authorization: Bearer $SPECTER_KEY"

The answer carries the board's columns, a page of rows (newest first), total, and write — exactly what a new row takes on this board.

QueryMeaning
limitRows per page. Default 100, at most 1000.
cursorThe nextCursor from the previous page. Opaque. nextCursor is null on the last page.
rows=falseThe shape and write only, no rows — the cheap way to learn what a row takes. Needs read.

What a row takes

data.write.columns lists every column: its id and label (either works as a cell key), its kind, a format in words, an example, a select's options, a person column's members, and writable: false with a why for columns the system fills. data.write.example is a whole body that would land on this board — post it unchanged for a first successful write.

Add a row

POST /v1/ingest/rows · scope rows:write

bash
curl -X POST https://neo-app-api-prod-836053680024.us-central1.run.app/v1/ingest/rows \  -H "Authorization: Bearer $SPECTER_KEY" \  -H "Content-Type: application/json" \  -d '{"cells": {"Company": "Acme Ltd", "Amount": 25000, "Close date": "2026-10-01"}}'

A 201 answers the row in data and a receipt: filled (columns that now hold a value), coerced (values changed on the way in — "$1,200.50" stored as 1200.5) and ignored (cells that stored nothing, and why).

Add many rows

Send rows instead of cells — up to 500, all or nothing. A refusal names every bad row by its position, so one fix-and-resend is enough:

bash
curl -X POST https://neo-app-api-prod-836053680024.us-central1.run.app/v1/ingest/rows \  -H "Authorization: Bearer $SPECTER_KEY" \  -H "Content-Type: application/json" \  -d '{"rows": [{"cells": {"Company": "Acme Ltd"}}, {"cells": {"Company": "Globex", "Amount": 12000}}]}'
json
{"error": {  "message": "1 of 2 rows were refused and nothing was written — …",  "errors": [{"index": 1, "message": "invalid value — Amount: not a number"}]}}

Cell formats

Strings always work; numbers and booleans may be JSON values. Each column's format is the authority for that board.

KindSendExample
text, long_texttext; newlines kept"Acme Ltd"
number, percenta decimal1250.5
currencyan amount; written amounts are read25000 or "$25,000"
ratinga whole number, 1 to the column's max4
dateYYYY-MM-DD"2026-09-09"
datetimeRFC 3339, stored in UTC"2026-09-09T14:05:00Z"
selectone of options"new"
checkboxa booleantrue
url, email, phonethe text"owner@acme.example"
persona member's id or email, from members"ana@yourfirm.example"
tagsan array of labels, or one["referral", "priority"]
addressan object; every key optional{"line1": "1 Main St", "city": "Austin"}
relation{"id", "label"} of a record on the related page
formula, lookup, filenot writable on a new row

Retrying safely

On a page key (Leads, Deals…), send external_id — your id for the record, up to 255 bytes. Posting the same one again answers the first record instead of making a second, so a timed-out request can be retried. Board keys refuse external_id; read the board before re-sending instead.