Build on your own
meeting notes.
Three surfaces, one credential: a REST API for notes and folders, signed webhooks for note and action-item events, and an MCP server your AI tools can talk to directly.
One key, minted in Settings.
A workspace admin creates a key under Settings, then Integrations, then Outbound Webhooks. The key is shown once at creation and only a hash is kept, so a copy you lose cannot be recovered. Send it as a bearer token or in an X-API-Key header.
curl https://api.reline.so/api/zapier/me \
-H "Authorization: Bearer rlk_your_key_here"
# X-API-Key: rlk_your_key_here works tooWhat a key can reach
A key acts as the admin who created it, inside that one workspace. Every read and write runs through the same permission checks that person gets in the app, so a key never reaches a private note its owner could not already open.
Revoking a key
Revoking blocks the key on the next request and deletes every webhook subscription it created, so listeners stop receiving events in the same moment. There is no grace window to wait out.
Six endpoints over notes and folders.
Responses are JSON. Failures come back with a 4xx status and an error field describing what went wrong.
| Method | Endpoint | What it does |
|---|---|---|
| GET | /api/zapier/me | Resolves the key to a workspace and a user. Use it to check a credential. |
| GET | /api/zapier/notes | Recent notes you can see, newest first. Narrow to one folder with folderId. |
| POST | /api/zapier/notes | Creates a note, optionally inside a folder you can edit. |
| GET | /api/zapier/folders | Folders you can see. Pass level=edit for the ones you can write into. |
| POST | /api/zapier/subscribe | Registers a webhook subscription for one event, optionally scoped to a folder. |
| DELETE | /api/zapier/subscribe | Removes a subscription by the id returned when it was created. |
curl -X POST https://api.reline.so/api/zapier/notes \
-H "Authorization: Bearer rlk_your_key_here" \
-H "Content-Type: application/json" \
-d '{"title":"Kickoff call","description":"Agenda + owners"}'
# 201 -> { "id": "...", "title": "Kickoff call", "url": "https://..." }The note object
The same shape comes back from the notes endpoint and rides inside every webhook payload, so a field you map once maps everywhere. Summary and action-item fields ride along on the events that carry them.
{
"id": "j57...",
"noteId": "j57...",
"title": "Kickoff call",
"url": "https://app.reline.so/acme/notes/j57...",
"folderId": "k21..." | null,
"folderName": "Clients" | null,
"isArchived": false,
"createdAt": 1788302403777,
"updatedAt": 1788302911204
}Six events, signed on the way out.
Subscribe in Settings or over the API. Each delivery is a POST carrying one event; scope a subscription to a folder to narrow what wakes it up.
Events
- A note was created, by a person, the calendar, or the API.
- A summary finished generating. Editing a summary later does not re-fire it.
- A note was moved to trash. Only the note acted on directly, never a cascade.
- A note came back out of trash.
- Action items were extracted for a note, delivered as one batch carrying the full current list.
- Somebody checked an action item off.
The delivery
Three headers travel with the body: the event name, a unique delivery id, and the signature.
POST https://your-endpoint.example.com
X-Reline-Event: note.summarized
X-Reline-Delivery: 9f3c...
X-Reline-Signature: t=1788302403,v1=6b8a...
{
"id": "9f3c...",
"event": "note.summarized",
"occurredAt": 1788302403777,
"workspace": { "id": "w1...", "slug": "acme", "name": "Acme" },
"data": { "noteId": "j57...", "summary": "# Kickoff\n..." }
}Verifying a delivery
The signature is an HMAC-SHA256 over the timestamp and the raw body, joined by a period, keyed with the signing secret shown when the subscription was created. Compute it over the bytes you received, before any JSON parsing, and compare in constant time.
import crypto from 'node:crypto'
// `raw` is the request body as received — verify BEFORE JSON.parse.
function verify(raw: string, header: string, secret: string): boolean {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${raw}`)
.digest('hex')
if (typeof parts.v1 !== 'string' || parts.v1.length !== expected.length) return false
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
}When a receiver breaks
Deliveries are retried, and a subscription that keeps failing is switched off automatically rather than retried forever. The last status and error of each hook is visible in Settings.
Point an AI tool at your workspace.
The server speaks the Model Context Protocol over HTTP, so it works in claude.ai, ChatGPT, Claude Code, Cursor, and anything else that supports the protocol. Sign in through OAuth, or send the same workspace API key as a bearer token.
claude mcp add --transport http reline https://mcp.reline.so/mcp
# or authenticate a plain HTTP client with the same workspace key:
# Authorization: Bearer rlk_your_key_hereTools that page return a cursor. A short page does not mean the end; only a null cursor does.
Reading
- search
- fetch
- get_note
- get_transcript
- list_notes
- count_notes
- list_meetings
- list_recent_meetings
- list_folders
- list_people
- list_calendar_events
- list_action_items
- list_workspaces
- get_workspace_info
Writing
- create_note
- append_to_note
- update_note
- create_folder
- complete_action_item
The numbers worth knowing.
120 requests per minute
Counted per key in a fixed one-minute window. Going over gets you a 429 until the window rolls.
10 active keys per workspace
Revoked keys do not count. Mint one per integration so you can retire them one at a time.
Admins only
Creating and revoking keys needs the admin role. Members can use an integration built on a key, but cannot mint one.
One workspace per key
A key never crosses into another workspace. Working across several means one key each.
Building something on this?
Tell us what you are wiring together and what is missing. The surface grows where people actually push on it.