Skip to content

Create a campaign

POST
/campaigns
import { createClient, createResources } from "@morevoice/sdk";
const mv = createResources({
client: createClient({ baseUrl: "https://api.morevoice.ai/v1", auth: process.env.MOREVOICE_API_KEY }),
});
const campaign = await mv.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",
},
],
},
});
console.log(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.

Try it in the API playground with a test-mode key.

MoreVoice-Version
string
/^\d{4}-\d{2}-\d{2}$/

The API version to use for this request. Defaults to the version the API key is pinned to.

Example
2026-11-01
Idempotency-Key
string
>= 1 characters <= 255 characters

A unique key (for example a UUID) that makes this request safe to retry: for 24 hours, a retry with the same key and parameters returns the first response instead of acting twice.

Example
5f0c1e8a-7b2d-4c3e-9f1a-2b6d8e4c0a17
Media typeapplication/json

A new campaign (state draft). Unset fields take the defaults the dashboard uses.

object
amd
object
message
string
<= 1000 characters
mode
string
Allowed values: off hangup leave_message
assistant_id
Any of:

A assistant ID (asst_…).

string
<= 200 characters /^asst_[0-9A-Za-z]+$/
caller_id
Any of:
string
<= 32 characters
calls_per_second
integer
<= 100
connection_id
Any of:

A connection ID (conn_…).

string
<= 200 characters /^conn_[0-9A-Za-z]+$/
disclosure
object
enabled

Null: the organisation’s default (on for marketing). A marketing campaign can’t turn it off through the API.

boolean | null
text
string
<= 1000 characters
dispositions
Array<string>
<= 50 items
first_message

Overrides the assistant’s first message. {{variables}} come from the contacts’ variables, name and phone.

string
<= 2000 characters
max_concurrent
integer
>= 1 <= 500
name
required
string
>= 1 characters <= 120 characters
opt_out_dtmf_key
Any of:
string
/^[0-9*#]$/
priority
integer
>= 1 <= 10
purpose
required

Required on create: marketing, service or survey. It decides the compliance checks.

string
Allowed values: marketing service survey
retry
object
busy
object
delay_minutes
integer
>= 1 <= 20160
enabled
boolean
declined
object
delay_minutes
integer
>= 1 <= 20160
enabled
boolean
failed
object
delay_minutes
integer
>= 1 <= 20160
enabled
boolean
max_attempts
integer
>= 1 <= 20
no_answer
object
delay_minutes
integer
>= 1 <= 20160
enabled
boolean
voicemail
object
delay_minutes
integer
>= 1 <= 20160
enabled
boolean
ring_timeout_seconds
integer
>= 5 <= 120
schedule
object
end_at
Any of:
string format: date-time
respect_holidays

Never dial on Jewish holidays. Like respect_shabbat, it can only add to the organisation’s setting.

boolean
respect_shabbat

Never dial on Shabbat. The organisation’s compliance settings enforce Shabbat for every campaign by default; this flag can add the restriction, never remove it.

boolean
start_at
Any of:
string format: date-time
timezone

IANA time zone of the windows and of contacts without their own, e.g. Asia/Jerusalem.

string
>= 1 characters <= 64 characters
windows
Array<object>
<= 14 items

A weekly calling window in the campaign’s time zone.

object
days
required

Weekdays the window applies to.

Array<string>
>= 1 items <= 7 items
Allowed values: sun mon tue wed thu fri sat
end
required

Closes at, local time (HH:MM, 24-hour).

string
/^([01]\d|2[0-3]):[0-5]\d$|^24:00$/
start
required

Opens at, local time (HH:MM, 24-hour).

string
/^([01]\d|2[0-3]):[0-5]\d$|^24:00$/
script

Extra instructions for the assistant. {{variables}} come from the contacts’ variables, name and phone.

string
<= 10000 characters

Created

Media typeapplication/json

An outbound calling campaign.

object
amd
required

Answering-machine detection.

object
message
required

The voicemail message (leave_message).

string
mode
required

Answering-machine detection: off, hang up on a machine, or leave message.

string
Allowed values: off hangup leave_message
assistant_id
required
Any of:

A assistant ID (prefix asst_).

string
/^asst_[0-9A-Za-z]+$/
caller_id
required

The number presented to contacts; null: the connection’s default.

string | null
calls_per_second
required

New calls per second; 0: only the connection limits it.

integer
>= -9007199254740991 <= 9007199254740991
completed_at
required
Any of:

An ISO-8601 timestamp in UTC.

string format: date-time
connection_id
required
Any of:

A connection ID (prefix conn_).

string
/^conn_[0-9A-Za-z]+$/
created_at
required

An ISO-8601 timestamp in UTC.

string format: date-time
disclosure
required

The AI and recording disclosure played at the start of each call.

object
enabled
required

Play the AI / recording disclosure before the first message. null: the organisation’s default (on for marketing).

boolean | null
text
required

The disclosure text; empty: the organisation’s.

string
dispositions
required

Outcomes the assistant can record.

Array<string>
first_message
required

Overrides the assistant’s first message ({{variables}} allowed); empty: the assistant’s.

string
id
required

A campaign ID (prefix cmp_).

string
/^cmp_[0-9A-Za-z]+$/
livemode
required

true in live mode, false in test mode.

boolean
max_concurrent
required

Simultaneous calls this campaign may hold.

integer
>= -9007199254740991 <= 9007199254740991
name
required
string
object
required
string
Allowed value: campaign
opt_out_dtmf_key
required

The key that opts a contact out; null: the organisation’s.

string | null
pause_reason
required

Why the campaign paused itself (for example, the national registry can’t check it).

string | null
priority
required

1–10; higher is served first when campaigns compete for lines.

integer
>= -9007199254740991 <= 9007199254740991
purpose
required

Marketing needs recorded consent with evidence (§30A) and a national-registry check for Israeli numbers.

string
Allowed values: marketing service survey
retry
required

Retry policy per call result.

object
busy
required
object
delay_minutes
required

Minutes before the next attempt.

integer
>= -9007199254740991 <= 9007199254740991
enabled
required

Retry after this result.

boolean
declined
required
object
delay_minutes
required

Minutes before the next attempt.

integer
>= -9007199254740991 <= 9007199254740991
enabled
required

Retry after this result.

boolean
failed
required

Network or carrier errors and interrupted calls.

object
delay_minutes
required

Minutes before the next attempt.

integer
>= -9007199254740991 <= 9007199254740991
enabled
required

Retry after this result.

boolean
max_attempts
required

Total dial attempts per contact, the first one included.

integer
>= -9007199254740991 <= 9007199254740991
no_answer
required
object
delay_minutes
required

Minutes before the next attempt.

integer
>= -9007199254740991 <= 9007199254740991
enabled
required

Retry after this result.

boolean
voicemail
required

An answering machine was detected.

object
delay_minutes
required

Minutes before the next attempt.

integer
>= -9007199254740991 <= 9007199254740991
enabled
required

Retry after this result.

boolean
ring_timeout_seconds
required

Hang up an unanswered call after this long.

integer
>= -9007199254740991 <= 9007199254740991
schedule
required

When the campaign dials.

object
end_at
required
Any of:

An ISO-8601 timestamp in UTC.

string format: date-time
respect_holidays
required

Never dial on Jewish holidays. Like respect_shabbat, it can only add to the organisation’s setting.

boolean
respect_shabbat
required

Never dial on Shabbat. The organisation’s compliance settings enforce Shabbat for every campaign by default; this flag can add the restriction, never remove it.

boolean
start_at
required
Any of:

An ISO-8601 timestamp in UTC.

string format: date-time
timezone
required

IANA time zone of the windows and of contacts without their own, e.g. Asia/Jerusalem.

string
>= 1 characters <= 64 characters
windows
required

When the campaign may dial. The organisation’s calling hours apply on top: a call happens only inside both.

Array<object>
<= 14 items

A weekly calling window in the campaign’s time zone.

object
days
required

Weekdays the window applies to.

Array<string>
>= 1 items <= 7 items
Allowed values: sun mon tue wed thu fri sat
end
required

Closes at, local time (HH:MM, 24-hour).

string
/^([01]\d|2[0-3]):[0-5]\d$|^24:00$/
start
required

Opens at, local time (HH:MM, 24-hour).

string
/^([01]\d|2[0-3]):[0-5]\d$|^24:00$/
script
required

Extra instructions for this campaign ({{variables}} allowed).

string
started_at
required
Any of:

An ISO-8601 timestamp in UTC.

string format: date-time
state
required

Draft → running ⇄ paused → completed | cancelled (scheduled: waits for schedule.start_at).

string
Allowed values: draft scheduled running paused completed cancelled
stats
required

Contact counts per status and the calls in progress.

object
by_status
required

Contacts per status.

object
callback
required
integer
>= -9007199254740991 <= 9007199254740991
cancelled
required
integer
>= -9007199254740991 <= 9007199254740991
dialing
required
integer
>= -9007199254740991 <= 9007199254740991
dnc
required
integer
>= -9007199254740991 <= 9007199254740991
done
required
integer
>= -9007199254740991 <= 9007199254740991
failed
required
integer
>= -9007199254740991 <= 9007199254740991
invalid
required
integer
>= -9007199254740991 <= 9007199254740991
pending
required
integer
>= -9007199254740991 <= 9007199254740991
scheduled
required
integer
>= -9007199254740991 <= 9007199254740991
skipped
required
integer
>= -9007199254740991 <= 9007199254740991
finished
required

Contacts that will not be dialled again (done, failed, do-not-call, skipped, invalid, cancelled).

integer
>= -9007199254740991 <= 9007199254740991
live
required

Calls in progress right now (this server’s dialer).

object
connected
required
integer
>= -9007199254740991 <= 9007199254740991
dialing
required
integer
>= -9007199254740991 <= 9007199254740991
ringing
required
integer
>= -9007199254740991 <= 9007199254740991
total
required

Contacts in the campaign.

integer
>= -9007199254740991 <= 9007199254740991
updated_at
required

An ISO-8601 timestamp in UTC.

string format: date-time
Example
{
"amd": {
"message": "",
"mode": "off"
},
"assistant_id": "asst_3kTzL9Qe2R",
"caller_id": "+97235550100",
"calls_per_second": 0,
"completed_at": null,
"connection_id": "conn_8DbH2nXy",
"created_at": "2026-11-01T08:00:00.000Z",
"disclosure": {
"enabled": null,
"text": ""
},
"dispositions": [
"interested",
"not-interested",
"callback-requested"
],
"first_message": "",
"id": "cmp_2Yb7mCq9aPLk",
"livemode": true,
"max_concurrent": 10,
"name": "November renewals",
"object": "campaign",
"opt_out_dtmf_key": null,
"pause_reason": null,
"priority": 5,
"purpose": "marketing",
"retry": {
"busy": {
"delay_minutes": 15,
"enabled": true
},
"declined": {
"delay_minutes": 240,
"enabled": false
},
"failed": {
"delay_minutes": 10,
"enabled": true
},
"max_attempts": 3,
"no_answer": {
"delay_minutes": 60,
"enabled": true
},
"voicemail": {
"delay_minutes": 120,
"enabled": true
}
},
"ring_timeout_seconds": 30,
"schedule": {
"end_at": null,
"respect_holidays": true,
"respect_shabbat": true,
"start_at": null,
"timezone": "Asia/Jerusalem",
"windows": [
{
"days": [
"sun",
"mon",
"tue",
"wed",
"thu"
],
"end": "20:00",
"start": "09:00"
},
{
"days": [
"fri"
],
"end": "13:00",
"start": "09:00"
}
]
},
"script": "Offer the {{plan}} renewal at the loyalty price.",
"started_at": "2026-11-02T07:00:00.000Z",
"state": "running",
"stats": {
"by_status": {
"callback": 3,
"cancelled": 0,
"dialing": 5,
"dnc": 9,
"done": 120,
"failed": 6,
"invalid": 1,
"pending": 812,
"scheduled": 40,
"skipped": 4
},
"finished": 140,
"live": {
"connected": 1,
"dialing": 2,
"ringing": 2
},
"total": 1000
},
"updated_at": "2026-11-02T07:00:00.000Z"
}

The request is invalid: a parameter is missing, malformed or unknown, or the version header is unknown.

Media typeapplication/json

Every /v1 error.

object
error
required
object
code
required

A stable, machine-readable code from the error-code catalogue.

string
details

Structured context, e.g. required_scope or the compliance verdict.

object
key
additional properties
doc_url
required

A link to the documentation of this code.

string
message
required

A human-readable explanation. Do not parse it.

string
param

The request parameter the error relates to, e.g. to or metadata[order_id].

string
request_id
required

The X-Request-Id of this request. Quote it when you contact support.

string
type
required

The category of the error.

string
Allowed values: invalid_request_error authentication_error permission_error not_found conflict rate_limit_error compliance_error idempotency_error api_error
Example
{
"error": {
"code": "parameter_missing",
"doc_url": "https://docs.morevoice.ai/api/errors#parameter-missing",
"message": "Missing required parameter: to.",
"param": "to",
"request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ",
"type": "invalid_request_error"
}
}
X-Request-Id
string

The request’s ID (req_…). Quote it when you contact support.

No valid API key was sent.

Media typeapplication/json

Every /v1 error.

object
error
required
object
code
required

A stable, machine-readable code from the error-code catalogue.

string
details

Structured context, e.g. required_scope or the compliance verdict.

object
key
additional properties
doc_url
required

A link to the documentation of this code.

string
message
required

A human-readable explanation. Do not parse it.

string
param

The request parameter the error relates to, e.g. to or metadata[order_id].

string
request_id
required

The X-Request-Id of this request. Quote it when you contact support.

string
type
required

The category of the error.

string
Allowed values: invalid_request_error authentication_error permission_error not_found conflict rate_limit_error compliance_error idempotency_error api_error
Example
{
"error": {
"code": "invalid_api_key",
"doc_url": "https://docs.morevoice.ai/api/errors#invalid-api-key",
"message": "Invalid API key.",
"request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ",
"type": "authentication_error"
}
}
X-Request-Id
string

The request’s ID (req_…). Quote it when you contact support.

The key may not do this (a missing scope, a plan limit, or a compliance block).

Media typeapplication/json

Every /v1 error.

object
error
required
object
code
required

A stable, machine-readable code from the error-code catalogue.

string
details

Structured context, e.g. required_scope or the compliance verdict.

object
key
additional properties
doc_url
required

A link to the documentation of this code.

string
message
required

A human-readable explanation. Do not parse it.

string
param

The request parameter the error relates to, e.g. to or metadata[order_id].

string
request_id
required

The X-Request-Id of this request. Quote it when you contact support.

string
type
required

The category of the error.

string
Allowed values: invalid_request_error authentication_error permission_error not_found conflict rate_limit_error compliance_error idempotency_error api_error
Example
{
"error": {
"code": "missing_scope",
"doc_url": "https://docs.morevoice.ai/api/errors#missing-scope",
"message": "This API key lacks the calls:write scope.",
"request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ",
"type": "permission_error"
}
}
X-Request-Id
string

The request’s ID (req_…). Quote it when you contact support.

The request conflicts with the object’s state, or the Idempotency-Key was reused with other parameters.

Media typeapplication/json

Every /v1 error.

object
error
required
object
code
required

A stable, machine-readable code from the error-code catalogue.

string
details

Structured context, e.g. required_scope or the compliance verdict.

object
key
additional properties
doc_url
required

A link to the documentation of this code.

string
message
required

A human-readable explanation. Do not parse it.

string
param

The request parameter the error relates to, e.g. to or metadata[order_id].

string
request_id
required

The X-Request-Id of this request. Quote it when you contact support.

string
type
required

The category of the error.

string
Allowed values: invalid_request_error authentication_error permission_error not_found conflict rate_limit_error compliance_error idempotency_error api_error
Example
{
"error": {
"code": "idempotency_mismatch",
"doc_url": "https://docs.morevoice.ai/api/errors#idempotency-mismatch",
"message": "This Idempotency-Key was already used with different parameters.",
"request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ",
"type": "idempotency_error"
}
}
X-Request-Id
string

The request’s ID (req_…). Quote it when you contact support.

Too many requests, or no call capacity right now. Retry after the Retry-After delay.

Media typeapplication/json

Every /v1 error.

object
error
required
object
code
required

A stable, machine-readable code from the error-code catalogue.

string
details

Structured context, e.g. required_scope or the compliance verdict.

object
key
additional properties
doc_url
required

A link to the documentation of this code.

string
message
required

A human-readable explanation. Do not parse it.

string
param

The request parameter the error relates to, e.g. to or metadata[order_id].

string
request_id
required

The X-Request-Id of this request. Quote it when you contact support.

string
type
required

The category of the error.

string
Allowed values: invalid_request_error authentication_error permission_error not_found conflict rate_limit_error compliance_error idempotency_error api_error
Example
{
"error": {
"code": "rate_limited",
"doc_url": "https://docs.morevoice.ai/api/errors#rate-limited",
"message": "Too many requests. Retry after 1 second.",
"request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ",
"type": "rate_limit_error"
}
}
Retry-After
integer

Seconds to wait before retrying.

X-Request-Id
string

The request’s ID (req_…). Quote it when you contact support.

Something went wrong on MoreVoice’s side. Retry with the same Idempotency-Key.

Media typeapplication/json

Every /v1 error.

object
error
required
object
code
required

A stable, machine-readable code from the error-code catalogue.

string
details

Structured context, e.g. required_scope or the compliance verdict.

object
key
additional properties
doc_url
required

A link to the documentation of this code.

string
message
required

A human-readable explanation. Do not parse it.

string
param

The request parameter the error relates to, e.g. to or metadata[order_id].

string
request_id
required

The X-Request-Id of this request. Quote it when you contact support.

string
type
required

The category of the error.

string
Allowed values: invalid_request_error authentication_error permission_error not_found conflict rate_limit_error compliance_error idempotency_error api_error
Example
{
"error": {
"code": "internal_error",
"doc_url": "https://docs.morevoice.ai/api/errors#internal-error",
"message": "Something went wrong on MoreVoice's side.",
"request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ",
"type": "api_error"
}
}
X-Request-Id
string

The request’s ID (req_…). Quote it when you contact support.