readyDocs Open the appOpen the app

Send and control campaigns

#Send a campaign

Sends a draft, scheduled, paused or failed campaign now, at your per-segment rate for each recipient (check it first with quote). A send that goes out at once is charged from your balance before the first text; large sends go out over time at your account’s sending speed and are charged as each batch goes out. A paused campaign skips everyone it already texted, and a failed one skips everyone whose text didn’t fail. Needs the send_sms permission.

Parameters

attestation_idinteger
Instead of consent_attested: a consent record already made on your account for exactly this audience, less than 30 minutes old and not used yet.
send_nowboolean
true skips the automatic spreading of a large send over time.
send_capinteger
Send to only this many. Use affordable_recipients from an insufficient_balance answer.
More parameters (4)

Some sends answer 200 with success: false and a needs_confirmation field instead of sending. Nothing was saved, charged or sent. Read message, then repeat the same request with one of these answers.

confirm_empty_mergeboolean
Answer to empty_merge_field, when some recipients have no value for a merge field like {{contact.first_name}}. true sends with a blank there.
skip_empty_mergeboolean
Answer to empty_merge_field. true skips those people.
confirm_duplicateboolean
Answer to duplicate_campaign, when anyone in this audience got the same or a 90%-similar text from another campaign within 7 days. true sends anyway.
duplicate_exclude_blast_idinteger
Answer to duplicate_campaign: pass duplicate.other.id from that answer to send only to people who weren’t in that campaign.
Returns
data.statusstring
sending.
data.total_recipientsinteger
How many it’s going to.
data.staggeredboolean
true when it goes out over time. data.scheduled is then how many we queued.
data.interval_secinteger
Seconds between texts, when the send is paced: your drip_interval_sec, or a pace we picked to spread a large send. A campaign with smart_send_enabled, or with both ends of a delivery window set, goes out over time without it.
Errors
HTTPCodeWhen
400no_recipientsNobody in the audience can be texted.
400AUDIENCE_TOO_LARGEThe audience is over 500,000 recipients, the most one campaign sends to. Nothing is sent. Narrow it or split it into smaller campaigns.
400no_active_numberYou have no active number to send from.
400already_sentIt finished or was stopped. Duplicate it to send again, or use Send to the people it missed.
400ALL_ALREADY_SENTEveryone it would reach already got it.
402insufficient_balanceYour balance doesn’t cover even one recipient, or doesn’t cover the send_cap you set. On a send that goes out at once without send_cap, a short balance sends to as many people as it covers and data.balance_capped_from is the full audience. To text the rest, top up, then add the same audience to the campaign: anyone who already got it is left out. The answer has needed, affordable_recipients and total_recipients.
402monthly_limitIt would pass your monthly text limit.
402BILLING_PAST_DUEYour last payment failed. Update your card in Billing.
403attestation_requiredNo consent_attested: true and no attestation_id.
403attestation_*The attestation_id doesn’t fit: the code names why, like attestation_expired or attestation_list_hash_mismatch.
409already_sendingIt’s already sending.
409send_in_progressAnother request is already sending it.
422CONTENT_BLOCKEDThe message breaks the content policy. reasons lists why. Nothing is sent.
500SEND_UNCONFIRMEDSomething broke after sending may have started. Check the campaign instead of sending again.
500SEND_FAILEDNothing was charged or sent. Retry.
500SEND_FAILED_AFTER_CHARGEWe charged for the send and nothing went out. Schedule the campaign for now to send it with that payment, or delete it to get the charge back.
503BILLING_UNAVAILABLENothing was charged or sent. Retry in a moment.

#Pause a campaign

Pauses a scheduled campaign, or one sending over time. Texts already sent stay sent. Needs the send_sms permission. Returns the campaign as saved (the saved shape) with status: "paused".

Errors
HTTPCodeWhen
400not_pausableIt’s sending all at once. Use stop.
409state_changedIts status changed first. Check it and try again.

#Resume a campaign

Picks a paused campaign back up where it left off. Resuming is free; texts still to go that weren’t paid for when the send started are charged as they go out. Needs the send_sms permission. Returns the campaign as saved (the saved shape).

Errors
HTTPCodeWhen
400not_pausedIt isn’t paused.
409resume_conflictIt changed while we resumed it.
503resume_failedStill paused, nothing sent. Try again.

#Unschedule a campaign

Turns a scheduled campaign back into a draft. The older path /campaigns/:id/cancel still works and does the same. Neither stops a campaign that is sending; use stop for that. Nothing was charged yet, so there’s nothing to refund. Needs the send_sms permission. Returns the campaign as saved (the saved shape) with status: "draft".

Errors
HTTPCodeWhen
400already_sendingIt started sending. Use stop.
400not_scheduledIt isn’t scheduled.
409state_changedIts status changed while you unscheduled it. Check it and try again.

#Stop a campaign

Stops a sending or paused campaign for good. Texts already sent stay sent. You aren’t charged for people it never reached. On a campaign that is sending, the stop is seen within the next 100 or so recipients (per sending lane), so a few more texts can go out and the answer may still show status “sending”; it turns “completed” once the send stops. A paused campaign stops at once. Needs the send_sms permission. Returns the campaign as saved (the saved shape).

Errors
HTTPCodeWhen
400not_stoppableIt’s a draft, scheduled (use unschedule) or already finished.
500stop_failedThe stop didn’t take. Call it again.
500stop_unconfirmedWe couldn’t confirm the campaign stopped. Get the campaign, and call it again if it’s still sending.

#Get your sending speed

The most texts per second your account can send. Large campaigns are paced to it.

Returns
cap_per_secinteger
Your limit.
fallbackinteger
The speed we use if we can’t read yours.

#Send to the people it missed

Finishes a completed or failed campaign whose send was cut off: it texts the recipients who have no text from it yet, in the background. Recipients the first send already paid for aren’t charged again; the rest are charged from your balance at your per-segment rate before they go out. If your balance doesn’t cover them, nothing more is sent. Opted-out people are still skipped. A campaign you stopped is refused, and so is one that never texted anyone (send that one with Send a campaign). Needs the send_sms permission.

Returns
data.missedinteger | null
About how many it’s sending to, or null when we couldn’t count them.
data.notestring
What happens next, in a sentence.
Errors
HTTPCodeWhen
400never_sentNobody got it yet. Nothing was sent.
400still_sendingIt’s still sending. Try again once it has made no progress for a while.
404CAMPAIGN_NOT_FOUNDNo campaign with that id on your account, or you deleted it.
409blast_was_stoppedYou stopped it, so we won’t text the people it hadn’t reached.
409ALREADY_SENDINGAnother request is already sending the rest.
503CAMPAIGN_BUSYNothing changed. Try again in a few seconds.
500FINISH_UNCONFIRMEDSomething broke after sending may have started. Check the campaign before you try again.

#Send the rest now

For a campaign going out over time: moves every text still waiting to now and turns its pace off. Texts already picked up for the current batch aren’t moved, and waiting texts still keep to your delivery window. This call only changes when the texts go; each is charged as it goes out, the same as before. A campaign with nothing waiting answers flushed: 0. Needs the send_sms permission.

Returns
data.flushedinteger
How many waiting texts were moved to now.
data.notestring
What happened, in a sentence.
Errors
HTTPCodeWhen
404CAMPAIGN_NOT_FOUNDNo campaign with that id on your account.
409campaign_pausedIt’s paused. Resume it first.
409not_sendingIt’s a draft or scheduled and hasn’t started sending yet. Nothing changed, and its pace is kept.
500SEND_REMAINING_FAILEDNothing changed. Try again.

#Change a campaign’s pace

Sets how fast a campaign sends. On a draft or scheduled campaign it saves the pace for when it starts. On a campaign sending over time it re-spaces every text still waiting, starting now, inside your delivery window. Free; it doesn’t change what the texts cost. Send one of the fields below. Needs the send_sms permission.

Parameters

interval_secinteger
Seconds between texts. Read first when you send it.
per_hournumber
Texts per hour. per_second, per_minute and per_day work the same way. Without interval_sec, the first of per_second, per_minute, per_hour, per_day that is above 0 counts.

Every pace becomes whole seconds between texts, rounded up so it is never faster than you asked, from 2 seconds to 7 days.

Returns
interval_secinteger
The seconds between texts we saved.
per_hournumber
The same pace per hour.
pendinginteger
Texts still waiting. 0 before the campaign starts.
eta_hoursnumber
About how long the waiting texts take. Only on a sending campaign; a campaign that hasn’t started answers mode: "prestart" instead.
Errors
HTTPCodeWhen
400PACE_REQUIREDNone of the pace fields was a usable number.
400PACE_NOT_EDITABLEIt isn’t a draft, scheduled, or sending over time.
400NOTHING_PENDINGIt’s sending, but nothing is waiting.
404CAMPAIGN_NOT_FOUNDNo campaign with that id on your account.
409CAMPAIGN_STARTEDIt started sending while we saved. Nothing changed; try again.
503PENDING_READ_FAILEDNothing changed. Try again in a minute.

#Add recipients

Texts the same campaign to more people. It works on a campaign sending over time, a completed one (which starts sending again), or a scheduled one with hand-picked recipients. Anyone already in the campaign is left out. This call charges nothing itself: people added to a sending or completed campaign join the end of its queue at its pace and are charged as each batch goes out, at your per-segment rate, and a queued send can add the compliance surcharge, a per-segment charge for number validation and TCPA scrubbing, each when it’s on (see Billing; your per-segment price is compliance_usd_per_segment in Get your balance). People added to a scheduled campaign are charged when it sends. Needs the send_sms permission. The Campaign object says when this works in can_add_recipients.

Parameters

Pick the people with the same audience parameters as Create a campaign: recipient_filter, segment_id, recipient_rules or recipient_contact_ids.

Returns
addedinteger
How many were added.
skipped_existinginteger
How many were already in the campaign.
total_recipientsinteger
The campaign’s audience now.
resumedboolean
true when a completed campaign started sending again.
compliance_surcharge_usdnumber
An estimate of the compliance surcharge for the people added. It’s 0 when the estimate couldn’t be read, so 0 doesn’t promise there’s no charge: each wave is billed as it sends. Not on a scheduled campaign.
compliance_per_segment_usdnumber
The compliance surcharge per segment behind that estimate. Not on a scheduled campaign.
eta_hoursnumber | null
About how long until everyone waiting is texted. Not on a scheduled campaign.
Errors
HTTPCodeWhen
400CONSENT_REQUIREDNo consent_attested: true.
400campaign_not_extendableIt’s a draft, paused, sending all at once, failed, or scheduled with a filter or smart list audience. error says which.
400blast_was_stoppedYou stopped it. Duplicate it to reach these people.
400NO_ELIGIBLE_RECIPIENTSNobody you picked can be texted.
400ALREADY_IN_CAMPAIGNEveryone you picked is already in it. If you just retried, your first add went through.
402BILLING_PAST_DUEYour last payment failed. Update your card in Billing.
404CAMPAIGN_NOT_FOUNDNo campaign with that id on your account, or you deleted it.
409CAMPAIGN_CHANGEDThe scheduled campaign changed or started while we added. Nobody was added.
500CAMPAIGN_NOT_RESTARTEDPeople were added but the completed campaign didn’t start again, so they won’t be texted yet. Contact support; don’t add them again.

#Campaign results

Reads for one campaign while it sends and after. Any key can call them, test keys included. An id that isn’t a whole number answers 400 INVALID_ID, and one that isn’t a campaign on your account answers 404 CAMPAIGN_NOT_FOUND.

#Get delivery results

Delivery, reply and failure numbers for one campaign, by carrier, and by version for an A/B test. The answer is in data (and repeated at the top level for older clients). A part we couldn’t read is named in unavailable. Totals, carriers and failure reasons are then null, never a zero. The A/B numbers in by_variant read 0 when by_variant_delivery, by_variant_replies or by_variant_optout is in unavailable, so check it before you compare versions. Needs the view_reports permission.

Parameters

partsenum · query
totals answers only campaign, totals and by_variant. Faster.
Returns
data.campaignobject
id, name and status.
data.totalsobject
total sent, delivered, failed, pending, replies (people who replied), positive (positive replies), skipped, and delivered_pct, failed_pct, pending_pct.
data.carrier_breakdownobject[]
Per carrier: carrier, total, delivered, failed, pending. carrier is one of verizon, att, tmobile, uscellular, sprint, other, international, or (unknown) when no carrier is on record. These are the same words GET /sms/my-delivery-rate uses. Number health shows the display name instead (T-Mobile, Unknown carrier).
data.top_errorsobject[]
Up to 5 failure reasons, most common first: error_reason, error_detail, count and an explanation.
data.by_variantobject[]
Only for an A/B test. Per version: variant (A, B, ...), body, sent, delivered, failed, replied, positive_replied, optout.
Errors
HTTPCodeWhen
400invalid_fieldparts is something other than totals.
500BREAKDOWN_UNAVAILABLEWe couldn’t read the totals. Try again.

#Get skipped recipients

Why recipients were left out of a campaign, counted by reason, and the texts held for quiet hours.

Returns
data.reasons[]object[]
Each reason with a count above 0: reason (like opt_out or quiet_hours), count, and phrase, a short description or null.
data.heldobject
Texts still waiting for quiet hours to end: count and next_at, when the next one goes.
data.sent_after_quiet_hoursinteger
Texts held for quiet hours that have since gone out.
Errors
HTTPCodeWhen
500SKIPS_UNAVAILABLEWe couldn’t read them. Try again.

#Get the send schedule

For a campaign going out over time: how many texts are still waiting, per day, and when the next and last go. A campaign that sends all at once has nothing waiting, so its lists are empty.

Parameters

tzstring · queryDefault the campaign’s time zone
IANA time zone the days are counted in, like America/Chicago. Left out or unknown, the days are counted in the campaign’s own time zone, or UTC when it has none.
Returns
data.schedule_14d[]object[]
date and count for every day with a text waiting, not only the next 14.
data.pending_totalinteger
All texts waiting.
data.queued_nowinteger
Texts already due.
data.next_send_atISO 8601 string | null
When the next waiting text goes.
data.last_send_atISO 8601 string | null
When the last waiting text goes.
Errors
HTTPCodeWhen
500SCHEDULE_UNAVAILABLEWe couldn’t read it. Try again.