SheetgoDevelopers

Developers › REST API › Guides

REST API · guides

Guides

Topics that apply across many endpoints. Latest versions: Rate Limiting · API Key Scopes · Smart Tags · Cell References.

Rate Limiting

To keep the platform fast and fair, the API limits how many requests each account can make in a short window. If you exceed the limit, further requests are temporarily rejected with HTTP 429 (Too Many Requests) until the window resets. Rate limits protect you too — they stop a runaway script from exhausting your account's capacity.

How the limits work

  • Per account. Limits apply to your Sheetgo user account, across all of your API keys combined. Creating extra API keys does not add capacity — the budget is shared by the account.
  • Two separate budgets:
    • Reads — GET and HEAD requests (higher allowance).
    • Writes — POST, PUT, PATCH, DELETE requests (lower allowance).
  • Per-minute window. Each budget refills on a rolling one-minute basis.

Current default limits (per account, per minute): 120 read, 30 write. Do not hard-code these numbers — some accounts have higher allowances and limits may change. Read the limit from the response headers instead.

Response headers (on every response)

Header Meaning
X-RateLimit-Limit Your current limit for that category (read or write).
X-RateLimit-Remaining Requests left in the current window.
X-RateLimit-Reset Seconds until the window resets.

When X-RateLimit-Remaining approaches 0, slow down before you get blocked — the most effective way to avoid 429s.

When you are throttled

A 429 response includes a Retry-After header and a JSON body:

{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded: 120 read requests per minute. Retry after 37 seconds.",
  "retry_after": 37,
  "limit": 120,
  "remaining": 0,
  "reset": 37,
  "scope": "read"
}
Field Meaning
error Stable code: always rate_limit_exceeded.
message Human-readable explanation.
retry_after Seconds to wait before retrying (same as the Retry-After header).
limit / remaining / reset Your limit, requests left (0), seconds to reset.
scope Which budget you exhausted: read or write.

Consuming the API reliably

  1. Honor Retry-After on a 429 — wait at least that many seconds before retrying.
  2. Use exponential backoff with jitter for other transient errors.
  3. Self-throttle using X-RateLimit-Remaining — slow down proactively.
  4. Spread work out with small delays rather than bursting.
  5. Cache and avoid redundant calls — reads count even when data is unchanged.
  6. Treat 429 as normal — catch it, wait, and retry transparently.

Reference retry loop:

for attempt in range(max_retries):
    resp = call_api(...)
    if resp.status_code != 429:
        return resp
    wait = int(resp.headers.get("Retry-After", 2 ** attempt))
    sleep(wait + random_jitter())

Automated agents and LLM tools

The response body carries everything needed to recover (retry_after, scope, and a plain-language message) — parse the body, not just the status code. Honor retry_after rather than retrying in a tight loop. Most HTTP client libraries already back off automatically on 429 + Retry-After; keep that on.

Need higher limits?

If your legitimate workload consistently approaches the limits, contact Sheetgo support to raise your account's capacity. A change takes effect automatically — and because you read the limit from X-RateLimit-Limit, your integration needs no code change.

API Key Scopes

Sheetgo API keys let apps, scripts, and AI agents act on your Sheetgo account. By default a key can do everything you can — read, edit, run, and delete any workflow, automation, form, and more.

Scopes let you narrow that down. You can limit a key to certain actions (view only, or edit, or delete) and to certain items (all of your workflows, or only a specific few). This is useful when you hand a key to an AI agent or script that should only read data, an integration that should touch only one or two workflows, or a partner who should have limited access.

Scopes only limit the key — not you. Restricting a key never changes what you can do when you log in to Sheetgo yourself; it only limits requests made with that key.

The two things a scope controls

A scope combines what actions are allowed with which items they apply to.

Actions

Action What it allows
View (read) See and list items — read a workflow, list automations, view a form or schedule.
Edit (write) Create, change, and run items — edit a workflow, trigger a run, set a schedule, submit a form.
Delete Remove items — archive/delete a workflow, delete a form, remove a trigger.
Full All of the above.

Running a workflow counts as "Edit", not "View." A View-only key cannot start runs — give it Edit if it needs to.

Items

For each action you can choose all items of that type (all workflows, all automations, …) or only specific items you pick. You can also apply a scope to everything at once (all resource types) — for example, "View everything."

Item types you can scope: workflows, automations, forms, triggers (schedules), webhooks, Outlook, and API destinations.

Setting scopes in your Account

  1. Go to Account → Services and account → Sheetgo API.
  2. Create a new key, or open an existing key to edit it.
  3. Choose the access level:
    • Full access (default) — the key can do everything.
    • All items, limited actions — e.g. View only across everything.
    • Custom — pick actions per item type, and optionally restrict each to specific items.
  4. Save. When creating a key, copy it immediately — it is shown only once. When editing, changes take effect right away; you don't need to regenerate the key — the same key keeps working with its new limits.

Examples

  • Read-only monitoring key — View → All items. Lists and reads everything; cannot edit, run, or delete.
  • Run/edit only two workflows — Workflows → Edit → "Monthly Report", "Sales Sync". Can run and edit those two, nothing else.
  • Read everything, edit one — View → All items plus Workflows → Edit → "Client Import". A common "safe agent" setup.
  • Partner access to one workflow — Workflows → Full → "Partner Feed". View, edit, run, and delete that one workflow only.
  • No restriction (default) — Full access.

Good to know

  • Restricting to specific items means the key can't create new ones. Limiting Edit to a specific list lets the key change those items but not create brand-new ones. Give Edit → All items to allow creation.
  • Forms and schedules follow their workflow. A form or trigger is reachable only if the key can also view its workflow.
  • Lists respect the scope. A key limited to specific workflows sees only those when it lists workflows.
  • Keep keys secret. A key is shown only once; if it leaks, delete it and create a new one. Scopes reduce the damage a leaked key can do but don't replace keeping it safe.
  • Changing a scope doesn't rotate the key — editing limits keeps the same key string working.

Smart Tags

A smart tag is a {{placeholder}} that Sheetgo replaces with a value from your data while an automation runs. They are used by the document destination — both inside the Google Docs template and in the destination's file_name.

How a tag resolves

A tag matches a column header in the data reaching the destination, and is replaced with that row's value. One document is generated per row.

Data header Tag to write Result
Customer {{Customer}} Acme Ltd
Invoice No {{Invoice No}} 2026-0042

Header names are matched as they appear in your data, spaces included. There is no mapping to configure: name the tag after the column.

Where tags can be used

  • In the template document (document destination) — anywhere in the body, including headers, footers and tables.
  • In file_name (document) — so each generated document gets a distinct name, e.g. "Invoice {{Invoice No}} - {{Customer}}".
  • In subject and body (share, mail_merge) — the email is rendered per row, so each recipient sees their own values.
  • As a recipient (share, mail_merge) — to, cc, bcc and reply_to accept a "{{Header}}" string instead of addresses, which reads the address from that column. The reference must be the whole value: "{{Email}}" works, ["{{Email}}"] and "cc: {{Email}}" do not.

When a tag has no matching column

unused_fields decides:

  • error (default) — the run fails, so a template/data mismatch is visible.
  • ignore — the tag is replaced with an empty string and the run continues.

Reserved tags

Tag Meaning
{{!group-start}} … {{!group-end}} Repeat the enclosed block once per row within a group, instead of generating one document per row.
{{image:Column}} Insert the image at the URL held in Column. img:, picture: and pic: are accepted as equivalents.

PDF settings

The pdf destination has no smart tags — generated PDFs take their name from the file they were converted from. Its paper_size, page_orientation, scale and merge_files fields control the export. Note that paper_size values for ISO sizes are uppercase: A3, A4, A5, B4, B5.

Cell References

A cell reference is a {{Tab!Ref}} placeholder you put inside an api source's request. When the automation runs, Sheetgo reads that cell from the automation's Google Sheets destination and substitutes the value before the request goes out — so the request changes as your sheet changes, with no API call needed.

GET https://api.example.com/events?since={{Log!A:last|date|fmt:iso_dt}}

Which {{ }} am I looking at?

Three unrelated syntaxes share the double-brace shape. They are not interchangeable.

Syntax Example Where it works
Cell reference {{Sheet1!A1|date|fmt:iso_d}} api source — endpoint, headers, body
Smart tag {{Customer}} document, share, mail_merge destinations
Body template {{DATA}}, {{for row in ROWS}} webhook destination body

A cell reference always contains a !. A smart tag is a bare column name. The body template uses the reserved names DATA and ROWS and the block tags {{for}}, {{if}} and {{except-last}}.

Grammar

{{ <tab>!<ref> [|<filter>]* }}
  • <tab> — a tab in the destination spreadsheet. Quote it with single quotes if it contains a space, a special character, or starts with a digit: {{'My Sheet'!A1}}, {{'2026 Sales'!A1}}. Double an apostrophe inside a quoted name: {{'O''Brien'!C3}}. When in doubt, quote it — the quoted form always works.
  • <ref> — a single cell (A1, B7, AB42) or A:last, the last non-empty cell in column A. Case-insensitive. Ranges (A1:B5), whole columns (A:A), whole rows, named ranges and formulas are not supported.
  • |<filter> — optional, chainable, applied left to right.

Filters

Render mode — must be the first filter if used. Default is F.

Filter Value you get Cell displaying $1,234.50
F (default) the formatted display text "$1,234.50"
U the raw underlying value 1234.5

F and U after another filter are invalid, and the placeholder is left as literal text.

String — trim (strip whitespace), upper, lower.

Numeric — int, float. Both fail the run on a non-numeric value.

Date input — promote the value to a date, always doing work:

Filter Behaviour
date auto-detect, US-leaning on ambiguous input
date_us month first — 01/02/2026 is 2 January
date_eu day first — 01/02/2026 is 1 February
date_iso strict ISO 8601 only

Accepts strings, Sheets serial numbers, and existing dates. On its own a date filter renders ISO datetime; chain a fmt:* to change that.

Date output — fmt:*, a no-op unless a date input filter came first:

fmt:day, fmt:month, fmt:year, fmt:timestamp (Unix seconds), fmt:timestamp_ms (Unix milliseconds), fmt:serial (Sheets serial), fmt:iso_dt, fmt:iso_d, fmt:us_dt, fmt:us_d, fmt:eu_dt, fmt:eu_d. _dt includes the time, _d is date only.

Where they go

Location Substitution
endpoint URL-encoded per component. Keep placeholders out of the scheme and host.
headers verbatim, with CR/LF stripped
body verbatim, no escaping — you are responsible for valid JSON. "{{A1}}" yields a quoted string; {{A1|U}} unquoted yields a bare JSON value.

When something goes wrong

Situation Behaviour
Invalid syntax, unknown filter, unbalanced braces treated as literal text — your API receives the raw {{...}}
Tab does not exist run fails, naming the placeholder and its location
Empty cell, out-of-bounds cell, :last on an empty column substituted as "", warning logged, run continues
Numeric or date conversion fails run fails
Network failure reading the sheet retried 3× with backoff, then the run fails

⚠️ Requires a Google Sheets destination

Substitution reads from the automation's destination, so it only happens when that destination is a Google Sheets file. With any other destination the placeholders are sent to your API as literal text, with no warning.

⚠️ Never resolves alongside a webhook destination

A webhook destination must be an automation's only destination, so such an automation has no Sheets destination to read from. Cell references in it will always be sent literally. Pair cell references with a file destination instead.