Get the thread
A session’s conversation history: up to 200 messages across its 10 most recently started conversations, oldest first. The most recently active conversations fill the 200 first.
A session that has never written returns conversationId: null, status: null, and an empty messages array, not an error. Messages can span several conversations. A resolved thread stays in the history and the next message starts a new one, so draw a divider where conversationId changes. Internal notes and system lines are never included.
GET
/threadAuthorization
AuthorizationBearer token · headerrequiredA MEDIAN_KEY from Settings under API. It starts with `median_key_` and stays on your server. The tool endpoint routes also accept an OAuth access token (`median_oat_`) from `median login` or an MCP client, acting as the person who approved it. The messaging routes accept only a Median key.
Query parameters
sessionstringrequiredThe visitor's session token, 8 to 128 characters.
min length 8 · max length 128
Responses
200The thread, newest message last.
conversationIdstring | nullrequiredNull for a session that has never written.
statusstring | nullrequired`resolved` once the conversation is resolved or closed.
Allowed:
openresolvednullawaitingHumanbooleanrequiredTrue while the next reply will come from a person.
messagesMessage[]requiredShow propertiesHide properties
Array of
MessageidstringrequiredconversationIdstringrequiredcreatedAtintegerrequiredMilliseconds since the epoch.
senderstringrequired`agent` covers both the AI and your team; `agent.kind` says which.
Allowed:
visitoragentagentAgent | anyrequiredNull on a visitor's own message.
Show propertiesHide properties
One of:
Agent
kindstringrequiredAllowed:
aihumannamestringrequiredavatarUrlstring | nullrequiredany
anybodystringrequiredpendingbooleanrequiredA reply still being written. It updates in place, keeping its id.
attachmentsAttachment[]requiredShow propertiesHide properties
Array of
Attachmentnamestringrequiredsizeintegerrequiredtypestringrequiredurlstring | nullrequiredWhere to download it.
400`invalid_request`: the `session` query parameter is missing. `invalid_session`: the session is not 8 to 128 characters.
errorobjectrequiredShow propertiesHide properties
codestringrequiredBranch on this rather than on the message.
messagestringrequired401`missing_api_key`: no bearer token. `invalid_api_key`: the key matches no organization or was revoked. `publishable_key`: a `median_pk_` key was sent. An OAuth access token is refused here with `invalid_api_key`.
errorobjectrequiredShow propertiesHide properties
codestringrequiredBranch on this rather than on the message.
messagestringrequired429The organization's API allowance for this class of request is used up. Wait the `Retry-After` header's seconds. Limits depend on the plan. See [rate limits](/api/errors-and-limits#rate-limits).
errorobjectrequiredShow propertiesHide properties
codestringrequiredBranch on this rather than on the message.
messagestringrequiredRequest
curl -X GET "https://api.median.sh/v1/thread?session=user_42" \
-H "Authorization: Bearer YOUR_TOKEN"const response = await fetch("https://api.median.sh/v1/thread?session=user_42", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_TOKEN"
}
});Response
{
"conversationId": "js7...",
"status": "open",
"awaitingHuman": false,
"messages": [
{
"id": "jd2...",
"conversationId": "js7...",
"createdAt": 1754990000000,
"sender": "visitor",
"agent": null,
"body": "How do I export my data?",
"pending": false,
"attachments": []
},
{
"id": "jd3...",
"conversationId": "js7...",
"createdAt": 1754990004000,
"sender": "agent",
"agent": {
"kind": "ai",
"name": "Median AI",
"avatarUrl": null
},
"body": "Settings, then Export. It arrives as a zip.",
"pending": false,
"attachments": []
}
]
}{
"error": {
"code": "invalid_session",
"message": "Session tokens are 8 to 128 characters."
}
}{
"error": {
"code": "invalid_api_key",
"message": "That Median key does not match any organization. Copy the median_key_ key again from Settings under API."
}
}{
"error": {
"code": "rate_limited",
"message": "Your organization's API allowance is temporarily full. Please retry shortly."
}
}