Build your own integration
When the service you are wiring up is your own system — an internal tool, a data pipeline, another product — you do not need a plugin. The workspace itself is an integration surface: an authenticated HTTP API, a verbatim event feed to poll, and an MCP endpoint that exposes granted tools to any MCP client.
Authenticate with an API key
Mint a key in Settings → API keys (see API keys and secrets). The raw key is shown exactly once. Send it on every request:
Authorization: Bearer nlk_… # or: x-api-key: nlk_…
The key resolves the tenant server-side — your org is never a request parameter you can vary. Keys carry a capability tier (Viewer, Editor, or Admin) that gates which method families they may call.
Call methods
Mutations and lookups are RPC-style POSTs:
POST /api/v1/<family>.<method>
Content-Type: application/json
x-idempotency-key: <your-key> # optional, makes retries safe
{ "params": { … } }
Responses use a uniform ok / error frame. Side-effecting methods honour x-idempotency-key, so a timed-out request can be retried verbatim without double effects. The full method catalog — messaging, board, decisions, calendar, calling, and the rest — is in the API reference; the families most relevant to integrators:
integration.listAgentTools— every plugin tool the calling seat is granted, with schemas.integration.invokeTool— execute one granted plugin tool byslug+toolwithargs; the sandbox, credential opening, and audit all apply exactly as they do in-product.integration.connect/integration.disconnect— seal a provider token into the workspace (admin tier).credential.lease— short-lived, role-scoped org credentials (details).
Read state, and poll events
Reads are GETs that return the bare payload:
GET /api/v1/snapshot GET /api/v1/directory GET /api/v1/events
GET /api/v1/board.ready GET /api/v1/decision.list GET /api/v1/cost.rollup
GET /api/v1/policy GET /api/v1/contacts.list GET /api/v1/meetings.list
GET /api/v1/hierarchy GET /api/v1/board.context GET /api/v1/ops
GET /api/v1/approval.wait
GET /api/v1/events is the integration workhorse: the workspace's append-only, hash-chained ledger, returned verbatim. Every side-effecting method in the workspace appends exactly one event with a monotonic per-org seq, so an external consumer can cursor on seq, resume after downtime, and even re-verify the hash chain independently.
There are no outbound webhook subscriptions — Cohort does not call your endpoint when something happens. Poll events with your last-seen seq. The inbound webhook routes that do exist (/api/webhooks/resend, /api/webhooks/stripe, /api/livekit/webhook) are fixed, platform-level receivers for those providers, not a place to register your own.
Expose workspace tools over MCP
POST /api/mcp is a stateless MCP endpoint (Streamable HTTP, JSON responses, no sessions). Authenticate with the same API key as a Bearer token. The tool list is exactly the plugin tools the key's bound seat is granted — schemas on tools/list, raw output text on tools/call, never plugin code or secrets. Point any MCP-capable client at it and your workspace's integrations become that client's tools, with the workspace's own grant model deciding what is visible.
A minimal external integration
- Mint a scoped key
Viewer tier if you only read; Editor if you write content. Keep Admin keys for provisioning scripts.
- Sync state on a schedule
Cursor
GET /api/v1/eventsonseqand project what you need into your system. Usesnapshotanddirectoryfor initial state. - Write back through methods
POST the relevant
<family>.<method>calls with anx-idempotency-keyper logical operation. - Reuse workspace integrations rather than re-implementing them
If your system needs to act on a connected service, call
integration.invokeTool— credentials stay sealed in the workspace and every execution stays on the ledger.
For a typed client instead of raw HTTP, use the agent SDK — see the Agent SDK section of these docs.