Skip to content

client.campaigns

Outbound calling campaigns. These methods are on client.campaigns, where client is a MoreVoice client (see the Python SDK). On AsyncMoreVoice the same methods are awaited. Each one returns the response object and raises an exception when the API answers with an error.

Cancel a campaign. Stops the campaign for good: unanswered calls are hung up and the contacts not yet dialled are cancelled.

client.campaigns
def cancel(self, id: str, body: _m.CampaignActionParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Campaign

client.campaigns.cancel() · await async_client.campaigns.cancel() · POST /campaigns/{id}/cancel · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).

Campaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
livemode boolean true in live mode, false in test mode.
name string —
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).
purpose "marketing" | "service" | "survey" marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.
assistant_id string | null asst_… ID.
connection_id string | null The SIP connection it dials through; null: the default one.
caller_id string | null The number presented to contacts; null: the connection’s default.
priority integer 1–10; higher is served first when campaigns compete for lines.
max_concurrent integer Simultaneous calls this campaign may hold.
calls_per_second integer New calls per second; 0: only the connection limits it.
schedule CampaignSchedule When the campaign dials.
ring_timeout_seconds integer Hang up an unanswered call after this long.
retry CampaignRetry Retry policy per call result.
amd CampaignAmd Answering-machine detection.
disclosure CampaignDisclosure The AI and recording disclosure played at the start of each call.
first_message string Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.
script string Extra instructions for this campaign ({{variables}} allowed).
dispositions string[] Outcomes the assistant can record.
opt_out_dtmf_key string | null The key that opts a contact out; null: the organisation’s.
pause_reason string | null Why the campaign paused itself (for example, the national registry can’t check it).
stats CampaignStats Contact counts per status and the calls in progress.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign = client.campaigns.cancel("cmp_7Hk2Lm9Qp", {})
print(campaign)

Add contacts to a campaign. Adds up to 1,000 contacts and answers what was added and what was left out, like a dashboard import of the same list: numbers are normalised and de-duplicated, do-not-call numbers are kept as dnc (never dialled), and in a marketing campaign a contact without consent evidence is added but skipped by the dialer (§30A).

client.campaigns.contacts
def create(self, id: str, body: _m.ContactBatchParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.ContactBatchResult

client.campaigns.contacts.create() · await async_client.campaigns.contacts.create() · POST /campaigns/{id}/contacts · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
Field Type Required Description
contacts ContactInputInput[] yes Up to 1000 contacts.
default_country string no Country of numbers written without a country code (ISO 3166-1 alpha-2, default IL).
drop_dnc boolean no Leave numbers on the do-not-call list out entirely (default false: they are kept with status dnc, for the record, and never dialled).

ContactBatchResult:

Field Type Description
object "contact_batch_result" Always contact_batch_result.
campaign_id string A campaign ID (prefix cmp_).
livemode boolean true in live mode, false in test mode.
received integer Non-empty contacts / rows received.
imported integer Contacts added to the campaign for dialling.
rejected integer Contacts not added for dialling (invalid, duplicate, do-not-call).
rejected_reasons ContactRejectedReasons Rejected contacts per reason.
without_consent integer Marketing: contacts added without a consent record. The dialer skips them (§30A) unless consent is recorded first.
consent_recorded integer Consent records created from the evidence sent.
errors object[] Rejected contacts (the first 100).
warnings object[] Contacts added with a problem, e.g. consent claimed without complete evidence (the first 100).
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
contact_batch_result = client.campaigns.contacts.create("cmp_7Hk2Lm9Qp", {
"contacts": [
{
"consent": {
"channel": "web",
"granted_at": "2026-09-20T14:02:00+03:00",
"source": "website_form_2026",
},
"name": "Dana Levi",
"phone": "+972501234567",
"variables": {
"plan": "Gold",
},
},
{
"name": "Yossi Cohen",
"phone": "052-765-4321",
"variables": {
"plan": "Silver",
},
},
],
"default_country": "IL",
})
print(contact_batch_result)

Import a contact list in the background. Imports a CSV or XLSX list in the background through the dashboard’s import path and answers 202 with the import; poll GET /v1/imports/{id} until it succeeds or fails. Send the file as multipart/form-data (a file part plus the options as text fields, mapping as a JSON string), or as JSON: CSV text, a base64 file, or an https URL to download. An Idempotency-Key is required, so a retried upload never imports twice.

client.campaigns.contacts
def import_(self, id: str, body: _m.ContactImportParamsInput | _m.CampaignsContactsImportFilesBody | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.ContactImport

client.campaigns.contacts.import_() · await async_client.campaigns.contacts.import_() · POST /campaigns/{id}/contacts/import · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
Field Type Required Description
consent_channel "web" | "phone" | "sms" | "email" | "whatsapp" | "app" | "written" | "in_person" | … no How every consenting row consented, when the file has no channel column.
consent_source string no Where every consenting row consented, when the file has no source column.
csv string no The list as CSV text (UTF-8; comma, semicolon, tab or pipe separated).
default_country string no Country of numbers written without a country code (ISO 3166-1 alpha-2, default IL).
drop_dnc boolean no Leave do-not-call numbers out entirely (default false: kept with status dnc, never dialled).
file object no A CSV or XLSX file.
has_header boolean no The first row holds column names (default: detected).
mapping ImportMappingInput no Which column holds what: contact field → header name (or 0-based index). Any other key names a {{variable}}. Omit the mapping to detect the columns like the dashboard does.
url string no An https URL to download the CSV / XLSX from (public addresses only, ≤ 10 MB).

ContactImport:

Field Type Description
id string A import ID (prefix imp_).
object "import" Always import.
livemode boolean true in live mode, false in test mode.
campaign_id string A campaign ID (prefix cmp_).
status "pending" | "processing" | "succeeded" | "failed" pending → processing → succeeded | failed. Poll GET /v1/imports/{id}.
source "csv" | "xlsx" | "url" —
filename string | null —
received integer Non-empty contacts / rows received.
imported integer Contacts added to the campaign for dialling.
rejected integer Contacts not added for dialling (invalid, duplicate, do-not-call).
rejected_reasons ContactRejectedReasons Rejected contacts per reason.
without_consent integer Marketing: contacts added without a consent record. The dialer skips them (§30A) unless consent is recorded first.
consent_recorded integer Consent records created from the evidence sent.
errors object[] Rejected rows (the first 100).
warnings object[] Rows added with a problem (the first 100).
error object | null Why the import failed (status failed): a stable code and a message to show.
created_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
contact_import = client.campaigns.contacts.import_("cmp_7Hk2Lm9Qp", {
"csv": "Mobile,Name,Plan\n0501234567,Dana Levi,Gold\n0527654321,Yossi Cohen,Silver\n",
"default_country": "IL",
"mapping": {
"name": "Name",
"phone": "Mobile",
"variables": {
"plan": "Plan",
},
},
})
print(contact_import)

List a campaign’s contacts. Lists the contacts of a campaign, newest first, with each contact’s status, attempts and outcome. Filter by status (several, comma-separated), by outcome (the recorded disposition) or by phone.

client.campaigns.contacts
def list(self, id: str, *, limit: int | Unset = 20, starting_after: str | Unset = UNSET, ending_before: str | Unset = UNSET, status: str | Unset = UNSET, outcome: str | Unset = UNSET, phone: str | Unset = UNSET, more_voice_version: str | Unset = UNSET) -> AsyncPage[_m.CampaignContact]

client.campaigns.contacts.list() · await async_client.campaigns.contacts.list() · GET /campaigns/{id}/contacts · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
limit integer no How many objects to return, 1–100 (default 20).
starting_after string no A cursor (next_cursor) or object ID: return the objects after it (older).
ending_before string no A cursor or object ID: return the objects before it (newer).
status string no Only these statuses, comma-separated (e.g. pending,scheduled).
outcome string no Only contacts with this recorded disposition.
phone string no Only this number.

A page of results (CampaignContactList): data, has_more and next_cursor.

from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
for contact in client.campaigns.contacts.list("cmp_7Hk2Lm9Qp"):
print(contact)

List a contact’s dial attempts. Lists the dial attempts made to one contact of the campaign, newest first: when each one started, how it ended, and the call it placed.

client.campaigns.contacts
def list_attempts(self, id: str, contact_id: str, *, limit: int | Unset = 20, starting_after: str | Unset = UNSET, ending_before: str | Unset = UNSET, more_voice_version: str | Unset = UNSET) -> AsyncPage[_m.CampaignAttempt]

client.campaigns.contacts.list_attempts() · await async_client.campaigns.contacts.list_attempts() · GET /campaigns/{id}/contacts/{contact_id}/attempts · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
contact_id str yes A contact ID (ctc_…).
limit integer no How many objects to return, 1–100 (default 20).
starting_after string no A cursor (next_cursor) or object ID: return the objects after it (older).
ending_before string no A cursor or object ID: return the objects before it (newer).

A page of results (CampaignAttemptList): data, has_more and next_cursor.

from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
for contact in client.campaigns.contacts.list_attempts("cmp_7Hk2Lm9Qp", "ctc_7Hk2Lm9Qp"):
print(contact)

Retrieve a campaign contact. Returns one contact of a campaign: the number, its variables, its status, how many times it was dialled and the outcome.

client.campaigns.contacts
def retrieve(self, id: str, contact_id: str, *, more_voice_version: str | Unset = UNSET) -> _m.CampaignContact

client.campaigns.contacts.retrieve() · await async_client.campaigns.contacts.retrieve() · GET /campaigns/{id}/contacts/{contact_id} · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
contact_id str yes A contact ID (ctc_…).

CampaignContact:

Field Type Description
id string A contact ID (prefix ctc_).
object "campaign_contact" Always campaign_contact.
livemode boolean true in live mode, false in test mode.
campaign_id string A campaign ID (prefix cmp_).
phone string E.164.
name string —
variables Record<string, string> —
timezone string | null —
consent boolean The import said the person consented. Marketing calls also need a consent record with evidence (§30A).
status "pending" | "scheduled" | "callback" | "dialing" | "done" | "failed" | "dnc" | "skipped" | … pending → dialing → scheduled | callback → … → done | failed; skipped, dnc, invalid and cancelled are never dialled.
skip_reason string | null Why it is not dialled: dnc_import, dnc_dial_time, registry, no_consent, no_consent_evidence, no_calling_window, manual, …
attempts integer —
next_attempt_at string | null When it is due (dialable statuses only).
last_result string | null The last attempt’s result (answered, no_answer, busy, voicemail, …).
outcome string | null The disposition the assistant recorded.
outcome_data object | null —
last_call_id string | null call_… ID.
last_attempt_at string | null —
completed_at string | null —
row integer | null The row it came from in its import.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign_contact = client.campaigns.contacts.retrieve("cmp_7Hk2Lm9Qp", "ctc_7Hk2Lm9Qp")
print(campaign_contact)

Requeue or skip a campaign contact. status scheduled dials the contact again now (refused for a number on the do-not-call list); skipped takes it out of the campaign. A contact being dialled can’t change.

client.campaigns.contacts
def update(self, id: str, contact_id: str, body: _m.ContactUpdateParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET) -> _m.CampaignContact

client.campaigns.contacts.update() · await async_client.campaigns.contacts.update() · PATCH /campaigns/{id}/contacts/{contact_id} · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
contact_id str yes A contact ID (ctc_…).
Field Type Required Description
status "scheduled" | "skipped" yes scheduled: dial it again now (refused for a do-not-call number); skipped: take it out of the campaign.

CampaignContact:

Field Type Description
id string A contact ID (prefix ctc_).
object "campaign_contact" Always campaign_contact.
livemode boolean true in live mode, false in test mode.
campaign_id string A campaign ID (prefix cmp_).
phone string E.164.
name string —
variables Record<string, string> —
timezone string | null —
consent boolean The import said the person consented. Marketing calls also need a consent record with evidence (§30A).
status "pending" | "scheduled" | "callback" | "dialing" | "done" | "failed" | "dnc" | "skipped" | … pending → dialing → scheduled | callback → … → done | failed; skipped, dnc, invalid and cancelled are never dialled.
skip_reason string | null Why it is not dialled: dnc_import, dnc_dial_time, registry, no_consent, no_consent_evidence, no_calling_window, manual, …
attempts integer —
next_attempt_at string | null When it is due (dialable statuses only).
last_result string | null The last attempt’s result (answered, no_answer, busy, voicemail, …).
outcome string | null The disposition the assistant recorded.
outcome_data object | null —
last_call_id string | null call_… ID.
last_attempt_at string | null —
completed_at string | null —
row integer | null The row it came from in its import.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign_contact = client.campaigns.contacts.update("cmp_7Hk2Lm9Qp", "ctc_7Hk2Lm9Qp", {
"status": "skipped",
})
print(campaign_contact)

Create a campaign. Creates a draft campaign. Add contacts, then start it. The purpose decides the compliance checks: marketing needs consent with evidence (§30A) and, for Israeli numbers, the national do-not-call registry.

client.campaigns
def create(self, body: _m.CampaignCreateParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Campaign

client.campaigns.create() · await async_client.campaigns.create() · POST /campaigns · API reference

Field Type Required Description
name string yes —
purpose "marketing" | "service" | "survey" yes Required on create: marketing, service or survey. It decides the compliance checks.
amd object no —
assistant_id string | null no asst_… ID.
caller_id string | null no —
calls_per_second integer no —
connection_id string | null no conn_… ID.
disclosure object no —
dispositions string[] no —
first_message string no Overrides the assistant’s first message. {{variables}} come from the contacts’ variables, name and phone.
max_concurrent integer no —
opt_out_dtmf_key string | null no —
priority integer no —
retry object no —
ring_timeout_seconds integer no —
schedule object no —
script string no Extra instructions for the assistant. {{variables}} come from the contacts’ variables, name and phone.

Campaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
livemode boolean true in live mode, false in test mode.
name string —
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).
purpose "marketing" | "service" | "survey" marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.
assistant_id string | null asst_… ID.
connection_id string | null The SIP connection it dials through; null: the default one.
caller_id string | null The number presented to contacts; null: the connection’s default.
priority integer 1–10; higher is served first when campaigns compete for lines.
max_concurrent integer Simultaneous calls this campaign may hold.
calls_per_second integer New calls per second; 0: only the connection limits it.
schedule CampaignSchedule When the campaign dials.
ring_timeout_seconds integer Hang up an unanswered call after this long.
retry CampaignRetry Retry policy per call result.
amd CampaignAmd Answering-machine detection.
disclosure CampaignDisclosure The AI and recording disclosure played at the start of each call.
first_message string Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.
script string Extra instructions for this campaign ({{variables}} allowed).
dispositions string[] Outcomes the assistant can record.
opt_out_dtmf_key string | null The key that opts a contact out; null: the organisation’s.
pause_reason string | null Why the campaign paused itself (for example, the national registry can’t check it).
stats CampaignStats Contact counts per status and the calls in progress.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign = client.campaigns.create({
"assistant_id": "asst_3kTzL9Qe2R",
"name": "November renewals",
"purpose": "marketing",
"retry": {
"busy": {
"delay_minutes": 30,
},
"max_attempts": 3,
"no_answer": {
"delay_minutes": 240,
},
},
"schedule": {
"respect_shabbat": True,
"timezone": "Asia/Jerusalem",
"windows": [
{
"days": [
"sun",
"mon",
"tue",
"wed",
"thu",
],
"end": "19:00",
"start": "09:00",
},
],
},
})
print(campaign)

Delete a campaign. Deletes a campaign that is not running or scheduled, with its contacts and attempts. Calls already made stay in the call log.

client.campaigns
def delete(self, id: str, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.DeletedCampaign

client.campaigns.delete() · await async_client.campaigns.delete() · DELETE /campaigns/{id} · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).

DeletedCampaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
deleted true —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
deleted_campaign = client.campaigns.delete("cmp_7Hk2Lm9Qp")
print(deleted_campaign)

Export a campaign’s contacts or attempts as CSV. The dashboard’s export, streamed: UTF-8 with a byte-order mark (opens in Excel with Hebrew intact). kind=contacts (default) has one row per contact with its result and variables; kind=attempts one row per dial attempt.

client.campaigns
def export(self, id: str, *, kind: _m.CampaignsExportKind | Unset = "contacts", more_voice_version: str | Unset = UNSET) -> str

client.campaigns.export() · await async_client.campaigns.export() · GET /campaigns/{id}/export · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
kind "contacts" | "attempts" no contacts (default) or attempts.

Nothing, on success.

from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
data = client.campaigns.export("cmp_7Hk2Lm9Qp")
print(data)

List campaigns. Lists the campaigns of this mode, newest first, with each campaign’s contact counts. Filter by state or purpose.

client.campaigns
def list(self, *, limit: int | Unset = 20, starting_after: str | Unset = UNSET, ending_before: str | Unset = UNSET, state: _m.CampaignsListState | Unset = UNSET, purpose: _m.CampaignsListPurpose | Unset = UNSET, more_voice_version: str | Unset = UNSET) -> AsyncPage[_m.Campaign]

client.campaigns.list() · await async_client.campaigns.list() · GET /campaigns · API reference

Name Type Required Description
limit integer no How many objects to return, 1–100 (default 20).
starting_after string no A cursor (next_cursor) or object ID: return the objects after it (older).
ending_before string no A cursor or object ID: return the objects before it (newer).
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" no Only campaigns in this state.
purpose "marketing" | "service" | "survey" no Only campaigns with this purpose.

A page of results (CampaignList): data, has_more and next_cursor.

from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
for campaign in client.campaigns.list():
print(campaign)

Pause a campaign. Stops dialling new calls; calls in progress finish. Resume it to continue.

client.campaigns
def pause(self, id: str, body: _m.CampaignActionParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Campaign

client.campaigns.pause() · await async_client.campaigns.pause() · POST /campaigns/{id}/pause · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).

Campaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
livemode boolean true in live mode, false in test mode.
name string —
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).
purpose "marketing" | "service" | "survey" marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.
assistant_id string | null asst_… ID.
connection_id string | null The SIP connection it dials through; null: the default one.
caller_id string | null The number presented to contacts; null: the connection’s default.
priority integer 1–10; higher is served first when campaigns compete for lines.
max_concurrent integer Simultaneous calls this campaign may hold.
calls_per_second integer New calls per second; 0: only the connection limits it.
schedule CampaignSchedule When the campaign dials.
ring_timeout_seconds integer Hang up an unanswered call after this long.
retry CampaignRetry Retry policy per call result.
amd CampaignAmd Answering-machine detection.
disclosure CampaignDisclosure The AI and recording disclosure played at the start of each call.
first_message string Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.
script string Extra instructions for this campaign ({{variables}} allowed).
dispositions string[] Outcomes the assistant can record.
opt_out_dtmf_key string | null The key that opts a contact out; null: the organisation’s.
pause_reason string | null Why the campaign paused itself (for example, the national registry can’t check it).
stats CampaignStats Contact counts per status and the calls in progress.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign = client.campaigns.pause("cmp_7Hk2Lm9Qp", {})
print(campaign)

Check whether a campaign can start. Runs the checks that starting the campaign runs, without starting it: the same checks as the dashboard’s Start button. ok says whether it can start; errors block the start, warnings don’t. window_open and next_window_at say whether the campaign’s calling window (and Shabbat and holidays) lets it dial now, and when it next can.

client.campaigns
def preflight(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.CampaignPreflight

client.campaigns.preflight() · await async_client.campaigns.preflight() · GET /campaigns/{id}/preflight · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).

CampaignPreflight:

Field Type Description
object "campaign_preflight" Always campaign_preflight.
campaign_id string A campaign ID (prefix cmp_).
ok boolean No errors: the campaign can start.
errors string[] What blocks the start (missing assistant or connection, no contacts, no marketing consent, no registry, …).
warnings string[] What the dialer will skip or delay (contacts without consent, outside calling hours now, …).
dialable integer Contacts the dialer may call.
window_open boolean Calling is allowed right now (calling hours, Shabbat, holidays).
next_window_at string | null When calling is next allowed; null if never in the next 3 weeks.
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign_preflight = client.campaigns.preflight("cmp_7Hk2Lm9Qp")
print(campaign_preflight)

Resume a paused campaign. Runs the pre-flight checks again and resumes dialling.

client.campaigns
def resume(self, id: str, body: _m.CampaignActionParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Campaign

client.campaigns.resume() · await async_client.campaigns.resume() · POST /campaigns/{id}/resume · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).

Campaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
livemode boolean true in live mode, false in test mode.
name string —
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).
purpose "marketing" | "service" | "survey" marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.
assistant_id string | null asst_… ID.
connection_id string | null The SIP connection it dials through; null: the default one.
caller_id string | null The number presented to contacts; null: the connection’s default.
priority integer 1–10; higher is served first when campaigns compete for lines.
max_concurrent integer Simultaneous calls this campaign may hold.
calls_per_second integer New calls per second; 0: only the connection limits it.
schedule CampaignSchedule When the campaign dials.
ring_timeout_seconds integer Hang up an unanswered call after this long.
retry CampaignRetry Retry policy per call result.
amd CampaignAmd Answering-machine detection.
disclosure CampaignDisclosure The AI and recording disclosure played at the start of each call.
first_message string Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.
script string Extra instructions for this campaign ({{variables}} allowed).
dispositions string[] Outcomes the assistant can record.
opt_out_dtmf_key string | null The key that opts a contact out; null: the organisation’s.
pause_reason string | null Why the campaign paused itself (for example, the national registry can’t check it).
stats CampaignStats Contact counts per status and the calls in progress.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign = client.campaigns.resume("cmp_7Hk2Lm9Qp", {})
print(campaign)

Retrieve a campaign. Returns a campaign: its settings, its state and its contact counts. GET /v1/campaigns/{id}/stats has the detailed results.

client.campaigns
def retrieve(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.Campaign

client.campaigns.retrieve() · await async_client.campaigns.retrieve() · GET /campaigns/{id} · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).

Campaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
livemode boolean true in live mode, false in test mode.
name string —
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).
purpose "marketing" | "service" | "survey" marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.
assistant_id string | null asst_… ID.
connection_id string | null The SIP connection it dials through; null: the default one.
caller_id string | null The number presented to contacts; null: the connection’s default.
priority integer 1–10; higher is served first when campaigns compete for lines.
max_concurrent integer Simultaneous calls this campaign may hold.
calls_per_second integer New calls per second; 0: only the connection limits it.
schedule CampaignSchedule When the campaign dials.
ring_timeout_seconds integer Hang up an unanswered call after this long.
retry CampaignRetry Retry policy per call result.
amd CampaignAmd Answering-machine detection.
disclosure CampaignDisclosure The AI and recording disclosure played at the start of each call.
first_message string Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.
script string Extra instructions for this campaign ({{variables}} allowed).
dispositions string[] Outcomes the assistant can record.
opt_out_dtmf_key string | null The key that opts a contact out; null: the organisation’s.
pause_reason string | null Why the campaign paused itself (for example, the national registry can’t check it).
stats CampaignStats Contact counts per status and the calls in progress.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign = client.campaigns.retrieve("cmp_7Hk2Lm9Qp")
print(campaign)

Start a campaign. Runs the dashboard’s pre-flight checks and starts dialling (or schedules the start). A failed check answers 409 preflight_failed with the list. Once running, every call is still checked against the do-not-call list, consent, the national registry, the calling hours and Shabbat; a marketing campaign the registry can’t check pauses itself (pause_reason).

client.campaigns
def start(self, id: str, body: _m.CampaignStartParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Campaign

client.campaigns.start() · await async_client.campaigns.start() · POST /campaigns/{id}/start · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
Field Type Required Description
start_at string | null no Start later: the campaign is scheduled and starts dialling at this time.

Campaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
livemode boolean true in live mode, false in test mode.
name string —
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).
purpose "marketing" | "service" | "survey" marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.
assistant_id string | null asst_… ID.
connection_id string | null The SIP connection it dials through; null: the default one.
caller_id string | null The number presented to contacts; null: the connection’s default.
priority integer 1–10; higher is served first when campaigns compete for lines.
max_concurrent integer Simultaneous calls this campaign may hold.
calls_per_second integer New calls per second; 0: only the connection limits it.
schedule CampaignSchedule When the campaign dials.
ring_timeout_seconds integer Hang up an unanswered call after this long.
retry CampaignRetry Retry policy per call result.
amd CampaignAmd Answering-machine detection.
disclosure CampaignDisclosure The AI and recording disclosure played at the start of each call.
first_message string Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.
script string Extra instructions for this campaign ({{variables}} allowed).
dispositions string[] Outcomes the assistant can record.
opt_out_dtmf_key string | null The key that opts a contact out; null: the organisation’s.
pause_reason string | null Why the campaign paused itself (for example, the national registry can’t check it).
stats CampaignStats Contact counts per status and the calls in progress.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign = client.campaigns.start("cmp_7Hk2Lm9Qp", {})
print(campaign)

Retrieve a campaign’s results. Returns the campaign’s results so far: contacts per status, dial attempts per result with talk and ring time, the dispositions recorded, and the contacts compliance checks skipped, by reason.

client.campaigns
def stats(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.CampaignResults

client.campaigns.stats() · await async_client.campaigns.stats() · GET /campaigns/{id}/stats · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).

CampaignResults:

Field Type Description
object "campaign_stats" Always campaign_stats.
campaign_id string A campaign ID (prefix cmp_).
livemode boolean true in live mode, false in test mode.
contacts CampaignStats Contact counts per status and the calls in progress.
attempts object —
outcomes Record<string, integer> Contacts per recorded disposition (interested, not-interested, …).
skip_reasons Record<string, integer> Contacts the compliance checks or a user took out, per reason (dnc_import, registry, no_consent, …).
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign_results = client.campaigns.stats("cmp_7Hk2Lm9Qp")
print(campaign_results)

Update a campaign. Changes the fields you send and keeps the rest. A completed or cancelled campaign can’t change; pause a running one before changing its purpose.

client.campaigns
def update(self, id: str, body: _m.CampaignUpdateParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET) -> _m.Campaign

client.campaigns.update() · await async_client.campaigns.update() · PATCH /campaigns/{id} · API reference

Name Type Required Description
id str yes A campaign ID (cmp_…).
Field Type Required Description
amd object no —
assistant_id string | null no asst_… ID.
caller_id string | null no —
calls_per_second integer no —
connection_id string | null no conn_… ID.
disclosure object no —
dispositions string[] no —
first_message string no Overrides the assistant’s first message. {{variables}} come from the contacts’ variables, name and phone.
max_concurrent integer no —
name string no —
opt_out_dtmf_key string | null no —
priority integer no —
purpose "marketing" | "service" | "survey" no Required on create: marketing, service or survey. It decides the compliance checks.
retry object no —
ring_timeout_seconds integer no —
schedule object no —
script string no Extra instructions for the assistant. {{variables}} come from the contacts’ variables, name and phone.

Campaign:

Field Type Description
id string A campaign ID (prefix cmp_).
object "campaign" Always campaign.
livemode boolean true in live mode, false in test mode.
name string —
state "draft" | "scheduled" | "running" | "paused" | "completed" | "cancelled" draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).
purpose "marketing" | "service" | "survey" marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.
assistant_id string | null asst_… ID.
connection_id string | null The SIP connection it dials through; null: the default one.
caller_id string | null The number presented to contacts; null: the connection’s default.
priority integer 1–10; higher is served first when campaigns compete for lines.
max_concurrent integer Simultaneous calls this campaign may hold.
calls_per_second integer New calls per second; 0: only the connection limits it.
schedule CampaignSchedule When the campaign dials.
ring_timeout_seconds integer Hang up an unanswered call after this long.
retry CampaignRetry Retry policy per call result.
amd CampaignAmd Answering-machine detection.
disclosure CampaignDisclosure The AI and recording disclosure played at the start of each call.
first_message string Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.
script string Extra instructions for this campaign ({{variables}} allowed).
dispositions string[] Outcomes the assistant can record.
opt_out_dtmf_key string | null The key that opts a contact out; null: the organisation’s.
pause_reason string | null Why the campaign paused itself (for example, the national registry can’t check it).
stats CampaignStats Contact counts per status and the calls in progress.
created_at string An ISO-8601 timestamp in UTC.
updated_at string An ISO-8601 timestamp in UTC.
started_at string | null —
completed_at string | null —
from morevoice import MoreVoice
client = MoreVoice() # MOREVOICE_API_KEY from the environment
campaign = client.campaigns.update("cmp_7Hk2Lm9Qp", {
"max_concurrent": 20,
"schedule": {
"end_at": "2026-11-30T18:00:00+02:00",
},
})
print(campaign)