Connect to Wavemaker
The session API, the twelve tools over HTTP and MCP, and the CLI reach the same workspace and credits. Start here for auth, base URLs, a first request and how billing applies.
Updated
Wavemaker's developer surface reaches the same workspace, credits and hosted agent as the web app. Use it to have the hosted agent make finished ads from a brief, to drive individual generation and editing jobs yourself, or to give your own agent Wavemaker's tools. This page explains the layers, how to authenticate, and how credits apply, then walks through a first request.
- Get a key
Create a credential in Connections › Developer setup.
- Price it
Quote the brief; a quote holds no credits.
- Run it
Post the brief as a turn and follow its events.
- Collect
Read the turn and download each delivery.
What you can build
- A backend that sends a brief and receives finished videos, stills, audio or HTML5 banners, checked against a destination spec such as
ctv/standard. - An editor or review tool where each "make this change" message is one more turn in the same conversation.
- A pipeline that runs single jobs itself: search for a model or graph, price it, generate, follow the job and download the result.
- An agent of your own (Claude, ChatGPT, Cursor, Grok or another MCP host) that uses Wavemaker's twelve tools in its own loop.
- Terminal automation with the
wavemakerCLI, once it is released. The CLI has no public release yet.
The three layers
| Layer | Use it when | Entry point |
|---|---|---|
| Session API | You want the hosted Wavemaker agent to plan and make the work from a brief | POST /v1/sessions, then POST /v1/sessions/{id}/turns |
| The twelve tools | You drive each step yourself, from code or from your own agent | POST /v1/tools/{tool} over HTTP, or the same tools at /mcp |
| CLI | You work from a terminal: sign in, call a tool, run a production | wavemaker |
The twelve tools are search, read, write, generate, edit, compose, watch, listen, compare, review, deliver and run. The hosted agent uses the same tools, so anything it can do in a turn, your code can do with tool calls. HTTP, MCP and the CLI return the same result for the same call.
The Python, TypeScript and Go clients wrap the session API and the tools. Python, TypeScript and Go clients says whether each one is on a public registry yet; until a client is published, call the HTTP API or connect over MCP. Small example apps are described in Standalone starter apps.
Base URLs
| Purpose | URL |
|---|---|
| API, OAuth issuer and signed downloads | https://api.wavemaker.io |
| MCP endpoint | https://api.wavemaker.io/mcp |
| Web app | https://app.wavemaker.io |
Paths answer directly, with no redirects. Three routes help you check the service before you write code:
GET /healthanswers{"ok": true, "service": "wmcore"}without a credential.GET /v1/toolslists each tool'sname,scope,summaryandargs_schema. It needs a credential.GET /openapi.jsonlists every route the service answers.
The HTTP API page has the full route reference and a live operation browser.
Authentication options
Every request carries Authorization: Bearer {credential}. The credential fixes the workspace: every read, write and charge is scoped to it.
| Credential | Who uses it | How you get it |
|---|---|---|
| Developer credential | Your backend, scripts and CI | Connections › Developer setup › Create credential in the web app; lasts 1, 7 or 30 days |
| OAuth sign-in | MCP hosts and the CLI | The host or wavemaker login opens a browser sign-in and consent page |
Ask for the read, write and run scopes. Together they cover the session API and all twelve tools. publish is needed only for publishing versions and community listings. See Client credentials and provider keys for scopes, expiry, replacement and revocation.
Quickstart: your first brief in five minutes
This walkthrough uses curl. Each step shows an abbreviated response.
- In the web app, open Connections, choose the Developer setup tab and select Create credential.
- Give it a Name, keep Read projects and results, check Create and edit source and Run work, choose Expires in and select Create credential.
- Copy the credential from the Save your credential dialog. It is shown once.
- Save it in a private curl config file so it stays off the command line.
- Check which workspace the credential belongs to.
- Search and price the work. Neither step spends credits.
- Create a session, post the brief, follow the events and read the result.
Save the credential and check it:
umask 077
printf 'header = "Authorization: Bearer %s"\n' "$WAVEMAKER_KEY" > ~/.config/wavemaker-curl
curl --config ~/.config/wavemaker-curl --fail-with-body https://api.wavemaker.io/v1/identity
# → 200 {"ok": true, "data": {"schema": "wmcore.identity/1", "workspace": "...",
# "kind": "api_key", "mode": "live", "scopes": ["read", "run", "write"],
# "projects": null, "expires_at": 1793000000.0}, "error": null, ...}Search the catalog. search never spends:
curl --config ~/.config/wavemaker-curl --fail-with-body \
--json '{"args": {"query": "vertical video ad", "kinds": ["card", "format"], "limit": 5}}' \
https://api.wavemaker.io/v1/tools/search
# → 200 {"ok": true, "data": {"results": [{"kind": "card", "id": "...", "title": "...",
# "uri": "wm://card/..."}], "next": "..."}, ...}Price the brief without starting anything:
curl --config ~/.config/wavemaker-curl --fail-with-body \
--json '{"text": "A 15-second vertical video ad for a neighborhood coffee shop.",
"deliverables": [{"id": "spot", "kind": "video", "aspect": "9:16", "duration_s": 15}]}' \
https://api.wavemaker.io/v1/quotes
# → 200 {"ok": true, "data": {"schema": "wmcore.quote/1", "quote_id": "q_...",
# "p50_microcredits": 52000000, "p90_microcredits": 81000000,
# "hold_microcredits": 81000000, "expires_at": ..., "balance_microcredits": ...}, ...}Create a session. The response carries the controller token you need for every later write:
curl --config ~/.config/wavemaker-curl --fail-with-body \
--json '{"request_id": "coffee-session-1", "title": "Coffee shop spring spot"}' \
https://api.wavemaker.io/v1/sessions
# → 201 {"ok": true, "data": {"schema": "wmcore.session/1", "id": "ses_...",
# "state": "active", "harness": "claude", "collaboration": "autopilot",
# "controller": {"token": "wmc_...", "expires_at": ..., "generation": 1}}, ...}Post the brief as the first turn:
curl --config ~/.config/wavemaker-curl --fail-with-body \
--json '{"request_id": "coffee-brief-1", "controller": "wmc_...",
"text": "A 15-second vertical video ad for a neighborhood coffee shop.",
"deliverables": [{"id": "spot", "kind": "video", "aspect": "9:16", "duration_s": 15}]}' \
https://api.wavemaker.io/v1/sessions/ses_.../turns
# → 202 {"ok": true, "data": {"schema": "wmcore.turn/1", "id": "trn_...", "state": "queued", ...}, ...}Follow the events with a long poll. Save next_after after you process each page, and read again until the turn ends:
curl --config ~/.config/wavemaker-curl --fail-with-body \
"https://api.wavemaker.io/v1/sessions/ses_.../events?after=0&wait_s=25"
# → 200 {"ok": true, "data": {"schema": "wmcore.events/1", "items": [
# {"seq": 2, "type": "turn.queued", ...}, {"seq": 3, "type": "turn.started", ...}],
# "next_after": 3, "more": false, "session_state": "active", "active_turn_id": "trn_..."}, ...}When a turn.completed, turn.failed or turn.interrupted event arrives, read the turn by the request_id you posted:
curl --config ~/.config/wavemaker-curl --fail-with-body \
https://api.wavemaker.io/v1/sessions/ses_.../requests/coffee-brief-1
# → 200 {"ok": true, "data": {"schema": "wmcore.turn/1", "state": "completed",
# "outcome": {"status": "delivered", "deliveries": [{"deliverable_id": "spot",
# "mime": "video/mp4", "sha256": "...", "url": "https://api.wavemaker.io/v1/downloads/...",
# "url_expires_at": ...}]}, "cost": {"charged_microcredits": ..., "settled": true}}, ...}Check that it worked
outcome.statusisdeliveredwhen every requested deliverable was delivered, andpartialwhen only some were.- Each delivery's
urldownloads the bytes without a credential untilurl_expires_at. Check the downloaded file against itssha256. cost.charged_microcreditsis what the turn cost. Unused hold returns to your balance when the turn settles.
The full session reference, including approvals, interrupts and deliverable specs, is in Make an ad.
The response envelope
Every /v1 JSON response is the same envelope: {ok, data, error, job, cost, hints}.
ok: truemeansdataholds the result anderroris null.ok: falsemeansdatais null anderroris{code, message, retryable, retry_after_s?, details?}.- The HTTP status follows
error.code, for example401 unauthenticated,402 insufficient_creditsor429 rate_limited. - Branch on
error.codeanderror.retryable, never onmessage. - Unknown request fields are refused with
invalid_requestanddetails.path. Ignore response fields you don't recognize; new ones can appear at any time.
See Errors and retries for every code.
Request identity and safe retries
Every write that can start work takes a request_id, a string you choose for that one piece of work.
- Sending the same request again with the same
request_idreturns the original result. Nothing runs or is charged twice. Session API replies carry the headerWavemaker-Replayed: trueon a replay. - Reusing a
request_idfor different work is refused:request_id_mismatch(409) on the session API andrequest_conflict(409) on the tools (composeanswersconflict, also 409). - After a dropped connection or your own timeout, resend the identical request with the same
request_id, or read the original. Never mint a new id for the same intent. - A spending tool call needs a
request_idunless it only prices or checks the work (quote_onlyorvalidate_only).
How credits apply to API use
API, MCP and CLI work draws on the same workspace credit balance as the web app. Amounts are integer microcredits: 1 credit is 1,000,000 microcredits.
| Action | Spends credits? |
|---|---|
search, read, write, watch, deliver | No |
| Creating a session | No. The hosted agent starts on the first turn |
| A turn of the hosted agent | Yes: the agent's model use plus every tool call it makes |
generate, edit, compose, run | Yes |
listen, compare, review | Yes, for the model call each one makes |
Any call with quote_only: true | No. It returns a price and holds nothing |
How a charge works:
- A quote gives
p50_microcredits(the typical cost) andhold_microcredits(what is reserved). A session quote lasts 1,800 seconds. - When work starts, the hold is reserved against your balance.
- When it settles, you are charged the measured usage, which can be below the quote and never exceeds the turn's cap. The rest of the hold is released.
Caps you can set:
max_microcreditson a session caps the whole session.max_microcreditson a turn caps that turn. Posting a turn with aquote_idmakes the quote's hold the cap, unless you also setmax_microcredits.- Without a cap, each tool call holds its own quoted cost against your balance. There is no other per-run credit ceiling.
What happens when money runs short:
- At post time, a balance below the hold is refused
insufficient_credits(402) withrequired_microcreditsandbalance_microcredits. Top up, then post again with a newrequest_id. - A turn cap too small for the agent's first model calls is refused
cap_exceeded(402) withdetails.minimum_microcredits. The first turn of a new session needs more than later turns. - If credits run out mid-turn, the turn ends
completedwithoutcome.statuspartialorstoppedandreason: budget. What was already made is kept.
read of wm://credits returns the workspace balance, and each finished turn links its receipt. When a saved provider key funds a call, the provider's model charge is zero credits; Wavemaker's own compute for the call is still charged. See Client credentials and provider keys. For plan and credit prices, see Plans and Credits.
Limits
| Limit | Value |
|---|---|
| JSON request body | 2 MB. Larger files go through the write upload flow |
| Long poll on session events | wait_s up to 25 seconds |
Long poll on a job (read of wm://job/{id}) | wait_s up to 85 seconds |
| Agent turns running at once | 24 per workspace; one more is refused rate_limited with details.limit hosted_turns_per_workspace and retry_after_s 30 |
| Tool calls per turn | 10 per second of requested output, at least 300 |
| Requests per credential | A per-credential rate; over it you get rate_limited with retry_after_s |
Versioning and changes
- Each
dataobject carries aschemaliteral such aswmcore.turn/1. A breaking change bumps the literal; additive fields don't. - The session API contract is version
1.0.0-draft.3. The tool schemas are dated, currently2026-10-18. - Older operations at
/api/v1/ops/{name}still answer in their olderwmlab.result/1envelope. See Account and workspace API access.
Changes to the API, the tools and the clients are listed in Changes.
Next steps
- Have the hosted agent make an ad: Make an ad
- Call the tools over HTTP: HTTP API
- Connect Claude, ChatGPT, Cursor or Grok: Connect an external agent with MCP
- Price and run individual jobs: Quote and run work
- Work from a terminal: Native CLI