Developers

Sentra REST API reference

Read Sentra's organization memory from any agent or service: meetings, email threads, entities, fact chunks with citations, relationships, and the memory agent.

Basics

Host. https://api.sentra.app. Every path starts with /external/v1.

Authentication. Send your key as Authorization: Bearer sk_sentra_… on every request. Generate a key in the Sentra app under Settings, API Access. Keys inherit the owner's access, so the API never returns anything that person could not see in the app.

Rate limit. 120 requests per minute per key, shared with the MCP server. Requests over the limit receive 429.

Machine-readable spec. OpenAPI document. Prefer MCP for agents: connect the Sentra MCP server.

Sentra Public API, version 2026.11.03

Meetings

List Meetings

GET /external/v1/meetings

List meetings visible to the API key's user. Use search to filter by keyword instead of paginating blindly. Admins see org meetings except private ones they did not attend; non-admins see meetings they attended.

ParameterInTypeDescription
start_datequerystringFilter meetings created at or after this UTC timestamp.
end_datequerystringFilter meetings created at or before this UTC timestamp.
pagequeryinteger
limitqueryinteger
searchquerystringCase-insensitive exact substring search within meeting names only.
statusquerystring[]Filter by meeting status. Repeat status to pass multiple values. skipped represents bot meetings where Sentra did not capture a usable recording/transcript (e.g. bot not admitted, or no meaningful captured content). It does not imply the user did not attend.
attendeequerystringFilter to meetings that include this attendee email.

Get Meeting

GET /external/v1/meetings/{meeting_id}

Return summary and full transcript for one meeting by Recall bot id (meeting_id). Expensive, returns large payloads. Call at most once per turn unless the user explicitly asks for multiple meetings. Prefer get_entity_chunks for cross-meeting questions about people or companies.

ParameterInTypeDescription
meeting_id (required)pathstring

Emails

Get Raw Email Thread

GET /external/v1/emails/threads/raw

Fetch every message in an email thread that the calling API key is allowed to see, with raw bodies and original RFC822 headers. Paginated. Two layered access checks apply, both enforced server-side: 1. The API-key owner must be assigned to a data-access role that carries the email_raw capability marker. Without it the request returns 403 even if the caller can otherwise read every message in the thread via the standard email endpoints. 2. Within the thread, only messages whose participant set (sender + To + Cc) intersects the address set granted by the caller's email data-access rules are returned. Messages the caller cannot see under the standard email visibility model are filtered out silently, the message count the caller sees may be smaller than the actual thread length stored. Pagination is keyset (cursor + limit). Pass the next_cursor from each response back as the cursor query parameter to fetch the next page; iteration ends when next_cursor is null. A page can be empty (message_count=0) while still carrying a non-null next_cursor, that signals a stretch of rows the caller is not allowed to see, and the caller should follow the cursor. Returns 404 only on the FIRST page (no cursor) when no message in the thread is visible to the caller, regardless of whether the thread exists in the org. Returns 400 on a malformed cursor.

ParameterInTypeDescription
thread_key (required)querystringNormalized RFC822 Message-ID root identifying the thread. Carried as a query parameter, not a path segment, because Message-IDs legitimately contain /, ?, #, &, +, and =, which break path-segment routing across the ASGI / proxy stack.
cursorquerystringOpaque pagination cursor. Omit (or null) to fetch the first page; otherwise pass back the next_cursor value from the prior response unchanged.
limitqueryintegerMaximum messages to fetch from storage for this page. The visible portion of the page (after the per-message ACL filter) may be smaller, possibly zero, without implying the thread has ended; follow next_cursor until it is null. Defaults to 50, capped at 200.

List Email Threads For Address

GET /external/v1/emails/threads

List the unique email threads a given address participates in that the calling API key is allowed to see, most-recent first. Metadata only (subject, participants, dates, counts), no message bodies; use GET /external/v1/emails/threads/raw with a returned thread_key to fetch raw bodies for a single thread. email_address is required. Two layered access checks apply, both server-side: 1. The API-key owner must carry the email_raw data-access capability (403 otherwise), the same gate as the raw-thread endpoint. 2. Only threads containing at least one message the caller can see under their email data-access rules are returned; a thread's metadata (participants, count, latest date/subject) reflects only the messages the caller can see. If the caller has no access to the address's mail, the list is empty (this does not reveal whether the address has any mail). If the requested email_address is a user the caller has REVOKED, the list is always empty, a revoked user's threads are never surfaced when querying for that user, even shared-org threads. By default only business-context / business-critical classified threads are returned (the unfiltered corpus is too noisy for an audit list); set business_only=false to include every classification. Pagination is keyset (cursor + limit). Pass next_cursor back as cursor until it is null.

ParameterInTypeDescription
email_address (required)querystringRequired. The target participant address whose threads to list. Normalized (lowercased, display name stripped) before use; a value that does not parse to an address returns 400.
cursorquerystringOpaque pagination cursor. Omit (or null) for the first page; otherwise pass back the prior response's next_cursor unchanged. Iteration ends when next_cursor is null.
limitqueryintegerMaximum threads per page. Defaults to 50, capped at 200.
business_onlyquerybooleanWhen true (default), only business-context / business-critical classified threads are returned, the unfiltered corpus (newsletters, automated noise, etc.) is too noisy for an audit list. Set false to include every classification.

Followup burden

List Followup Burden

GET /external/v1/followup-burden

Latest follow-up-burden snapshot for every configured target the calling API key is allowed to see, plus a cohort block aggregating those visible targets (totals, ratios, and blocker-score summary). Requires the email_raw data-access capability (403 otherwise). Targets are filtered to those the caller's email access covers, an org-wide (ALL) key sees everyone; a scoped key sees only addresses it is granted, and its cohort reflects that subset. Items are ordered by blocker_score (highest-blocking first; unscored last), then by confirmed chases. Results are PAGED: items holds at most limit targets (default 100, max 500) starting at offset, while total is the full visible count and has_more says whether more pages remain, page on with offset = offset + count. cohort always covers ALL visible targets, not just the current page, so cohort ratios like chased_ask_ratio are complete from the first page and need no paging to total up. Pass as_of=YYYY-MM-DD to get each target's newest snapshot on or before that date (a past week's view); omit for today's latest. Follow the per-user endpoint and then the raw-thread endpoint for evidence.

ParameterInTypeDescription
as_ofquerystringOptional ISO date (YYYY-MM-DD). Returns each target's newest snapshot on or before this date, a past week's view. Omit for today's latest. The cohort block reflects the same set.
limitqueryintegerMax targets to return in items. cohort and total always cover every visible target, not just this page.
offsetqueryintegerTargets to skip before this page.

Get Followup Burden User

GET /external/v1/followup-burden/user

One target's follow-up-burden snapshot plus the evidence thread_keys (the threads the target was chased in). Requires the email_raw capability. Pass as_of=YYYY-MM-DD for that target's newest snapshot on or before that date (a past week's view); omit for the latest. Returns 404 when the target is not configured, has no snapshot by the requested date, or the caller's email access does not cover that person (the three are intentionally indistinguishable). The returned evidence_thread_keys are fetched from GET /emails/threads/raw?thread_key=..., which independently enforces per-message visibility, so a thread_key here never grants content the caller could not already read.

ParameterInTypeDescription
email (required)querystringTarget email address (carried as a query parameter because addresses can contain + and other characters that break path-segment routing). Normalized server-side.
as_ofquerystringOptional ISO date (YYYY-MM-DD). Returns the target's newest snapshot on or before this date, a past week's view. Omit for the latest.

Thread stalls

List Thread Stalls

GET /external/v1/thread-stalls

Latest snapshot of the organization's large, stalling/blocking business email threads, ranked by a blend of criticality (LLM-scored impact / urgency / scope with aging) and stall severity (how long a big, multi-party thread has gone quiet). Automation/noise (monitoring alerts, recurring digests, single-sender broadcasts) is filtered out. Requires the email_raw data-access capability (403 otherwise); rows are limited to threads the caller's email access covers. Each row's status is OPEN, CLOSED (resolved), or UNKNOWN (scoring failed for that thread). Open threads rank above closed ones. Each row carries a thread_key for the raw-thread endpoint, which independently enforces per-message visibility. Pass status=open to drop CLOSED threads (it keeps OPEN and UNKNOWN), or as_of=YYYY-MM-DD for a past day's snapshot; omit for today's latest.

ParameterInTypeDescription
statusquerystringOptional. open hides resolved (closed) threads; omit for all.
as_ofquerystringOptional ISO date (YYYY-MM-DD). Returns the newest snapshot on or before this date; omit for today's latest.

Sources

List Sources

GET /external/v1/sources

List the data sources the org can produce data from. Use this to discover (1) which values the source_types filter on get_entity_chunks / get_entity_relationships accepts and (2) which external integrations the org has connected. meeting, file, and manual are always connected=true; slack, github, linear, clickup, jira, erpnext, and every HubSpot object-type source (hubspot_contact / hubspot_company / hubspot_deal / hubspot_ticket / hubspot_note / hubspot_task / hubspot_call / hubspot_meeting / hubspot_lead / hubspot_line_item / hubspot_quote / hubspot_custom_object) are true iff the org has connected that integration and has synced records of that type (erpnext requires only that the integration is connected). ORG-LEVEL signal, a connected=true source can still return zero rows for the calling user if they aren't a member of the underlying Slack channel / Linear team / GitHub repo / ClickUp workspace, or lack BROWSE_PROJECTS on the Jira issue's project, hold no ERPNext permission on the document, or aren't the HubSpot record's owner / on its team (or, for manual, if no member of the org has authored a chunk visible to them).

Entities

List Entities

GET /external/v1/entities

List entities (people, companies, projects, etc.) the API key's user can see, grouped by type. Visibility is per-user: two keys in the same org may return different lists. Use entity_type to filter by type and search to find entities by name; use cursor for pagination. search is case-insensitive and matches both the entity's name (canonical_name) and its aliases (other names, spellings and abbreviations recorded for the entity). With search, the entities in each group are ranked best match first, and each one carries match_type and matched_text (the name or alias that matched). The match types, from strongest to weakest: - substring: the search text is part of the name or of an alias. - compact: the search text matches when spaces and punctuation are ignored (for example "AcmeCorp" and "Acme Corp"). - token: every word of the search text is in the name or in one alias, in any order (for example "Smith John" and "John Smith"). - fuzzy: the name or alias is similar to the search text but not the same (for example another spelling). A fuzzy match is a CANDIDATE, not a confirmed match: it is often a different entity with a similar name (for example "Daniel" and "Danielle"). Before you use a fuzzy match, read its chunks and confirm that they are about what you are looking for. Fuzzy matches always rank below the other match types. There are no fuzzy matches when the search text contains a digit. With search, when total_is_lower_bound is true, the search stopped early and there can be more matches than total_entities: use cursor for the next page. Each returned entity carries a UUID id that you must pass verbatim to get_entity_chunks / get_entity_relationships / fetch entity:<id>. Each entity carries a status you MUST respect: confirmed means it is likely to be a real, valid entity. proposed means the OPPOSITE, it is an UNCONFIRMED, hypothetical suggestion the org has NOT yet accepted (e.g. a proposed project is NOT a real project on the roadmap; it is a candidate a human still has to approve). NEVER present a proposed entity as a confirmed fact: if you mention one, you MUST explicitly label it as proposed / unconfirmed / not yet accepted, and prefer confirmed entities as the source of truth. rejected means a human explicitly declined it, do not rely on it.

ParameterInTypeDescription
entity_typequerystring[]Filter by entity type slug. Repeat entity_type to pass multiple types.
updated_sincequerystringOnly include entities with at least one visible chunk at or after this timestamp. A chunk's time is when its source content happened (a message, a meeting), not when Sentra ingested it. A synced document's chunks carry its last-modified time when its source reported one (so a newly synced older document can add chunks before the bound); otherwise they carry the time Sentra ingested the document. **Must be timezone-aware** (include Z or an explicit offset like +00:00); naive datetimes are rejected with an actionable error.
limitqueryintegerOptional page size for cursor pagination.
cursorquerystringOpaque cursor returned by the previous entities response.
searchquerystringOptional case-insensitive search on the entity's canonical_name and its aliases: a substring, the same text with spaces and punctuation ignored, all words in any order, or a similar spelling (fuzzy), ranked best match first in each group. Whitespace-only values are treated as no filter. Mirrors the in-app /entity-memory/entities route and the desktop Spotlight typeahead so the public API, the in-app surface, and the Spotlight share one search contract.

List Important Entities

GET /external/v1/entities/important

Return the user's important entities (projects, companies, topics, and the like, not people) as an unranked set: each item carries the entity id, type, and name, and the items are sorted by name. The set carries no scores and no ranks by design, the underlying scores are computed from org-wide data, so exposing them would leak activity the caller cannot see. Visibility is per-user: a user sees only entities they can access. This is a bounded top-N read: count is the number of returned items, and there is no total or pagination cursor.

ParameterInTypeDescription
limitqueryintegerThe maximum number of entities to return (1-100).
entity_typequerystring[]Restrict to these entity type slugs.

List Entity Types

GET /external/v1/entities/types

Return the org's configured entity type slugs and display names. Cheap lookup to resolve a slug from list_entities.

Get Entity Chunks

GET /external/v1/entities/{entity_id}/chunks

Return ACL-filtered fact chunks for one entity. Prefer this over get_meeting for cross-meeting questions, chunks are concise and include source citations. entity_id must be a UUID returned by list_entities (not a display name or slug); malformed values are rejected with an actionable error.

ParameterInTypeDescription
entity_id (required)pathstring
limitqueryintegerPage size; max 100.
offsetqueryinteger
source_typesquerystring[]Optional filter restricting chunks to a subset of source types. Repeat source_types to pass multiple values. Omit to return rows from every source the caller can see. Unknown values are rejected with an actionable error. Allowed values: ['basecamp', 'chat_update', 'clickup', 'confluence', 'email', 'erpnext', 'file', 'github', 'google_chat', 'hubspot_call', 'hubspot_company', 'hubspot_contact', 'hubspot_custom_object', 'hubspot_deal', 'hubspot_lead', 'hubspot_line_item', 'hubspot_meeting', 'hubspot_note', 'hubspot_quote', 'hubspot_task', 'hubspot_ticket', 'jira', 'linear', 'manual', 'meeting', 'personal_email', 'slack', 'teams_channel', 'teams_chat', 'zendesk'].

Get Entity Relationships

GET /external/v1/entities/{entity_id}/relationships

Return extracted links and co-attendance for one entity. Co-attendance defaults to the last 180 days. entity_id must be a UUID returned by list_entities; malformed values are rejected with an actionable error.

ParameterInTypeDescription
entity_id (required)pathstring
max_linksqueryintegerPage size for LLM-extracted link rows. Pagination is cursor-based: the response carries next_links_cursor when more rows are available, pass it back as links_cursor to fetch the next page.
links_cursorquerystringOpaque cursor returned as next_links_cursor on a previous response. Omit to fetch the first page. Malformed cursors are rejected with an actionable error.
max_counterpartsqueryinteger
max_events_per_counterpartqueryinteger
co_attendance_sincequerystringInclusive lower bound on source-event time for co-attendance aggregation. **Must be timezone-aware** (RFC 3339 with Z or an explicit offset like +00:00); naive datetimes are rejected with an actionable error. Defaults to 180 days before co_attendance_until (or before now if co_attendance_until is also omitted). Does NOT affect extracted links.
co_attendance_untilquerystringInclusive upper bound on source-event time for co-attendance aggregation. **Must be timezone-aware** when specified; naive datetimes are rejected with an actionable error. Omit for no upper bound.
source_typesquerystring[]Optional filter restricting links AND co-attendance to a subset of source types. Repeat source_types to pass multiple values. Omit to return rows from every source the caller can see. Unknown values are rejected with an actionable error. Allowed values: ['basecamp', 'chat_update', 'clickup', 'confluence', 'email', 'erpnext', 'file', 'github', 'google_chat', 'hubspot_call', 'hubspot_company', 'hubspot_contact', 'hubspot_custom_object', 'hubspot_deal', 'hubspot_lead', 'hubspot_line_item', 'hubspot_meeting', 'hubspot_note', 'hubspot_quote', 'hubspot_task', 'hubspot_ticket', 'jira', 'linear', 'manual', 'meeting', 'personal_email', 'slack', 'teams_channel', 'teams_chat', 'zendesk']. Co-attendance is only populated by the meeting adapter today, so a filter that excludes meeting returns an empty co_attendance list.

Memory agent

Start Memory Agent Run

POST /external/v1/memory-agent/runs

Start an asynchronous memory-agent run. The agent investigates your prompt over your Sentra memory and returns a written answer with source citations. The run uses your API key's identity and memory access. Caller should prefer this tool over other memory tools for complex, multi-step, or open-ended questions about Sentra memory: it runs a full research agent that plans, searches across sources, and synthesizes an answer, so it handles questions that a single lookup cannot. Runs typically take a few minutes and can run up to about 30 minutes, so this returns a job_id immediately; caller must then call GET /memory-agent/runs/{job_id} repeatedly. Status is one of 'queued', 'running', 'completed', or 'failed': 'queued' and 'running' are in-flight (keep polling), 'completed' and 'failed' are terminal (stop). Do not stop after a single call - the run starts in 'queued' and only reaches a terminal status once a worker finishes it. While status is non-terminal the run is still working as long as the result's 'elapsed_seconds' keeps increasing and 'last_updated_at' keeps advancing; do not treat a non-terminal status as a timeout. Poll no more than once every 10s. Polling shares the same 120 req/min per-API-key rate limit as every other public read, so a tight poll loop can exhaust the bucket for your unrelated reads too - back off accordingly.

Takes a JSON request body.

Get Memory Agent Run

GET /external/v1/memory-agent/runs/{job_id}

Fetch the current status and result of a memory-agent run started with the start endpoint. GET /memory-agent/runs/{job_id} returns immediately; while status is 'queued' or 'running' the run is not finished yet - re-call after about 10s. Every response includes timing fields: 'started_at' (ISO-8601 UTC), 'last_updated_at' (ISO-8601 UTC, bumped by a worker heartbeat while the run executes), and 'elapsed_seconds' (integer seconds since the run started). While the run is in flight 'elapsed_seconds' increases on every poll and 'last_updated_at' advances every few seconds as the worker heartbeats: as long as these keep moving the run is alive and working - keep polling and do not assume it timed out just because there is no answer yet. Runs can take up to about 30 minutes; if 'last_updated_at' stops advancing for well over a minute while status is still non-terminal, the run may be stuck. The final_response and citations are present only when status is 'completed'. Records expire 2 hours after creation. Polling counts against the shared 120 req/min per-key rate limit, so respect the cadence rather than busy-looping.

ParameterInTypeDescription
job_id (required)pathstring

Swimlanes

List Swimlanes Endpoint

GET /external/v1/swimlanes

List the organization's swimlanes (org-level project views over memory), each with the API key user's cached live-summary when one exists. Reading the list does not trigger generation.

Create Swimlane Endpoint

POST /external/v1/swimlanes

Create a swimlane. title and description are required; goal, owner_user_id, and stakeholder_user_ids are optional. Owner and stakeholders are Sentra user ids, resolve names to ids with list_org_members first. Creation triggers asynchronous entity discovery.

Takes a JSON request body.

Get Swimlane Endpoint

GET /external/v1/swimlanes/{swimlane_id}

Return one swimlane's own attributes (title, description, goal, owner, stakeholders, discovery state) by id. A person with is_pending_invite: true is an invited person who has not joined; they are not returned by list_org_members and stay on the swimlane when you send their id again in the same list.

ParameterInTypeDescription
swimlane_id (required)pathstring

Update Swimlane Endpoint

PATCH /external/v1/swimlanes/{swimlane_id}

Update a swimlane's user-authored fields. Every field is optional but at least one must be sent. stakeholder_user_ids accepts [] to clear its Sentra-user subset (external, unresolved people are preserved). Resolve ids with list_org_members. Changing title/description/goal re-triggers discovery. A person with is_pending_invite: true is an invited person who has not joined; they are not returned by list_org_members and stay on the swimlane when you send their id again in the same list. A suggested swimlane must keep at least one active (joined) owner or stakeholder; an update that leaves no active one is rejected. Send owner_user_id: null to clear the owner.

Takes a JSON request body.

ParameterInTypeDescription
swimlane_id (required)pathstring

Delete Swimlane Endpoint

DELETE /external/v1/swimlanes/{swimlane_id}

Archive (soft-delete) a swimlane for the WHOLE organization, this is destructive and affects every member, not just you. You must pass confirm=true to proceed; a call without it is rejected.

ParameterInTypeDescription
swimlane_id (required)pathstring
confirmquerybooleanMust be true to perform this destructive, org-wide archive. Any other value is rejected.

List Swimlane Activity Endpoint

GET /external/v1/swimlanes/{swimlane_id}/activity

Return a swimlane's Event Feed: the notable, real events that happened on the project, each typed (deploy_release, decision, milestone, blocker, stall, ...) and badged hard (observed) or soft (inferred). An empty feed is NOT authoritative ('nothing happened') until it has been generated for you: check state, and when it is empty or stale call refresh_swimlane_activity to generate it, then re-read. The feed is returned whole, so limit/cursor are ignored and next_cursor is always null, do not paginate. This read returns the latest cached result immediately with a state and freshness fields (is_stale, generated_at); it never starts generation. When is_stale is true (or no result exists yet), call the matching refresh_* operation to regenerate, then re-read. While a refresh you triggered is in flight, state is generating, re-read until it settles.

ParameterInTypeDescription
swimlane_id (required)pathstring
limitqueryinteger
cursorquerystring

Get Live Summary Endpoint

GET /external/v1/swimlanes/{swimlane_id}/live-summary

Return the API key user's live summary for a swimlane (the generated, ACL-filtered latest updates). This read returns the latest cached result immediately with a state and freshness fields (is_stale, generated_at); it never starts generation. When is_stale is true (or no result exists yet), call the matching refresh_* operation to regenerate, then re-read. While a refresh you triggered is in flight, state is generating, re-read until it settles.

ParameterInTypeDescription
swimlane_id (required)pathstring

Get Attention Endpoint

GET /external/v1/swimlanes/{swimlane_id}/attention

Return the API key user's active attention items for a swimlane (proactive assessments that the swimlane needs attention). Each item has a type (risk | contradiction | other); typed items (risk / contradiction) also carry an optional evidence payload (why it matters, a primary quote, the event trail, a suggested next step, and, for a contradiction, the two conflicting sides) and a confidence score. confidence is the detection ensemble's vote share (0-1), NOT the probability the risk is real, surface the evidence, do not read it as a truth likelihood. This read returns the latest cached result immediately with a state and freshness fields (is_stale, generated_at); it never starts generation. When is_stale is true (or no result exists yet), call the matching refresh_* operation to regenerate, then re-read. While a refresh you triggered is in flight, state is generating, re-read until it settles.

ParameterInTypeDescription
swimlane_id (required)pathstring

Get Whats Next Endpoint

GET /external/v1/swimlanes/{swimlane_id}/whats-next

Return the API key user's forward-looking items for a swimlane. This capability is in active development: an empty set is NOT authoritative ('nothing coming up') until the finder ships. This read returns the latest cached result immediately with a state and freshness fields (is_stale, generated_at); it never starts generation. When is_stale is true (or no result exists yet), call the matching refresh_* operation to regenerate, then re-read. While a refresh you triggered is in flight, state is generating, re-read until it settles.

ParameterInTypeDescription
swimlane_id (required)pathstring

Retry Discovery Endpoint

POST /external/v1/swimlanes/{swimlane_id}/discovery/retry

Re-trigger entity discovery for a swimlane (the explicit 'try again' for a failed discovery). This starts background work and uses compute; do not call it repeatedly. Returns the swimlane with discovery moved to initializing.

ParameterInTypeDescription
swimlane_id (required)pathstring

Refresh Live Summary Endpoint

POST /external/v1/swimlanes/{swimlane_id}/live-summary/refresh

Force regeneration of the API key user's live summary for a swimlane, bypassing the cache. This starts new AI generation and uses compute (latency and cost); do not call it repeatedly. It returns immediately with state=generating; re-read the matching read operation until state settles.

ParameterInTypeDescription
swimlane_id (required)pathstring

Refresh Attention Endpoint

POST /external/v1/swimlanes/{swimlane_id}/attention/refresh

Force regeneration of the API key user's attention items for a swimlane. This starts new AI generation and uses compute (latency and cost); do not call it repeatedly. It returns immediately with state=generating; re-read the matching read operation until state settles.

ParameterInTypeDescription
swimlane_id (required)pathstring

Refresh Whats Next Endpoint

POST /external/v1/swimlanes/{swimlane_id}/whats-next/refresh

Force regeneration of the API key user's forward-looking items for a swimlane. This starts new AI generation and uses compute (latency and cost); do not call it repeatedly. It returns immediately with state=generating; re-read the matching read operation until state settles.

ParameterInTypeDescription
swimlane_id (required)pathstring
viewer_nowquerystringThe caller's current local time as an RFC 3339 timestamp with offset (e.g. 2026-01-02T09:00:00-08:00). Pass it on a refresh so relative time phrases are correct for you; when omitted the server uses its own clock.

Refresh Activity Endpoint

POST /external/v1/swimlanes/{swimlane_id}/activity/refresh

Force regeneration of the API key user's Event Feed for a swimlane. This starts new AI generation and uses compute (latency and cost); do not call it repeatedly. It returns immediately with state=generating; re-read the matching read operation until state settles.

ParameterInTypeDescription
swimlane_id (required)pathstring
viewer_nowquerystringThe caller's current local time as an RFC 3339 timestamp with offset (e.g. 2026-01-02T09:00:00-08:00). Pass it on a refresh so relative time phrases are correct for you; when omitted the server uses its own clock.

Dismiss Attention Endpoint

DELETE /external/v1/swimlanes/{swimlane_id}/attention/{item_id}

Dismiss one attention item for the API key user (permanent, per-viewer). The item_id is valid only for the generation it was read from, it rotates on every regeneration, so read attention items immediately before dismissing. The response reports dismissed: true when a matching active item was dismissed, false when the id matched nothing (unknown or already-settled).

ParameterInTypeDescription
swimlane_id (required)pathstring
item_id (required)pathstring

Resolve Attention Endpoint

POST /external/v1/swimlanes/{swimlane_id}/attention/{item_id}/resolve

Resolve one active attention item for the API key user (permanent, per-viewer), the viewer has acted on it and closed it out. Any active item can be resolved; a risk or contradiction the viewer has handled is the primary case. The item_id is valid only for the generation it was read from, it rotates on every regeneration, so read attention items immediately before resolving. The response reports resolved: true when a matching active item was resolved, false when the id matched nothing (unknown or already-settled).

ParameterInTypeDescription
swimlane_id (required)pathstring
item_id (required)pathstring

Org

List Org Members Endpoint

GET /external/v1/org/members

List the members of the API key's organization as {id, display_name}. Use this to resolve a person's name to the numeric id the swimlane create/update contract requires for owner_user_id and stakeholder_user_ids. Pass search to filter by name or email instead of paginating the whole roster. Work emails are omitted by default; pass include_email=true only when you must disambiguate members who share a display name.

ParameterInTypeDescription
searchquerystringCase-insensitive substring match against member first name, last name, and email. Omit to list the whole org (paginated).
limitqueryinteger
include_emailquerybooleanInclude each member's work email in the response. Off by default to avoid broadcasting the roster's emails; turn on only to tell apart members who share a display name.