Update Contacts in Bulk
Change or clear fields on up to 5,000 contacts in a list in one call.
POST /update_contacts_bulk
Applies many updates to contacts in listname in one call. Each entry carries its own match, fields and clear_fields, with the same matching and the same write rules as Update a Contact.
Headers
Content-Type
application/json
Body
api_key
string
Required. Your API key.
listname
string
Required. The list the contacts are in.
contacts
array of objects
Required. One entry per update, each {match, fields, clear_fields}.
dry_run
boolean
Default false. When true, reports what would change and writes nothing.
Each entry's match, fields and clear_fields work exactly as on Update a Contact: null and "" values are skipped, clear_fields empties, and a field both set and cleared is refused.
Rules
All or nothing on field names. One unknown field name anywhere in the call refuses the whole call, so a typo cannot half-apply a batch.
Later entries win. When two entries reach the same contact, they are applied in order, field by field. A field only the first entry sets keeps its value; a field both set ends up with the second entry's value.
Up to 5,000 entries in one call. Past that, the call is refused rather than quietly truncated — send them in batches.
Send very large updates in batches. Use
dry_run: trueto see how many contacts a call would change, and keep each call to about 1,000 changed contacts. A call that changes 1,200 contacts typically answers in a few seconds.
Slow calls (504)
If a call takes longer than 75 seconds, it answers 504 with the message "The update is taking longer than usual and may still finish. Check the list, or run the same call with dry_run: true, before retrying."
A 504 does not mean the update failed. The work keeps going and may complete after the answer. Before sending it again, check the list, or repeat the call with dry_run: true. A 500 "Could not connect to the list service" means the call never reached the list and nothing changed.
Response
The same fields as Update a Contact, totalled across the whole call.
status
success, or not_found when nothing in the list matched.
data.list_name
The list.
data.rows_matched
How many contacts matched.
data.rows_updated
How many were changed.
data.fields_updated
Which fields were written, across all entries.
data.fields_cleared
Which fields were emptied, across all entries.
data.matched_on
Which identifier fields were used across the call.
data.dry_run
Whether this was a dry run.
credits_used
Always 0.
Example
The LinkedIn URL matched without https://www.. company_size appears in fields_updated although it was not sent: an exact headcount fills in the matching size band.
No match
A call that matches nothing answers status: not_found with rows_matched: 0 and the message No contacts in this list matched. Nothing changed and nothing was charged.