Add something a contact owns
const url = 'https://api.threadkite.app/v1/contacts/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/items';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"type":"owned_product","attributes":{"sku":"SKU-1042","name":"Oak dining table","boughtFromUs":true},"current":true,"externalSource":"my-dms","externalId":"VEH-44120"}'};
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/contacts/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/items \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "type": "owned_product", "attributes": { "sku": "SKU-1042", "name": "Oak dining table", "boughtFromUs": true }, "current": true, "externalSource": "my-dms", "externalId": "VEH-44120" }'Checked against the item type (/v1/contact-item-types). The same externalId from your system, or the same registration for this contact, updates the item that is already there (200) instead of adding another (201). Contact fields that follow their items (the finance end date) are kept in step. Pro.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”object
Example
owned_productChecked against the item type; amounts are { amountMinor, currency }
object
Example
{ "sku": "SKU-1042", "name": "Oak dining table", "boughtFromUs": true}Your system, with externalId
Example
my-dmsYour id for it: sending the same id again updates the item
Example
VEH-44120Responses
Section titled “Responses”It was already there and is updated
object
One of your industry pack’s item types
They have it now (false: sold or replaced)
Who added it
The item’s details, as the item type describes them (see /v1/contact-item-types)
object
Example
{ "type": "owned_product", "title": "Oak dining table", "subtitle": "SKU-1042 · Solid oak · 2025", "source": "staff", "externalSource": "my-dms", "externalId": "VEH-44120", "attributes": { "sku": "SKU-1042", "name": "Oak dining table", "warrantyEndDate": "2028-03-01", "price": { "amountMinor": 89900, "currency": "GBP" } }}Added
object
One of your industry pack’s item types
They have it now (false: sold or replaced)
Who added it
The item’s details, as the item type describes them (see /v1/contact-item-types)
object
Example
{ "type": "owned_product", "title": "Oak dining table", "subtitle": "SKU-1042 · Solid oak · 2025", "source": "staff", "externalSource": "my-dms", "externalId": "VEH-44120", "attributes": { "sku": "SKU-1042", "name": "Oak dining table", "warrantyEndDate": "2028-03-01", "price": { "amountMinor": 89900, "currency": "GBP" } }}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}