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
- A cell contains the custom function
=ASK_AI(...). - Apps Script sends the text to the Zukko API with
UrlFetchApp. - The model's answer appears in the cell.
- 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
- Open the API keys page in the dashboard.
- Create a separate key, for example "Google Sheets", give it a daily spend limit, and allow only the models you need.
- 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:
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).
CacheServicekeeps entries for at most 6 hours, with values up to 100 KB. To reset the cache, changeCACHE_VERSION. - Errors are returned as text in the cell rather than thrown, so you can see what happened right away:
401invalid key,402insufficient balance,429too many requests. - The
@customfunctioncomment 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:
- In the Apps Script editor, open Project Settings (the gear icon).
- Under Script Properties, add a
ZUKKO_API_KEYproperty with your key as the value. - 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):
| Quota | Consumer Google account | Google Workspace |
|---|---|---|
| UrlFetchApp calls per day | 20,000 | 100,000 |
| Custom function runtime | 30 seconds | 30 seconds |
| Script runtime | 6 minutes | 6 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:
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.
| Model | Price in/out per 1M | Calculation | Total |
|---|---|---|---|
glm-5.3-flash | $0.04 / $0.04 | 0.15 × 0.04 + 0.03 × 0.04 | $0.0072 |
gpt-5.6-luna | $0.1 / $0.1 | 0.15 × 0.1 + 0.03 × 0.1 | $0.018 |
claude-sonnet-5 | $0.3 / $0.3 | 0.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.
Related articles
- AI for testers: test cases, checklists and bug reportsHow a QA engineer can use a model for test cases, checklists and bug reports, check coverage, and avoid requirements the model made up.
- Anonymizing data before sending it to a neural network: a practical wayYou do not have to send personal data to a model for it to process a document. How to replace it with labels, restore it in the answer and check that nothing leaked.
- A neural network for HR: job posts, candidate emails and resume reviewA model can draft job posts and emails and do a first-pass resume review. What to hand over, how to treat candidates' personal data and how to prevent biased decisions.
- Generating an FAQ with a neural network from tickets and a knowledge baseA good FAQ is built on what customers really ask. A pipeline: group the tickets, answer from the knowledge base with a source reference, and verify the result.