Bulk actions and contact timeline
Change many contacts in one request, take back a bulk assign, and work with one contact: its activity history, its pinned number and its spam flag.
If a team member has "Only see assigned contacts and conversations" turned on, and isn’t an owner or admin, they can only act on contacts assigned to them or not assigned to anyone. The single-contact routes on this page answer 403 CONTACT_NOT_ASSIGNED for anyone else’s contact. The bulk routes skip those contacts instead, so check the count they return.
#The Bulk action object
tokenstring- Pass it to Undo a bulk action.
action_typestring- For example
assign,tagordelete. summarystring- What happened, like
Assigned 120 contacts. affected_countinteger- How many contacts it changed.
created_atstring- When it ran, ISO 8601.
undone_atstring- When it was undone, or
null.
#Bulk assign contacts
Assigns many contacts to one team member, or unassigns them. Select them by id, or by the same filters as List contacts. Up to 20000 contacts change in one update and return an undo token you can use for 48 hours. A bigger selection answers 202 with a job_id and is assigned in the background, with no undo. Needs the edit_contacts permission.
Parameters
assigned_tointeger- The team member’s user id. Send
nullor leave it out to unassign. contact_idsinteger[]- Up to 50,000 contact ids. Values that aren’t contact ids are skipped. When you send ids,
filtersandallare ignored. filtersobject- The List contacts filters as an object, like
{"tag": "vip"}. Every matching contact is assigned, with no cap.{}selects every contact. Before a filter orallcall, readtotalfrom List contacts with the same filters, so you know how many contacts it will change. Over 20000 the change has no undo. As in the list, contacts marked spam are left out unless you send"include_spam": "1". allbooleantrueselects every contact. Non-emptyfilterswin over it.
Returns updated (how many contacts changed), assigned_to and undo_token. When the action can’t be undone, undo_token is null and undo_unavailable says why: nothing_changed, snapshot_failed or undo_log_write_failed. Over 20000 contacts the answer is 202 with queued: true, job_id, assigned_to and undo_unavailable: "selection_too_large"; follow it with Get a bulk job.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | selection_required | No contact_ids, filters or all. |
| 400 | too_many_contacts | More than 50,000 ids. |
| 400 | no_valid_contacts | None of the ids is a contact id. |
| 400 | invalid_assignee | assigned_to isn’t a number. |
| 400 | ASSIGNEE_NOT_ON_ACCOUNT | assigned_to isn’t on your team. |
| 400 | invalid_field | Wrong type, such as filters that isn’t an object. |
| 400 | invalid_filter | A filter couldn’t be applied. error says why. |
| 429 | rate_limited | Too many bulk writes this minute. |
| 500 | bulk_assign_failed | Nothing changed, or some contacts may have changed. The error says which. Check before you retry. |
| 503 | ASSIGNEE_CHECK_UNAVAILABLE | We couldn’t check the team member. Nothing changed. Retry. |
#Bulk delete contacts
Permanently deletes up to 5,000 contacts by id. Each one goes the same way as Delete a contact: the contact and its conversation history, notes, tasks and call recordings are removed, and Ready keeps any opt-out on the number. This can’t be undone. There is no confirmation field, so check your list before you send it. Needs the edit_contacts permission.
Parameters
idsinteger[]Required- Up to 5,000 contact ids. Values that aren’t contact ids, like phone numbers, and ids that aren’t yours are skipped. Either all the rest are deleted, or none are.
Returns deleted, the number of contacts removed. It can be lower than the number you sent. The delete is listed by List bulk actions for your records, but undoing it answers 422.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | selection_required | ids is missing or empty. |
| 400 | too_many_contacts | More than 5,000 ids. |
| 400 | INVALID_CONTACT_ID | None of the values is a contact id. |
| 400 | invalid_field | ids isn’t a list. |
| 403 | CONTACT_NOT_ASSIGNED | A selected contact was reassigned to someone else during the delete. Nothing was deleted. |
| 409 | CONTACTS_CHANGED | A selected contact was deleted or merged during the delete. Nothing was deleted. Retry. |
| 423 | LITIGATION_HOLD | Under a legal hold. Nothing was deleted. |
| 429 | rate_limited | Too many bulk writes this minute. |
| 503 | HOLD_CHECK_UNAVAILABLE | We couldn’t check for a legal hold. Nothing was deleted. Retry. |
#List bulk actions
Your 25 newest bulk actions from the last 48 hours, newest first. A team member limited to assigned contacts sees only their own. Needs the view_contacts permission.
Returns a list of Bulk action objects in data. A failed read answers 500, never an empty list.
#Undo a bulk action
Puts back what a bulk assign or bulk tag change did, within 48 hours. A contact changed again since then keeps its newer value. A bulk delete can’t be undone. A team member limited to assigned contacts can only undo their own actions, and only on contacts they can edit. Needs the edit_contacts permission.
Parameters
tokenstring · pathRequired- The
undo_tokenor bulk actiontoken.
Returns restored (how many contacts changed back), action_type and summary.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_field | The token has characters a token never has. |
| 404 | undo_not_found | No such token, or older than 48 hours. |
| 409 | already_undone | Already undone. |
| 422 | not_undoable | The action can’t be undone, such as a bulk delete. |
| 429 | rate_limited | Too many bulk writes this minute. |
| 500 | undo_failed | Nothing changed. Retry. |
#Get a contact’s timeline
The contact’s activity history and notes, newest first, 10 per page. Needs the view_contacts permission.
Parameters
idinteger · pathRequired- The contact id.
pageinteger · queryDefault1Max1000- The page to read.
Returns the page’s items in data, the contact’s 20 newest notes in notes, and page, total_pages and total. Each item has:
idinteger- The activity id, or the note id for a note.
activity_typestring- What happened, like
spam_toggle. A note isnote_added. descriptionstring- A readable line. A note shows its first 80 characters in quotes.
metadatastring- Extra detail as a JSON-encoded string, or
null. actor_idinteger- The user who did it, or
nullfor automatic events. actor_namestring- First name and last initial, or
Team member. Left out when there is no actor. created_atstring- When it happened, ISO 8601.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | INVALID_CONTACT_ID | Not a contact id (for example a phone number). |
| 400 | invalid_page | page is over 1000. |
| 403 | CONTACT_NOT_ASSIGNED | The contact is assigned to someone else. |
| 404 | CONTACT_NOT_FOUND | No contact with this id. |
| 503 | CONTACT_TIMELINE_READ_FAILED | We couldn’t read the history. Retry. |
#Pin a number to a contact
Only texts sent from GoHighLevel use the pin. Sets which of your numbers texts this contact there. Campaigns, drip campaigns and the inbox pick their own number. Needs the edit_contacts permission.
Parameters
idinteger · pathRequired- The contact id.
phone_number_idinteger- The id of an active number you can send from (see List numbers). Send
nullor leave it out to remove the pin.
Returns data.pinned_phone_number_id, the number id or null.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | INVALID_CONTACT_ID | Not a contact id (for example a phone number). |
| 400 | NUMBER_NOT_YOURS | Not an active number on your account. |
| 403 | CONTACT_NOT_ASSIGNED | The contact is assigned to someone else. |
| 404 | CONTACT_NOT_FOUND | No contact with this id. |
| 409 | CONTACT_CHANGED | The contact was reassigned while saving. Nothing changed. |
| 500 | PIN_NOT_SAVED | The pin didn’t save. Retry. |
#Mark a contact as spam
Marking a contact as spam opts them out, the same way a STOP reply does. The opt-out is recorded on the number, and the contact gets dnd_sms 1, opt_out_locked 1 and status opted_out. opt_out_source becomes marked_spam, unless the contact was already opted out with another source, which stays. Unmarking clears the spam flag but doesn’t lift the opt-out: only the contact texting START does. Contacts marked spam are left out of List contacts by default. Needs the edit_contacts permission.
Parameters
idinteger · pathRequired- The contact id.
is_spambooleanRequiredtruemarks,falseunmarks. Marking opts the contact out for good.
Returns data.is_spam (1 or 0) and data.status, the contact’s status after the change.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | INVALID_CONTACT_ID | Not a contact id (for example a phone number). |
| 400 | invalid_field | is_spam is missing, or isn’t true or false. Nothing changed. |
| 403 | CONTACT_NOT_ASSIGNED | The contact is assigned to someone else. |
| 404 | CONTACT_NOT_FOUND | No contact with this id. |
| 409 | CONTACT_CHANGED | The contact was reassigned while saving. Nothing changed. |
| 503 | SPAM_NOT_SAVED | The change didn’t save. Retry. |
| 503 | SPAM_SUPPRESSION_NOT_SAVED | Marked as spam, but we couldn’t confirm the opt-out. Don’t text the number. Mark it again. |
| 503 | SPAM_RECEIPT_UNREAD | We couldn’t confirm the change. Read the contact before you text it. |