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

GET /api/v1/conversations

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

Response conversations-index.json Download
{
"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 — the type and id of every message
  • A top-level included array with every message in full, oldest first

An ID that doesn’t exist in your community returns 404.

Request

GET /api/v1/conversations/01k5examplec0nversat10n001

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

Response conversations-show.json Download
{
"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 the advocates or prospects permission; a key with only conversations gets a 403 there.

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.

© 2024-2026 Stoked — Real conversations. Real trust.