Connect AI to Google Sheets via Apps Script and API

A custom =ASK_AI() function for Google Sheets: classification, summaries, and data extraction right in a cell, with caching and Apps Script quotas in mind.

5 min · · бизнес · автоматизация

Lots of small text tasks live in spreadsheets: a list of reviews, an export of leads, a product catalog. You can connect an AI model to Google Sheets without a separate server, using the Apps Script built into every spreadsheet. You type =ASK_AI("Detect the sentiment", A2) in a cell and get the model's answer. Below are the function code, a safe key setup, caching, Google quotas, and batch processing for larger volumes.

How it works

  1. A cell contains the custom function =ASK_AI(...).
  2. Apps Script sends the text to the Zukko API with UrlFetchApp.
  3. The model's answer appears in the cell.
  4. A cache remembers the answer so an identical request isn't paid for twice.

Google Sheets recalculates a custom function when its arguments change. If the arguments stay the same, no new request is made.

Step 1: a Zukko key

  1. Open the API keys page in the dashboard.
  2. Create a separate key, for example "Google Sheets", give it a daily spend limit, and allow only the models you need.
  3. Copy the fetch_... key — it is shown in full only once.

A separate key with a limit is especially useful here: it's easy to copy a formula down a thousand rows, and the limit keeps spending within plan.

Step 2: the Apps Script code

Open the spreadsheet, choose Extensions → Apps Script, delete the sample code, and paste:

bash
const ZUKKO_API_URL = 'https://api.zukko.pro/v1/chat/completions';
const DEFAULT_MODEL = 'glm-5.3-flash';
const CACHE_SECONDS = 21600; // CacheService maximum — 6 hours
const CACHE_VERSION = 'v1';  // change it to reset the cache

/**
 * Sends a task to the model and returns the answer.
 * @param {string} prompt Task for the model.
 * @param {string} context Text or cell the task refers to.
 * @param {string} model Model ID (optional).
 * @return {string} The model's answer.
 * @customfunction
 */
function ASK_AI(prompt, context, model) {

Notes on the code:

  • Endpoint — the OpenAI-compatible https://api.zukko.pro/v1/chat/completions, so every Zukko model is called the same way.
  • Cache. The cache key is a SHA-256 hash of the model, task, and text, so long texts don't hit the key length limit (250 characters). CacheService keeps entries for at most 6 hours, with values up to 100 KB. To reset the cache, change CACHE_VERSION.
  • Errors are returned as text in the cell rather than thrown, so you can see what happened right away: 401 invalid key, 402 insufficient balance, 429 too many requests.
  • The @customfunction comment enables the function hint while typing a formula.

Step 3: the key in script properties

You don't need to put the key in the code:

  1. In the Apps Script editor, open Project Settings (the gear icon).
  2. Under Script Properties, add a ZUKKO_API_KEY property with your key as the value.
  3. Save.

Then pick testConnection in the function list and click Run. Google will ask once for permission to make external requests — approve it. The model's answer should appear in the execution log.

A security note: script properties aren't visible in the spreadsheet itself, but anyone with editor rights on the spreadsheet can open them through the same Apps Script editor. Don't give edit access to outsiders, and use a separate, limited key that you can revoke in the dashboard.

Example formulas

The argument separator depends on the spreadsheet locale: a semicolon in Russian and many European locales, a comma in the US locale. The examples below use commas.

Review sentiment (text in A2):

=ASK_AI("Classify the review's sentiment: positive, neutral, or negative. Answer with one word.", A2)

Short summary:

=ASK_AI("Summarize the text in one sentence.", A2)

Data extraction:

=ASK_AI("Find the name, email, and phone in the text. Answer as: name; email; phone.", A2)

A different model — as the third argument:

=ASK_AI("Write a polite reply to this review.", A2, "claude-sonnet-5")

Available models: glm-5.3-flash, glm-5.3, gpt-5.6-luna, gpt-5.6-sol, claude-sonnet-5, claude-opus-5-5. The current list is at GET https://api.zukko.pro/v1/models or on the "Models" page in the dashboard.

Google quotas and large sheets

Apps Script limits that affect this function (per Google's documentation):

QuotaConsumer Google accountGoogle Workspace
UrlFetchApp calls per day20,000100,000
Custom function runtime30 seconds30 seconds
Script runtime6 minutes6 minutes

If the model takes longer than 30 seconds, the formula returns an error, so keep max_tokens small for short tasks. And if you fill a formula down a thousand rows, the spreadsheet launches many calculations almost at once, and some requests may get 429.

For large volumes, a batch run from a menu is more reliable: the script walks the selected column and writes answers to the next column as plain values. They don't recalculate and cost nothing more. Add to the project:

bash
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('AI')
    .addItem('Sentiment for selected column', 'classifySelection')
    .addToUi();
}

function classifySelection() {
  const range = SpreadsheetApp.getActiveRange(); // select one column of texts
  const texts = range.getValues();
  const task = 'Classify the review sentiment: positive, neutral, or negative. Answer with one word.';
  const results = texts.map(row => [row[0] ? ASK_AI(task, row[0]) : '']);
  range.getSheet()
    .getRange(range.getRow(), range.getColumn() + 1, results.length, 1)
    .setValues(results);
}

A single run is limited to 6 minutes, so process the selection in parts — say, 100–200 rows at a time.

What it costs

Example: 1,000 calls, each with about 150 input tokens (task plus review text) and 30 output tokens. In total, 0.15M input and 0.03M output tokens.

ModelPrice in/out per 1MCalculationTotal
glm-5.3-flash$0.04 / $0.040.15 × 0.04 + 0.03 × 0.04$0.0072
gpt-5.6-luna$0.1 / $0.10.15 × 0.1 + 0.03 × 0.1$0.018
claude-sonnet-5$0.3 / $0.30.15 × 0.3 + 0.03 × 0.3$0.054

Real spending shows up in the history in the dashboard. Request parameters are in the Chat Completions docs, and key limits in the key limits section.

FAQ

The function says "script property ZUKKO_API_KEY is not set"

Check the property name in the project settings — it must match the code exactly. After adding the property, recalculate the formula: change an argument or re-enter the formula.

How do I get a fresh answer instead of a cached one?

Change the CACHE_VERSION value in the code (for example, to v2) and recalculate the formulas. Otherwise identical requests within 6 hours are served from the Apps Script cache.

Which model should I choose?

The default is the cheapest, glm-5.3-flash. Check whether it suits your task on 20–30 rows: run the same formula with two or three models in neighboring columns and compare the answers. The price difference is in the table above.

Can I share the spreadsheet with colleagues?

Yes. Requests use the key from the script properties, so any recalculation by any user spends that key's balance. The cache helps, but it's more reliable to store finished answers as values (the batch run above) and set a daily limit on the key.

zukko

Pay 25×
less

for Claude Code & ChatGPT

One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.

Get API keyDocumentation

api.zukko.pro · fetch_*

AI in Google Sheets: a custom formula with Apps Script · Zukko