Skip to main content
POST
Resume campaign
Puts a paused campaign back to running. Contacts keep the state, attempt counts and retry timers they had when the campaign stopped, so nothing is re-called from the beginning. Resume runs the same preflight as launch and refuses with 422 CAMPAIGN_NOT_READY if the campaign still cannot dial — which is the common case after a paused_config pause, where the underlying problem (inactive number, agent with no duration cap, no reachable calling window) has to be fixed first. Required scope: campaigns:manage.

Path parameters

There is no request body.

Resumable statuses

draft, paused, paused_insufficient_credit, paused_budget, paused_infra, paused_config. completed, stopped and archived are terminal and return 400. Resuming an already-running campaign returns it unchanged with "message": "Already running". Resume and POST /campaigns/{id}/launch are the same operation; they differ only in the audit event recorded (resumed versus launched). Use launch for the first start and resume afterwards, so the campaign’s history reads correctly.

Fix the cause first

Example request

Example response

HTTP 200 with the full campaign object, same shape as GET /campaigns/{id}:
Trimmed for brevity — the real response contains every field listed on GET /campaigns/{id}. last_tick_result still shows the reason for the previous pause until the next evaluation overwrites it, roughly within a minute. started_at is not moved by a resume.

Errors

Authorizations

Authorization
string
header
required

Your Yappr API key (e.g. ypr_live_...). Generate one in the dashboard under Settings → API Keys.

Path Parameters

id
string<uuid>
required

Response

Campaign is running

A paced bulk-outbound dialing job over enrolled contacts.

A campaign is an admission-only scheduler. It decides when each enrolled contact becomes eligible, then performs one ordinary outbound call — the same queue, the same priority, and the same concurrency limits as a call placed with POST /calls. The pacing fields below only control how fast a campaign hands calls to that queue; a campaign call never takes precedence over anything else.

Campaigns are always created as draft and are launched with POST /campaigns/{id}/launch.

Two independent per-contact stop conditions apply, whichever fires first: max_attempts, and the stop-disposition set (stop_disposition_ids plus the stop_on_* booleans). Landing a stop disposition retires that contact permanently; any other outcome retries until the attempt cap.

Fields marked Engine-owned are written by the campaign engine and are never writable. Sending one on create or update returns 400, as does any field name that isn't on the writable list — a misspelled stop_dispositions is rejected rather than silently ignored, so you can never believe a kill switch is armed when it is not.

id
string<uuid>
company_id
string<uuid>
name
string
Example:

"July reactivation"

description
string | null
status
enum<string>

Engine-owned. Move it with the transition endpoints (launch / pause / resume / stop), never with PATCH.

draft — created, not dialing. scheduled — waiting for starts_at. running — admitting contacts. paused — paused by you. A manual pause is never lifted automatically; it survives a top-up. paused_insufficient_credit — balance is below the minimum needed to place a call. Auto-resumes shortly after the balance is topped up. paused_budget — budget_cents reached. paused_infra — repeated platform-side failures. paused_config — a permanent configuration problem (from-number no longer active, agent missing a call-duration cap, no reachable calling window). completed — every enrolled contact reached a terminal state. stopped — stopped by you. Terminal. archived — soft-deleted by DELETE /campaigns/{id}. Terminal.

Available options:
draft,
scheduled,
running,
paused,
paused_insufficient_credit,
paused_budget,
paused_infra,
paused_config,
completed,
stopped,
archived
agent_id
string<uuid> | null

Agent that runs the calls. Required before launch.

agent
object | null

Full Agent object for agent_id.

from_phone_number_id
string<uuid> | null

Number the campaign calls from. Required before launch, and must still be active at launch time.

from_phone_number
object | null

Full PhoneNumber object for from_phone_number_id.

from_number
string | null

Engine-owned. E.164 snapshot of the from-number, kept for audit even if the number is later released.

Example:

"+972551234567"

retry_rules
object

Optional per-outcome retry overrides. Free-form object — the explicit max_attempts / retry_*_seconds fields cover the common cases.

calling_window
object

Optional campaign-level narrowing of the workspace calling hours. Omit to inherit the workspace schedule (GET /call-windows). A campaign can only ever dial inside the workspace window — this field cannot widen it.

stop_disposition_ids
string<uuid>[]

Disposition IDs that retire a contact permanently when assigned — the campaign's kill switch. Always IDs, never labels: labels are renameable, and a rename would silently disarm the rule.

Do not list No Answer, Failed or Voicemail here. Those three are also auto-assigned to calls nobody picked up, so using them as stop dispositions retires contacts you did in fact speak to. Use stop_on_no_answer and stop_on_voicemail instead.

Must contain dispositions belonging to your company; anything else is rejected with 400.

stop_dispositions
object[]

Full Disposition objects for stop_disposition_ids.

stop_on_no_answer
boolean

Retire a contact the first time a call goes unanswered.

Example:

false

stop_on_voicemail
boolean

Retire a contact the first time a call reaches an answering machine.

Example:

false

stop_on_unclassified
boolean

What to do when the outcome that arrives is Unclassified — the call happened but could not be matched to any of your outcomes. false retries the contact, true retires it. This is not a timeout. A call's outcome is authoritative and a contact is never advanced without one: if classification is slow, only that contact waits while the campaign keeps calling everyone else.

Example:

false

max_attempts
integer

Per-contact dial cap. One of the two independent stop conditions — the other is the stop-disposition set.

Required range: 1 <= x <= 999
Example:

3

max_infra_retries
integer

Separate budget for retries after a platform-side failure — a call that never reached the person. These do not consume max_attempts and are never terminal.

Required range: 0 <= x <= 20
Example:

3

retry_no_answer_seconds
integer

Delay before retrying a contact who did not answer.

Required range: 30 <= x <= 604800
Example:

3600

retry_completed_seconds
integer

Delay before retrying a contact whose call completed but landed on a non-stop disposition.

Required range: 60 <= x <= 604800
Example:

86400

randomize_retry_time
boolean

Which time of day a retry lands on. false keeps the wait exact, so a one-week wait retries at the same hour a week later. true picks a different hour inside the campaign's calling window, so repeat attempts do not always arrive at the same moment. The wait length itself is unchanged either way — a randomized retry is still never earlier than the configured wait.

Example:

false

double_dial_enabled
boolean

Ring a second time shortly after an unanswered first ring.

Example:

false

double_dial_gap_seconds
integer

Gap between the two rings when double_dial_enabled is true.

Required range: 10 <= x <= 3600
Example:

90

max_calls_per_day
integer

Daily admission cap, counted against the workspace timezone day.

Required range: 1 <= x <= 100000
Example:

200

min_seconds_between_calls
integer

Minimum spacing between two calls handed to the queue by this campaign.

Required range: 0 <= x <= 86400
Example:

30

max_in_flight
integer

Calls this campaign may have live at once. Platform concurrency limits still apply on top — raising this does not buy the campaign extra capacity.

Required range: 1 <= x <= 8
Example:

2

budget_cents
integer | null

Hard spend cap for the campaign, enforced against spent_cents + reserved_cents (credits are debited when a call ends, so in-flight cost has to count). null means no cap. On hit the campaign moves to paused_budget.

Required range: x >= 1
regulatory_basis
enum<string> | null

Your lawful basis for calling this list. Required before launch — recorded on the campaign's launch audit record alongside the enrolled count. lawful_basis_confirmed is what the dashboard records: a single attestation that the caller has consent or another lawful basis for everyone on the list. The four specific values are for callers that know which one applies.

Available options:
lawful_basis_confirmed,
consent,
existing_customer,
non_marketing,
registry_screened
starts_at
string<date-time> | null

Do not admit contacts before this time.

ends_at
string<date-time> | null

Do not admit contacts after this time.

daily_admitted_count
integer

Engine-owned. Calls handed to the queue during the current day window.

daily_window_date
string<date> | null

Engine-owned. Day daily_admitted_count belongs to.

last_admitted_at
string<date-time> | null

Engine-owned. When this campaign last handed a call to the queue.

estimate_cents
integer | null

Engine-owned. Projected campaign cost at the time of launch.

spent_cents
integer

Engine-owned. Settled spend so far.

reserved_cents
integer

Engine-owned. Worst-case cost of in-flight calls, held against budget_cents until they settle.

last_tick_at
string<date-time> | null

Engine-owned. Last time the engine evaluated this campaign.

last_tick_result
string | null

Engine-owned. Machine-readable answer to "why is nothing happening right now" — e.g. daily cap reached, outside the calling window, waiting on in-flight calls.

last_error
string | null

Engine-owned. Last error the engine recorded for this campaign.

started_at
string<date-time> | null

Engine-owned. First launch time.

completed_at
string<date-time> | null

Engine-owned. When the last contact reached a terminal state.

total_leads
integer

Engine-owned. Contacts currently enrolled.

stats
object

Engine-owned counter roll-up. Prefer GET /campaigns/{id}/stats.

created_at
string<date-time>
updated_at
string<date-time>
created_by
string<uuid> | null

Null when the campaign was created via the API.