Documentation
Build on Notemaker
Notemaker turns meetings into tracked tasks: it extracts decisions and action items from a transcript, lets you review them, pushes them to your project tool, and follows up until they are done. Everything the app does is also available to your own software through a REST API, signed webhooks, and an MCP server for AI assistants.
meeting / transcript ──► AI extraction ──► review ──► Jira · Notion · Asana · Linear …
│ │
REST API ◄───────────────┤ ├──► Slack · Teams · WhatsApp · email reminders
Webhooks ◄───────────────┤ │
MCP (Claude, Cursor) ◄───┘ status changes sync back both waysQuickstart (5 minutes)
- Sign up at /signup (email, or Google/Microsoft) and create your workspace.
- Add a meeting: Meetings → Add meeting. Paste a transcript (
Priya: I'll send the deck by Friday), upload a .txt/.vtt/audio file, or send the bot to a live Zoom/Meet/Teams link. - Review: Review tasks shows each extracted task with owner, deadline, confidence and the exact quote. Approve, edit or delete in one click.
- Connect your tools (see below). Approved tasks are pushed to your default project tool and owners get reminders.
- Integrate your own software: Developers → create an API key.
Where to connect what
All connections live under Integrations (admins only). Your callback/redirect URLs are your app URL plus the path shown. For this deployment the app URL is https://notemaker.autobot360.com. Self-hosting? Put the credentials in .env (see the README).
Jira Project tool
Where: Integrations → Jira → Connect
- developer.atlassian.com → Create → OAuth 2.0 integration.
- Permissions: Jira API with read:jira-work, write:jira-work, read:jira-user, manage:jira-webhook.
- Authorization: set the callback URL below.
- In Notemaker: Connect, then Settings → Load → pick the default project → Save. Webhooks register automatically on a public URL.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/jira/callback
Self-host env: JIRA_CLIENT_ID, JIRA_CLIENT_SECRET
Notion Project tool
Where: Integrations → Notion → Connect
- notion.so/my-integrations → New integration → type Public, set the redirect URI below.
- Make a tasks database with Name (title), Status (status/select), Owner (people), Due (date), Priority (select), and share it with the integration.
- Connect, pick the database as the default project. Rename properties under Field mapping if yours differ.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/notion/callback
Self-host env: NOTION_CLIENT_ID, NOTION_CLIENT_SECRET
Asana Project tool
Where: Integrations → Asana → Connect
- Asana developer console → create an app, add the redirect URL below.
- Connect, then choose the default project; the webhook is registered for you.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/asana/callback
Self-host env: ASANA_CLIENT_ID, ASANA_CLIENT_SECRET
Trello Project tool
Where: Integrations → Trello → Connect
- trello.com/power-ups/admin → create a Power-Up and copy the API key; add your site to Allowed origins.
- Connect, then choose the list new cards go to.
Callback / webhook URL: https://notemaker.autobot360.com/integrations/trello-callback
Self-host env: TRELLO_API_KEY
ClickUp Project tool
Where: Integrations → ClickUp → Connect
- ClickUp Settings → Apps → create an app with the redirect URL below.
- Connect, then pick the default list.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/clickup/callback
Self-host env: CLICKUP_CLIENT_ID, CLICKUP_CLIENT_SECRET
Linear Project tool
Where: Integrations → Linear → Connect
- Linear Settings → API → OAuth applications → create one with the callback below.
- Connect, then pick the team.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/linear/callback
Self-host env: LINEAR_CLIENT_ID, LINEAR_CLIENT_SECRET, LINEAR_WEBHOOK_SECRET
Monday.com Project tool
Where: Integrations → Monday.com → Connect
- monday developer center → OAuth app with boards:read/write, users:read, webhooks:write.
- Connect, then pick the board. Columns person, status, date, priority are used (override ids in Field mapping).
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/monday/callback
Self-host env: MONDAY_CLIENT_ID, MONDAY_CLIENT_SECRET
GitHub Issues Project tool
Where: Integrations → GitHub Issues → Connect
- GitHub → Settings → Developer settings → OAuth Apps → New OAuth App. Authorization callback URL = the URL below.
- Connect, then pick the repository (owner/name) as the default project. Tasks become issues with a priority label, assignee and due date in the body; closing an issue completes the task and vice-versa. The repo webhook is registered automatically on a public URL.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/github/callback
Self-host env: GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET
Todoist Project tool
Where: Integrations → Todoist → Connect
- Todoist App Management console → create an app; set the OAuth redirect URL to the one below.
- Connect and choose the default project. Todoist webhooks are configured in the same console (watch item:completed, item:uncompleted, item:deleted) pointing at the webhook URL shown in Integrations; the hourly sync catches anything missed.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/todoist/callback
Self-host env: TODOIST_CLIENT_ID, TODOIST_CLIENT_SECRET
Discord Chat
Where: Integrations → Discord → Enable → Settings
- In Discord: channel settings → Integrations → Webhooks → New Webhook → Copy Webhook URL.
- Enable Discord in Notemaker, paste the URL, Save, then press Send test message. Meeting summaries and reminders arrive as embeds with Done / Snooze / Need help links.
Google Chat Chat
Where: Integrations → Google Chat → Enable → Settings
- In a Google Chat space: Apps & integrations → Webhooks → add webhook → copy the URL.
- Enable Google Chat in Notemaker, paste the URL, Save, then Send test message. Cards carry Done / Snooze / Need help buttons.
Telegram Chat
Where: Integrations → Telegram → Enable → Settings
- Message @BotFather → /newbot → copy the bot token. Add the bot to your group or channel and get the chat ID (e.g. via @RawDataBot).
- Enable Telegram, paste the token (stored encrypted) and chat ID, Save, then Send test message. Messages include inline Done / Snooze / Need help buttons.
Calendar feed (Google / Apple / Outlook) Calendar
Where: Settings → My tasks in your calendar
- Settings → Show my calendar link → copy it. In Google Calendar: Other calendars → From URL; in Apple Calendar: File → New Calendar Subscription; in Outlook: Add calendar → From internet.
- Your open tasks with due dates appear as all-day events and refresh about hourly. The link is private: rotate it from the same card if it leaks.
Zapier / Make / n8n Automation
Where: Developers → Webhooks + API keys
- Trigger: add an Notemaker webhook endpoint (Developers → Webhooks) whose URL is a Zapier 'Catch Hook', Make 'Custom webhook' or n8n Webhook node. Events: task.created, task.updated, task.completed, meeting.processed.
- Action: use the REST API (Developers → API keys, read + write) from a Zapier 'Webhooks by Zapier' step, a Make HTTP module or an n8n HTTP Request node, e.g. POST /api/v1/tasks to create a task from any other tool. See the REST section above for the body.
- That covers hundreds of apps (HubSpot, Salesforce, Airtable, Notion, Sheets, Microsoft Planner…) without a dedicated connector.
Google Sheets Project tool (fallback)
Where: Integrations → Google Sheets → Connect
- Google Cloud → enable the Sheets API; add the redirect URI below to your OAuth client.
- Connect, then paste the spreadsheet ID as the default project. One row per task is written to a Tasks tab; status is read back hourly.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/sheets/callback
Self-host env: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
Slack Chat
Where: Integrations → Slack → Connect
- api.slack.com/apps → create an app; bot scopes chat:write, chat:write.public, im:write, users:read, users:read.email, channels:read, groups:read.
- Redirect URL: the callback below. Interactivity → Request URL: /api/slack/interactions on your domain (needs HTTPS).
- Connect, then paste the summary channel ID in Slack's settings card. Owners get DMs with Done / Snooze / Reassign / Need help buttons.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/slack/callback
Self-host env: SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, SLACK_SIGNING_SECRET
Microsoft Teams Chat
Where: Integrations → Microsoft Teams → Enable
- In your Teams channel add an Incoming Webhook (or a Workflows 'post to channel' flow) and copy the URL.
- Enable Teams in Notemaker and paste the URL. Cards carry signed Done / Snooze / Need help links.
WhatsApp Chat (Pro)
Where: Integrations → WhatsApp → Enable; Settings → My profile (phone)
- Twilio Console → WhatsApp sender (or sandbox). Set 'When a message comes in' to the URL below.
- Each person adds their number in Settings → My profile. Replying 1 = Done, 2 = Snooze, 3 = Need help updates the task.
Callback / webhook URL: https://notemaker.autobot360.com/api/whatsapp/inbound
Self-host env: TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_WHATSAPP_FROM
Google Calendar Calendar
Where: Integrations → Google Calendar → Connect
- Enable the Google Calendar API and add the redirect URI below.
- After connecting, upcoming meetings with a Zoom/Meet/Teams link appear under Meetings → Upcoming. Flip the toggle to send the bot.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/google-calendar/callback
Self-host env: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
Outlook Calendar Calendar
Where: Integrations → Outlook Calendar → Connect
- Entra ID app registration with Calendars.Read + offline_access; add the redirect URI below.
Callback / webhook URL: https://notemaker.autobot360.com/api/integrations/outlook-calendar/callback
Self-host env: AZURE_AD_CLIENT_ID, AZURE_AD_CLIENT_SECRET
Meeting bot Recording
Where: Meetings → Add meeting → Join now, or the Upcoming toggle
- Self-hosted (no vendor): set WORKER_SECRET in the app's .env, then run the worker: `docker compose up -d bot-worker` (see worker/README.md). It polls the app, joins Zoom/Meet/Teams as a named guest in a headless browser, records audio, transcribes it (Sarvam, Deepgram or Whisper) and sends the transcript back.
- Managed alternative: set RECALL_API_KEY (+ RECALL_WEBHOOK_SECRET and a Recall webhook to /api/webhooks/recall) and Recall's bots join instead.
- Either way the bot is named 'Notemaker Bot (recording)' and posts your consent message in the meeting chat. The host must admit it from the waiting room, and some Google Workspace / Teams tenants block anonymous guests. Google Meet usually blocks anonymous guests entirely: create a dedicated Google account for the bot and follow worker/README.md → 'Meet needs a signed-in bot account' (GOOGLE_STORAGE_STATE_B64).
Self-host env: WORKER_SECRET, ACTIONFLOW_URL (worker), SARVAM_API_KEY / DEEPGRAM_API_KEY / OPENAI_API_KEY (worker)
REST API
Base URL https://notemaker.autobot360.com/api/v1. JSON in, JSON out. Machine-readable spec: /api/v1/openapi.json (import into Postman, Insomnia, or an SDK generator).
Authentication
Create a key under Developers → API keys. Send it as a Bearer token. Keys are workspace-scoped; read keys can only GET, read + write keys can also create, update and delete. Keys are shown once and stored hashed. Revoke a key any time.
curl https://notemaker.autobot360.com/api/v1/summary \ -H "Authorization: Bearer af_YOUR_KEY"
Conventions
- Errors use one shape:
{"error":{"code":"not_found","message":"Task not found"}}. Codes: invalid_request (400), unauthorized (401), plan_limit (402), forbidden (403), not_found (404), unprocessable (422), rate_limited (429), internal (500). Every response has anx-request-idheader; quote it in support requests. - Pagination: list endpoints take
limit(1-100, default 25) andcursor; responses containdata,has_more,next_cursor. - Rate limit: 120 requests/minute per key (429 when exceeded). Dates are
YYYY-MM-DD; timestamps are ISO 8601 UTC. - Plan limits: the Free plan's 5 meetings/month applies to
POST /meetingstoo (402).
Endpoints
GET/api/v1/tasks List tasks (filter by status, owner, meeting, overdue, text)
List tasks (filter by status, owner, meeting, overdue, text). Cursor pagination.
Scope: read
curl -X GET "https://notemaker.autobot360.com/api/v1/tasks?status=TODO&overdue=true&limit=20" \ -H "Authorization: Bearer af_YOUR_KEY"
POST/api/v1/tasks Create a task
Create a task. Status TODO pushes it to your PM tool and notifies the owner; PENDING_REVIEW sends it to the review queue.
Scope: write · Returns 201
curl -X POST https://notemaker.autobot360.com/api/v1/tasks \
-H "Authorization: Bearer af_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Send Q3 deck","owner_email":"priya@acme.com","due_date":"2026-11-02","priority":"HIGH"}'GET/api/v1/tasks/{id} Get one task, including linked PM-tool items
Get one task, including linked PM-tool items.
Scope: read
curl -X GET "https://notemaker.autobot360.com/api/v1/tasks/task_id" \ -H "Authorization: Bearer af_YOUR_KEY"
PATCH/api/v1/tasks/{id} Update fields or status (e
Update fields or status (e.g. `DONE`). Changes sync to the linked PM tool.
Scope: write
curl -X PATCH https://notemaker.autobot360.com/api/v1/tasks/task_id \
-H "Authorization: Bearer af_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"DONE"}'DELETE/api/v1/tasks/{id} Delete a task
Delete a task.
Scope: write
curl -X DELETE "https://notemaker.autobot360.com/api/v1/tasks/task_id" \ -H "Authorization: Bearer af_YOUR_KEY"
GET/api/v1/meetings List meetings, newest first
List meetings, newest first.
Scope: read
curl -X GET "https://notemaker.autobot360.com/api/v1/meetings?q=roadmap" \ -H "Authorization: Bearer af_YOUR_KEY"
POST/api/v1/meetings Submit a transcript
Submit a transcript. AI extraction runs in the background (202). Poll GET /meetings/{id} until `status` is `REVIEW` or `DONE`.
Scope: write · Returns 202
curl -X POST https://notemaker.autobot360.com/api/v1/meetings \
-H "Authorization: Bearer af_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Weekly sync","transcript":"Priya: I'll send the deck by Friday.\nRahul: I will fix the webhook bug tomorrow."}'GET/api/v1/meetings/{id} Meeting with summary, decisions, open questions, risks and extracted tasks
Meeting with summary, decisions, open questions, risks and extracted tasks.
Scope: read
curl -X GET "https://notemaker.autobot360.com/api/v1/meetings/task_id" \ -H "Authorization: Bearer af_YOUR_KEY"
GET/api/v1/decisions Searchable decision log
Searchable decision log.
Scope: read
curl -X GET "https://notemaker.autobot360.com/api/v1/decisions?q=pricing" \ -H "Authorization: Bearer af_YOUR_KEY"
GET/api/v1/members Workspace members (use `email` as `owner_email` when creating tasks)
Workspace members (use `email` as `owner_email` when creating tasks).
Scope: read
curl -X GET "https://notemaker.autobot360.com/api/v1/members" \ -H "Authorization: Bearer af_YOUR_KEY"
GET/api/v1/summary Counts of open, overdue, awaiting-review and completed tasks
Counts of open, overdue, awaiting-review and completed tasks.
Scope: read
curl -X GET "https://notemaker.autobot360.com/api/v1/summary" \ -H "Authorization: Bearer af_YOUR_KEY"
Example: push a transcript, then read the tasks (Node 18+)
const H = { Authorization: "Bearer " + process.env.ACTIONFLOW_KEY, "Content-Type": "application/json" };
const api = (p, o) => fetch("https://notemaker.autobot360.com/api/v1" + p, { headers: H, ...o }).then(r => r.json());
const { id } = await api("/meetings", { method: "POST", body: JSON.stringify({
title: "Sprint planning",
transcript: "Priya: I'll finalize pricing by Wednesday.\nRahul: I will fix the webhook retries tomorrow.",
})});
let m;
do { await new Promise(r => setTimeout(r, 2000)); m = await api("/meetings/" + id); }
while (m.status === "PROCESSING");
console.log(m.summary, m.tasks);Example: complete a task from your own software (Python)
import os, requests
r = requests.patch(f"https://notemaker.autobot360.com/api/v1/tasks/{task_id}",
headers={"Authorization": f"Bearer {os.environ['ACTIONFLOW_KEY']}"},
json={"status": "DONE"})
r.raise_for_status() # reminders stop and the linked Jira/Notion item is updatedWebhooks
Developers → Webhooks → add an HTTPS endpoint and choose events. We POST JSON and expect a 2xx within 8 seconds; failures retry 3 times, and an endpoint is auto-disabled after 20 consecutive failed events (re-enable it in the UI). Use Send test to check your endpoint.
| meeting.processed | Extraction finished. Payload: meeting id, title, summary, task count. |
| task.created | A task was approved/created and is now active. |
| task.updated | A task's status, owner, due date or priority changed. |
| task.completed | A task was marked done (from the app, Slack, WhatsApp, email, your API, or a synced PM tool). |
POST /your/endpoint
X-Webhook-Signature: t=1760000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Content-Type: application/json
{
"id": "evt_9fKq…", "type": "task.completed", "created": "2026-10-16T10:30:00.000Z",
"data": { "task": { "id": "…", "title": "Send deck", "status": "DONE", "owner": {…}, "due_date": "2026-10-16", … } }
}Verify the signature
The signature is HMAC-SHA256(secret, timestamp + "." + rawBody) in hex. Reject requests whose timestamp is more than 5 minutes old. Always verify against the raw body.
// Node / Express
import { createHmac, timingSafeEqual } from "crypto";
app.post("/hooks/notemaker", express.raw({ type: "application/json" }), (req, res) => {
const [t, v1] = req.get("X-Webhook-Signature").split(",").map(p => p.split("=")[1]);
const expected = createHmac("sha256", process.env.AF_WEBHOOK_SECRET).update(t + "." + req.body).digest("hex");
const ok = expected.length === v1.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1))
&& Math.abs(Date.now() / 1000 - Number(t)) < 300;
if (!ok) return res.sendStatus(400);
const event = JSON.parse(req.body); // handle event.type
res.sendStatus(200);
});# Python / Flask
import hmac, hashlib, time
def verify(secret, header, raw_body: bytes) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"]) and abs(time.time() - int(parts["t"])) < 300MCP server (for AI assistants)
Notemaker ships a remote Model Context Protocol server so assistants like Claude and Cursor can answer "what's overdue?", "what did we decide about pricing?" and create or complete tasks. Endpoint: https://notemaker.autobot360.com/api/mcp (Streamable HTTP, stateless). Authenticate with the same API key; its scopes limit which tools work, so give assistants a read-only key unless you want them to change things.
Connect
# Claude Code claude mcp add --transport http notemaker https://notemaker.autobot360.com/api/mcp \ --header "Authorization: Bearer af_YOUR_KEY"
// Claude Desktop → Settings → Developer → Edit Config
{ "mcpServers": { "notemaker": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://notemaker.autobot360.com/api/mcp", "--header", "Authorization: Bearer af_YOUR_KEY"] } } }// Cursor → ~/.cursor/mcp.json
{ "mcpServers": { "notemaker": { "url": "https://notemaker.autobot360.com/api/mcp", "headers": { "Authorization": "Bearer af_YOUR_KEY" } } } }Anything else that speaks MCP over HTTP works the same way. You can also test by hand:
curl https://notemaker.autobot360.com/api/mcp -H "Authorization: Bearer af_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Tools
| get_workspace_summary | Counts of open, overdue, awaiting-review and completed tasks. Good first call to see how the team is doing. |
| list_tasks | List tasks. Filter by status (TODO, IN_PROGRESS, DONE, PENDING_REVIEW), owner_email, meeting_id, overdue=true, or text query q. Returns next_cursor for paging. |
| get_task | Get one task by id, including the quote it came from and linked Jira/Notion/etc. items. |
| create_task | Create a task. status=TODO makes it active immediately (syncs to the PM tool and notifies the owner); status=PENDING_REVIEW queues it for human review. owner_email must be a workspace member; due_date is YYYY-MM-DD. |
| update_task | Update a task's title, description, owner_email, due_date, priority or status. Changes sync to the linked PM tool. |
| complete_task | Mark a task done. Stops reminders and updates the linked PM tool. |
| list_meetings | List meetings (newest first); optional text query q. |
| get_meeting | Get a meeting's summary, decisions, open questions, risks and extracted tasks. |
| add_meeting_from_transcript | Submit a transcript ('Speaker: text' per line). Action items are extracted in the background; call get_meeting a few seconds later until status is REVIEW or DONE. |
| search_decisions | Search the decision log across all meetings. |
| list_members | List workspace members (names, emails, roles). Use emails as owner_email. |
Things to ask
- "What's overdue, and who owns it?"
- "Summarize the last three meetings and list open questions."
- "Create a high-priority task for priya@acme.com to send the Q3 deck by Friday."
- "Here's a transcript… extract the action items."
Roles, limits and security
- Roles: Admin (everything, incl. integrations, keys, billing), Member (edit tasks, add meetings), Viewer (read only).
- Plans: Free = 5 meetings/month and 1 integration; Pro = unlimited meetings, all integrations, WhatsApp; Business adds analytics, audit log and retention policies. See pricing.
- Data: transcripts and integration tokens are AES-256-GCM encrypted at rest. API keys and webhook secrets are workspace-scoped; keys are stored hashed. Delete transcripts or meetings in Settings; set retention on Business.
- Recording consent: the bot announces itself by name and posts your configurable consent message in the meeting chat.
- AI usage: one compact extraction call per meeting. Settings → AI & services shows the model and monthly token use.