Agent API

The most compatible meeting platform for frontier organisations.

Everywhere else, your agent has to drive a headless browser into a call and guess who spoke from one mixed audio stream. Here it joins with a key, and every line arrives with the speaker already attached.

That difference is architectural rather than clever. We own the room, so each microphone is transcribed on its own machine and the speaker on a line is the connection the words came in on. No container, no browser, no audio pipeline, no per-hour bill.

Here is where you can start.

Quickstart

Three calls, start to finish. Nothing below is a placeholder — run it.

1. Mint a key

curl -X POST https://teammeet.io/api/keys \
  -H 'content-type: application/json' \
  -d '{"name":"Notetaker","emoji":"📝"}'
{
  "key": "tmk_…",              // shown once, stored only as a hash
  "agent": { "id": "ag_…", "name": "Notetaker", "emoji": "📝" }
}

No account, no card, no sales call, no monthly minimum. The key is a bearer token — treat it like one.

2. Start a meeting the key owns

curl -X POST https://teammeet.io/api/meeting \
  -H 'authorization: Bearer tmk_…'
{ "code": "abc-defg-hij", "url": "https://teammeet.io/abc-defg-hij" }

Send that link to anyone. It opens in any browser, with no account and no download. A key is admitted automatically to a meeting it started; anywhere else it knocks at the door and a person decides.

3. Join it

import { WebSocket } from 'ws';

const ws = new WebSocket('wss://teammeet.io');

ws.on('open', () => ws.send(JSON.stringify({
  type: 'agent-hello',
  key: process.env.TEAMMEET_KEY,
  meeting: 'abc-defg-hij',
})));

ws.on('message', raw => {
  const m = JSON.parse(raw);

  if (m.type === 'agent-ready') {
    console.log('in the room with', m.members.map(x => x.name).join(', '));
  }

  if (m.type === 'transcript') {
    // m.line.speaker is a name, not a guess
    console.log(`${m.line.speaker}: ${m.line.text}`);

    if (/what did we decide/i.test(m.line.text)) {
      ws.send(JSON.stringify({ type: 'say', text: 'You decided to ship the API first.' }));
    }
  }
});

That is a working meeting bot. It has no browser in it.

What this costs, and why

A bot in someone else's ZoomAn agent here
How it joinsHeadless browser driving the UIA WebSocket and a key
Who said itDiarization on mixed audio — a guessThe connection the words came in on
Speaker identityOften "Speaker 1", unstable between meetingsA stable id and the name they joined under
InfrastructureContainers, autoscaling, session lifecycleOne socket
Typical cost$0.35–$1.00 per hour, sometimes a $1,000/mo floorFree
Speaking in the roomRare, awkward, often unsupportedOne message
Breaks whenThe host platform changes its interfaceWe change this protocol, which is versioned
ConsentA bot in the participant list nobody agreed toAnnounced in chat, listed, removable by anyone

It is free because it is nearly free for us. A bot company pays for a browser and a machine per meeting; we are already in the room, and an agent is one more socket on a server that is already broadcasting to everyone else in it.

The protocol

What you receive

agent-readyYou are in. Carries the member list, the mode, the transcript so far, and exactly what you may do.
transcriptOne line, as it is said. { line: { at, speaker, speakerId, text, meeting } }
chatA chat message from anyone in the room.
stateThe room changed — who is in it, the mode, the live notes, the recording.
recordingA recording finished. Carries its share link.
endEveryone left.
agent-errorSomething you sent was refused, and why.
agent-removedA person removed you, or the host turned agents off. This is final.

What you can send

saySpeak out loud in the meeting. Joins the transcript, so it is on the record like anything else said. One every 5s.
chatPost to the meeting chat under your own name. One every 0.7s.
drawGenerate a picture into the room. { kind: 'diagram' | 'infographic' | 'visual' | 'meme', prompt } One every 25s.
notePut a note in front of everyone. One every 2s.
leaveGo.

The rate limits are a product decision, not a defence. An agent that can talk over people twice a second makes the room worse, so the ceiling is set at the speed a person could plausibly want to be interrupted at.

What an agent cannot do

Webhooks

If your workflow lives in n8n, Make, Zapier or a cloud function, you do not need a socket at all. Register a URL and the meeting comes to you.

curl -X PATCH https://teammeet.io/api/keys/me \
  -H 'authorization: Bearer tmk_…' \
  -H 'content-type: application/json' \
  -d '{"webhook":{"url":"https://your-n8n.example.com/webhook/teammeet"}}'

You get back a signing secret, once. Events:

meeting.startedA meeting this key created has begun.
transcript.lineBatched every few seconds, so a busy meeting does not become a request storm.
chat.messageSomeone posted in chat.
meeting.endedThe whole transcript, the recap and the notes, in one payload.
recording.readyA recording finished, with its link.

Verifying a delivery

Signed the way Stripe and GitHub sign theirs, so whatever you are using already knows how to check it: an HMAC-SHA256 over timestamp.body, with the timestamp in its own header so a captured delivery cannot be replayed tomorrow.

import crypto from 'node:crypto';

function verify(req, rawBody, secret) {
  const ts  = req.headers['x-teammeet-timestamp'];
  const sig = req.headers['x-teammeet-signature'];
  const mine = 'sha256=' + crypto.createHmac('sha256', secret)
    .update(ts + '.' + rawBody).digest('hex');
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;   // stale
  return crypto.timingSafeEqual(Buffer.from(mine), Buffer.from(sig));
}

Webhook URLs must be https. Failed deliveries retry three times, then stop.

MCP

Point any assistant that speaks the Model Context Protocol at https://teammeet.io/mcp with your key, and a meeting becomes something it can reach directly — start one, read what was actually said, answer in the room.

Connect Claude in two steps → — a key, and the config with the key already in it. This page is the reference; that one is the setup.

{
  "mcpServers": {
    "teammeet": {
      "type": "http",
      "url": "https://teammeet.io/mcp",
      "headers": { "Authorization": "Bearer tmk_…" }
    }
  }
}
start_meetingReturns a code and a link. Optionally sets the mode and an agenda.
list_meetingsYour live meetings and who is in them.
get_transcriptEvery line with its speaker. Takes since for polling.
get_notesDecisions, open questions, actions — each carrying a verbatim quote.
send_messagePost into the meeting chat.
speakSay something out loud in the room.
drawPut a picture in front of everyone.
list_recordingsRecordings and their share links.

What this is not, yet

Worth knowing before you build on it.