create_contact
ChatGPTAdd a brand-new contact from the details the user gave: at least ONE identifying signal (a first or last name, a company name, an email address or a phone number; any one is enough, and an email or phone lets Nexusplus check reliably whether the person is already there), optionally with WHY it was captured (a lead, a competitor, ...). Nexusplus first checks for an existing contact: if a strong match exists it REFUSES to create a duplicate and returns that contact (outcome 'matched_existing'; use submit_contact_revision on its masterId to add the new email/phone/company instead, and pass the reason there as its intent to attach it to the existing contact). A weaker match still creates the contact (outcome 'created') but also files it as a possible duplicate (list_duplicate_candidates) and HOLDS its publishing until that pair is resolved, so call list_duplicate_candidates after a create to learn whether a hold exists. Nexusplus records the creation and creates the contact within a few seconds; it does NOT create synchronously, so re-read with search_contacts or get_contact_dossier to obtain the masterId. When disposition is omitted, the list's publish setting decides: by default the new contact is published, which sends it to the user's connected Outlook and iCloud accounts (narrowed by destinations when given), while a list set to hold changes lands it in the needs-review queue instead, exactly like an imported contact. Pass disposition to override the list setting either way. Publishing requires ADMIN access: a non-admin's request is staged for review instead. Optionally pass destinations to choose exactly which connected accounts it goes to (the same rules as set_contact_destinations). Requires write access to the list.
dismiss_duplicate_candidate
ChatGPTDismiss a duplicate-candidate proposal as NOT a duplicate (the two contacts are genuinely different people or companies). Nexusplus records the dismissal and applies it within a few seconds, marking the proposal 'dismissed' so it won't resurface even if the matcher finds the pair again. The dismissal is durable and cannot be undone: no call reopens a dismissed proposal. It changes only that review-queue proposal and does not touch either contact (the pair can still be merged deliberately). Requires write access. Use list_duplicate_candidates to find proposed pairs; re-read to confirm.
find_duplicate_candidates
ChatGPTFind possible duplicate masters for a given contact using the SAME matcher the inbound sync uses. Returns scored candidates (matchType email|phone|name, confidence 0-100). The inbound pipeline auto-merges at >=85, so the 60-84 band is the system's own 'probably a duplicate, needs human review' queue. Excludes the contact itself. Read-only.
get_contact_dossier
ChatGPTGet the full detail view (dossier) for one contact master: canonical identity, effective version, emails/phones/addresses/org-roles/urls, normalization status, mixed-identity diagnostics, captured intents (intents: every engagement_intent capture — kind/subKind/note/source/status/capturedAt/capturedVia — most recent first; see create_contact and submit_contact_revision), and the outbound destination designation (destinations: {designated, allowed, denied} — designated is true once this contact has ANY explicit destination permission row (from create_contact's destinations, set_contact_destinations, or the web UI); allowed/denied are the connected integrations' NAMES currently in effect, accounting for source bindings and each integration's own allow-new default, not just explicit rows — see set_contact_destinations).
get_contact_sources
ChatGPTGet the provenance of a contact: which external source records (Outlook/iCloud/CSV/etc.) contributed to this master, with each record's status.
get_contact_versions
ChatGPTGet the version history for a contact master (published + superseded; optionally all draft revisions).
get_relationship_network
ChatGPTGet the relationship graph around an entity (people/companies it is connected to) as nodes and edges, including employment relationships.
list_contacts
ChatGPTList/browse contacts in a list with optional filtering and pagination. Returns contacts plus total and hasMore.
list_duplicate_candidates
ChatGPTList the saved duplicate-candidate PROPOSALS in a list. Each row is a canonical-ordered pair of contact masters the system flagged as the same entity, with a confidence and matchType. A row whose reasons include 'name_disagreement' (with metadata.autoMergeBlockedBy) is a REVIEW HOLD, not an assertion of sameness: the pair shares identifiers but the names plainly disagree, so the auto-merge policy blocked it and held it for a human decision at the honest (boost-withheld) confidence. Status: 'active' = a proposal awaiting review; 'merged' = the pair was merged; 'dismissed' = a human marked it not-a-duplicate; 'stale' = invalidated because a side was merged away. Defaults to active. Unlike find_duplicate_candidates (which recomputes live for one contact), this reads the saved proposal queue for the whole list. Read-only. Use merge_preview to see what merging a pair would produce.
list_integrations
ChatGPTList the connected accounts / integrations for a list (Outlook, iCloud, CSV, etc.) with their status. Credentials are never exposed.
list_my_lists
ChatGPTList the contact lists you can access, with their ids and your access level. Use a returned id as listId for the other tools.
merge_contacts
ChatGPTMerge contacts that are the SAME person or company (e.g. confirmed duplicates) into one survivor. Nexusplus records the merge and applies it within a few seconds; it does NOT merge synchronously, so re-read the contacts (or call list_duplicate_candidates) to confirm it landed. Merging is always an explicit decision, never inferred from confidence. A clean, recent two-way merge can be undone with unmerge_contact. After a merge, the next send of the surviving contact to an account that held the absorbed contact's card (a publish, or a sync the user runs for an account that has sending turned on) deletes that extra card there, and until the merged contact is published that send carries the surviving contact's previously published details, not the merged ones. Requires ADMIN access to the list. REQUIRES a mergeToken from a merge_preview of exactly these contacts (same user, unexpired, contacts unchanged since the preview) — call merge_preview first to show the user what the merge produces and to obtain the token.
merge_preview
ChatGPTPreview what merging two or more contact masters would produce: each master's effective version, sources, and emails/phones. Read-only — it does NOT merge. Use it to show a human the diff before any merge is performed. Returns a short-lived mergeToken bound to this principal, this exact set of contacts, and their current content state (any edit/publish/merge on a previewed contact stales it); merge_contacts REQUIRES that token, so a merge can never execute against a stale or foreign preview. The token is stateless and reusable within its TTL (replay is controlled by the state binding plus the pipeline's idempotent apply); it binds the CONTACTS' state only — sibling review-queue decisions (e.g. a dismissal) do not invalidate it — and the merge direction is chosen by merge_contacts' explicit primaryMasterId, not by the token.
publish_contact
ChatGPTPublish the pending unpublished change (draft) of one or more contacts so it goes live and is sent to the user's connected Outlook and iCloud accounts. This is the step that makes a prior merge or edit actually leave Nexusplus, and it overwrites the matching fields of the contact's existing record in those accounts (every prior version stays in Nexusplus's version history). When Nexusplus successfully sends a contact to a connected Outlook or iCloud account that holds more than one card linked to that contact (typically the absorbed contact's card after a merge), it then deletes the extra cards from that account after marking each as superseded, keeping any extra card it cannot read or that changed after it read it. Nexusplus records the publish and applies it within a few seconds; it does NOT publish synchronously, so re-read (get_contact_dossier) to confirm. Contacts with no pending draft are skipped (already published). Requires ADMIN access to the list. Publishing more than 25 at once requires confirmCount to equal the number of masterIds.
search_contacts
ChatGPTQuick search for contacts by name or email within a list. Returns lightweight matches; use get_contact_dossier for full detail.
set_contact_destinations
ChatGPTChoose the COMPLETE set of connected accounts an EXISTING contact is sent to. By default a contact goes to every connected account that accepts new contacts; this lets the user say 'this one is work-only'. The new set REPLACES the contact's previous allow/deny set: no call restores the earlier set (to go back, name it again), and an exclusion can stop this contact from reaching an account that would otherwise receive it. destinations is an array where each entry is either a connected account's name as list_integrations shows it (case-insensitive, e.g. "Work Outlook", "Outlook Personal", "iCloud") or an alias: 'work' (every Outlook work account), 'personal' (Outlook Personal and iCloud), 'all' (every connected outbound account), or 'default' (must be the ONLY entry: clears the setting and restores the default behavior). Naming a set allows each resolved account and excludes every OTHER currently connected outbound account: an exclusion fully suppresses that account even if it would otherwise accept this contact or already holds a record of it, and an allow overrides an account's own 'no new contacts' default for THIS contact only. A name that matches no connected account, an alias that matches no connected account (even when other entries do match), or a name that matches more than one account is REFUSED with the list of valid names or of every match; nothing is guessed. Excluding an account stops FUTURE sends only: it does NOT delete anything already sent there; an existing record stays as-is and goes stale. This call writes only routing settings, which take effect immediately in Nexusplus; it sends nothing itself, and the setting applies from the next publish or the next sync the user runs for an account that has sending turned on. Requires write access to the list.
split_contact
ChatGPTSplit a CONFLATED contact (a false merge: one contact that actually holds two different people's source records) by re-routing some of its source records onto a DIFFERENT, already existing person contact. The inverse of merge_contacts. Nexusplus records the split and applies it within a few seconds; source EVIDENCE is never rewritten, only current ownership moves, and the contact the records move away from is rebuilt from what remains (and retired locally if emptied). Re-read get_contact_dossier / get_contact_sources to confirm. Workflow: call get_contact_sources on the conflated contact to get its source binding ids, then partition EVERY active binding into groups: keep_on_original bindings stay, and exactly ONE move_to_existing group names the target person contact (use search_contacts to find it). The target must already exist; creating a brand-new contact for the moved records is not supported, so if none exists the user must create it in the Nexusplus app first (create_contact may refuse because the identity matches the conflated contact). Relationship facts are NOT moved automatically (held for separate review). The split itself sends nothing to any connected account; if the target contact then holds two cards in one connected account, the next send of it there (a publish, or a sync the user runs for an account that has sending turned on) deletes the extra card there, and until the target is published that send carries its previously published details. Requires ADMIN access.
submit_contact_revision
ChatGPTSubmit content changes to an EXISTING contact on the user's behalf: revise scalar fields (name parts, company, title, birthday, anniversary, notes), add ONE net-new attribute (an email, phone, address, org-role or url; a social profile such as LinkedIn or Facebook is a url with the matching urlType), and/or edit tags (add or remove), and/or record WHY the user is noting this contact with intent (a reason such as a lead or a competitor, for example a saved contact who has now asked for a trial). fields replaces the value of each field you pass; addAttribute only ever adds (a new phone or email sits beside the existing ones, nothing is replaced or removed, and an added attribute cannot be removed through this tool). Nexusplus records the change and applies it as a draft revision within a few seconds; it does NOT write synchronously, so re-read with get_contact_dossier to confirm. First locate the contact with search_contacts / get_contact_dossier to get its masterId. When disposition is omitted, the list's publish setting decides: by default the revision is published, which sends it to the user's connected Outlook and iCloud accounts and overwrites the matching fields of the existing record there (prior versions stay in Nexusplus's version history; see publish_contact for what else a publish to an account does), while a list set to hold changes stages it for review instead. Pass disposition to override the list setting either way. A staged revision stays inside Nexusplus until it is published. Publishing (accept_now) requires ADMIN: a non-admin's request is staged for review instead. intent is evidence about the user's relationship to the contact, never a field on the contact card, and it can be sent on its own, with no fields, addAttribute or tags: the reason is then attached to the contact, the card itself is unchanged and nothing is published or sent to any account (disposition does not apply). The dossier's intents lists every recorded reason, most recent first. Requires write access to the list.
unmerge_contact
ChatGPTReverse a previous merge, bringing the absorbed contact back as its own independent contact and re-deriving the survivor so it no longer carries the absorbed person's data. The inverse of merge_contacts. Nexusplus records the unmerge and applies it within a few seconds; re-read the contacts to confirm. It is refused, with the reasons, unless the merge is a clean, recent two-way merge with no edit to the survivor since, a completion record exists, and the survivor was not itself merged away later; merges that moved relationships, merges of three or more contacts, and chained or incomplete merges are not supported. If the merge was already published and the absorbed contact's card was deleted from a connected account, the unmerge is refused if that account does not accept new contacts of that type, and otherwise the restored contact gets a NEW card in that account the next time it is published (the deleted card's identity and any edits made to it there are not restored). Requires ADMIN access. Pass the survivorMasterId (the contact that absorbed the other); omit mergeEventId to reverse the most recent merge into it.