Conversations API
Read the conversations between your advocates and prospects, including tags, the AI summary, the resolution, and every message.
Requires the conversations permission.
| Endpoint | Returns |
|---|---|
GET /api/v1/conversations |
A paginated list of conversations |
GET /api/v1/conversations/:id |
One conversation with all of its messages |
List conversations
GET https://integrations.stokedhq.com/api/v1/conversations
With no filters, the list contains every conversation in your community — pending, active, and closed. This differs from the admin portal’s Conversations list, which hides closed conversations by default.
Parameters
| Parameter | Description |
|---|---|
filter[status] |
One or more of pending, active, closed, separated by commas: filter[status]=pending,active |
filter[created_since] |
Only conversations created at or after this time |
filter[updated_since] |
Only conversations updated at or after this time. Use this for incremental syncing. |
filter[advocate] |
Only conversations with this advocate, by advocate id |
filter[prospect] |
Only conversations with this prospect, by prospect id |
page[number] |
The page to return. Defaults to 1. |
page[size] |
Conversations per page. Defaults to 50, maximum 200. |
Time filters accept an ISO 8601 timestamp with a time zone (2026-09-01T00:00:00Z) or a date (2026-09-01, read as midnight UTC). Both are inclusive.
filter[advocate] and filter[prospect] can be combined with each other and with the other filters. An id that doesn’t belong to an advocate or prospect in your community returns a 400 error rather than an empty list. An advocate or prospect record links straight to its filtered list in relationships.conversations.links.related.
Any other parameter — including sort — returns a 400 error. Conversations always come back least recently updated first.
Request
cURL
curl -G "https://integrations.stokedhq.com/api/v1/conversations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/vnd.api+json" \
--data-urlencode "filter[status]=active,closed" \
--data-urlencode "filter[updated_since]=2026-09-01T00:00:00Z"
Ruby
require "net/http"
require "json"
uri = URI("https://integrations.stokedhq.com/api/v1/conversations")
uri.query = URI.encode_www_form("filter[status]" => "active,closed", "filter[updated_since]" => "2026-09-01T00:00:00Z")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"
request["Accept"] = "application/vnd.api+json"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
raise "HTTP #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPSuccess)
puts JSON.parse(response.body)["data"]
Python
import requests
response = requests.get(
"https://integrations.stokedhq.com/api/v1/conversations",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Accept": "application/vnd.api+json",
},
params={"filter[status]": "active,closed", "filter[updated_since]": "2026-09-01T00:00:00Z"},
)
response.raise_for_status()
print(response.json()["data"])
C#
using System.Net.Http.Headers;
using System.Text.Json;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_KEY");
client.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.api+json");
using var response = await client.GetAsync("https://integrations.stokedhq.com/api/v1/conversations?filter[status]=active,closed&filter[updated_since]=2026-09-01T00:00:00Z");
response.EnsureSuccessStatusCode();
using var document = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
Console.WriteLine(document.RootElement.GetProperty("data"));
JavaScript
const url = new URL("https://integrations.stokedhq.com/api/v1/conversations");
url.searchParams.set("filter[status]", "active,closed");
url.searchParams.set("filter[updated_since]", "2026-09-01T00:00:00Z");
const response = await fetch(url, {
headers: {
Authorization: "Bearer YOUR_API_KEY",
Accept: "application/vnd.api+json",
},
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const { data } = await response.json();
console.log(data);
Response
{
"data": [
{
"type": "conversations",
"id": "01k5examplec0nversat10n001",
"attributes": {
"status": "closed",
"messages_count": 4,
"tags": [
"test-ride"
],
"created_at": "2026-09-01T15:00:00Z",
"updated_at": "2026-09-06T17:30:00Z",
"activated_at": "2026-09-01T15:00:00Z",
"closed_at": "2026-09-06T17:30:00Z",
"last_message_at": "2026-09-01T15:20:00Z",
"summary": {
"who_and_what": "Mike asked Sarah about trying her cargo bike for school drop-off. They arranged a Saturday test ride.",
"status": "Closed after a test ride."
},
"resolution": {
"close_reason": "Test ride completed",
"note": "Mike took the test ride and plans to order.",
"closed_at": "2026-09-06T17:30:00Z",
"closed_by": "admin"
}
},
"relationships": {
"advocate": {
"data": {
"type": "advocates",
"id": "01k5exampleadv0cate0000001"
},
"links": {
"related": "https://integrations.stokedhq.com/api/v1/advocates/01k5exampleadv0cate0000001"
}
},
"prospect": {
"data": {
"type": "prospects",
"id": "01k5examplepr0spect0000001"
},
"links": {
"related": "https://integrations.stokedhq.com/api/v1/prospects/01k5examplepr0spect0000001"
}
}
},
"links": {
"self": "https://integrations.stokedhq.com/api/v1/conversations/01k5examplec0nversat10n001"
}
}
],
"links": {
"self": "https://integrations.stokedhq.com/api/v1/conversations?filter%5Bupdated_since%5D=2026-09-01T00%3A00%3A00Z&page%5Bnumber%5D=1&page%5Bsize%5D=50",
"first": "https://integrations.stokedhq.com/api/v1/conversations?filter%5Bupdated_since%5D=2026-09-01T00%3A00%3A00Z&page%5Bnumber%5D=1&page%5Bsize%5D=50",
"prev": null,
"next": null,
"last": "https://integrations.stokedhq.com/api/v1/conversations?filter%5Bupdated_since%5D=2026-09-01T00%3A00%3A00Z&page%5Bnumber%5D=1&page%5Bsize%5D=50"
},
"meta": {
"page": 1,
"per_page": 50,
"total_count": 1,
"total_pages": 1
}
}
The list doesn’t include messages. Fetch a single conversation to get them.
Get a conversation
GET https://integrations.stokedhq.com/api/v1/conversations/:id
Returns the same conversation record as the list, plus:
relationships.messages— thetypeandidof every message- A top-level
includedarray with every message in full, oldest first
An ID that doesn’t exist in your community returns 404.
Request
cURL
curl "https://integrations.stokedhq.com/api/v1/conversations/01k5examplec0nversat10n001" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/vnd.api+json"
Ruby
require "net/http"
require "json"
uri = URI("https://integrations.stokedhq.com/api/v1/conversations/01k5examplec0nversat10n001")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"
request["Accept"] = "application/vnd.api+json"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
raise "HTTP #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPSuccess)
puts JSON.parse(response.body)["data"]
Python
import requests
response = requests.get(
"https://integrations.stokedhq.com/api/v1/conversations/01k5examplec0nversat10n001",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Accept": "application/vnd.api+json",
},
)
response.raise_for_status()
print(response.json()["data"])
C#
using System.Net.Http.Headers;
using System.Text.Json;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_KEY");
client.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.api+json");
using var response = await client.GetAsync("https://integrations.stokedhq.com/api/v1/conversations/01k5examplec0nversat10n001");
response.EnsureSuccessStatusCode();
using var document = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
Console.WriteLine(document.RootElement.GetProperty("data"));
JavaScript
const url = new URL("https://integrations.stokedhq.com/api/v1/conversations/01k5examplec0nversat10n001");
const response = await fetch(url, {
headers: {
Authorization: "Bearer YOUR_API_KEY",
Accept: "application/vnd.api+json",
},
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const { data } = await response.json();
console.log(data);
Response
{
"data": {
"type": "conversations",
"id": "01k5examplec0nversat10n001",
"attributes": {
"status": "closed",
"messages_count": 4,
"tags": [
"test-ride"
],
"created_at": "2026-09-01T15:00:00Z",
"updated_at": "2026-09-06T17:30:00Z",
"activated_at": "2026-09-01T15:00:00Z",
"closed_at": "2026-09-06T17:30:00Z",
"last_message_at": "2026-09-01T15:20:00Z",
"summary": {
"who_and_what": "Mike asked Sarah about trying her cargo bike for school drop-off. They arranged a Saturday test ride.",
"status": "Closed after a test ride."
},
"resolution": {
"close_reason": "Test ride completed",
"note": "Mike took the test ride and plans to order.",
"closed_at": "2026-09-06T17:30:00Z",
"closed_by": "admin"
}
},
"relationships": {
"advocate": {
"data": {
"type": "advocates",
"id": "01k5exampleadv0cate0000001"
},
"links": {
"related": "https://integrations.stokedhq.com/api/v1/advocates/01k5exampleadv0cate0000001"
}
},
"prospect": {
"data": {
"type": "prospects",
"id": "01k5examplepr0spect0000001"
},
"links": {
"related": "https://integrations.stokedhq.com/api/v1/prospects/01k5examplepr0spect0000001"
}
},
"messages": {
"data": [
{
"type": "messages",
"id": "900001"
},
{
"type": "messages",
"id": "900002"
},
{
"type": "messages",
"id": "900003"
},
{
"type": "messages",
"id": "900004"
}
]
}
},
"links": {
"self": "https://integrations.stokedhq.com/api/v1/conversations/01k5examplec0nversat10n001"
}
},
"included": [
{
"type": "messages",
"id": "900001",
"attributes": {
"content": "Hi Sarah! I'm thinking about a cargo bike for school drop-off. Could I try yours?",
"status": "active",
"source": "sms_relay",
"created_at": "2026-09-01T15:05:00Z",
"blocked_at": null
},
"relationships": {
"sender": {
"data": {
"type": "prospects",
"id": "01k5examplepr0spect0000001"
},
"links": {
"related": "https://integrations.stokedhq.com/api/v1/prospects/01k5examplepr0spect0000001"
}
}
}
},
{
"type": "messages",
"id": "900002",
"attributes": {
"content": "Absolutely! I'm free Saturday morning. It fits both of my kids plus groceries.",
"status": "active",
"source": "sms_relay",
"created_at": "2026-09-01T15:10:00Z",
"blocked_at": null
},
"relationships": {
"sender": {
"data": {
"type": "advocates",
"id": "01k5exampleadv0cate0000001"
},
"links": {
"related": "https://integrations.stokedhq.com/api/v1/advocates/01k5exampleadv0cate0000001"
}
}
}
},
{
"type": "messages",
"id": "900003",
"attributes": {
"content": "Hi both, Alex from the team here. Mike, remember to bring a helmet on Saturday!",
"status": "active",
"source": "web",
"created_at": "2026-09-01T15:15:00Z",
"blocked_at": null,
"sender_name": "Alex Placeholder"
},
"relationships": {
"sender": {
"data": {
"type": "admins",
"id": "01k5exampleadm1n0000000001"
}
}
}
},
{
"type": "messages",
"id": "900004",
"attributes": {
"content": "Perfect, see you Saturday at 10. Thanks!",
"status": "active",
"source": "sms_relay",
"created_at": "2026-09-01T15:20:00Z",
"blocked_at": null
},
"relationships": {
"sender": {
"data": {
"type": "prospects",
"id": "01k5examplepr0spect0000001"
},
"links": {
"related": "https://integrations.stokedhq.com/api/v1/prospects/01k5examplepr0spect0000001"
}
}
}
}
]
}
Conversation attributes
Records with "type": "conversations".
| Attribute | Type | Description |
|---|---|---|
status |
string | pending (the prospect hasn’t verified their contact details yet), active, or closed |
messages_count |
integer | Number of messages in the conversation |
tags |
array of strings | Names of the tags applied to the conversation |
created_at |
timestamp | When the prospect started the conversation |
updated_at |
timestamp | When the conversation last changed. See What changes updated_at. |
activated_at |
timestamp or null | When the conversation became active |
closed_at |
timestamp or null | When the conversation was closed. null while it is open. |
last_message_at |
timestamp or null | When the most recent message was sent |
summary |
object or null | The AI-generated summary: who_and_what (who is talking and what about) and status (where the conversation stands now). null until one has been generated. |
resolution |
object or null | How the conversation was most recently closed. null if it has never been closed with a reason. |
The resolution object
| Field | Type | Description |
|---|---|---|
close_reason |
string | The close reason that was selected, for example “Test ride completed” |
note |
string or null | The optional note entered when closing |
closed_at |
timestamp | When this resolution was recorded |
closed_by |
string | Who closed it: admin, advocate, prospect, or system |
Relationships
| Relationship | Type | Description |
|---|---|---|
advocate |
advocates |
The advocate in the conversation. links.related is their Advocates API URL. |
prospect |
prospects |
The prospect in the conversation. links.related is their Prospects API URL. |
messages |
messages |
Every message. Only present when fetching a single conversation. |
A conversation never contains the advocate’s or prospect’s details, only their
type,id, and link. Fetching the link requires theadvocatesorprospectspermission; a key with onlyconversationsgets a403there.
What changes updated_at
A conversation’s updated_at moves forward whenever anything in its API record changes:
- A message arrives, or a message’s status changes (for example, it is flagged or blocked)
- The AI summary is created or updated
- The conversation is activated, closed, resolved, or reopened
- A tag is added, removed, renamed, or reordered
Message attributes
Records with "type": "messages". Messages only appear in the included array of a single conversation.
| Attribute | Type | Description |
|---|---|---|
content |
string | The text of the message |
status |
string | active for a normal message. Otherwise pending (still being processed), flagged (held for moderation review), blocked (stopped by moderation), or failed. |
source |
string | How the message was sent: sms_relay (by text message) or web (from a Stoked site) |
created_at |
timestamp | When the message was sent |
blocked_at |
timestamp or null | When the message was blocked. null for messages that weren’t blocked. |
sender_name |
string | Only present when the sender is not the advocate or prospect: the admin’s name, or System for automated messages |
Flagged and blocked messages are included so your copy matches the full transcript. Check status and blocked_at if you only want messages the other person actually received.
Relationships
| Relationship | Type | Description |
|---|---|---|
sender |
advocates, prospects, or admins |
Who sent the message. null for automated system messages. Compare the id with the conversation’s advocate and prospect to tell who is speaking. Advocate and prospect senders carry a links.related URL; admins don’t, as there is no admins endpoint. |