Bulk create or update contacts

Up to 500 per request, keyed on phone number, with the same merge rule as POST /contacts.

POST/v1/contacts/import

Body Parameters

  • contactsarray of ContactInputrequired

    At most 500 items.

  • campaign_idstring

    Applies to every opt_in row that does not name its own campaign_id Example: reg_a1B2c3D4e5F6.

  • dry_runboolean
  • check_line_typesboolean

    dry_run only. Looks up line types to count landlines; live lookups are paid, so only the first 500 numbers are checked.

  • import_idstring

    From a previous response, to group several requests as one import.

  • namestring

    A label for the import (first request only).

Details

Rows that cannot be imported come back in skipped; the rest still land. dry_run: true returns the summary (found, valid, malformed, duplicates, landlines, already opted out, will create / update, eligible) and writes nothing.

A row with opt_in.status: true (or a date or source) stores opt-in evidence in the consent ledger; opt_in.status: false records the number as opted out. An import never opts anyone back in.

Responses

  • 200JSON object

    Import result, or the dry-run preview

  • 400Error

    Invalid request

  • 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

  • 429Error

    Rate limit or quota exceeded

Response Fields

  • objectcontact_import, contact_import_preview
  • createdinteger
  • updatedinteger
  • skippedarray of object
  • skipped[].indexinteger

    Position of the row in the request

  • skipped[].valuestring
  • skipped[].reasonstring
  • import_idstring

    Example: imp_a1B2c3D4e5.

  • opted_outinteger

    Rows recorded as opted out because they were marked unsubscribed.

  • summaryobject

    dry_run only.

  • summary.foundinteger
  • summary.validinteger
  • summary.malformedinteger
  • summary.duplicatesinteger
  • summary.landlinesinteger

    null unless check_line_types was set Nullable.

  • summary.already_opted_outinteger
  • summary.marked_unsubscribedinteger
  • summary.will_createinteger
  • summary.will_updateinteger
  • summary.eligibleinteger

    Would receive a broadcast today

  • rejectedarray of object

    dry_run only.

  • rejected[].indexinteger
  • rejected[].phone_numberstring
  • rejected[].reasonmalformed, duplicate, landline
  • rejected[].detailstring

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

  • 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

  • 429

    Rate limit or quota exceeded