Write a range
Overwrites one A1 range.
Permission
The key must be granted sheets.values.write
A key without it gets 403 insufficient_scope, with the missing permission named in details.
Value writes merge: setting a cell is last-write-wins on that one key, so two writers produce a defined result and this never answers 409. No precondition is needed, and none is accepted.
Path parameters
| Field | Type | Description |
|---|---|---|
id required |
string | The spreadsheet to write to. |
range required |
A1 range | Where the block lands. Values are anchored at its top-left corner. |
Request body
Values shorter than the range leave the rest of it untouched: writing two rows into a ten-row range writes two rows. Clearing is a separate call for exactly that reason.
| Field | Type | Description |
|---|---|---|
values required |
array[][] | Rows, each an array of cells. A cell is a string, a number or a boolean; a formula is a string beginning with =. An empty string DELETES a cell rather than storing a blank, because a stored blank would keep it inside the sheet's used extent and widen every unbounded range from then on. |
Request
curl https://api.veruapis.com/v1/spreadsheets/:id/values/:range \
-X PUT \
-H "Authorization: Bearer vak_live_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"values": [["North", 1200], ["South", 980]]
}'
Idempotency-Key is required on every write. Retrying with the same key returns the original response rather than repeating the operation, so a timeout is something you retry rather than something you investigate.
Response
| Field | Type | Description |
|---|---|---|
range |
A1 range | The range actually written. |
updated_cells |
integer | How many cells changed. |
state |
string | The document's state after the write. Send it as If-Match on a structural change, or compare it with your last one to notice somebody else's edit. |
changed |
boolean | False when the write stored nothing new — writing a cell the value it already holds. Not an error and not worth retrying: no new state was produced and no collaborator was notified. |
{
"data": {
"range": "Sheet1!A2:B3",
"updated_cells": 4,
"state": "b2c3d4e5f6a7b8c9",
"changed": true
},
"meta": { "request_id": "req_01j8z9...", "timestamp": "2026-09-02T10:00:00Z" }
}
Values are anchored at the range's top-left corner, and a shorter block leaves the rest of the range untouched. Clearing is its own call for that reason. An empty string deletes a cell rather than storing a blank, which would widen every unbounded range from then on.
Every failure uses the same shape, with a stable string code you can branch on. See the error reference.
Related
- POST Append rows
- POST Read several ranges
- POST Change a spreadsheet's structure
- POST Write several ranges
- POST Clear a range
- GET List the sheets in a spreadsheet
- GET Get the current state
- GET Read a range