Contacts

Space MCP tools in the Contacts scope (contacts). Reach these with a wks_live_ key over space-mcp or space-api.

Tools in the contacts scope, callable over space-mcp (tools/call) or space-api (REST) with a wks_live_* key that grants contacts.

add_campaign_people_to_list

Scope: contacts:write

Put EVERYONE behind a campaign number into a contact list — an existing list (list_id, from list_audiences) or a new one (new_list_name) — e.g. "make a list of everyone who opened but never replied, for a follow-up campaign". A filter audience cannot take people by hand.

ParameterTypeRequiredDescription
campaign_idstringyes
metricall | sent | delivered | opened | clicked | replied | unsubscribed | not_arrivedWhich number: all (everyone in it) · sent · delivered · opened · clicked · replied · unsubscribed · not_arrived (bounced or refused). Default all.
email_numbernumberOne email of the campaign (1 = the first). Leave out for any of them — e.g. metric opened + email_number 2 = who opened email 2.
list_idstringAn existing LIST in this space.
new_list_namestringMake a new list with this name instead.

add_contact_note

Scope: contacts:write

Add a short note to a contact's Memory — the running log a human reads to remember a person. One plain sentence per note. Preferred way to 'remember X about' or 'log a call/message on' a contact.

ParameterTypeRequiredDescription
contact_idstringyes
bodystringyesOne short plain sentence.

add_social_identity

Scope: contacts:write

Attach a social identity (Instagram/X/LinkedIn/Facebook/TikTok/etc.) to a contact. Provide handle (no leading @) and/or external_id. This is what powers inbound DM matching — prefer it over the legacy social_media JSONB.

ParameterTypeRequiredDescription
contact_idstringyes
platformstringyes
handlestring
external_idstring
profile_urlstring
display_namestring

bulk_tag_contacts

Scope: contacts:write

Add and/or remove tags across many contacts in ONE call. Pass contact_ids plus add_tag_ids and/or remove_tag_ids. Prefer this over looping tag_contact.

ParameterTypeRequiredDescription
contact_idsstring[]yes
add_tag_idsstring[]
remove_tag_idsstring[]

count_contacts

Scope: contacts:read

Count contacts matching structured filters (search/company/location/relationship_type/tag_ids/has_email/has_phone/auto_created/created_after/created_before). Cheaper than listing when you only need a number.

ParameterTypeRequiredDescription
searchstring
companystring
locationstring
line_of_workstring
relationship_typestring
tag_idsstring[]
has_emailboolean
has_phoneboolean
auto_createdboolean
email_permissiongranted | not_given | unknownCount by whether they agreed to hear from you.
created_afterstring
created_beforestring

create_audience

Scope: contacts:write

Create an audience (a list campaigns send to). Two kinds: picked people (contact_ids) or a FILTER that fills itself as contacts change (rules), e.g. everyone tagged lead in Austin: { combinator: "AND", conditions: [{ field: "tags", op: "contains_any", value: ["lead"] }, { field: "location", op: "contains", value: "Austin" }] }. Fields: tags (ops contains_any, contains_all, not_contains, is_empty, is_not_empty; value = tag names), email, name, first_name, last_name, company, phone, location, website, line_of_work, custom_fields.<key> (ops equals, not_equals, contains, not_contains, starts_with, ends_with, is_empty, is_not_empty), email_permission (ops equals, not_equals; value granted · not_given · unknown — e.g. everyone who agreed to hear from you), created_at, updated_at (ops before, after, between). Or from_audiences: [two or more audience ids] = anyone in any of them (what the campaign page makes when you pick several), then point the campaign at it. Only contacts with an email count. Audiences target both email and SMS campaigns.

ParameterTypeRequiredDescription
namestringyes
descriptionstring
contact_idsstring[]Picked people. Leave out for a filter list.
from_audiencesstring[]Two or more audience ids: the new audience is anyone in any of them (use instead of contact_ids / rules).
rulesobjectA filter list: { combinator: AND|OR, conditions: [{ field, op, value }] }. Leave out for picked people.

create_contact

Scope: contacts:write

Create a new contact in the space. Only name is required (email is optional — social-DM/walk-in contacts have none). Name is split into first/last automatically; pass first_name/last_name explicitly for precise splitting. tags are matched/created by name.

ParameterTypeRequiredDescription
namestringyesFull display name, e.g. 'Sarah Lee'.
first_namestringOptional — overrides the auto-split first name.
middle_namestring
last_namestringOptional — overrides the auto-split last name.
usernamestring
emailstringOptional.
additional_emailsstring[]
phonestring
companystring
line_of_workstringJob title / role.
locationstring
websitestring
birthdaystringISO date YYYY-MM-DD.
avatarstringAvatar image URL.
biostring
relationship_typestringe.g. 'lead', 'client', 'contact', 'partner'.
how_we_metstring
interestsstring[]
personal_notesstring
social_mediaobjectJSONB map of platform → handle.
tagsstring[]Tag names — matched case-insensitively, created if missing.
custom_fieldsobject
email_permissiongranted | not_given | unknownWhether they agreed to hear from the space by email. granted needs permission_note saying how; not_given keeps every newsletter from them. Written into their consent history under your name.
permission_notestringHow you know, e.g. "signed up at our stand on 3 May", "said no on the phone".

create_contact_section

Scope: contacts:write

Add a content section to a contact (documents/links/custom boxes). For simple 'remember X' notes prefer add_contact_note. section_type: notes | documents | links | insights | custom.

ParameterTypeRequiredDescription
contact_idstringyes
titlestringyes
section_typestring
contentstring
metadataobject
sort_ordernumber

create_tag

Scope: contacts:write

Create a new contact tag. Colors: gray, red, orange, amber, yellow, green, teal, blue, indigo, purple, pink.

ParameterTypeRequiredDescription
namestringyes
colorstring
descriptionstring
iconstring

delete_contact

Scope: contacts:write

Permanently delete ONE contact by its id (cascades to its tags, notes, sections, and social identities). Destructive and irreversible — only call with an explicit contact_id the user unambiguously asked to delete. There is no bulk/filter delete; delete one id at a time.

ParameterTypeRequiredDescription
contact_idstringyes

delete_contact_section

Scope: contacts:write

Permanently delete a contact section. Destructive.

ParameterTypeRequiredDescription
section_idstringyes

delete_tag

Scope: contacts:write

Permanently delete a tag from this space (removes it from every contact). Destructive.

ParameterTypeRequiredDescription
tag_idstringyes

erase_contact

Scope: contacts:write

Consequential and permanent: erase a person who asked to be forgotten — their emails and conversations, campaign places, form answers, bookings, notes, audiences, agent memory, consent history and the contact itself. Orders and payments stay, unlinked. Their address is kept only as a one-way hash so nobody emails them again by mistake, and a record without their name goes to Space Settings → Privacy. The owner approves it in this chat every time. confirm = their email address exactly (or their name when they have no email). Offer export_contact_data first if they also asked for a copy.

ParameterTypeRequiredDescription
contact_idstringyes
confirmstringyesTheir email address, exactly — or their name when there is no email.
reasonstringWhy, in a sentence ("asked by email on 26 Sep").

export_contact_data

Scope: contacts:read

Everything this space holds about one person, as one document — their details, tags, audiences, notes, form answers, bookings, every email to and from them, orders, what agents remember, and their consent history. Use it when someone asks for a copy of their data; hand it to the person who asked for them.

ParameterTypeRequiredDescription
contact_idstringyes

get_contact

Scope: contacts:read

Fetch ONE contact by id with everything attached: all columns, tags, social identities, and recent sections. Use this to read a contact's full profile before editing.

ParameterTypeRequiredDescription
contact_idstringyes

Scope: contacts:read

How a contact came to hear from this space and every change since: signed up (which form, the page, the ip), confirmed their email, imported (with what the importer said about permission), added to an audience (by whom), unsubscribed or came back (which campaign), stopped all emails, permission set — plus their email permission (granted · not_given · unknown) and the campaigns they are in or left. Read it before mailing someone whose permission you are unsure of; a contact marked not_given gets no newsletter.

ParameterTypeRequiredDescription
contact_idstringyes

import_contacts

Scope: contacts:write

Add up to 500 people at once — a lead list you researched, a list someone gave you. Each person is matched by email: someone the space already has is UPDATED (blanks filled, custom fields merged, tags added), never added twice; someone erased at their own request is skipped. Put each person's personal lines in custom_fields (e.g. {"reason_line": "Saw you're hiring two SDRs"}) — an email step writes {{reason_line}} and it fills from the contact. Keys are stored as lowercase_with_underscores. People found by research have email_permission "unknown" (the default): say where they came from in lead_source. Answers counts, what was skipped and why, and contact_ids in row order — hand them to add_people_to_campaign.

ParameterTypeRequiredDescription
contactsobject[]yesThe people. name (or first_name + last_name) is required; email is how they are matched.
tagsstring[]Tags on everyone in this call, e.g. ["Outbound: dental clinics TX"]. Created if missing.
custom_fieldsobjectValues for everyone (a person's own values win).
relationship_typestringDefault "lead".
lead_sourcestringWhere they came from, e.g. "apollo", "google_maps", "event list". Default "import".
email_permissiongranted | not_given | unknownFor everyone. People found by research are "unknown" (the default). "granted" needs permission_note saying how they agreed. An answer a person already gave is never changed by an import.
permission_notestring
on_existingupdate | skipupdate (default): fill blanks, merge custom fields, add tags. skip: leave people the space already has as they are.

list_audiences

Scope: contacts:read

List audiences (saved contact groups used to target email and SMS campaigns).

list_contact_erasures

Scope: contacts:read

The space's record of people erased on request: when, by whom, why and what was taken — never their name or address.

ParameterTypeRequiredDescription
limitnumberDefault 100.

list_contact_notes

Scope: contacts:read

List a contact's Memory notes, newest first.

ParameterTypeRequiredDescription
contact_idstringyes
limitnumberMax notes (default 20).

list_contact_sections

Scope: contacts:read

List the content sections (notes/documents/links/insights/custom) attached to a contact.

ParameterTypeRequiredDescription
contact_idstringyes
section_typestring

list_contacts

Scope: contacts:read

List contacts in the space. Supports search and pagination.

ParameterTypeRequiredDescription
searchstringMatch against name/email/company.
email_permissiongranted | not_given | unknownOnly people who agreed to hear from you (granted), who did not (not_given), or whose permission is not recorded (unknown).
limitnumber
offsetnumber

list_tags

Scope: contacts:read

List the contact tags in this space (id, name, color, description). Call before tagging to resolve tag names → ids.

merge_contacts

Scope: contacts:write

Merge two duplicate contacts: fold source_contact_id into target_contact_id. All threads, tags, sections, and social identities move to the target, then the source row is deleted. Prefer this over delete for de-duplication. Destructive — confirm before merging curated contacts.

ParameterTypeRequiredDescription
source_contact_idstringyesThe duplicate that will be deleted.
target_contact_idstringyesThe contact that survives and inherits everything.

preview_contact_erase

Scope: contacts:read

What erasing a contact would take (emails, conversations, campaign places, form answers, bookings, notes, audiences, agent memory) and what it keeps (orders and payments, the shop inbox, jobs — the law asks a business to keep those). Read before erase_contact.

ParameterTypeRequiredDescription
contact_idstringyes

remove_social_identity

Scope: contacts:write

Delete a social identity row from a contact.

ParameterTypeRequiredDescription
identity_idstringyes

set_contact_email_permission

Scope: contacts:write

Record whether this space may email a contact in bulk: 'granted' (they said yes — say how in note), 'not_given' (no newsletter or campaign reaches them until it changes) or null (unknown). It lands in their consent history with your name and the note. Never mark 'granted' without a real yes from the person.

ParameterTypeRequiredDescription
contact_idstringyes
permissiongranted | not_given | nullyes
notestringHow you know, in a sentence ("said yes on our call of 3 May").

tag_campaign_people

Scope: contacts:write

Tag EVERYONE behind a campaign number with one contact tag, e.g. everyone who clicked email 2 → "warm", everyone who never opened → "cold". The tag is made if the space does not have it. People with no contact in this space are left out and counted.

ParameterTypeRequiredDescription
campaign_idstringyes
metricall | sent | delivered | opened | clicked | replied | unsubscribed | not_arrivedWhich number: all (everyone in it) · sent · delivered · opened · clicked · replied · unsubscribed · not_arrived (bounced or refused). Default all.
email_numbernumberOne email of the campaign (1 = the first). Leave out for any of them — e.g. metric opened + email_number 2 = who opened email 2.
tagstringyesThe tag's name.

tag_contact

Scope: contacts:write

Attach one tag to one contact.

ParameterTypeRequiredDescription
contact_idstringyes
tag_idstringyes

untag_contact

Scope: contacts:write

Detach one tag from one contact.

ParameterTypeRequiredDescription
contact_idstringyes
tag_idstringyes

update_audience

Scope: contacts:write

Rename an audience or add/remove member contacts.

ParameterTypeRequiredDescription
audience_idstringyes
namestring
descriptionstring
add_contact_idsstring[]
remove_contact_idsstring[]

update_contact

Scope: contacts:write

Update fields on an existing contact. Only supplied fields change (pass null to clear one). Pass tag_ids to REPLACE the entire tag set (omit to leave tags unchanged). Get the contact first to resolve its id.

ParameterTypeRequiredDescription
contact_idstringyes
namestring
first_namestring
middle_namestring
last_namestring
usernamestring
emailstring
additional_emailsstring[]
phonestring
companystring
line_of_workstring
locationstring
websitestring
birthdaystring
avatarstring
biostring
relationship_typestring
how_we_metstring
interestsstring[]
personal_notesstring
social_mediaobject
custom_fieldsobject
tag_idsstring[]REPLACES the full tag set. Resolve ids via list_tags.
email_permissiongranted | not_given | unknownWhether they agreed to hear from the space by email. granted needs permission_note saying how; not_given keeps every newsletter from them. Written into their consent history under your name.
permission_notestringHow you know, e.g. "signed up at our stand on 3 May", "said no on the phone".

update_contact_section

Scope: contacts:write

Update an existing contact section's title, content, type, metadata, or sort_order.

ParameterTypeRequiredDescription
section_idstringyes
titlestring
section_typestring
contentstring
metadataobject
sort_ordernumber

update_social_identity

Scope: contacts:write

Update an existing social identity row (handle, external_id, profile_url, display_name).

ParameterTypeRequiredDescription
identity_idstringyes
handlestring
external_idstring
profile_urlstring
display_namestring

update_tag

Scope: contacts:write

Rename or restyle an existing tag.

ParameterTypeRequiredDescription
tag_idstringyes
namestring
colorstring
descriptionstring
iconstring

On this page