> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymorfa.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Drip sequences

> Send campaign steps over days and enroll contacts as they arrive.

> [!NOTE]
>
> This beta contract is pending release. Access is unavailable until the beta is offered to your team.

Drip sequences are a beta. Your team must have access and join the beta before
creating a drip, launching or resuming it, or enrolling contacts. Requests without
access return `403 feature_unavailable`. Withdrawing pauses running drips before
their next send. Results remain readable. You can close continuous enrollment, pause or stop without beta access.

A drip sends up to 10 composed messages from linked-device or test numbers.
Every later step uses the number that sent the first. Templates, A/B variants,
weighted alternatives and receipt-timed `followUp` cannot be combined with a drip.

A drip can use a [saved audience segment](/guides/campaigns/audience-segments).
Selecting or launching that audience requires a team API key or signed-in
Dashboard session and access to both audience betas as well as the drip beta.
Launch freezes the matching profiles and their variables once. Later steps use
that snapshot; editing the segment does not change an active drip's recipients.
The same drip content and sending-number checks still apply.

## Build a drip in the Console

After your team joins the beta, open **Campaigns**, create a campaign and choose
**Drip**. On the **Steps** page:

1. Write each step's message. Add up to 10 steps and reorder them with **Move up**
   and **Move down**.
2. Set each later step's wait in days, hours and minutes, up to 30 days.
3. Optionally turn on **Step send window** to choose that step's days and hours.
   The step keeps the campaign time zone.
4. Choose **Launch audience** or **Continuous** enrollment and set the exit rules.

A drip can't use a message template, A/B variants or a follow-up. If a draft
already has a follow-up, the builder asks you to remove it before launch.

The campaign page shows enrollment totals and results for each step, numbered
from 1. For a running or paused continuous drip, **Close enrollment** stops new
enrollments and lets current contacts finish. It stays available after your team
leaves the beta. Each recipient row shows the steps
sent, the next step's time or why the contact left the drip.

## Create and launch with the API

Use `POST /platform/campaigns` with a team API key and `campaigns:manage`.
Project tokens derive the project from the credential; team keys supply `projectId`.
Replace the example IDs with your project and sending number IDs.

```json theme={null}
{
  "projectId": "01900000-0000-7000-8000-000000000001",
  "name": "Welcome series",
  "senderConfig": { "sessionIds": ["01900000-0000-7000-8000-000000000002"] },
  "drip": {
    "enrollment": "continuous",
    "exitOnReply": true,
    "exitOnLinkClick": false
  },
  "messagesArray": [
    { "version": 2, "source": "Welcome {{name | there}}" },
    {
      "version": 2,
      "source": "Here is your next tip",
      "delayAfterSec": 259200,
      "delayUnit": "days",
      "sendWindow": {
        "days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
        "hours": [{ "start": "09:00", "end": "17:00" }]
      }
    }
  ]
}
```

Launch with `POST /platform/campaigns/{campaignId}/launch`. Ordinary Campaigns
sender eligibility, approval, pacing, opt-out and safety checks still apply.
A drip with a Cloud API sending pool is refused at launch or paused before sending.

`delayAfterSec` is the minimum wait after the previous step was accepted, from 0
to 2,592,000 whole seconds (30 days). The first step has no delay. `delayUnit` is
optional display information: `minutes`, `hours` or `days`. Seconds must be a
whole multiple of that unit. Pacing, pauses and send windows can extend the wait.

The first step uses the campaign `sendWindow`. A later step's window replaces
its weekdays and hours, retaining the campaign time zone and recipient time-zone
settings. Without a campaign window, step windows use the team time zone saved
when drip settings were configured. Each step window accepts one to four non-overlapping hour ranges. Omit a step window to use the campaign window.

## Enroll contacts

`enrollment: "audience"` sends to contacts present at launch.
`enrollment: "continuous"` also accepts contacts while running or paused:

```http theme={null}
POST /platform/campaigns/{campaignId}/enrollments
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
```

```json theme={null}
{
  "projectId": "01900000-0000-7000-8000-000000000001",
  "phone": "+15555550123",
  "variables": { "name": "Ada" }
}
```

The response's `data` contains `campaignId`, `recipientId`, normalized `phone`,
`created`, `status` and `enrolledAt` (Unix milliseconds). Repeating a phone returns
`created: false` without changing its variables or restarting its steps, even if
the contact already completed or exited. An opted-out phone is stored as `skipped`
and receives nothing. A drip not accepting new enrollments returns `409 state_conflict`.

The same enrollment is available through
`POST /messaging/projects/{projectSlug}/campaigns/{id}/enrollments`.

Continuous drips stay open after all enrolled contacts finish. Close enrollment
with `PATCH /platform/campaigns/{campaignId}`, supplying `projectId` and
`drip: { enrollment: "audience" }`. Omitted exit flags keep their stored values. Once every
contact finishes, the campaign completes. You cannot reopen enrollment or change
step content after launch; duplicate the campaign for a new series.

Closing remains available after beta withdrawal. Send only `drip` and the project
selector in that PATCH. Omit the exit flags to preserve them, or send their
unchanged values. Bundled edits still require
beta access. Closing prevents new enrollments; it does not resume a paused drip
or send its remaining steps while beta access is unavailable.

Campaign list and detail reads return `enrollmentOpen`: `true` for continuous
enrollment, `false` for audience enrollment (including a closed drip), and `null`
for a non-drip. A continuous draft also returns `true`; enrolling still requires
running or paused status and beta access. `pauseReason` contains the current stored
pause reason while paused, or `null` for a manual pause without a reason, when
the current reason is unavailable, and for other statuses. A reason from an
earlier pause is not carried across a resume.

## Exits and results

Opt-outs always stop remaining steps. Replies to the sending number stop them
unless `exitOnReply` is false. With `exitOnLinkClick: true`, a GET request to any
of the campaign's tracked links also stops them when it records an open. HEAD
requests, known link previews, crawlers, security scanners and requests marked
as prefetch still redirect but do not record an open or stop remaining steps.
Detection is best effort: unknown or disguised automated fetches can still
count and trigger an exit. An open does not prove a person clicked. Configure tracked links
through the separate [link tracking beta](/guides/campaigns/link-tracking).
An already dispatched message can finish after an exit is recorded. A reply or
tracked-link request during the first send still stops all later steps, even
when the first send has not yet returned its result.

`GET /platform/campaigns/{campaignId}/analytics?projectId=...` returns `data.drip`:

* `enrollment`, `enrolled`, `enrolledByApi`, `active`, `completed` and `exited`.
* `steps`, ordered by zero-based `step`, with `entered`, `waiting`, `sent`,
  `delivered`, `read`, `replied`, `exited` and `failed` counts.

`entered` counts contacts who reached the step's delay, including every enrolled
contact for step 0. `waiting` includes queued and in-flight sends. Replies are
attributed to the latest sent step within seven days, before the next step.
Receipt counts depend on WhatsApp returning receipts. First-message campaign
counts retain their meaning; later sends appear in step results and recipient
logs with their message position. Each step is a separate send and follows the
same usage and billing rules as other campaign messages. No separate drip fee
is introduced.

A paused continuous drip keeps checking progress at least once a minute. Closing
its enrollment lets it complete once every contact is settled, even while paused.
Closing never resumes sending. If contacts still have steps waiting, resume or
stop the campaign explicitly.

A drip must contain at least one sendable composed message before launch. An
empty draft can be saved, but launch returns `400 invalid_parameter` on
`messagesArray` until content is ready. When no sending numbers are selected,
a drip uses eligible linked-device or test numbers from the project; Cloud API
numbers do not displace a supported test sender. Explicit selections still
must use a supported sending type.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.