Calendar and calls

The calendar, calling, and meetings families cover time: scheduling on the workspace calendar, live-call lifecycle and in-call actions, and recording what a meeting decided. Scopes: calendar.read / calendar.write for the calendar, calling.write for call actions (call reads ride org.read).

Schedule an event

curl -X POST https://os.cohortapp.com/api/v1/calendar.create \
  -H "Authorization: Bearer $COHORT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-idempotency-key: kickoff-2026-08-10" \
  -d '{"params": {
    "title": "Q3 kickoff",
    "kind": "MEETING",
    "startsAt": "2026-08-10T14:00:00Z",
    "endsAt": "2026-08-10T14:45:00Z",
    "attendees": [{ "memberId": "mem_ada" }, { "email": "pat@client.com", "name": "Pat" }],
    "channelId": "ch_growth"
  }}'

Event kind is one of MEETING, REVIEW, FOCUS, AGENT_BLOCK, ALL_HANDS, HOLD. Attendees may be workspace members (memberId) or external people (email, name). An optional channelId links the event to a Space, and agendaFileId attaches an agenda doc from the drive. Creating, updating, rescheduling, and deleting queue real invite, update, and cancellation emails to attendees.

The rest of the family: update, reschedule, rsvp, delete, the reads get / list, and ask (a grounded question over the calendar, visibility-floored to what your seat can see).

Find a time

calendar.findATime is a deterministic free-slot scan across the named attendees — it proposes times and changes nothing, so it rides the read scope. Use it before calendar.create rather than guessing.

Run a call

The calling family drives live calls in the workspace app:

| Task | Methods | | --- | --- | | Lifecycle | start, join, end, invite | | In-call actions | react, raiseHand, lowerHand, setMute, chat (the in-call chat panel) | | Recording and transcript | recordingStart, recordingStop, addTranscriptLine (authorised agents write finalized transcript lines) | | Reads | getDetails, getTranscript — participation-gated: you see a call's details only if you are in it | | Host moderation | removeParticipant, setLock (block new joins; existing participants unaffected) |

Host moderation is gated in the domain layer: only the call's starter may remove or lock, and an agent host may act only on AI participants. A refused moderation act does not throw — the call succeeds and the result reports the refusal, with one audited *_refused event on the ledger. Check the result.

Transcripts and chat are redacted on the ledger

addTranscriptLine and calling.chat persist their content to the call record, but the ledger event they append carries no line or message body — the same redaction rule as messaging.

Record what a meeting decided

The meetings family is knowledge capture (it rides knowledge.write):

  • meetings.record — file a meeting's participants, outcome, and decisions into the org's meeting registry.
  • meetings.recapFile — the notetaker's landing verb: files a held meeting's recap and transcript into the workspace drive as two documents plus a meeting record, all cross-linked.
  • GET /meetings.list and GET /contacts.list read the registries back (ACL-filtered).