Google Sheets API v4 bindings: read and write cell values (single,
batch, append, clear) with every render and input option, rows as
records (header row to Maps and back), spreadsheet metadata and
creation, and batchUpdate with builders for sheets, freezing,
resizing and basic formatting. Credentials and scopes come from
google-core.
Namespaces
::google::sheets::values- get, batch-get, update, batch-update, append, clear, batch-clear,read-records,write-records,append-records::google::sheets::spreadsheets- get, create,batch-update, list/add/rename/delete/duplicate sheets, freeze, auto-resize::google::sheets::requests- pure builders forbatchUpdaterequests (sheets, freeze, resize, formatting, rows and columns)::google::sheets::records- pure conversion between value grids and records, A1 notation helpers
Every function has an options arity taking an opts Map. Sheets
query parameters use the API's own names (valueRenderOption,
valueInputOption, fields, ...); credential keys (token,
refresh-token, service-account, subject, scopes, retry) are
handled by google-core and override context for that call.
Quick start
::values ::google::sheets::values
leads ::values/read-records("1AbCspreadsheetId", "Leads!A:D")
::values/append-records("1AbCspreadsheetId", "Leads!A:D", [{name: "Ada", email: "ada@example.com"}], ["name", "email"])
Values
API_ROOT
API_ROOT: Str "https://sheets.googleapis.com"
BASE_URL
BASE_URL: Str "https://sheets.googleapis.com/v4/spreadsheets"
FILE_SCOPE
FILE_SCOPE: Str "https://www.googleapis.com/auth/drive.file"
READ_SCOPE
READ_SCOPE: Str "https://www.googleapis.com/auth/spreadsheets.readonly"
SCOPE
SCOPE: Str "https://www.googleapis.com/auth/spreadsheets"
Functions
api-root
fn (): Str
The API root, https://sheets.googleapis.com unless the google.sheets.api-root context variable points at a proxy or emulator.
google.sheets.api-root
append-records of ::google::sheets::values/append-records
fn (spreadsheet-id: Str, range: Str, records: Vec, columns: Vec): Map
fn (spreadsheet-id: Str, range: Str, records: Vec, columns: Vec, opts: Map): Map
Append records below the table at range, one row each, cells in
columns order (match the sheet's header). Missing values are
written as empty cells. Scope: spreadsheets.
::google::sheets::values/append-records(id, "Leads!A:C", [{name: "Ada", email: "ada@example.com", source: "web"}], ["name", "email", "source"])
append-values of ::google::sheets::values/append-values
fn (spreadsheet-id: Str, range: Str, values: Vec): Map
fn (spreadsheet-id: Str, range: Str, values: Vec, opts: Map): Map
POST /{id}/values/{range}:append - append rows after the last row of
the table found at range (e.g. "Log!A:C"). insertDataOption: "INSERT_ROWS" inserts new rows instead of overwriting empty ones.
Returns {tableRange, updates}. Scope: spreadsheets.
::google::sheets::values/append-values(id, "Log!A:C", [["2026-11-01", "deploy", "ok"]], {insertDataOption: "INSERT_ROWS"})
batch-get-values of ::google::sheets::values/batch-get-values
fn (spreadsheet-id: Str, ranges: Vec): Map
fn (spreadsheet-id: Str, ranges: Vec, opts: Map): Map
GET /{id}/values:batchGet - read several ranges in one call. Returns {spreadsheetId, valueRanges: [...]} in request order. Same options as get-values. Scope: spreadsheets.readonly.
batch-update of ::google::sheets::spreadsheets/batch-update
fn (spreadsheet-id: Str, requests: Vec): Map
fn (spreadsheet-id: Str, requests: Vec, opts: Map): Map
POST /{id}:batchUpdate - apply structural and formatting requests
atomically, in order (build them with ::google::sheets::requests).
Returns {spreadsheetId, replies}, one reply per request (empty for
most; addSheet replies carry the new sheet's properties). If any
request fails, none is applied. Scope: spreadsheets.
clear-values of ::google::sheets::values/clear-values
fn (spreadsheet-id: Str, range: Str): Map
fn (spreadsheet-id: Str, range: Str, opts: Map): Map
POST /{id}/values/{range}:clear - clear a range's values (formatting and validation are kept). Returns {clearedRange}. Scope: spreadsheets.
compact
fn (body: Map): Map
Drop null values from a request body (Sheets bodies never carry JSON null for unset fields).
create-spreadsheet of ::google::sheets::spreadsheets/create-spreadsheet
fn (title: Str): Map
fn (title: Str, opts: Map): Map
POST /v4/spreadsheets - create a spreadsheet. Returns the resource
with spreadsheetId and spreadsheetUrl. It lands in the
authenticated user's My Drive root (move it with google-drive's
move-file); a service account without domain-wide delegation owns
it alone, so share it before anyone else can open it. Scope:
spreadsheets (or drive.file).
book ::google::sheets::spreadsheets/create-spreadsheet("Q3 pipeline", {sheets: ["Leads", "Summary"], timeZone: "America/New_York"})
book.spreadsheetId
creds
fn (opts: Map): Map
The google-core part of opts (credentials, scopes, retry), passed through to ::google::api.
encode-id
fn (id: Str): Str
URL-encode a spreadsheet id for a path segment.
encode-range
fn (range: Str): Str
URL-encode an A1 range for a path segment: "My Sheet!A1:B2" becomes My%20Sheet%21A1%3AB2.
get-spreadsheet of ::google::sheets::spreadsheets/get-spreadsheet
fn (spreadsheet-id: Str): Map
fn (spreadsheet-id: Str, opts: Map): Map
GET /{id} - spreadsheet metadata: properties (title, locale,
timeZone), sheets (each with properties: sheetId, title,
index, gridProperties), namedRanges, spreadsheetUrl. Pass
{ranges: ["Sheet1!A1:C5"], includeGridData: true} for cell data
and formatting, and fields to trim the response. Scope:
spreadsheets.readonly.
get-values of ::google::sheets::values/get-values
fn (spreadsheet-id: Str, range: Str): Map
fn (spreadsheet-id: Str, range: Str, opts: Map): Map
GET /{id}/values/{range} - read a range in A1 notation (e.g.
"Sheet1!A1:C10", "Leads" for a whole sheet, or a named range).
Returns {range, majorDimension, values?}; values is absent when
the range is empty. Scope: spreadsheets.readonly.
raw ::google::sheets::values/get-values(id, "Data!A2:D", {valueRenderOption: "UNFORMATTED_VALUE"})
json
fn (scope: Str, method: Str, full-url: Str, body: Any, opts: Map): Any
::google::api/json with this package's conventions: credential opts and a JSON (or empty) body.
query-params
fn (defaults: Map, opts: Map): Map
fn (defaults: Map, opts: Map, local-keys: Vec): Map
Build a call's query parameters: defaults, overridden by the Sheets
parameters in opts (credential keys and the function's own
local-keys are removed), with nulls dropped. Pass a key as null in
opts to drop a default.
read-records of ::google::sheets::values/read-records
fn (spreadsheet-id: Str, range: Str): Vec
fn (spreadsheet-id: Str, range: Str, opts: Map): Vec
Read a range whose first row is a header and return one Map per row
(::google::sheets::records/rows-to-records). Uses
valueRenderOption: "UNFORMATTED_VALUE" unless set, so numbers come
back as numbers. Scope: spreadsheets.readonly.
leads ::google::sheets::values/read-records(id, "Leads!A:F")
filter(leads, (l) { eq(l.status, "new") })
update-values of ::google::sheets::values/update-values
fn (spreadsheet-id: Str, range: Str, values: Vec): Map
fn (spreadsheet-id: Str, range: Str, values: Vec, opts: Map): Map
PUT /{id}/values/{range} - overwrite a range with rows (a Vec of
Vecs). Returns {updatedRange, updatedRows, updatedColumns, updatedCells, updatedData?}. See the namespace doc for options.
Scope: spreadsheets.
url
fn (path: Str): Str
fn (path: Str, params: Map): Str
A Sheets v4 URL: /v4/spreadsheets + path with non-null params
(Vec values repeat the key, as ranges needs).
url("/abc/values/Sheet1%21A1").
values-path
fn (spreadsheet-id: Str, range: Str): Str
fn (spreadsheet-id: Str, range: Str, verb: Str): Str
The path of a values call: /{id}/values/{range} plus an optional :verb (append, clear), with id and range encoded.