Campaigns
A campaign pairs one message with an audience, the accounts that send it, and the hours it may go out. This page covers its lifecycle, the checks before launch, how to write the message, and what Oqim guarantees about delivery.
Lifecycle#
- Only drafts can be launched (
POST /campaigns/{id}/start). Launching freezes the message and the audience: editing a template or a list afterwards doesn't change what's sent or to whom. - Resuming returns a campaign to
RUNNINGif it had started sending, otherwise toSCHEDULED. It's refused when the end time has passed (moveend_atfirst) or none of its accounts can send. - Scheduled, running and paused campaigns count toward your plan's limit on active campaigns.
- Duplicate copies any campaign into a new draft with the same message, audience, accounts and schedule, including a repeat rule.
- A campaign with a repeat rule runs as a series: each run is a campaign of its own going through this lifecycle, and Oqim adds and launches the next run when one completes. Cancelling a run stops the series. See Repeating campaigns.
When Oqim pauses a campaign
- An account in it stopped: Telegram restricted it, its session ended, it couldn't reach Telegram, or it hit a flood wait longer than the platform allows (15 minutes by default).
- Its failed and unreachable sends passed 35% of attempts, judged once it has made 40 attempts (platform defaults). This also opens an abuse report for the platform's administrators, because a high failure rate usually means the audience didn't expect the message. After you resume, only the sends made since the pause are judged.
- The organization was suspended; once it's reactivated, you resume these campaigns yourself. Or a platform administrator paused this campaign, which only the platform's support can undo.
Fix the cause, then resume. Paused campaigns never resume on their own.
Pre-launch validation#
Launch runs sixteen checks. A failed check blocks launch; a warning doesn't. Run them any time with POST /campaigns/{id}/validate; the report is also saved on the campaign as validation. If launch finds a failure it answers 422 campaign_invalid with the report in the response's validation field; see Errors.
Message length and variables are checked by rendering the message for up to 5,000 recipients from the audience. The report's estimated_hours is deliberately conservative: each active account sends at most one message per interval and its daily limit per open day, only while the window is open, plus 15% for retries and flood waits.
Writing messages#
parse_mode decides how the text is read. MARKDOWN, the default, uses the syntax below. HTML accepts Telegram's subset (b, strong, i, em, u, ins, s, strike, del, code, pre, blockquote, tg-spoiler and a href) and shows any other tag as text. PLAIN sends the text exactly as written.
- Links may use
http,httpsortg://. Consecutive lines starting with>form one quote. - Formatting doesn't span lines, except code blocks.
- Text is escaped before formatting is applied, and variable values are escaped too, so recipient data can't inject formatting. A recipient named
<b>Ann</b>sees exactly that.
Variables#
Add a fallback after a pipe: {{first_name|there}} renders there when the recipient has no first name. A variable with no value and no fallback renders as nothing, and validation warns about it. Names may contain letters, digits, underscores and dots, and spaces inside the braces are ignored.
Length limits#
Telegram allows 4,096 characters in a text message and 1,024 in the caption of a photo, document or video. Oqim counts the visible text after variables are filled in; formatting markup doesn't count. Because names and attributes vary, validation checks the longest rendering across your audience, not just the preview.
Attachments#
A campaign can carry one attachment, uploaded with POST /attachments or in the composer. JPEG, PNG and WebP images go out as photos (up to 10 MB), videos as videos, and anything else as a document; files can be up to 20 MB. The message text becomes the caption. disable_link_preview turns off the preview card Telegram would otherwise show for the first link.
Delivery and idempotency#
Each recipient in a campaign has exactly one delivery record. The worker that sends it gives Telegram a random_id derived from that record. If a send is retried after a timeout, a restart or a network error, Telegram recognises the repeat (RANDOM_ID_DUPLICATE) and the recipient still gets one message.
Send jobs carry only IDs and reload everything from the database right before sending, so a delayed or duplicated job can't send an outdated message or reach someone who opted out after launch. Network errors, timeouts and Telegram-side errors are retried on the same account with growing delays, up to 8 times; after that the delivery fails. Five such errors in a row mark the account disconnected.