Authentication
Create a personal access token in any sheet: ⋯ → API tokens. Send it as a bearer token. Tokens act as you, with your workspace roles (viewers stay read-only).
H="Authorization: Bearer lrt_your_token"
curl https://liquidrows.com/api/workspaces -H "$H"
Base URL: https://liquidrows.com/api. Request and response bodies are JSON. IDs are UUIDs.
Workspaces & sheets
GET /workspaces | Your workspaces and your role in each. |
GET /workspaces/:workspaceId/sheets | Sheets in a workspace. |
POST /workspaces/:workspaceId/sheets | Create a sheet — {"name": "Q3 leads"}. |
GET /sheets/:sheetId | Sheet details and settings. |
GET /sheets/:sheetId/columns | Columns: key, name, type (data, formula, ai, agent, http, waterfall, lookup), config. |
Rows
Each row has fields keyed by column key. Every cell is { "v": value, "s": state } where the state is success, running, error (with err) or pending.
# Add a row (keys are column keys; computed columns run if the sheet auto-runs)
curl -X POST https://liquidrows.com/api/sheets/$SHEET/records -H "$H" \
-H "Content-Type: application/json" -d '{"values": {"company": "Stripe", "domain": "stripe.com"}}'
# Read rows — paginate with limit/offset, sort by a column
curl "https://liquidrows.com/api/sheets/$SHEET/records?limit=500&offset=0&sort=company&dir=asc" -H "$H"
# Edit one cell
curl -X PATCH https://liquidrows.com/api/sheets/$SHEET/records/$ROW/cells/company -H "$H" \
-H "Content-Type: application/json" -d '{"value": "Stripe, Inc."}'
# Delete rows (restorable for a while from the app)
curl -X POST https://liquidrows.com/api/sheets/$SHEET/records/delete -H "$H" \
-H "Content-Type: application/json" -d '{"ids": ["…"]}'
Filtering: pass filter as URL-encoded JSON — field rules use eq, neq, contains, starts_with, ends_with, is_empty, is_not_empty, gt, lt, gte, lte, between; status rules match a column’s cell state.
filter='{"combine":"and","fields":[{"column":"country","op":"eq","value":"US"}],"status":[{"column":"ceo","state":"error"}]}'
curl -G https://liquidrows.com/api/sheets/$SHEET/records --data-urlencode "filter=$filter" -H "$H"
The response is { "rows": [...], "total": n }; pages hold up to 1,000 rows; add count=0 to skip the total on very large sheets. Unknown keys in values are ignored.
Running enrichments
POST /sheets/:sheetId/run | Run every enrichment column on every row (cached cells are free). |
POST /sheets/:sheetId/columns/:colKey/run | Run one column. ?mode=empty fills blanks only, ?mode=errors retries failures, ?limit=10 runs a pilot on the first rows. |
GET /sheets/:sheetId/columns/:colKey/estimate | Estimated cost before you run. |
POST /sheets/:sheetId/records/:recordId/run | Run all columns for one row. |
POST /sheets/:sheetId/records/:recordId/cells/:colKey/run | Run a single cell and wait for the result (up to ~2 min). |
GET /sheets/:sheetId/run-progress | Live progress of the current run. |
POST /sheets/:sheetId/cancel-run | Stop queued work for the sheet. |
Export
Exports run as a background job; poll it, then download from the signed URL.
job=$(curl -s -X POST https://liquidrows.com/api/sheets/$SHEET/export -H "$H" \
-H "Content-Type: application/json" -d '{}' | jq -r .id)
curl https://liquidrows.com/api/jobs/$job -H "$H" # → {"status":"success","downloadUrl":"https://…"}
Pass the same filter object (and columns, a list of column keys) in the body to export a slice.
Inbound webhooks
Every sheet has a private webhook URL (Webhook in the sheet toolbar) — no token needed, the URL is the secret. POST one JSON object per row; keys become column keys. A payload with an email updates the existing row with that email instead of adding a duplicate.
curl -X POST https://liquidrows.com/api/webhooks/$WEBHOOK_TOKEN \
-H "Content-Type: application/json" -d '{"email": "ada@example.com", "company": "Analytical Engines"}'
Webhooks accept up to 600 calls a minute and 50,000 a day per sheet (HTTP 429 beyond that).
Errors & limits
401— missing or invalid token.403— your role doesn’t allow it (e.g. a viewer trying to edit).404— not found or not yours.400responses carry a human-readablemessage.429— slow down; retry after a short wait.- Enrichment spend is capped by your sheet and workspace spend limits — runs past the limit stop instead of billing on.