Sales, with first and last touch side by side, and cost per lead, appointment and sale
const url = 'https://api.threadkite.app/v1/reports/sales?preset=today&granularity=day&inboxType=sales&sourceCategory=website&channel=email&trafficChannel=paid_search&touch=first';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.threadkite.app/v1/reports/sales?preset=today&granularity=day&inboxType=sales&sourceCategory=website&channel=email&trafficChannel=paid_search&touch=first' \ --header 'Authorization: Bearer <token>'A sale is a thread closed as Won, a deal link marked won, or one your systems reported (POST /v1/sales), counted once per thread per deal. Each is credited to the contact’s leads in the look-back (first touch: the earliest; last touch: the latest before the sale). Only sales in threads you can see. Part of Pro.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Date range in your organisation’s time zone. Defaults to 30d (the last 30 days, today included); custom needs from and to. Dates without a preset are custom.
Date range in your organisation’s time zone. Defaults to 30d (the last 30 days, today included); custom needs from and to. Dates without a preset are custom.
First day (custom ranges), YYYY-MM-DD
First day (custom ranges), YYYY-MM-DD
Last day, included (custom ranges)
Last day, included (custom ranges)
Group charts over time by day or week. Defaults to days up to 62 days, else weeks
Group charts over time by day or week. Defaults to days up to 62 days, else weeks
Only this inbox (one you can see)
Only this inbox (one you can see)
Only inboxes of this type
Only inboxes of this type
Only leads at this location
Only leads at this location
Only leads from this source
Only leads from this source
Only sources of this kind
Only sources of this kind
Only threads this person owns, or unassigned for threads nobody owns
Only threads this person owns, or unassigned for threads nobody owns
Only leads on this channel
Only leads on this channel
Only leads from this campaign
Only leads from this campaign
Only leads whose visit came this way (paid search, email…)
Only leads whose visit came this way (paid search, email…)
Sales, funnel and campaigns reports: credit each sale to the first lead in the look-back (first) or the latest before the sale (last, the default). Source, source type, channel, campaign and traffic channel filters then apply to that lead.
Sales, funnel and campaigns reports: credit each sale to the first lead in the look-back (first) or the latest before the sale (last, the default). Source, source type, channel, campaign and traffic channel filters then apply to that lead.
Responses
Section titled “Responses”object
object
Your organisation’s time zone
The period compared against
object
The Free plan’s basic reports: only leads by source and first response times are filled in; other breakdowns are empty
Which lead each sale is credited to
Days before a sale that leads count towards it
Whether cost per lead, appointment and sale are worked out. Spend is entered for the whole organisation (or a location), so costs are only shown without inbox, owner or channel filters, to people who see every inbox.
object
Sales in the range (each deal once)
Sales in the period before
Value of sales with a value in the report’s currency, minor units
Sales with at least one lead from the contact in the look-back
Sales where a lead named the item sold
Leads in the range (same filters)
Sales as a share of leads (0 to 1)
All spend in the range
object
Spend in the range; null when no month in it has spend entered, in minor units of the report’s currency (pence for GBP)
Every month the range touches has spend entered
Months in the range with no spend entered (YYYY-MM)
All spend divided by all sales, in minor units of the report’s currency (pence for GBP)
object
The day, or the Monday of the week
First and last touch side by side; most sales first
object
Spend in the range; null when no month in it has spend entered, in minor units of the report’s currency (pence for GBP)
Every month the range touches has spend entered
Months in the range with no spend entered (YYYY-MM)
Null for leads with no source
Logo address; null shows an initial badge
Leads from this source in the range
Appointments booked after a lead from this source
Sales whose first touch was this source
Sales whose last touch was this source
Spend per lead; null without spend or leads, or when costs are not shown, in minor units of the report’s currency (pence for GBP)
Spend per appointment booked, in minor units of the report’s currency (pence for GBP)
Spend per sale, by the touch the report uses, in minor units of the report’s currency (pence for GBP)
object
By the person credited
object
The id grouped by; null for none
object
The id grouped by; null for none
object
The id grouped by; null for none
Sales by the contact’s primary company when the report is worked out (so a contact’s history moves with them), the 20 companies with most first, then “No company”
object
The id grouped by; null for none
The latest 50 sales
object
The contact’s name, if known
object
Minor units of currency
object
object
A lead in the look-back named the item sold
Example
{ "range": { "from": "2026-09-06", "to": "2026-10-05", "days": 30, "preset": "today", "timeZone": "Europe/London", "granularity": "day", "previous": { "from": "2026-09-06", "to": "2026-10-05", "days": 30 } }, "touch": "first", "lookbackDays": 90, "currency": "GBP", "spend": { "missingMonths": [ "2026-09" ] }, "bySource": [ { "missingMonths": [ "2026-09" ], "name": "Website form", "category": "website" } ], "byOrigin": [ { "origin": "outcome", "label": "Closed as Won" } ], "byPerson": [ { "name": "Leeds" } ], "byLocation": [ { "name": "Leeds" } ], "byInbox": [ { "name": "Leeds" } ], "byCompany": [ { "name": "Leeds" } ], "recent": [ { "item": { "title": "Blue cotton shirt" }, "currency": "GBP", "origin": "outcome", "firstTouch": { "name": "Google Ads" }, "lastTouch": { "name": "Google Ads" } } ]}Unusable dates or filters
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" } ]}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}