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 for batchUpdate requests (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.

Context Vars: google.sheets.api-root

append-records alias 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 alias 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 alias 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 alias 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 alias 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 alias 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 alias 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 alias 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 alias 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 alias 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.