Skip to content

What merging another contact into this one would move

GET
/v1/contacts/{id}/merge-preview
curl --request GET \
--url 'https://api.threadkite.app/v1/contacts/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/merge-preview?mergeContactId=2489E9AD-2EE2-8E00-8EC9-32D5F69181C0' \
--header 'Authorization: Bearer <token>'

Nothing changes. Merge with POST /v1/contacts/{id}/merge.

id
required
string format: uuid
mergeContactId
required

The contact that would be merged in

string format: uuid

The contact that would be merged in

Media typeapplication/json
object
contact
required

The contact that would be merged in

object
id
required
string format: uuid
name
required
string
nullable
email
required
string
nullable
phone
required

As given

string
nullable
phoneE164
required

E.164

string
nullable
avatarUrl
required

Their picture, uploaded by your team; null when none

string
nullable
companies
required

The companies they work for now, their primary company first (see /v1/contacts/{id}/companies for past ones)

Array<object>
object
company
required
object
id
required
string format: uuid
name
required
string
avatarUrl
required

The company’s picture (uploaded, or its website’s icon); null when none

string
nullable
status
required

As the register gives it (active, dissolved, liquidation…); null when not known

string
nullable
role
required

What they do for the company, in your words: Director, Accounts…

string
nullable
jobTitle
required
string
nullable
isPrimary
required

Their main company (at most one); shown first and with their name

boolean
source
required

How the link was made: manual (your team), domain (their email address is at one of the company’s domains), form, lead, import, api, integration or assistant

string
Allowed values: manual domain form lead import api integration assistant
endedAt
required

When they left the company; kept for history, not current

string format: date-time
nullable
createdAt
required
string format: date-time
emailInvalidAt
required

Email bounced or is not valid

string format: date-time
nullable
phoneInvalidAt
required

The number failed or is not valid

string format: date-time
nullable
mergedIntoId
required

Set when this contact was merged into another

string format: uuid
nullable
redactedAt
required

When the contact and their data were deleted (an erasure): what’s left is only kept so counts and reports add up

string format: date-time
nullable
externalIds
required
Array<object>
object
integration
required

The other system, e.g. my-dms

string
externalId
required

The contact’s id there

string
appName
required

The installed partner app this id belongs to (its integration is the app slug)

string
nullable
url
required

The contact in that app (from the app’s contact address), for Open in …

string
nullable
consents
required
Array<object>
object
channel
required
string
Allowed values: email sms whatsapp chat phone form api marketplace visit messenger instagram internal
status
required
string
Allowed values: opted_in opted_out unknown
source
required

Where the latest decision came from, in short: form, api, staff, stop_reply, unsubscribe, import, complaint, assistant, connection, merge or system. The full story (who, how, the wording shown) is in the consent history.

string
at
required
string format: date-time
pendingOptInAt
required

A contact form asked to opt them back in after they opted out. Not applied: anyone can type an address into a form.

string format: date-time
nullable
attributes
required

Contact field values by field key (see /v1/contact-fields): text, numbers, dates as YYYY-MM-DD and true or false

object
key
additional properties
One of:
string
marketingSuppressed
required

Channels on which this person asked not to receive marketing: their email address or number is on the marketing suppression list (someone with it opted out and their data was deleted). Marketing opt-ins there are kept as pending and marketing sends are refused; replies and service messages are unaffected

Array<string>
threadId
required

The contact’s most recent live thread you can see, if any (a contact has one thread per inbox)

string format: uuid
nullable
threadIds
required

The contact’s live threads you can see, one per inbox, most recent first

Array<string>
createdAt
required
string format: date-time
updatedAt
required
string format: date-time
messages
required

Messages in threads you can see that would move to the surviving contact

number
links
required

Linked records you can see that would move

number
externalIds
required

Ids that would move

Array<object>
object
integration
required

The other system, e.g. my-dms

string
externalId
required

The contact’s id there

string
consents
required

Consent that would move (channels the surviving contact has no record for)

Array<object>
object
channel
required
string
Allowed values: email sms whatsapp chat phone form api marketplace visit messenger instagram internal
status
required
string
Allowed values: opted_in opted_out unknown
source
required

Where the latest decision came from, in short: form, api, staff, stop_reply, unsubscribe, import, complaint, assistant, connection, merge or system. The full story (who, how, the wording shown) is in the consent history.

string
at
required
string format: date-time
pendingOptInAt
required

A contact form asked to opt them back in after they opted out. Not applied: anyone can type an address into a form.

string format: date-time
nullable
filled
required

Blank details on the surviving contact that would be filled in

Array<string>
Allowed values: name email phone

Example

{
"contact": {
"name": "Sarah Turner",
"email": "sarah.turner@example.co.uk",
"phone": "07911 123456",
"phoneE164": "+447911123456",
"avatarUrl": "https://api.threadkite.com/avatars/9b0d….jpg",
"companies": [
{
"company": {
"name": "Acme Fleet Services Ltd",
"avatarUrl": "https://api.threadkite.com/avatars/6c1f….png",
"status": "active"
},
"role": "Fleet manager",
"jobTitle": "Head of Transport",
"source": "manual"
}
],
"externalIds": [
{
"integration": "my-dms",
"externalId": "CUST-10442",
"appName": "Northern DMS",
"url": "https://dms.example/customers/CUST-10442"
}
],
"consents": [
{
"channel": "email",
"status": "opted_in",
"source": "stop_reply"
}
],
"attributes": {
"finance_end_date": "2027-01-03",
"budget": 15000
},
"marketingSuppressed": [
"email"
]
},
"messages": 4,
"links": 1,
"externalIds": [
{
"integration": "my-dms",
"externalId": "CUST-10442"
}
],
"consents": [
{
"channel": "email",
"status": "opted_in",
"source": "stop_reply"
}
],
"filled": [
"name"
]
}
Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}

Missing or invalid API key

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}

The organisation is on the Free plan (code upgrade_required)

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
feature
required

The feature that needs Pro

string
nullable
Allowed values: extraSeats connections aiAssistant aiReplies rules fullReports api inboxes bulkMessages videoMessages
upgradePath
required

Where to upgrade or pay, in the web app

string

Example

{
"statusCode": 402,
"code": "upgrade_required",
"message": "Connections are part of Pro. Upgrade to connect texts, calls and more.",
"feature": "extraSeats",
"upgradePath": "/settings/billing"
}

The key does not have the scope (or the person the permission)

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}
Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
errors

With code invalid: every problem with the request, by field (message is the first)

Array<object>
object
path
required

Dotted path inside the item, e.g. attributes.price.amountMinor

string
message
required
string

Example

{
"statusCode": 403,
"code": "forbidden",
"message": "You do not have permission to do that.",
"errors": [
{
"message": "Enter the make"
}
]
}

Rate limit reached

Media typeapplication/json
object
statusCode
required
number
code
required

Stable machine-readable reason

string
message
required
string
retryAfter
required

Seconds until another request will be accepted

number

Example

{
"statusCode": 429,
"code": "rate_limited",
"message": "Too many requests. Each key can make 120 requests a minute; try again in 12 seconds.",
"retryAfter": 12
}