Skip to content

Spreadsheet endpoints

All endpoints use the base URL https://app.visigrid.app/api/connector and require bearer authentication. Examples use synthetic data. Replace {pid} with the pid UUID returned by the list endpoint.

GET /sheets · Scope: read · Response: 200

Returns an array of accessible spreadsheets, including shared workbooks. There is no pagination envelope. An empty result is [].

[
{
"id": 42,
"pid": "00000000-0000-4000-8000-000000000042",
"name": "Leads",
"revision": 3,
"folder_id": null,
"role": "owner",
"can_manage_sharing": true,
"created_at": "2026-10-08T12:00:00Z",
"updated_at": "2026-10-08T12:05:00Z"
}
]

role is owner, editor, or viewer. Use pid in URLs. Integrations that write should offer only workbooks with an owner or editor role. can_manage_sharing describes the account’s permission; these REST endpoints do not expose sharing management.

POST /sheets · Scope: create · Response: 201

Field Required Description
name Yes Workbook name, 1–255 characters after trimming whitespace.
document Yes Complete workbook JSON object. Use the v2 format below for cell operations.
{
"name": "Leads",
"document": {
"format": "visigrid-json",
"version": 2,
"sheets": [
{
"name": "Sheet1",
"cells": [
{ "row": 0, "col": 0, "value": "Email" },
{ "row": 0, "col": 1, "value": "Name" }
]
}
]
}
}

Returns a spreadsheet object with the same fields as a list entry, an owner role, and revision 0. Creation through this endpoint puts the workbook in the account’s root; folder_id, if supplied, is ignored.

Document cells use zero-based row and col, so (0, 0) is A1. Each worksheet needs a nonempty name unique within the workbook, ignoring case. For an empty workbook, use a single worksheet with "cells": [].

Creation stores the supplied document; it does not recalculate formulas. Use Write cells to calculate formula edits.

GET /sheets/{pid}/workbook · Scope: read · Response: 200

Lists worksheet tabs without returning all their cells.

{
"sheet_id": "00000000-0000-4000-8000-000000000042",
"name": "Leads",
"revision": 0,
"sheets": [
{
"index": 0,
"name": "Sheet1",
"cell_count": 2,
"used_range": "A1:B1",
"frozen_rows": 0,
"frozen_cols": 0,
"has_charts": false,
"has_conditional_formatting": false
}
]
}

Use index as sheet_index for range reads and cell writes. Indexes are zero-based and may change when tabs are reordered. used_range is null for a worksheet without stored cells. Stored formatting-only cells can count toward cell_count and used_range; neither field identifies a table’s last data row.

GET /sheets/{pid}/range?range=A1:B20&sheet_index=0 · Scope: read · Response: 200

Query parameter Required Description
range Yes One cell (A1) or an A1 rectangle (A1:B20), at most 5,000 positions.
sheet_index No Nonnegative worksheet index; defaults to 0.

Use sheet_index to select the worksheet; do not prefix the range with a worksheet name. Unknown or repeated query parameters are rejected.

Terminal window
curl --fail-with-body --get \
-H "Authorization: Bearer $VISIGRID_API_TOKEN" \
--data-urlencode 'range=A1:B20' \
--data-urlencode 'sheet_index=0' \
"https://app.visigrid.app/api/connector/sheets/$VISIGRID_SHEET_ID/range"

Example response:

{
"sheet_id": "00000000-0000-4000-8000-000000000042",
"revision": 0,
"sheet": "Sheet1",
"sheet_index": 0,
"range": "A1:B20",
"cells": [
{ "ref": "A1", "row": 0, "col": 0, "value": "Email" },
{ "ref": "B1", "row": 0, "col": 1, "value": "Name" }
]
}

The cell list is sparse, ordered by row then column. Unstored blank cells are omitted; stored cells may contain null values or formatting only. Cells can also include formula and format. A single-cell range is normalized to a rectangle such as A1:A1.

GET /sheets/{pid}/snapshot · Scope: read · Response: 200

Returns the full stored workbook document together with its revision.

{
"sheet_id": "00000000-0000-4000-8000-000000000042",
"revision": 0,
"document": {
"format": "visigrid-json",
"version": 2,
"sheets": [
{
"name": "Sheet1",
"cells": [
{ "row": 0, "col": 0, "value": "Email" },
{ "row": 0, "col": 1, "value": "Name" }
]
}
]
}
}

Use this endpoint when an operation depends on data across the whole workbook, or when preparing a complete document save. Preserve fields you do not modify, including formatting, charts, and other workbook metadata.

POST /sheets/{pid}/cells · Scope: write · Response: 200

Field Required Description
expected_revision Yes Nonnegative integer revision from the preceding read.
sheet_index No Zero-based worksheet index; defaults to 0.
edits Yes Array of 1–1,000 edits with distinct cell references.

Each edit contains ref and exactly one of value or formula:

Edit Meaning
{"ref":"A2","value":"person@example.com"} Write literal text.
{"ref":"B2","value":12} Write a number. Booleans are also supported.
{"ref":"C2","formula":"=B2*2"} Write and evaluate a formula.
{"ref":"D2","value":null} Clear the value and any formula, preserving formatting.

A string in value is always literal, even if it starts with =. Arrays and objects are not cell values. A literal replaces any existing formula; the response reports the formulas replaced this way.

This example assumes the preceding read returned revision 0. Substitute the revision you actually read before sending a request.

Terminal window
curl --fail-with-body \
-H "Authorization: Bearer $VISIGRID_API_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"expected_revision":0,"sheet_index":0,"edits":[{"ref":"A2","value":"person@example.com"},{"ref":"B2","value":"Taylor"}]}' \
"https://app.visigrid.app/api/connector/sheets/$VISIGRID_SHEET_ID/cells"

Example response:

{
"sheet_id": "00000000-0000-4000-8000-000000000042",
"revision": 1,
"replaced_formulas": [],
"cells": [
{ "ref": "A2", "row": 1, "col": 0, "value": "person@example.com" },
{ "ref": "B2", "row": 1, "col": 1, "value": "Taylor" }
]
}

cells contains read-back cells when available and may be empty after a successful live write. Read the range if you need the resulting values. replaced_formulas entries contain ref and the previous formula. Formula edits are recalculated through VisiGrid’s engine.

POST /sheets/{pid}/save · Scope: write · Response: 200

Replaces the entire document, subject to the same revision check as cell writes. Use cell writes for ordinary data updates. Omitting existing content from a complete save removes that content.

{
"expected_revision": 0,
"document": {
"format": "visigrid-json",
"version": 2,
"sheets": [
{
"name": "Sheet1",
"cells": [
{ "row": 0, "col": 0, "value": "Updated heading" }
]
}
]
}
}

Both fields are required. document must be a JSON object. Returns the updated spreadsheet object with the same fields as a list entry. This endpoint stores the supplied document without recalculating formulas. Use a snapshot read as your starting point and preserve all other fields.

See errors and limits before implementing retries or batch writes.