API referenceCampaigns
POST
/campaigns/{id}/senders/{accountId}/rebalance

JavaScript SDK: swarmhit.campaigns.rebalanceSender(campaignId, accountId)

Move a paused or failed sender's not-yet-contacted leads in this campaign onto the campaign's other available senders, evenly. Leads the sender already contacted stay pinned to it. Returns how many leads moved and how many receivers took them; receivers: 0 means no other sender was available and nothing moved (still 200). 422 when the account is not in the campaign's sender pool.

Authorization

bearerAuth
AuthorizationBearer <token>

An API key created on the Access tokens page.

In: header

Path Parameters

id*string
accountId*string

The sender account whose leads to move.

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/campaigns/string/senders/string/rebalance"
{  "data": {    "moved": 0,    "receivers": 0  }}

List campaigns GET

**JavaScript SDK:** [`swarmhit.campaigns.list(params?)`](/smart-api/sdk/methods#campaigns)

Update a campaign PATCH

**JavaScript SDK:** [`swarmhit.campaigns.update(campaignId, params)`](/smart-api/sdk/methods#campaigns) Updates any subset of a campaign's writable fields: `name`, `status` (set `active` to start sending, `paused` to stop), the sender pool (`linkedinAccountIds`), the outreach `sequence`, the send `schedule`, `aiInterestEnabled`, the email `unsubscribe` line and `tracking`, and the lead-exclusion rules (`excludeListIds` plus the `exclude*` flags). `sequence` and `schedule` are replaced wholesale — send the complete object you want, not a partial patch of it. A full `sequence` replacement can update the content of any step or A/B variant. For variant A, keep the step's legacy flat copy/media fields identical to the corresponding values in `config.variants[0]`; conflicting values are rejected with `400`. Updating a later variant only requires changing that variant object. For a single existing step or variant, prefer `PATCH /campaigns/{id}/sequence/{stepId}` so unrelated sequence structure cannot be overwritten. Once a campaign has leads in progress, the `sequence` may only be edited safely: you can change step messages and delays and append new steps, but removing, reordering or retyping existing steps is rejected with `400` (a lead's progress is pinned to a step id). Duplicate the campaign to rework its sequence from scratch. An `active` campaign must keep at least one sender: sending an empty `linkedinAccountIds` while the campaign is (or is being set) `active` is rejected with `400`. A campaign won't go `active` while a step has nothing to send: a `message`, `inmail`, `email` or `whatsapp_message` variant with no text (a file alone will do on a `message` or `whatsapp_message`), a `voice_note` without its recording, an `ai_voice_note` without its script, or the first `email` of a path without a subject. That is a `400` with `code: empty-step`: `message` names the steps by their number in the sequence, and `details.steps` lists them (`[{ id, type }]`) to fix with `PATCH /campaigns/{id}/sequence/{stepId}`. Once a campaign has been launched, a `sequence` that empties a step is refused the same way. With accounts of senders in its pools, a campaign won't go `active`, nor an active one change its pools, while a sender (or an account without one on the primary channel: LinkedIn when the sequence has a LinkedIn step or no step, else email, else WhatsApp) has no account on a channel the sequence uses and no account without a sender is there to share: a `400` with `code: sender-no-mailbox` or `sender-no-whatsapp`. Attaching senders with `senderIds` has its own refusals, listed there.