Scheduling
A campaign sends only inside its schedule: after its start, before its end, during its daily window and on its chosen weekdays, all in the campaign's own time zone. It can also repeat on a rule.
Schedule fields#
Times in the window are wall-clock times in the campaign's time zone, so a 10:00 window stays 10:00 across daylight-saving changes. start_at and end_at are absolute instants.
Daily windows#
A window that crosses midnight belongs to the day it opens. With window_days of [5] and 22:00–02:00, sending runs from Friday 22:00 to Saturday 02:00, and not on Saturday night.
Validation fails when the window is empty (start equals end), when no days are set, or when the window never opens between the start and the end time.
Repeating campaigns#
Set recurrence on a draft to send it again on a rule: every few days, on chosen weekdays, or on a day of the month. Each send is a run: a campaign of its own, with its own audience, counters and delivery log, linked to the first run by series_id and numbered by occurrence.
Rule errors come back per field, like recurrence.weekdays. The rule can change only while the campaign is a draft.
When runs happen
- You launch the first run, and it needs a
start_at. Every later run starts at the first run's time of day, on the dates the rule allows, in the campaign's time zone. A 10:00 run stays at 10:00 across daylight-saving changes; a time the clocks skip, such as 02:30 on the night they jump forward, moves to 03:30, and a time that happens twice is the first one. - The interval counts from the first run: every 2 weeks means the first run's week, then every other week. A Monday and Thursday rule whose first run is on a Tuesday runs next on that Thursday.
DAILYruns only on the campaign's sending days, so daily with Monday to Friday sends on weekdays. A monthly run whose date isn't a sending day starts on it and waits for the window to open.- Runs never overlap. The next run is placed when the current one finishes, on the first date after that; dates missed while a run was still sending are skipped, not made up.
- A run lasts as long, on the wall clock, as the one before it: 10:00 to 18:00 is followed by 10:00 to 18:00.
How each run is added and launched
- When a run completes, Oqim adds the next one as a draft, named like Weekly digest · run 3, with the same message, attachment, audience definition (lists, tags and chosen recipients), accounts, window, time zone and rule, and notifies the organization.
- At
auto_launch_at, 15 minutes before the run starts, Oqim launches it with the same checks asPOST /campaigns/{id}/start: organization active, acceptable-use policy accepted, room in the plan, healthy accounts, consent and a valid schedule. The audience is resolved then, so people added to a list since the last run get it and people who opted out don't. - If a check fails, the run stays a draft, its automatic launch is called off, and the organization is notified with the reasons. Fix the cause and launch it yourself; the series goes on from there.
- Until it launches, the next run is an ordinary draft. Edits apply to it and carry over to the runs after it. A new start or end time applies to this run only; its automatic launch moves with its start, and later runs keep the rule's times.
Stopping a series
POST /campaigns/{id}/stop-repeatingon any run stops the series; a run in progress finishes normally. The next run waiting to launch is deleted if nobody edited it, and kept as an ordinary draft if someone did. The run you call it on is always kept.- A series also ends after its last run (
AFTER), when no date is left beforeuntil, when a run is cancelled or fails, or when the next run is deleted while it's a draft. - Each of these endings sends a webhook event,
campaign.repeat_stopped, with the reason. Settingrecurrencetonullon the next run instead makes that run the last one.
A run keeps recurrence while it still leads to another run; once its successor is added, its own copy is cleared. next_run_at projects when the run after a campaign would start. GET /campaigns/{id} adds a series summary: runs launched so far, the planned total, whether it still repeats, the rule, the next run and the runs before and after this one.
Pausing and resuming#
- Pausing stops dispatch immediately; a message a worker has already picked up may still go out. Running and scheduled campaigns can be paused.
- While paused or scheduled you can change the end time, the window, the days and the accounts. The message and the audience are fixed at launch.
- Resuming outside the window is fine: the campaign waits for the window to open. A campaign that never started goes back to
SCHEDULED. - A pause by Oqim, after a restriction, a long flood wait or a high failure rate, has a
status_reason. Deal with the cause before resuming.
How dispatch paces accounts#
The scheduler runs every second. It starts scheduled campaigns whose start time has come, completes those past their end time, and then, for each running campaign whose window is open, looks for the campaign's accounts that are ready to send: ACTIVE, not cooling down, with no message in flight, under their daily limit and past their next send time. It hands each ready account one message. When the send finishes, the account's next send time is set min_interval_seconds ahead.
- Recipients go to whichever account is ready next. Three accounts at 8-second intervals deliver roughly one message every 3 seconds between them, while each sends at most one every 8 seconds.
- An account in several campaigns has one pace, one daily limit and one message in flight across all of them, and serves the campaigns in turn.
- Pacing is exact. There's no random jitter, nothing speeds up to catch up, and no message moves to another account to get around a limit. If the window closes before everyone is reached, sending continues at the same pace when it next opens.
- At
end_atthe campaign completes; recipients not yet sent to are marked cancelled.