Waterr AI Logo
EngineeringAugust 5, 2026

AI Meeting SDK: What You Actually Need, and What You Should Skip

Most teams searching for an AI meeting SDK don't want a package — they want to write less code. Here's the honest breakdown: two REST calls, eight webhook events, a forty-line client you own, and the agent-native path that's replacing SDKs entirely.

Harshit SharmaFounder & CEO, Waterr AI

Let me answer the search query directly before the post starts, because you're evaluating and you don't need a preamble.

Waterr does not ship an official SDK. No npm package, no pip package. What we ship is a REST API, signed webhooks, an MCP server, and skills that teach coding agents the API surface. If a language SDK is a hard procurement requirement, you now know in twenty seconds instead of after an evaluation call.

Here's the case for why that's the right shape for this workload, and what to build in the space where the SDK would have been.

Waterr for developers — ship the conversation, not the plumbing (1:14) — watch on YouTube

What "SDK" is usually standing in for

When a team searches for an AI meeting SDK, they're almost never asking about a package. They're asking one of these:

  • How much code do I write before the first meeting runs?
  • What do I have to understand before I can start?
  • What happens to the results — do I poll for them, or do they come to me?
  • When it breaks at 2am, can I see why?

A package answers none of those on its own. Plenty of SDKs are a thin wrapper over HTTP with worse documentation than the HTTP. What actually matters is the shape of the surface underneath.

The whole thing is two calls

List your scenarios, then create a meeting from one:

bash
curl https://api.waterr.ai/v1/scenarios \
  -H "Authorization: Bearer wai_<your_key>"

curl -X POST https://api.waterr.ai/v1/meetings \
  -H "Authorization: Bearer wai_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{ "scenario_id": "<id>" }'

That's a joinable meeting with a persona attached. Base URL https://api.waterr.ai/v1, bearer auth with a key prefixed wai_.

There's no client library standing between you and that, and honestly there isn't much for one to do. The savings an SDK offers over two curl-shaped calls is a rounding error against the time you'll spend on the parts that actually have depth: scenario design, the tool calls your agent makes mid-meeting, and what you do with the scores.

What an AI meeting SDK would have to cover

If you're evaluating platforms, this is the checklist worth running rather than "do they have a package." Here's the whole surface and where each piece lives:

CapabilityWhere it lives
Create a sessionPOST /v1/meetings
Configure persona and goalsScenario, set once and reused
Get the participant inHosted join link, or a signed-JWT iframe embed
Call your code mid-meetingCustom functions — signed webhook or client-side
Know the meeting endedmeeting.ended webhook
Retrieve the transcripttranscript.ready webhook → GET /v1/transcripts/meeting/{id}
Retrieve the scoressession.analysis_complete webhook, payload included
Retrieve the recordingrecording.ready webhook → GET /v1/recordings/url-with-thumbnail/{id}
Debug a failed deliveryGET /v1/webhooks/endpoints/{id}/deliveries

Note the pattern. Half of it isn't request/response at all — it's events arriving at you. An SDK is the wrong abstraction for the half that matters most, which is why the more useful question is what the event surface looks like, not what's on npm.

The forty-line client you own

If you want typed calls, write them. This is the entire thing for the common path:

ts
const BASE = 'https://api.waterr.ai/v1';

type Meeting = {
  id: string;
  scenario_id: string;
  join_url: string;
  status: string;
};

class Waterr {
  constructor(private key: string) {}

  private async req<T>(path: string, init: RequestInit = {}): Promise<T> {
    const res = await fetch(`${BASE}${path}`, {
      ...init,
      headers: {
        Authorization: `Bearer ${this.key}`,
        'Content-Type': 'application/json',
        ...init.headers,
      },
    });
    if (!res.ok) {
      throw new Error(`waterr ${init.method ?? 'GET'} ${path} → ${res.status}: ${await res.text()}`);
    }
    return res.json() as Promise<T>;
  }

  listScenarios() {
    return this.req<{ scenarios: unknown[] }>('/scenarios');
  }

  createMeeting(scenarioId: string, body: Record<string, unknown> = {}) {
    return this.req<Meeting>('/meetings', {
      method: 'POST',
      body: JSON.stringify({ scenario_id: scenarioId, ...body }),
    });
  }

  getTranscript(meetingId: string) {
    return this.req(`/transcripts/meeting/${meetingId}`);
  }

  getRecordingUrl(meetingId: string) {
    return this.req(`/recordings/url-with-thumbnail/${meetingId}`);
  }
}

Verify the response shapes against docs.waterr.ai/openapi.yaml before you rely on the types — that spec is the contract, and you can generate a fuller client from it if you'd rather not hand-write one.

The advantage of owning this file is that it fits your codebase's error handling, your retry policy, and your telemetry, and it never blocks you waiting for a vendor to cut a release when you need a field that shipped last week.

The part that would actually save you time

Not a client library. Webhooks.

The default mistake is polling a meeting until its status changes, which is both rude to the API and wrong, because the interesting things don't finish at the same time. The meeting ends. The transcript persists a moment later. The analysis takes a few minutes. The recording lands whenever its upload completes, and — this one catches people — it is explicitly not guaranteed to arrive after the analysis.

Register an endpoint once and the events come to you:

bash
curl -X POST https://api.waterr.ai/v1/webhooks/endpoints \
  -H "Authorization: Bearer wai_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/waterr",
    "subscribed_events": ["session.analysis_complete", "meeting.ended"]
  }'

session.analysis_complete arrives carrying the analysis inline — goal_results with a score and written feedback per goal, plus strengths, growth_areas, recommendations, and timestamped highlights. No follow-up request needed for the thing you're actually integrating for.

Deliveries are signed with an HMAC-SHA256 header, retried on a 30s → 5m → 30m → 2h → 12h ladder, and logged so you can inspect or replay any of them. That's the layer worth understanding properly, and it's covered end to end in the webhooks guide.

The agent-native path

Here's the part I think genuinely replaces what an SDK used to do.

The reason SDKs existed was discovery — a package gave your editor autocomplete so you didn't have to hold the API in your head. Your coding agent can do that better, if you give it the API.

Two ways in. The MCP server exposes Waterr to any MCP client at https://api.waterr.ai/v1/mcp with bearer auth, and works with Claude Desktop, Claude Code, ChatGPT, Cursor, Codex CLI, and anything else speaking the MCP HTTP transport. It exposes five tools: list_scenarios, get_scenario, list_meetings, get_meeting, and get_analysis. That means your agent can read your actual scenarios and the analysis of a real meeting while it writes your integration, instead of guessing at shapes.

The Claude Code skill goes further:

bash
npx skills add waterrai/skills

It teaches the local agent to build on Waterr — it runs a sub-skill that interviews you and produces a written scope of work first, then fetches the relevant API reference pages, writes the integration, and cites the docs URL next to each endpoint it uses. It also encodes the pitfalls, down to specifics like the difference between membership_id and user ID. There's a Codex equivalent.

Ask for "a candidate screening flow on Waterr" and you get scoped, cited, working code. That's the autocomplete argument for SDKs, answered better.

When you genuinely do need an SDK

I'd rather be useful than absolutist. Reach for a real client library when:

  • You're doing heavy client-side media work. Managing microphones, cameras, and device permissions from your own frontend needs a media SDK, and no REST surface substitutes.
  • You're on mobile native. Swift and Kotlin apps want an idiomatic package, not hand-rolled URLSession calls.
  • You need offline queuing. Buffering requests through unreliable connectivity is real client-side infrastructure.

For a server-orchestrated meeting API — you create sessions from your backend, participants join a link or an embed, results arrive by webhook — REST plus events is the correct shape, and adding a package on top mostly adds a version to upgrade.

Frequently asked questions

Does Waterr have an official SDK? No. There's a REST API, signed webhooks, an MCP server, and skills for Claude Code and Codex. If you want typed calls, generate a client from docs.waterr.ai/openapi.yaml or write the forty lines above.

SDK or API — which should I evaluate on? Evaluate on the event surface and the result payload. Ask what arrives when the meeting ends, whether it's signed, what the retry policy is, and whether you can replay a delivery. Those determine what your integration is like to operate. A package doesn't.

Can I generate a client from your OpenAPI spec? Yes — docs.waterr.ai/openapi.yaml. That's the supported path to a typed client in any language, and it stays current with the API rather than with a release schedule.

How much code before my first meeting runs? Two calls to create a joinable meeting. Add a webhook endpoint and a signature verifier, and you have the full loop — create, run, receive scores — in well under a hundred lines.

What about the embedded widget — is there an SDK for that? The embed path mints a short-lived signed JWT and gives you a ready-to-paste iframe snippet, so it's a token call plus markup rather than a frontend package to install.


Start at the API quickstart for the two calls, or what an AI meeting API actually is if you're still scoping the category.

APISDKEngineeringAI Meetings