Skip to main content
The Contacts API lets you create and update people in your Topo workspace, query who Topo already knows, and attach arbitrary key-value variables to a contact or its account. Variables are the primary way to pass CRM data, lead scores, or personalization tokens into Topo’s AI sequences.
Listing and reading contacts requires contacts:read. Creating or updating a contact (POST /v1/contacts), reassigning owners, and managing variables require contacts:write.

Upsert a contact

POST /v1/contacts creates a contact or updates the matching one if it already exists. Topo matches inside your organization on email first, then on linkedin_url (both normalized), so re-sending the same person is safe and always returns the same id. Fields you send overwrite stored values; fields you omit are left untouched. Both create and update return 201. At least one of email or linkedin_url is required.
company_domain links the contact to an account — the account (and its company) is created when it does not exist yet, and company_name is only used for that creation. Sending company_name alone does not link an account.
Use upsert before enrolling someone you already know about, or when syncing CRM contacts into Topo. For bulk prospect imports with enrichment, prefer contact lists and entries.

List and filter contacts

GET /v1/contacts returns every contact attached to your workspace with the standard pagination envelope. GET /v1/contacts/{contact_id} fetches a single contact.

Custom variables

Each scope (contact or account) holds a maximum of 200 variables. Setting a key’s value to null clears the value but does not free its slot toward the limit — use DELETE /v1/contacts/{contact_id}/variables/{key} to fully remove a key.
  • GET /v1/contacts/{contact_id}/variables — read contact and account variables
  • PATCH /v1/contacts/{contact_id}/variables — merge contact_variables and account_variables
  • DELETE /v1/contacts/{contact_id}/variables/{key}?scope=contact|account — remove one key
account_variables live on the contact’s linked account, so every contact at the same company shares them. The same data is also manageable directly through the Account variables endpoints when you hold an account_id — the contact response exposes it as account_id.

Reassign owner

PATCH /v1/contacts/{contact_id}/owner with { "owner_user_id": "<uuid>" } reassigns the contact’s owner to a workspace user.