Send a batch

One body to up to 10,000 recipients, each with its own merge variables (or to contacts by tag), sent as individual messages through the normal pipeline.

POST/v1/batches

Body Parameters

  • fromstring

    One of your numbers. Optional while the key's mode has one number. Example: +15005550100.

  • bodystringrequired

    At most 1600 characters. Example: Hi {{first_name}}, your order {{order_id}} has shipped..

  • namestring

    At most 80 characters.

  • recipientsarray of object

    At most 10000 items.

  • recipients[].tostringrequired

    Example: +14155550132.

  • recipients[].variablesobject
  • tagsarray of string

    Send to contacts carrying any of these tags (instead of recipients).

  • contact_idsarray of string
  • segment_idstring

    Send to the contacts in this saved segment, evaluated when the batch is created (instead of recipients).

  • list_idstring

    Send to the contacts in this list, as it is when the batch is created (instead of recipients).

  • categorymarketing, transactional, otp

    Optional. It can make the batch stricter (marketing), never looser: the sending number's registration and the wording decide (which messages are marketing). From a number with no registration, a batch is marketing.

  • quiet_hoursblock, defer

    Optional. What to do with a message in the recipient's quiet hours: block refuses it (403 quiet_hours), defer holds it until their next 8:00am. Omitted: each recipient in quiet hours is held until their 8:00am.

  • topic_idstring

    Subscription topic. Recipients unsubscribed from it are removed at validation (topic_unsubscribed) and skipped at send time, like opt-outs. Omit to apply opt-outs only. Example: tp_marketing.

  • scheduled_atstring

    Future ISO timestamp or epoch ms, up to 30 days out.

  • dry_runboolean

    Validate only: returns a BatchValidation and sends nothing.

  • check_line_typesboolean

    Reject landlines (first 500 unique numbers are checked).

Details

Numbers are normalized, deduplicated and checked against opt-outs before queueing; rejected rows are returned with reasons. Set dry_run to validate without sending.

Responses

  • 200BatchValidation

    Dry run result

  • 201Batch

    Batch created

  • 400Error

    Invalid request or no valid recipients

  • 401Error

    Missing, malformed, or revoked API key

  • 402Error

    Billable live calls only: the prepaid credit balance cannot cover the call (insufficient_credits); nothing was done or charged

  • 403Error

    from not owned, or key mode does not match the number

  • 429Error

    Rate limit or quota exceeded

Response Fields (200)

  • objectbatch_validation
  • countsobject
  • counts.rowsinteger
  • counts.validinteger
  • counts.invalidinteger
  • counts.duplicatesinteger
  • counts.opted_outinteger
  • counts.topic_unsubscribedinteger

    Unsubscribed from the batch topic_id; 0 without a topic

  • counts.missing_variableinteger
  • counts.landlineinteger
  • counts.empty_after_mergeinteger
  • unknown_variablesarray of string
  • segmentsobject
  • segments.totalinteger
  • segments.maxinteger
  • segments.encodingGSM-7, UCS-2
  • estimated_cost_usdnumber
  • previewarray of object
  • preview[].tostring
  • preview[].bodystring
  • preview[].segmentsinteger
  • rejectedarray of object
  • rejected[].rowinteger

    0-based index into recipients

  • rejected[].tostring
  • rejected[].reasoninvalid, duplicate, opted_out, topic_unsubscribed, missing_variable, landline, empty_after_merge
  • rejected[].detailstring
  • consentobject

    Dry run only. What the consent gate would decide at send time for the first 1,000 accepted recipients: no_opt_in would be refused consent_required (marketing without an opt-in on file, or a recurring message from a registered number). Informational; every message is still checked when it sends.

  • consent.checkedinteger
  • consent.uncheckedinteger

    Accepted recipients past the first 1,000, not checked

  • consent.no_opt_ininteger
  • consent.no_opt_in_samplearray of string

    Up to 20 of them

  • consent.unknowninteger

    Consent could not be read; the send retries these

Response Fields (201)

  • idstring

    Example: bc_a1B2c3D4e5F6.

  • objectbatch
  • namestring
  • statusscheduled, sending, paused, complete, canceled
  • fromstring
  • bodystring
  • sourceapi, csv, contacts
  • testboolean
  • scheduled_atstring (date-time)

    Nullable.

  • created_atstring (date-time)
  • completed_atstring (date-time)

    Nullable.

  • countsobject

    total = queued + sent + failed + opted_out + canceled, always. "sent" = accepted by the carrier; what happened next (delivered, failed, replies) is GET /v1/batches/{id}/results. "opted_out" also counts recipients unsubscribed from the batch topic.

  • counts.totalinteger
  • counts.queuedinteger
  • counts.sentinteger
  • counts.failedinteger
  • counts.opted_outinteger
  • counts.canceledinteger
  • rejectedobject

    Rows dropped at validation (not part of total), by reason. Nullable.

  • variablesarray of string
  • retriesinteger

Errors

Every error has the same JSON shape, and request_id matches the X-Request-Id response header. Errors lists every code and what to do about it.

  • 400

    Invalid request or no valid recipients

  • 401

    Missing, malformed, or revoked API key

  • 402

    Billable live calls only: the prepaid credit balance cannot cover the call (insufficient_credits); nothing was done or charged

  • 403

    from not owned, or key mode does not match the number

  • 429

    Rate limit or quota exceeded