Apps Script 90-minute daily trigger runtime: polling Sume jobs
Consumer Google accounts get 90 minutes of trigger runtime a day. Poll Sume jobs from one time-driven trigger that scans the sheet, not one trigger per row.

Use one time-driven trigger that scans the sheet for rows with a job id and no terminal status, and checks each with GET /v1/jobs/{id}/status. Google's quota page lists total trigger runtime at 90 minutes a day for consumer accounts and 6 hours a day for Google Workspace accounts, and 20 triggers per user per script, so a trigger per row runs out of both long before a poll loop does.
Quota figures are from Google's Quotas for Google Services (read 2026-10-02); the status endpoint from Sume's Jobs and results. Google notes that quotas can change, so recheck the page before sizing.
Which Apps Script quotas matter for polling?
Three limits bite a poller, and they are separate from the 6-minute single-execution cap and the daily UrlFetch count covered in the UrlFetch post.
| Quota | Consumer account | Google Workspace account |
|---|---|---|
| Triggers total runtime | 90 min / day | 6 hr / day |
| Triggers | 20 / user / script | 20 / user / script |
| Script runtime | 6 min / execution | 6 min / execution |
| URL Fetch calls | 20,000 / day | 100,000 / day |
How much time can each poll run take?
This is arithmetic from the quota, not a measurement. A trigger that fires every 5 minutes runs 288 times a day. Dividing 90 minutes (5,400 seconds) by 288 gives about 18.75 seconds of runtime per run on a consumer account, and 6 hours (21,600 seconds) gives 75 seconds on Workspace. Every UrlFetchApp.fetch call spends that time, so a run that checks 40 open rows one by one needs to stay inside the average or the day's budget runs out before the day does.
Two ways to spend less: poll less often (Sume's status response can carry next_poll_after_seconds, which tells you when checking again is worthwhile), and only fetch rows still open. A finished row costs nothing the next time round.
What does the poll loop look like?
Columns here are A row id, B Sume job id, C status. The key is read from Script Properties, which Google limits to 9 KB per value and 500 KB per store, so keep ids in the sheet rather than in properties.
function pollSumeJobs() {
const sheet = SpreadsheetApp.getActiveSheet();
const key = PropertiesService.getScriptProperties().getProperty("SUME_API_KEY");
const rows = sheet.getDataRange().getValues();
const done = ["completed", "failed", "canceled"];
for (let i = 1; i < rows.length; i++) {
const jobId = rows[i][1];
if (!jobId || done.indexOf(rows[i][2]) !== -1) continue;
const res = UrlFetchApp.fetch(
"https://api.sume.com/v1/jobs/" + jobId + "/status",
{ headers: { Authorization: "Bearer " + key }, muteHttpExceptions: true }
);
if (res.getResponseCode() !== 200) continue;
const s = JSON.parse(res.getContentText());
if (s.terminal) sheet.getRange(i + 1, 3).setValue(s.sume_status);
}
}When is a webhook the better route?
When the poll budget is tight. Sume's mode: "webhook" sends the terminal event to a public HTTPS URL, so no trigger time is spent waiting. An Apps Script web app can receive it, but the doPost handler cannot read request headers, so it cannot check Sume's signature header; the doPost post covers that. Keep this poller as the backup either way, because Sume's docs say delivery is never the only recovery path.
Sources
Related posts
More in Integrations
- Apps Script UrlFetch 20,000 calls a day: budget Sume polling
Consumer Apps Script allows 20,000 UrlFetch calls a day and 90 minutes of trigger time. One Sume bulk run per sheet plus a slow poll fits well inside both.
- Make an avatar video from an MCP agent: tools, dry run, spend cap
The hosted MCP server of Sume exposes avatars_list, avatar-videos_create and jobs_wait. How dry_run and max_spend_usd gate a paid call, and the scope you need.
- Poll a Sume job from a CI step with curl and jq: exit codes
A 23-line bash script that polls /v1/jobs/{id}/status and exits 0, 1, 2 or 3, so a CI step can tell done, failed, still running and a bad request apart.
- Bun.serve webhook receiver for Sume: raw body, verify, dedupe
A 24-line Bun.serve receiver for Sume job webhooks: read the raw body first, verify sume-v1, dedupe on job_id, answer 204 before the work. Tested on Bun 1.4.
Written by Sume