Short path: OpenAI-compatible API · Multi-model API · AI API pricing · Models
Last verified: August 3, 2026
To call an OpenAI-compatible API from Google Sheets, use a bound Apps Script, store the inference key in Script Properties, send JSON with UrlFetchApp.fetch, and write results back in one batch. Prefer a menu action over a volatile custom formula: spreadsheet recalculation can otherwise create repeated API calls, unpredictable cost and duplicate output.
The example below processes selected prompts from column A and writes answers to column B through LumeAPI's Chat Completions endpoint.
Set up the sheet and secret
- Create a sheet with
Promptin A1 andAnswerin B1. - Choose Extensions → Apps Script.
- In Project Settings → Script Properties, add:
LUMEAPI_API_KEY: your inference keyLUMEAPI_MODEL:gpt-5.6-terraor another current catalog ID
- Paste the script below and save it.
- Reload the spreadsheet and use the new LumeAPI menu.
Google documents Script Properties as project-scoped key-value storage. They are safer than placing a key in a cell or source file, but anyone with sufficient script-project access may still be able to view or use them. Choose access controls accordingly.
Runnable Apps Script
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('LumeAPI')
.addItem('Generate answers for selected rows', 'generateSelectedAnswers')
.addToUi();
}
function generateSelectedAnswers() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getActiveRange();
if (!range || range.getColumn() !== 1) {
throw new Error('Select one or more prompt cells in column A.');
}
const lock = LockService.getDocumentLock();
lock.waitLock(5000);
try {
const prompts = range.getValues();
const answers = prompts.map(([value]) => {
const prompt = String(value || '').trim();
if (!prompt) return [''];
try {
return [callLumeApi_(prompt)];
} catch (error) {
return [`ERROR: ${error.message}`];
}
});
sheet
.getRange(range.getRow(), 2, answers.length, 1)
.setValues(answers);
} finally {
lock.releaseLock();
}
}
function callLumeApi_(prompt) {
const properties = PropertiesService.getScriptProperties();
const apiKey = properties.getProperty('LUMEAPI_API_KEY');
const model = properties.getProperty('LUMEAPI_MODEL') || 'gpt-5.6-terra';
if (!apiKey) {
throw new Error('Missing LUMEAPI_API_KEY in Script Properties.');
}
const response = UrlFetchApp.fetch(
'https://api.lumeapi.site/v1/chat/completions',
{
method: 'post',
contentType: 'application/json',
headers: {
Authorization: `Bearer ${apiKey}`,
},
payload: JSON.stringify({
model,
messages: [
{
role: 'system',
content: 'Answer clearly. Do not invent missing facts.',
},
{ role: 'user', content: prompt },
],
temperature: 0,
}),
muteHttpExceptions: true,
},
);
const status = response.getResponseCode();
const text = response.getContentText();
let data;
try {
data = JSON.parse(text);
} catch (error) {
throw new Error(`HTTP ${status}: response was not JSON`);
}
if (status < 200 || status >= 300) {
const message = data.error && data.error.message
? data.error.message
: text.slice(0, 300);
throw new Error(`HTTP ${status}: ${message}`);
}
const answer = data.choices &&
data.choices[0] &&
data.choices[0].message &&
data.choices[0].message.content;
if (!answer) {
throw new Error('The API returned no assistant content.');
}
return answer;
}The code reads all selected prompts at once and writes all answers with one setValues call. It still makes one model request per non-empty row; the batch write reduces Sheets operations, not inference calls.
Why a menu action is safer than =AI(A2)
Custom functions can recalculate when referenced cells change, when the sheet opens, or when formulas are copied. A visible formula is also easy to fill down thousands of rows. A menu action makes the user choose a bounded range and run it intentionally.
| Pattern | Benefit | Risk |
|---|---|---|
| Custom formula | Familiar spreadsheet UX | Recalculation can repeat calls and cost |
| Menu action | Explicit range and timing | Requires authorization and a click |
| Installable trigger | Automated schedule or event | Runs as its creator and can fail out of view |
| External worker | Strong queues, retries and observability | More infrastructure |
For small editorial or classification batches, the menu pattern is a practical default. For large or regulated workloads, send jobs to a controlled backend rather than turning the spreadsheet into the execution engine.
Quotas and cost controls
Google's published Apps Script quotas are per user and can change. The current documentation lists daily URL Fetch limits and per-call size limits; a model provider has separate rate and billing limits. You must satisfy both systems.
Add these controls before letting a team use the sheet:
- cap the number of selected rows per run;
- skip rows whose answer column is already populated;
- add a confirmation dialog for large selections;
- record model ID and processed time in separate columns;
- use a document lock to prevent two users from running the same range concurrently;
- truncate or reject unexpectedly long prompts;
- keep sensitive data out of prompts unless policy permits the external request;
- review usage logs after the first real batch.
The exact google sheets openai api query is small, while the broader google sheets ai topic is larger and more competitive. One comprehensive owner page should therefore cover secret storage, UrlFetchApp, batching, quotas and repeat-call prevention instead of creating separate thin pages for every phrasing.
Troubleshooting
Authorization prompt appears: UrlFetchApp requires permission to make external requests. Review the requested scope and authorize only the intended script project.
401 response: verify the Script Property name and that the value is an inference key. Do not read the key from a spreadsheet cell.
404 response: confirm the URL contains /v1/chat/completions exactly once.
Model not found: copy the current ID from the LumeAPI model catalog.
Too many calls: reduce the selected range, skip completed rows and wait for quota or rate-limit recovery. Do not immediately rerun the whole batch.
Answers overwrite data: keep prompts in column A and reserve column B before running, or change the output column in the script.
Sources and testing boundary
- Google Apps Script <code>UrlFetchApp</code>
- Google Apps Script Properties Service
- Google Apps Script quotas
- Google Sheets and Apps Script
- LumeAPI developer documentation
The JavaScript was syntax-reviewed on August 3, 2026. No customer inference key or live Google Sheet was available in this editorial workspace, so run the script on a small test range and inspect both the Apps Script execution log and LumeAPI usage record before wider use.