{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-docs/api-reference/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["api-container","endpoint"]},"redocly_category":"API Reference","searchWeight":120,"type":"markdown"},"seo":{"title":"Shared Thread Presence","description":"Complete API reference and documentation for Freddy AI-powered backend system by Aitronos","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"shared-thread-presence","__idx":0},"children":["Shared Thread Presence"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The slug-scoped twin of the thread presence endpoints, for a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["both ways"]}," between the owner and every joiner."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Allowed ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["only when the link's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["access_level"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["live"]}]}," (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}," otherwise); an unknown or unauthorized link returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]},". Presence is transient cache state — these endpoints make no database writes, and an empty present set is a valid answer."]},{"$$mdtype":"Tag","name":"ApiContainer","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"heartbeat-presence","__idx":1},"children":["Heartbeat presence"]},{"$$mdtype":"Tag","name":"Endpoint","attributes":{"method":"POST","path":"https://api.aitronos.com/v1/shared-threads/{slug}/presence"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"authentication","__idx":2},"children":["Authentication"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Requires ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["user"]}," authentication (Bearer token). API-key authentication is rejected with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"path-parameters","__idx":3},"children":["Path Parameters"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["slug"]}]}," string ",{"$$mdtype":"Tag","name":"em","attributes":{"style":{"color":"#ef4444 !important","fontWeight":"600 !important","fontStyle":"normal !important"}},"children":["required"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The share-link slug (must be a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["live"]}," link)."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"body-parameters","__idx":4},"children":["Body Parameters"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["state"]}]}," string ",{"$$mdtype":"Tag","name":"em","attributes":{"style":{"color":"#9ca3af !important","fontWeight":"500 !important","fontStyle":"normal !important"}},"children":["optional"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["One of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["viewing"]}," (default), ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["typing"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["prompting"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}]}," string ",{"$$mdtype":"Tag","name":"em","attributes":{"style":{"color":"#9ca3af !important","fontWeight":"500 !important","fontStyle":"normal !important"}},"children":["optional"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A stable id for the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["device or tab"]}," sending this heartbeat. Pattern ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["^[A-Za-z0-9_-]+$"]},", max 64 characters. Generate it once per surface and reuse it for that surface's lifetime."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"returns","__idx":5},"children":["Returns"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A list of the users currently present on the underlying thread, each with their ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["user_id"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["state"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["avatar_url"]}," (profile-image URL, or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]}," — falls back to initials), and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["last_seen"]}," (Unix timestamp)."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"get-presence-snapshot","__idx":6},"children":["Get presence snapshot"]},{"$$mdtype":"Tag","name":"Endpoint","attributes":{"method":"GET","path":"https://api.aitronos.com/v1/shared-threads/{slug}/presence"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Returns the same present set on demand, without recording a heartbeat."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"code-examples","__idx":7},"children":["Code Examples"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"curl","__idx":8},"children":["cURL"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -X POST https://api.aitronos.com/v1/shared-threads/abc123slug/presence \\\n  -H \"Authorization: Bearer YOUR_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"state\": \"typing\"}'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"python-sdk","__idx":9},"children":["Python SDK"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"from aitronos import Aitronos\n\nclient = Aitronos(api_key=\"\", token=\"YOUR_TOKEN\")\npresent = client.threads.shared.presence(slug=\"abc123slug\", state=\"typing\")\nprint([p.user_id for p in present.data])\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"python-requests","__idx":10},"children":["Python (requests)"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import requests\n\nresponse = requests.post(\n    \"https://api.aitronos.com/v1/shared-threads/abc123slug/presence\",\n    headers={\"Authorization\": \"Bearer YOUR_TOKEN\"},\n    json={\"state\": \"typing\"},\n)\nprint(response.json()[\"data\"])\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"javascript","__idx":11},"children":["JavaScript"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const response = await fetch(\n  \"https://api.aitronos.com/v1/shared-threads/abc123slug/presence\",\n  {\n    method: \"POST\",\n    headers: {\n      Authorization: \"Bearer YOUR_TOKEN\",\n      \"Content-Type\": \"application/json\",\n    },\n    body: JSON.stringify({ state: \"typing\" }),\n  },\n);\nconst present = await response.json();\nconsole.log(present.data);\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"response-examples","__idx":12},"children":["Response Examples"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"success-200","__idx":13},"children":["Success (200)"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"object\": \"list\",\n  \"thread_id\": \"thread_9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a\",\n  \"data\": [\n    {\n      \"user_id\": \"usr_3ae598ea791242898b5feb69e4c4e30c\",\n      \"state\": \"typing\",\n      \"name\": \"Aitronos Team Dev\",\n      \"avatar_url\": \"https://cdn.aitronos.com/avatars/usr_abc123.png\",\n      \"last_seen\": 1782681710.5\n    },\n    {\n      \"user_id\": \"usr_38893a99f74344e4a6cac1e99d813f74\",\n      \"state\": \"viewing\",\n      \"name\": \"Owner\",\n      \"avatar_url\": null,\n      \"last_seen\": 1782681709.1\n    }\n  ]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error--not-a-live-link-403","__idx":14},"children":["Error — Not a live link (403)"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INSUFFICIENT_PERMISSIONS\",\n    \"message\": \"You do not have permission to perform this action.\",\n    \"system_message\": \"This share link does not grant live co-working access\",\n    \"type\": \"authorization_error\",\n    \"status\": 403,\n    \"details\": {\n      \"link_id\": \"tslnk_2b1c3d4e5f6a7b8c9d0e1f2a3b4c5d6e\",\n      \"access_level\": \"view\"\n    },\n    \"trace_id\": \"...\",\n    \"timestamp\": \"...\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"related-resources","__idx":15},"children":["Related Resources"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/api-reference/shared-threads/join-shared-thread"},"children":["Join Shared Thread"]}," — Create the persistent joined entry"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/api-reference/shared-threads/live-shared-thread"},"children":["Live Shared Thread"]}," — The live co-working event stream (presence updates fan out here)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/api-reference/shared-threads/leave-shared-thread"},"children":["Leave Shared Thread"]}," — Remove the joined entry"]}]}]}]},"headings":[{"value":"Shared Thread Presence","id":"shared-thread-presence","depth":1},{"value":"Heartbeat presence","id":"heartbeat-presence","depth":2},{"value":"Authentication","id":"authentication","depth":3},{"value":"Path Parameters","id":"path-parameters","depth":3},{"value":"Body Parameters","id":"body-parameters","depth":3},{"value":"Returns","id":"returns","depth":3},{"value":"Get presence snapshot","id":"get-presence-snapshot","depth":2},{"value":"Code Examples","id":"code-examples","depth":2},{"value":"cURL","id":"curl","depth":3},{"value":"Python SDK","id":"python-sdk","depth":3},{"value":"Python (requests)","id":"python-requests","depth":3},{"value":"JavaScript","id":"javascript","depth":3},{"value":"Response Examples","id":"response-examples","depth":2},{"value":"Success (200)","id":"success-200","depth":3},{"value":"Error — Not a live link (403)","id":"error--not-a-live-link-403","depth":3},{"value":"Related Resources","id":"related-resources","depth":2}],"frontmatter":{"title":"Shared Thread Presence","seo":{"title":"Shared Thread Presence"}},"lastModified":"2026-10-26T18:32:31.653Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/api-reference/shared-threads/shared-thread-presence","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}