JavaScript SDK
@midwater/sdk is a typed client for the Midwater API, with no runtime dependencies. It works in Node 18 and later, as ESM or CommonJS. Source: midwater-sdk-js.
Install
Section titled “Install”npm install github:MidWaterAI/midwater-sdk-js#v0.1.0From launch, install from npm:
npm install @midwater/sdkCreate a client
Section titled “Create a client”Both the API key and the base URL are required. There’s no default host.
import { Midwater } from "@midwater/sdk";
const midwater = new Midwater(); // reads MIDWATER_API_KEY and MIDWATER_BASE_URLconst configured = new Midwater({ apiKey: process.env.MIDWATER_API_KEY, baseUrl: process.env.MIDWATER_BASE_URL, timeoutMs: 30_000, maxRetries: 2 });Keep the key on your server. The client runs in browsers too, but a key in a web page is a key anyone can read.
Send and read conversations
Section titled “Send and read conversations”const { id, duplicate, replayed } = await midwater.conversations.create({ external_id: "call_8f2a91", channel: "voice", agent: { id: "front-desk", name: "Front desk", version: "3.2.0" }, transcript: [ { speaker: "agent", text: "Thanks for calling. How can I help?" }, { speaker: "user", text: "I need to move my appointment to Thursday." }, ],});
const conversation = await midwater.conversations.wait(id, { timeoutMs: 60_000 });console.log(conversation.outcome, conversation.results);
await midwater.conversations.feedback("call_8f2a91", { check_key: "appointment_not_completed", verdict: "fail" });Every POST sends an Idempotency-Key: yours if you pass { idempotencyKey }, otherwise a new one per call, reused on that call’s retries.
Health
Section titled “Health”const agent = await midwater.agents.health("front-desk");const group = await midwater.groups.health("brightsmile-dental");console.log(agent.health_status, group.agents.length);Errors and retries
Section titled “Errors and retries”Errors extend MidwaterError. API errors (APIError and its subclasses) have status, type, message, fields, body and requestId; there’s a class for each status in Errors, and unknown statuses map by class. APIConnectionError means no answer; WaitTimeoutError means wait gave up.
import { ValidationError } from "@midwater/sdk";
try { await midwater.conversations.create({ external_id: "x", channel: "voice", transcript: [] });} catch (e) { if (e instanceof ValidationError) console.log(e.fields, e.requestId); else throw e;}The client retries 408, 429, 5xx and network errors on calls that are safe to repeat (GETs and conversations.create), at most 3 times, with exponential backoff, honouring Retry-After. Feedback isn’t retried until the API honours idempotency keys there.
Webhooks
Section titled “Webhooks”import { verifyWebhook } from "@midwater/sdk/webhooks";
const event = verifyWebhook(rawBody, request.headers, process.env.MIDWATER_WEBHOOK_SECRET!);The webhooks entry point uses node:crypto, so it runs on servers. See Verifying signatures.
Every request and response type is exported: ConversationCreateParams, Conversation, CheckResult, Outcome, AgentHealth, GroupHealth, HealthWindow, WebhookEvent (a union you can narrow on type) and more.