Skip to main content
A contact is one customer. A contact has a name, owner, tags, custom fields and a list of handles (identities): a phone number, an email address or an account on a channel. Conversations, notes and consent attach to the contact. All routes are under https://api.impellabs.tech/api/v1. Send Authorization: Bearer imp_... on each request. See Authentication and Conventions. The API reference lists every field.

Who can see a contact

A token acts as the person who made it. A contact answers 404 with There is no contact like that. when it does not exist or when the person may not see it. A contact has a visibility: workspace (everyone) or owner (its owner and their managers). A removed contact is archived, not deleted. Its handles become free for a new contact.

List contacts

GET /contacts returns a page: { results, count, page, page_size, pages }. page_size is 20 unless you send page_size (1 to 100).

Create a contact

POST /contacts. Send a name, a phone, an email, or any of them. You must send at least one. Write a phone number with its country code.
The reply is 201:

Read, update and remove

  • GET /contacts/{contact_id} returns the contact with consent, timeline, suggestions (the number of suggested merges), crm_lead and app_records.
  • PATCH /contacts/{contact_id} changes only the fields you send. The editable fields are name, owner_id, visibility, language, time_zone, tags, custom_fields, do_not_contact. Set a custom field to null to remove its value.
  • DELETE /contacts/{contact_id} answers 204.
GET /contacts/{contact_id}/timeline returns the contact’s history. Use limit (1 to 100), before (the time from next) and kind (one kind, or kinds separated by commas; note returns the notes).

Handles

  • POST /contacts/{contact_id}/identities with { "kind", "value" } adds a handle, for example phone, whatsapp, email or instagram. A typed handle is not verified. 201 returns { id, kind, value, verified }. If another contact holds the value, the reply is 409 and ImpelLabs adds a suggested merge.
  • DELETE /contacts/{contact_id}/identities/{identity_id} removes a handle. 404 if the contact has no such handle.

Notes

  • GET /contacts/{contact_id}/notes returns the notes you may see, newest first.
  • POST /contacts/{contact_id}/notes with { "text", "visibility"?, "department_id"? }. text has 5000 characters at most. visibility is everyone (the default), department or private. A department note needs department_id, one of your departments.
  • PATCH and DELETE /contacts/{contact_id}/notes/{note_id} work only for the person who wrote the note. Others get 404.
POST /contacts/{contact_id}/consent records a decision of the customer. The reply is 201 with { "consent": [ { "channel", "purpose", "status", "source", "at" } ] }: the newest decision for each channel and purpose. The source is staff.

Merge

Two contacts can be one person. ImpelLabs suggests merges when handles or names match.
  • GET /contacts/matches lists suggestions. state is review (the default) or merged. contact limits the list to one contact.
  • POST /contacts/matches/{match_id}/accept merges the two contacts. reject dismisses the suggestion. undo splits a merge that was made.
  • POST /contacts/{contact_id}/merge with { "other_id" } merges two contacts you name. The reply is 201 with the match. A merge that is not allowed answers 400 with detail.

Contact fields

A contact field is a custom field of the workspace, such as a customer number.
  • GET /contacts/fields lists the fields.
  • POST /contacts/fields creates one: key (small letters, numbers and _, starting with a letter), label, kind (default text), and optionally required, choices, value_map, help_text and order. A select or multiselect field needs choices.
  • PATCH and DELETE /contacts/fields/{field_id} change and archive a field.
All three changes need an owner or an admin.

Import contacts from a sheet

An import loads a CSV or Excel file. You send the file first, then check the column mapping, then start the job.
  1. POST /files with a multipart file. The reply has the file id.
  2. POST /imports/groups with { "file_id", "group", "mapping"? }. The mapping holds column names: email, and optionally name, company and consent. ImpelLabs suggests columns from the headers. Each person in the file gets the tag group:<name>. The reply is 201 with the import, the file headers, sample rows and the suggested columns.
  3. POST /imports/{import_id}/check with { "mapping": { "group": "<name>", "email": "<column>", "name": "<column>" } } saves the mapping and runs a dry run. Nothing is written. The mapping always names the group and the email column. name, company and consent are optional columns.
  4. POST /imports/{import_id}/start starts the job. It answers 202. A large import can wait for an approval first; the import status shows waiting.
  5. GET /imports/{import_id} shows status and the rows counts. GET /imports/{import_id}/errors pages the rows that had a problem.
  6. POST /imports/{import_id}/undo reverses the import inside its undo window. Outside it, the reply is 409.
A row without a valid email is left out and reported in the errors. A person is on the list for marketing email only when the file has a yes or no column that you map as consent, or when consent exists already. The same file again changes nothing. You can read only the imports you made.