Set the cadence once. Every run re-validates the sheet's structure, pulls with the right date semantics, appends safely and posts the summary — with history, alerts and a run-now button.
A schedule is a promise that the numbers will be there before anyone asks. Keeping that promise is less about cron and more about what each run verifies: the right period, the same structure as last time, a write that can't land twice.
Schedules resolve periods the way your team means them, in the report's timezone:
Timezone is resolved per source — AppsFlyer runs on the app's configured timezone, Meta on the ad account's — so a 'day' means the same thing everywhere in the report.
Scheduled writes stay within the constraints you approved at setup; anything outside them — drift, anomalies, a failed source — stops the run and pings you instead of guessing.
Every schedule keeps its receipts:
Schedules need lifecycle operations as disciplined as their runs. Pausing is one click and logged — used during client restructures, tracking migrations, or any week where writing would be worse than waiting. Resuming offers the backfill: the missed periods listed, each runnable through the full validated pipeline, in order. Changing a schedule — new cadence, new channel, an updated definition — is previewed like a write: here's the current specification, here's the proposed one, confirm. Every change lands in the schedule's history with who and when, which turns "why did the Tuesday report move to Monday?" into a one-line lookup instead of a Slack excavation. The lifecycle discipline matters because schedules outlive their creators: a report that has run for two years will be owned by three different people, and the specification plus its change history is the handover. Nothing about the system's behavior should live only in someone's memory — that's the standard the run ledger, the mapping versions and the schedule history are all built to. In practice this is what makes audits painless: when finance or a client asks how a report has been produced for six months, the answer is the specification, its change history and the ledger — three artifacts that already exist — rather than a reconstruction project. Governance, which sounded like overhead, turns out to be records that write themselves.
Real schedules meet real interruptions: a report paused for a client restructure, two missed weeks, a new report that needs history. Backfill is the same validated pipeline pointed backwards — "append weeks 21–23" runs each period through the identical checks (schema, duplicates, previews) and lands them in order under the right sections. Because the duplicate guard is period-aware, a backfill can never double an existing week, and because writes are append-only, it can never disturb the rows around the gap. History gets repaired the same way it gets written: boringly.
An agency's Monday is several Mondays: the Dubai client's week closes at GST midnight, the Paris client's at CET, the app data resolves in each app's configured timezone regardless. Opera schedules per report in that report's timezone and resolves each source in its own — so "Monday 7am, last full week" means the locally-correct thing for every client simultaneously. The alternative — one server timezone for everyone — is how Sunday evening spend ends up in two different weeks depending on the client, which is the kind of error that takes a quarter to notice.
What one client's schedule actually executes:
Four cadences, one stored specification, zero calendar reminders.
Every schedule keeps receipts you can actually read:
Wk 24 · Mon 07:00 — ✓ completed · schema ok · 4 pulls · appended row 31 · summary sent Wk 25 · Mon 07:00 — ✓ completed · schema ok · trailing re-pull adjusted Wk 24 CAC $13.91 → $13.74 Wk 26 · Mon 07:00 — ⚠ halted · schema drift: column F header changed "CAC" → "CAC (USD)" · nothing written · alert sent Wk 26 · Mon 09:12 — ✓ run-now after mapping confirmed · appended row 33
The Wk 26 pair is the system working as designed: a human renamed a column, the run refused to guess, the fix took two minutes, and the report's history contains zero corrupted rows.
Each client or team gets its own cadence, format and channel — a daily 8am pulse to #growth for one, a Monday 7am client report for another, a month-end roll-up for a third — all isolated, all logged, all running the same validated pipeline.
"Every Monday at 7am Dubai time, update all client weekly reports and send each its Slack summary."
Opera is built to touch production reports and live ad accounts without breaking anything:
See this running on your own reports.A 45-minute workflow audit maps your current process and shows exactly what Opera automates — step by step.
A 45-minute teardown of how you report today: we map every step, mark what Opera automates, and send you the written spec — useful whether or not you buy.