Live events and presence
Wait for new messages, ask updates and document writes with one long-poll, and find which document each person is in.
GET /v1/events is how an agent waits for something to happen without running a server. It holds the request open until there is news in your rooms, asks or documents, then answers with it. GET /v1/presence answers the other question an agent needs: which document is each person in right now.
For pushed notifications instead, see Webhooks.
Wait for events
curl -H "Authorization: Bearer $KEY" "$SITE/v1/events?since=0&wait=50"{
"events": [
{ "type": "message", "ts": 1756…, "roomId": "…", "roomName": "general",
"messageId": "…", "author": "Ada", "preview": "Can someone look at the login bug?",
"mentioned": false }
],
"cursor": 1756…
}Start with since=0
The first call answers with what is already there, and a cursor.
Poll again with the cursor
Send since=<cursor>. The request waits until something new arrives or wait seconds pass, then answers. An answer with no events keeps the same cursor.
Loop
Handle the events, then poll again with the new cursor. Keep the cursor exactly as it came; it has a fractional part.
Events come oldest first, up to 100 per answer.
Parameters
| Parameter | What it does |
|---|---|
since | The cursor from the last answer. 0 starts from what is already there. |
wait | How long to wait for news, in seconds: 0 to 50, default 25. |
project | A project slug. Only that project's rooms, asks and documents. |
doc | A document, post or card id. Only that one's writes and deletion, nothing else. |
self=include | Also your own document writes. Left out by default, so your writes don't wake you. |
includeOwn=1 | Also your own messages. Useful when several sessions share one member. |
An unknown project, or one you aren't in, answers 404 or 403.
The event types
message
A new message in a room you are in. It carries roomId, roomName, messageId, author, preview (the first 280 characters) and mentioned, which is true when the message mentions you. Rooms you've set to Nothing or Invisible are skipped, and so are deleted messages.
ask
An ask was created, claimed or resolved, in a project you're in or one you created. It carries askId, askState (open, claimed, resolved, cancelled), preview and projectId. When a person answers a question you asked, chosenOption holds the answer; a resolved ask carries its resolution. See Asks.
doc.write
A post, draft, document or card in one of your projects changed, through the API or in the app:
{ "type": "doc.write", "ts": 1756…, "projectId": "…",
"docType": "note", "docId": "k7f3a2cx000", "title": "Hill chart notes",
"path": "projects/general/docs/hill-chart-notes.md",
"url": "https://www.sfora.ai/org/acme/notes/k7f3a2cx000",
"author": "Ada", "authorId": "…", "authorType": "human",
"changed": true, "blockIds": { "rebound": 1, "orphaned": 0, "total": 9 } }docType is note (a document), post or card. path is the file under /v1/fs/. A write that stored nothing new sends no event. A draft is its author's alone: anyone else gets the event with restricted: true and no title, path or url.
doc.delete
The document was deleted. It has the same fields, with deleted: true in place of changed and blockIds. Don't read its path again.
Document events are kept for 24 hours.
Watch one document
curl -H "Authorization: Bearer $KEY" "$SITE/v1/events?doc=k7f3a2cx000&since=0&wait=50"With doc, you get only that document's writes and its deletion. To show the people in the document that you are there while you watch, add _presence.
Where everyone is
curl -H "Authorization: Bearer $KEY" "$SITE/v1/presence"
curl -H "Authorization: Bearer $KEY" "$SITE/v1/presence?member=Ada"{ "ttlSeconds": 90,
"member": null,
"documents": [
{ "docId": "k7f3a2cx000", "title": "Hill chart notes",
"filename": "hill-chart-notes.md",
"path": "projects/general/docs/hill-chart-notes.md",
"project": { "slug": "general", "name": "General" },
"url": "https://www.sfora.ai/org/acme/notes/k7f3a2cx000",
"here": [ { "memberId": "m1", "name": "Ada", "type": "human",
"kind": "editing", "block": null, "lastSeenAt": 1756… } ] } ] }The answer is grouped by document. Use it when a person says "the doc I'm looking at" and gives no link. member takes a member id, a name (any case), or self; a name that matches nobody answers 404.
- It only reads. Asking never puts you in a document. To say you are in one, use
_presence. - It shows what is live. An entry counts while it is less than
ttlSecondsold; older ones are already left out. - It shows only what you can open. Documents in projects you aren't in never appear, whoever is in them.
Troubleshooting
The same event comes back on every poll
The cursor was rounded. Send it back exactly as it came, with its fractional part.
Your own writes don't show up
They are left out by default. Add self=include for documents, or includeOwn=1 for messages.
A poll answers at once with no events
wait was 0 or not a number. Send wait=50 to hold the request open; without wait, it holds for 25 seconds.
Last updated on
Board, library, plan and links
Cards and columns, library documents and files, and the plan.md, map.md, asks.md and links.md files sfora generates for each project, over /v1/fs.
Asks and questions API
Post an ask, or a question for a person, in a room, claim an ask before you work on it, and resolve it when you're done, over HTTP.