Skip to content
Build · Wave API

Build on the conversations that move work forward.

Turn Wave sessions into searchable product context, automations, agent memory, and live workflows—with clean JSON and scopes you control.

Scoped accessOpenAPI 3.1JSON everywhere
first-request.sh
Request
curl -H 'Authorization: Bearer $WAVE_API_KEY' \
  https://api.wave.co/v1/sessions?limit=2
Response200 OK
{
  "sessions": [{
    "id": "sess_01J...",
    "title": "Product review",
    "type": "meeting"
  }],
  "has_more": true
}
Base URL
https://api.wave.co/v1

Search

Semantic recall

Find the moment, not just the meeting.

Shape

Structured data

Sessions, transcripts, folders, and actions.

React

Live events

Cursor feeds and signed webhooks.

Start here

Make your first request in minutes.

Create a scoped token, send it as a Bearer credential, and get back predictable JSON.

1. Get an API token

Create a token at app.wave.co/settings/integrations/api. Choose the scopes your application needs.

2. Make your first request

Include your token in the Authorization header:

curl -H "Authorization: Bearer wave_api_xxx..." \
  https://api.wave.co/v1/sessions

3. Handle the response

All responses are JSON. Successful responses return the data directly:

{
  "sessions": [
    {
      "id": "abc123",
      "title": "Weekly Standup",
      "timestamp": "2025-01-20T10:00:00Z",
      "duration_seconds": 1800,
      "type": "meeting",
      "platform": "zoom"
    }
  ],
  "next_cursor": "2025-01-19T09:00:00Z",
  "has_more": true
}

Sessions of type phone also include a phone object with the call direction (inbound / outbound), to_number, from_number, status, and an ongoing flag for live calls. Inbound calls are bridge connections, so the other party is unknown — to_number is your verified caller ID and from_number is null.

Access control

Authentication

All API requests must be authenticated using a Bearer token in the Authorization header.

Creating a Token

  1. Go to app.wave.co/settings/integrations/api
  2. Click "Create Token" and give it a descriptive name
  3. Select the permissions (scopes) your application needs
  4. Copy the token immediately — it will only be shown once

Scopes

Tokens are granted specific permissions that control what data they can access. Request only the scopes your application actually needs.

sharing:manage

Share sessions with other Wave users and manage who has access. Required for listing access, creating or resetting links, sending or cancelling invites, and removing people.

sessions:read

List sessions and retrieve session metadata including titles, timestamps, summaries, and notes. Also allows access to session statistics and bulk export.

Required for: GET /v1/sessions, GET /v1/sessions/:id, GET /v1/sessions/stats, POST /v1/sessions/bulk

sessions:write

Update session metadata including title, notes, tags, favorite status, and structured action items. Lets agents write back action items extracted from a session so users can edit them and the agent can re-read the edits — a closed loop.

Required for: PATCH /v1/sessions/:id

folders:read

List and fetch folders (id, name, color, session count, timestamps, and the pinned / sort_order / order / last_opened_at preferences when set). The least-privilege grant for discovering folders; sessions:read is also accepted on these endpoints for backward compatibility.

Required for: GET /v1/folders, GET /v1/folders/:id

folders:write

Create, rename, recolour, pin, reorder and delete folders, and add or remove sessions from folders. Folders are non-exclusive — a session can sit in many folders at once (Gmail-labels model, not Finder-folders). Deleting a folder never deletes sessions.

Required for: POST /v1/folders, PATCH /v1/folders/:id, DELETE /v1/folders/:id, POST /v1/sessions/:id/folders/:folderId, DELETE /v1/sessions/:id/folders/:folderId

events:read

Pull and acknowledge events from the per-token cursor feed. An alternative to running a webhook receiver — Wave keeps your cursor server-side so you never have to track “did I already process this event?” yourself.

Required for: GET /v1/events, POST /v1/events/ack

sessions:delete

Permanently delete sessions. Storage files are cleaned up asynchronously.

Required for: DELETE /v1/sessions/:id

sessions:search

Perform semantic search across all your sessions using natural language queries.

Required for: POST /v1/sessions/search

transcripts:read

Access full session transcripts with speaker attribution and timestamps. Also required when requesting transcripts in bulk exports.

Required for: GET /v1/sessions/:id/transcript

media:read

Access signed URLs for session audio and video files. URLs expire after 1 hour.

Required for: GET /v1/sessions/:id/media

account:read

Read account information including subscription status and total session count.

Required for: GET /v1/account

webhooks:manage

Create, list, update, delete, and test webhook endpoints. Manage signing secrets.

Required for: All /v1/webhooks/* endpoints

Token Security

  • Tokens are only shown once when created — store them securely
  • Tokens expire after 1 year but can be revoked at any time
  • Use environment variables to store tokens, never commit them to code
  • Create separate tokens for different applications
  • Revoke tokens immediately if they may have been compromised
  • Grant only the scopes your application needs (principle of least privilege)

Error Responses

Authentication errors return appropriate HTTP status codes:

401unauthorized

Missing or malformed Authorization header

{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid Authorization header"
  }
}
401invalid_token

Token is invalid, expired, or has been revoked

{
  "error": {
    "code": "invalid_token",
    "message": "Token is invalid, expired, or revoked"
  }
}
403insufficient_scope

Token does not have the required scope for this endpoint

{
  "error": {
    "code": "insufficient_scope",
    "message": "This endpoint requires the 'sessions:write' scope"
  }
}

Build surface

API Endpoints

Quick reference for all Wave API endpoints. For request/response schemas and a built-in request builder, see the Interactive API Reference.

All endpoints require a Bearer token. Base URL: https://api.wave.co

Sessions

MethodPathScopeDescription
GET/v1/sessionssessions:readList sessions with cursor-based pagination
GET/v1/sessions/:idsessions:readGet session details (metadata, summary, notes, tags)
PATCH/v1/sessions/:idsessions:writeUpdate title, notes, tags, favorite, or structured action_items (supports If-Match for optimistic concurrency)
GET/v1/sessions/:id/action-itemssessions:readRead structured action items + current version (pass as If-Match on PATCH)
GET/v1/sessions?tag=<name>sessions:readFilter by tag (exact, case-sensitive). Repeatable or comma-separated; pair with tag_mode=all to require every tag.
DELETE/v1/sessions/:idsessions:deletePermanently delete a session
POST/v1/sessions/searchsessions:searchSemantic search across all sessions
GET/v1/sessions/statssessions:readAggregated session statistics for a date range
POST/v1/sessions/bulksessions:readBulk export up to 50 sessions by ID (set include_transcript: true for full transcripts)

Folders

Folders are non-exclusive — a session can live in many folders at once. Pair GET /v1/folders with GET /v1/sessions?folder=… to scope results, or use the membership endpoints to organize sessions programmatically.

MethodPathScopeDescription
GET/v1/foldersfolders:readList the user's folders (id, name, color, session count, created_at/updated_at, plus pinned/sort_order/order/last_opened_at when set), pinned first, then by order, then name. sessions:read is also accepted.
GET/v1/folders/:idfolders:readFetch one folder by id (404 if missing). sessions:read is also accepted.
POST/v1/foldersfolders:writeCreate a folder (name collisions return the existing folder — safe to retry)
PATCH/v1/folders/:idfolders:writeRename, recolour, pin, reorder or set the session sort of a folder ({ name?, color?, pinned?, sort_order?, order? }; at least one required)
DELETE/v1/folders/:idfolders:writeDelete a folder (204). Sessions in it are never deleted.
POST/v1/sessions/:id/folders/:folderIdfolders:writeAdd a session to a folder (non-exclusive; idempotent)
DELETE/v1/sessions/:id/folders/:folderIdfolders:writeRemove a session from a folder
GET/v1/sessions?folder=<id|name>sessions:readFilter the sessions list to one folder (accepts folder id or case-insensitive name)

Event Feed

Stripe-style per-token cursor. Wave keeps track of where you are in the event stream on the server, so you don't have to maintain dedupe state on the client. Use instead of — or alongside — webhooks. Same event shapes, same ids.

MethodPathScopeDescription
GET/v1/eventsevents:readPull events since the last ack (or a passed cursor). Includes next_cursor + has_more.
POST/v1/events/ackevents:readAdvance the cursor (monotonic). Later polls skip events at or before this cursor.

Transcripts

MethodPathScopeDescription
GET/v1/sessions/:id/transcripttranscripts:readFull transcript with optional speaker segments

Media

MethodPathScopeDescription
GET/v1/sessions/:id/mediamedia:readSigned audio/video URLs (expire after 1 hour)

Account

MethodPathScopeDescription
GET/v1/accountaccount:readUser profile, subscription status, and session count

Sharing

Read sessions shared with you through REST or MCP. Shared sessions are read-only; each grant determines access to summaries, transcripts, audio, and action items. Keep both the owner ID and session ID.

GET /v1/shared-sessions lists the latest 500 active grants with pagination (limit 20–100; pass next_cursor unchanged).

GET /v1/sessions?include=shared appends those rows to the first page of your own list (access: "shared" with an owner), so one call covers everything you can read.

GET /v1/shared-sessions/:owner_id/:id returns metadata, summary, and action items allowed by the grant. Append /transcript, /action-items, or /media for content. Metadata and action items require sessions:read; transcripts require transcripts:read; media requires media:read.

Owners use GET /v1/sessions/:id/sharing to see people and pending invites. The link URL is always null here: create a link with POST /v1/sessions/:id/sharing/link.

Email up to 10 people with POST /v1/sessions/:id/sharing/invites and a JSON body containing emails and an optional message (up to 500 characters). Cancel with DELETE on the same path (email and optional invite_id in JSON, or ?email=).

Remove a recipient with DELETE /v1/sessions/:id/sharing/people/:recipient_id. Reset the link with POST /v1/sessions/:id/sharing/link/reset; set remove_everyone to true to revoke all recipients too.

All owner operations require sharing:manage. Links expire after 30 days and are claimed in the app. Revoked recipient access returns 404. Callable rate limits return 429 sharing_rate_limited; temporary failures return 503 sharing_unavailable.

Search and the regular sessions list cover your own sessions only. Shared sessions cannot be filtered by folder or tag. Shared action items omit edit provenance and use version 0 / updated_at null because they are read-only. Sharing events/webhooks, Teams sources, and setting per-invite scopes are deferred; scope is read-only.

Full sharing request, response, and error reference

Reactive workflows

Webhooks

Register HTTPS endpoints to receive real-time notifications when sessions are completed, updated, or deleted. Payloads are signed with HMAC-SHA256 for verification.

MethodPathScopeDescription
GET/v1/webhookswebhooks:manageList all registered webhooks
POST/v1/webhookswebhooks:manageRegister a new webhook (returns signing secret)
PATCH/v1/webhooks/:idwebhooks:manageUpdate URL, events, or active status
DELETE/v1/webhooks/:idwebhooks:manageDelete a webhook
POST/v1/webhooks/:id/rotate-secretwebhooks:manageRegenerate the signing secret
POST/v1/webhooks/:id/testwebhooks:manageSend a test event and report delivery status

Webhook Events

EventTriggered When
session.completedFires once, after a session finishes processing and the summary, notes, and tags are queryable. This is the “session is ready to use” event.
session.updatedSession metadata was changed (title, summary, notes, tags, favorite). Fires for edits from any source — the API, mobile app, or web app.
session.action_items.updatedStructured action items on a session were written or edited via PATCH. Carries the full session in data.session, including the new action_items and action_items_version.
session.deletedSession was deleted (soft-delete or hard-delete of a completed session)

Signature Verification

Each delivery includes these headers for verification:

HeaderDescription
X-Wave-Webhook-IdUnique event ID
X-Wave-Webhook-TimestampUnix timestamp of the delivery
X-Wave-Webhook-SignatureHMAC-SHA256 signature

To verify: compute HMAC-SHA256(secret, "webhookId.timestamp.body") and compare with the signature header.

Predictable failures

Error Codes

All errors return a consistent JSON structure:

{
  "error": {
    "code": "error_code",
    "message": "Human-readable description"
  }
}
CodeStatusDescription
invalid_request400Missing or invalid parameters
unauthorized401Missing or invalid Authorization header
invalid_token401Token is invalid, expired, or revoked
insufficient_scope403Token lacks required permission
not_found404Resource not found
limit_exceeded400Resource limit reached (e.g. max webhooks)
rate_limit_exceeded429Too many requests
internal_error500Server error

Usage guardrails

Rate Limits

  • 60 requests per minute per token
  • 10,000 requests per day per token

Rate limit info is included in every response:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1706000000

Machine-readable contract

API Reference

The full OpenAPI 3.1 specification is available at:

https://api.wave.co/v1/openapi.json

Use it to generate client libraries, import into Postman, or validate requests.

Want to try these endpoints? Open the Interactive API Reference for a built-in request builder with live responses.