The slug-scoped twin of the thread presence endpoints, for a recipient who joined a live-shared thread (and is therefore not the thread owner or a space member). Lets the joiner heartbeat their presence — and read who is present — so "who's here / who's typing" fans out both ways between the owner and every joiner.
Allowed only when the link's access_level is live (403 otherwise); an unknown or unauthorized link returns 404. Presence is transient cache state — these endpoints make no database writes, and an empty present set is a valid answer.
Records (or refreshes) that the caller is present on the shared thread, and what they are doing. Clients ping this every ~20 seconds while the thread is open; presence auto-expires ~50 seconds after the last heartbeat.
Requires user authentication (Bearer token). API-key authentication is rejected with 403.
slug string required
The share-link slug (must be a live link).
state string optional
One of viewing (default), typing, or prompting.
client_id string optional
A stable id for the device or tab sending this heartbeat. Pattern ^[A-Za-z0-9_-]+$, max 64 characters. Generate it once per surface and reuse it for that surface's lifetime.
Send it whenever one account may have the shared thread open in more than one place — a phone and a desktop. Each device then holds its own presence entry, so one device's heartbeat cannot overwrite another's state and closing one does not remove the other. Presence is still reported per user: the snapshot collapses a user's devices into a single entry carrying their most recently active state, so the response shape is unchanged. Omit it and the caller is treated as that user's only device.
A list of the users currently present on the underlying thread, each with their user_id, state, name, avatar_url (profile-image URL, or null — falls back to initials), and last_seen (Unix timestamp).
Returns the same present set on demand, without recording a heartbeat.
curl -X POST https://api.aitronos.com/v1/shared-threads/abc123slug/presence \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"state": "typing"}'from aitronos import Aitronos
client = Aitronos(api_key="", token="YOUR_TOKEN")
present = client.threads.shared.presence(slug="abc123slug", state="typing")
print([p.user_id for p in present.data])import requests
response = requests.post(
"https://api.aitronos.com/v1/shared-threads/abc123slug/presence",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"state": "typing"},
)
print(response.json()["data"])const response = await fetch(
"https://api.aitronos.com/v1/shared-threads/abc123slug/presence",
{
method: "POST",
headers: {
Authorization: "Bearer YOUR_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ state: "typing" }),
},
);
const present = await response.json();
console.log(present.data);{
"object": "list",
"thread_id": "thread_9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a",
"data": [
{
"user_id": "usr_3ae598ea791242898b5feb69e4c4e30c",
"state": "typing",
"name": "Aitronos Team Dev",
"avatar_url": "https://cdn.aitronos.com/avatars/usr_abc123.png",
"last_seen": 1782681710.5
},
{
"user_id": "usr_38893a99f74344e4a6cac1e99d813f74",
"state": "viewing",
"name": "Owner",
"avatar_url": null,
"last_seen": 1782681709.1
}
]
}{
"success": false,
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "You do not have permission to perform this action.",
"system_message": "This share link does not grant live co-working access",
"type": "authorization_error",
"status": 403,
"details": {
"link_id": "tslnk_2b1c3d4e5f6a7b8c9d0e1f2a3b4c5d6e",
"access_level": "view"
},
"trace_id": "...",
"timestamp": "..."
}
}- Join Shared Thread — Create the persistent joined entry
- Live Shared Thread — The live co-working event stream (presence updates fan out here)
- Leave Shared Thread — Remove the joined entry