Base de conhecimento GetMyBot

Campaigns

Multi-step automated subscriber journeys: immutable versions, entry triggers, graph nodes, preflight, publishing, per-version reports, and one journey's trace.

Nesta página

A campaign is a multi-step automated subscriber journey: entry on a trigger, then a sequence of nodes (messages, delays, conditions, experiments) that can stretch over days or weeks. It is not the same thing as a broadcast or an email campaign , those send one content document in one wave; a campaign is a branching graph that reads and changes subscriber data at every step.

Versions and the draft

A campaign always has exactly one editable draft, and, once it has ever been published, a history of immutable versions: draft → published → retired. The draft carries the trigger, audience, settings, and node graph. Editing the draft goes through PUT /draft with an expected_revision: if someone else already saved the draft first, the request is rejected as a conflict instead of silently overwriting their edit.

Publishing (POST /publish) freezes the current draft as a new published version and immediately opens the next draft as its copy. A subscriber who entered while version N was published walks their whole path on version N, even after version N+1 is published later: the trigger, audience, settings, and graph an already-running journey is executing never change under it.

The node graph can only be edited while the campaign is stopped: saving a graph while the campaign is Running or Paused is refused: a subscriber may be sitting on exactly that node by its id, and the executable graph must not change under a live subscriber.

Separate from versions, there is cloning: any existing version: a draft, a published one, or a retired one: can be opened as a new draft, replacing whichever draft is currently open. A campaign can also be archived (taken off the active list without deleting its history), but only while stopped.

Entry triggers

  • Manual: no configuration; the editor's "send a test to myself" button takes the same path and runs the entry node immediately, without waiting for the background sweep.
  • Site event: the same client SDK/widget event as in reactions, with the same condition editor.
  • Schedule: once, at a fixed instant, or recurring. A recurring schedule is a local time of day (HH:MM) in an explicit IANA timezone: "Local" is refused: an optional weekday filter, and mandatory start_at/end_at no more than two years apart: a recurring schedule must have an end, or a forgotten campaign would sweep the audience forever. A wall-clock moment that does not exist because of a spring-forward transition is simply absent from the schedule by default; the "next valid instant" policy moves it to the end of the gap instead of skipping it.
  • Label changed: one specific label added or removed, never both at once : those are different journeys with different content.
  • Property changed: a transition of one approved profile property from one state to another. The "previous" and "new" conditions are independent and both optional; re-saving the same value is not a transition and never triggers entry.
  • Segment entered: a membership transition from "not a member" to "member" of a ready segment. An ordinary recompute that merely reconfirms existing membership does not count as entry.

Graph nodes

The graph is nodes and edges, and an edge carries a branch label (for example yes/no). Exactly one node has no incoming edges: the entry point; terminal nodes ("Goal", "Exit") have no outgoing edges, and every node must have a path to at least one terminal: a graph with an unreachable node or a node with no path to a finish will not save. One node's configuration is capped at 32 KiB; a campaign as a whole is capped at 200 nodes and 400 edges.

  • Message: text/photo/file/delay blocks, run as an ordinary reaction against the same subscriber. AI blocks, a nested reaction, "expected answer" state, and parameter writes with a side effect are not supported here: retrying the node after a failure has to stay safe.
  • Content: unlike "Message", sends one specific published, version- pinned content document on one explicitly named channel (Telegram, VK, WhatsApp, or web chat), and never switches channel by itself: an unreachable recipient either takes a separate "when unavailable" branch, if one is wired, or the node fails visibly.
  • Delay: waits a fixed number of seconds (up to 180 days).
  • Wait for event: waits for a client event by name (up to 64 characters, no reserved $ prefix) with a timeout of up to 180 days; the node has exactly two branches: the default one (the event arrived) and timeout.
  • Condition: branches yes/no on subscriber parameters, time periods, time since last seen, or message count: the same condition vocabulary as reactions.
  • Split: a weighted A/B branch: a subscriber lands in the same branch deterministically, by a hash of the node and their own id, and that does not change on re-evaluation or restart.
  • Experiment: branches on a shared experiment's variant, with a pinned experiment id and version; two to sixteen variants, and every declared variant is a mandatory branch: an unwired variant would silently strand whoever the experiment assigns to it.
  • Channel available: branches yes/no on whether the subscriber can actually be reached right now on one explicitly named channel (email and phone do not qualify: neither is a delivery channel). It exists so an author decides the fallback channel question explicitly, rather than relying on a send silently switching channel on its own.
  • Action: change labels; unset parameters (setting, appending, and incrementing are not supported here: the same retry-safety principle as "Message"); a synchronous web request (no async mode, no nested reaction on success/error; the Idempotency-Key header is reserved: the platform sets it itself and sends the same value when the same step is retried, so your endpoint can use it to drop duplicates, and you cannot set your own); sync to a connected CRM; assign the support dialog to an agent or a group; emit a customer event (the same as a widget track() call: segments, funnels, and a matching trigger will see it); start a lead bot.
  • Goal and Exit: terminal nodes with no configuration: the first is a successful finish, the second is leaving without one.

Preflight and publishing

POST /preflight checks the current draft's shape (the same graph validator that runs on every save) and its cross-entity references: do the named segments, content documents, and experiments actually exist: and sends nothing. The response is ready, the version number, its checksum, and a list of errors with a code (invalid_graph, invalid_reference) and a message. Preflight does not estimate audience size, channel eligibility, or consent: that is out of scope for it.

POST /publish re-runs the same reference checks again, in one transaction: a client that skipped preflight, or whose world changed since, still cannot publish a campaign pointing at a deleted segment or document. Publishing requires the draft's current revision: a stale revision or an already- published draft returns a conflict with no partial result.

Per-version reports and the journey trace

The report (GET /report) is computed per version, not for the campaign as a whole: version N and version N+1 carry different counters, and publishing a new version never shifts an old one's numbers. The report has a journey funnel (entered, active, waiting, on retry, done, exited, failed) and, per node, entered/completed/failed counts. A report is sealed once its version can no longer take a new entrant and no journey on it can move any further: those numbers are stored as final and never recomputed; a live published version's report is always recomputed on read.

One journey's trace (GET /journeys/{subscriberID}/{runNo}) is a bounded event log: entering a node, an effect firing, parking on a wait, leaving a wait, a retry being scheduled, giving up after exhausting attempts, finishing. The trace carries ids, branches, attempt counts, and error codes: never a message body or a provider response: it is an audit of the path taken, not a copy of what was sent. A truncated flag shows a journey exceeded the event cap and part of its history was not kept. A separate list (GET /failures) shows who is stuck, and on which node, after the runner exhausted its attempts; a stuck journey can be retried (POST /journeys/{subscriberID}/{runNo}/retry).

Quiet hours

A version has a free-form settings blob, seeded by default as {"allow_reentry": false, "timezone_mode": "bot", "quiet_hours": {"enabled": false}}. Re-entry (allow_reentry) is a separate, genuinely enforced field on the campaign itself (not on version settings): it decides whether one subscriber may enter the campaign a second time. timezone_mode and quiet_hours inside settings, however, are currently a reserved configuration shape only: the campaign runner does not read or apply them. That is what sets them apart from the same-named feature in Web Push, where quiet hours genuinely defer delivery. Do not assume a campaign will wait for a "convenient" time on its own: model a pause with a "Delay" node or a time-period condition instead.

Permissions

Personal tokens and roles see campaigns through three separate scopes: campaigns:read, campaigns:write, and campaigns:publish: publishing a version and retrying a stuck journey are kept apart from ordinary draft editing. All three require the "Reactions" bot right: without it, the campaigns section is neither visible nor reachable for reading or writing.

What's next