Add threads and their history to an import
const url = 'https://api.threadkite.app/v1/imports/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/threads';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"threads":[{"externalId":"deal-1042","contact":{"contactId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","externalId":{"integration":"my-dms","externalId":"CUST-10442"},"name":"Sarah Turner","email":"sarah.turner@example.co.uk","phone":"07911 123456","company":{"id":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","name":"Acme Fleet Services","domain":"acme.co.uk","companyNumber":"01234567","externalId":{"integration":"my-dms","externalId":"CUST-10442"},"jobTitle":"Head of Transport","role":"Director"}},"inboxId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","lead":{"at":"2026-04-15T12:00:00Z","channel":"form","source":"facebook","subject":"example","message":"","fields":{"additionalProperty":"example"},"items":[{"id":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","source":"my-dms","externalId":"example","identifier":"SKU-1042","label":"Tow bar","quantity":1,"addOns":[{"id":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","source":"my-dms","externalId":"example","identifier":"SKU-1042","label":"Tow bar","quantity":1}]}]},"entries":[],"owner":{"email":"sam@example.co.uk","name":"Sam Lee"},"state":"open","outcome":"deal","outcomeNote":"example","closedAt":"2026-04-15T12:00:00Z","tags":["Trialling"]}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.threadkite.app/v1/imports/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/threads \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "threads": [ { "externalId": "deal-1042", "contact": { "contactId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "externalId": { "integration": "my-dms", "externalId": "CUST-10442" }, "name": "Sarah Turner", "email": "sarah.turner@example.co.uk", "phone": "07911 123456", "company": { "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "name": "Acme Fleet Services", "domain": "acme.co.uk", "companyNumber": "01234567", "externalId": { "integration": "my-dms", "externalId": "CUST-10442" }, "jobTitle": "Head of Transport", "role": "Director" } }, "inboxId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "lead": { "at": "2026-04-15T12:00:00Z", "channel": "form", "source": "facebook", "subject": "example", "message": "", "fields": { "additionalProperty": "example" }, "items": [ { "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "source": "my-dms", "externalId": "example", "identifier": "SKU-1042", "label": "Tow bar", "quantity": 1, "addOns": [ { "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "source": "my-dms", "externalId": "example", "identifier": "SKU-1042", "label": "Tow bar", "quantity": 1 } ] } ] }, "entries": [], "owner": { "email": "sam@example.co.uk", "name": "Sam Lee" }, "state": "open", "outcome": "deal", "outcomeNote": "example", "closedAt": "2026-04-15T12:00:00Z", "tags": [ "Trialling" ] } ] }'Up to 25 threads at a time, each with its contact, the lead that started it, and its messages, notes and events in any order. Contacts are matched as leads are (your id, then email, then phone), so someone already in Threadkite is found, not added again; history for a contact whose current thread is here goes on that thread, which keeps its own owner and state. Each thread is matched on the import’s source and its externalId, and each entry on its own externalId (or when it happened and what it says), so sending the same thread again, in this import or a later one, adds only what is new. A thread that cannot be imported is reported as failed (a refusal writes nothing; send it again to finish one that stopped part way); the rest still go in.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”object
object
Its id in the other system (a deal, ticket or lead)
Example
deal-1042object
A Threadkite contact id, if you have it
The contact’s id in your system
object
The other system, e.g. my-dms
Example
my-dmsThe contact’s id there
Example
CUST-10442Example
Sarah TurnerExample
sarah.turner@example.co.ukExample
07911 123456The company they work for, found or made (see CompanyCaptureDto): linked as their primary company when they have none
object
One of your companies
Its name: the company with that name, or a new one when nothing else finds one
Example
Acme Fleet ServicesIts web domain (or website address): finds the company with it
Example
acme.co.ukIts registered number (Companies House)
Example
01234567The company’s id in your system
object
The other system, e.g. my-dms
Example
my-dmsThe contact’s id there
Example
CUST-10442Their job title there
Example
Head of TransportWhat they do for the company, in your words
Example
DirectorThe default inbox when left out
The lead that started it, counted as a lead on its date. Without one, the thread starts with its first message
object
When they first got in touch
The lead source, as a key; made if new
Example
facebookOther details from the old system, shown with the lead (question to answer)
object
What it is about: catalogue items or free-text lines, with add-ons
object
A Threadkite item id
The item’s source, with externalId
Example
my-dmsThe item’s id in that source
An identifier on the item, matched exactly (a SKU or a pack identifier)
Example
SKU-1042A free-text line, when it is not in the catalogue
Example
Tow barAdded to this item (a warranty, delivery, build options)
object
A Threadkite item id
The item’s source, with externalId
Example
my-dmsThe item’s id in that source
An identifier on the item, matched exactly (a SKU or a pack identifier)
Example
SKU-1042A free-text line, when it is not in the catalogue
Example
Tow barIts messages, notes and events, in any order
object
message: from or to the contact; note: the team’s internal note; event: a line in the timeline (a stage change, a call logged)
For messages: in from the contact, out from your team
For messages; email when left out
Example
emailWhen it happened
Example
2026-08-06T13:00:48ZEmail as it was sent or received, shown as it was
Who on your team wrote it (outgoing messages, notes and events)
object
Matched to a member of your team: their messages and notes show as theirs, and an owner given this way gets the thread
Example
sam@example.co.ukShown when the email is not one of your team
Example
Sam LeeEmail: every address on it as it was sent (from, to, cc)
object
Its id in the other system. Without one, an entry is recognised by when it happened and what it says
Who looks after it: a member of your team, by email
object
Matched to a member of your team: their messages and notes show as theirs, and an owner given this way gets the thread
Example
sam@example.co.ukShown when the email is not one of your team
Example
Sam LeeFor a done thread: deal (won), lost, none or no_reply
When it was closed; its last entry when left out
Tags as well as the import’s own (made if new)
Example
[ "Trialling"]Responses
Section titled “Responses”object
A batch of history brought in from another system
object
open takes more threads; undone has had what it made removed
object
Threads already in Threadkite that it added history to
Messages, notes and events stored
object
created: a new thread; updated: history added to a thread already in Threadkite (imported before, or the contact’s current thread); failed: nothing written, see error
Entries already there from an earlier run
object
Example
{ "import": { "source": "pipedrive", "status": "open" }, "results": [ { "status": "created" } ]}object
Stable machine-readable reason
With code invalid: every problem with the request, by field (message is the first)
object
Dotted path inside the item, e.g. attributes.price.amountMinor
Example
{ "statusCode": 403, "code": "forbidden", "message": "You do not have permission to do that.", "errors": [ { "message": "Enter the make" } ]}Missing or invalid API key
object
Stable machine-readable reason
With code invalid: every problem with the request, by field (message is the first)
object
Dotted path inside the item, e.g. attributes.price.amountMinor
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)
object
Stable machine-readable reason
The feature that needs Pro
Where to upgrade or pay, in the web app
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)
object
Stable machine-readable reason
With code invalid: every problem with the request, by field (message is the first)
object
Dotted path inside the item, e.g. attributes.price.amountMinor
Example
{ "statusCode": 403, "code": "forbidden", "message": "You do not have permission to do that.", "errors": [ { "message": "Enter the make" } ]}object
Stable machine-readable reason
With code invalid: every problem with the request, by field (message is the first)
object
Dotted path inside the item, e.g. attributes.price.amountMinor
Example
{ "statusCode": 403, "code": "forbidden", "message": "You do not have permission to do that.", "errors": [ { "message": "Enter the make" } ]}object
Stable machine-readable reason
With code invalid: every problem with the request, by field (message is the first)
object
Dotted path inside the item, e.g. attributes.price.amountMinor
Example
{ "statusCode": 403, "code": "forbidden", "message": "You do not have permission to do that.", "errors": [ { "message": "Enter the make" } ]}Rate limit reached
object
Stable machine-readable reason
Seconds until another request will be accepted
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}