API
The dashboard talks to a JSON API you can call yourself. This page covers the main tenant-facing and public
surfaces (core tenant ops, MCP capabilities, jobs, scheduling, media, connections). A few dashboard-only or
agency/ops routes are omitted. Programmatic access authenticates with your tenant access key (wgk_…) —
find and rotate it under Settings → API access.
The access key is your API credential. Day-to-day dashboard sign-in uses email links instead; you only need the key for scripts and integrations.
Base URL: https://waveguide.adwave.com
Authentication
Exchange your access key for a tenant-scoped session token (30-day expiry):
curl -X POST https://waveguide.adwave.com/auth/login \
-H "content-type: application/json" \
-d '{"access_key": "wgk_..."}'
# → { "token": "eyJ...", "tenant": { "tenantId": "ten_...", "name": "Acme" } }
Use it as a bearer on every call:
export WG_TOKEN="eyJ..."
curl -H "authorization: Bearer $WG_TOKEN" \
https://waveguide.adwave.com/tenants/ten_.../spend
Tokens are scoped to your tenant only. “Sign out everywhere” (Settings) and key rotation both invalidate outstanding sessions.
Endpoints
All paths below are relative to the base URL. :id is your tenant id (ten_…). Unless noted, endpoints require
Authorization: Bearer $WG_TOKEN.
Tenant core
| Method | Path | Purpose |
|---|---|---|
| GET | /tenants/:id | Tenant status + connections |
| GET | /tenants/:id/spend | Month-to-date model spend by category |
| GET | /tenants/:id/sessions | Recent agent sessions |
| GET | /tenants/:id/audit | Audit log (most recent 200) |
| GET | /tenants/:id/approvals | Pending approvals |
| GET/POST | /tenants/:id/soul | Read / replace SOUL.md |
| GET/PUT | /tenants/:id/soul-profile | Structured persona (identity, scheduling, send windows) |
| GET/POST/PATCH/DELETE | /tenants/:id/policies[/:pid] | Standing policies |
| POST | /tenants/:id/wake | Wake the agent with a message (rate-limited); optional conversation_id continues an ask chat |
| GET | /tenants/:id/wakes/:wakeId | Wake / session status |
| GET | /tenants/:id/conversations | List ask + mission chats |
| POST | /tenants/:id/conversations | Create ask chat; optional first text wakes |
| GET | /tenants/:id/conversations/:cid/messages | Messages for one chat |
| POST | /tenants/:id/conversations/:cid/messages | Continue ask or mission chat |
| POST | /tenants/:id/conversations/:cid/make-job | Promote ask chat → mission chat |
| GET | /tenants/:id/inbox | Hybrid Inbox (projected suggestions/approvals + ambient updates) |
| POST | /tenants/:id/inbox/:iid/read | Mark materialized inbox item read (inb:…) |
| POST | /tenants/:id/inbox/:iid/dismiss | Dismiss ambient item or suggestion (opp:…) |
| POST | /tenants/:id/inbox/:iid/start | Start job from Inbox item |
| GET | /tenants/:id/ask-thread | Compat: ?conversation_id= returns that chat; without it { migrated: true, messages: [] } |
| GET | /tenants/:id/reactive-status | Live reactive session hint |
| GET | /tenants/:id/sessions/:sessionId/stream | SSE activity stream |
| POST | /tenants/:id/kill | Kill switch |
| POST | /tenants/:id/resume | Resume after pause/kill |
| POST | /tenants/:id/rotate-key | Rotate the access key (returned once) |
| POST | /tenants/:id/export | Full data export → returns a bundle key |
| GET | /tenants/:id/export-download | Download export bundle |
| GET | /tenants/:id/artifacts | Tenant artifact listing |
| POST | /tenants/:id/delete | Permanent delete (irreversible) |
| GET | /tenants/:id/channels | List channel bindings |
| DELETE | /tenants/:id/channels/:bindingId | Remove a channel binding |
| POST | /tenants/:id/channels/telegram-code | Start Telegram link |
| GET | /tenants/:id/billing-portal | Stripe customer portal URL |
| POST | /tenants/:id/upgrade | Free → paid Checkout (no trial) |
| GET/POST/PATCH/DELETE | /tenants/:id/members… | Team members + invites |
| PATCH | /tenants/:id/settings | Tenant settings |
| PATCH | /tenants/:id/onboarding | Onboarding progress |
| GET/DELETE | /tenants/:id/schedules[/:sid] | Time-based wake schedules |
| GET/POST/DELETE | /tenants/:id/suppression | Do-not-contact list |
| GET/PUT/DELETE | /tenants/:id/capability-bindings[/:bid] | Preferred providers per capability |
| GET | /tenants/:id/ledger-stats | CRM ledger rollups |
| GET | /tenants/:id/opportunities | Agent-suggested opportunities |
| POST | /tenants/:id/opportunities/:oid/{dismiss|snooze|start} | Act on an opportunity |
| GET | /tenants/:id/lane-health | Outreach lane health |
| POST | /tenants/:id/lane-health/:lane/resume | Resume a paused lane |
Persona enrichment & media
| Method | Path | Purpose |
|---|---|---|
| POST | /tenants/:id/soul-enrichment | Start Learn-from-URL job |
| GET | /tenants/:id/soul-enrichment/latest | Latest enrichment draft |
| POST | /tenants/:id/soul-enrichment/:jobId/apply | Accept draft (all or empty-only) |
| POST | /tenants/:id/soul-enrichment/:jobId/discard | Discard draft |
| GET/POST | /tenants/:id/media | List / upload media |
| GET | /tenants/:id/media/:mediaId/content | Media bytes |
| PATCH/DELETE | /tenants/:id/media/:mediaId | Update metadata / delete |
Scheduling
Configure mode (Waveguide / Calendly / external) on the soul profile. Native public booking is gated by
BOOKING_NATIVE_ENABLED.
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /tenants/:id/scheduling/calendly/event-types | bearer | List Calendly event types |
| POST | /tenants/:id/scheduling/calendly/sync | bearer | Reconcile recent Calendly events |
| GET | /book/:slug | public | Booking page HTML |
| GET | /book/:slug/slots | public | Available slots JSON |
| POST | /book/:slug | public (rate-limited) | Create a booking |
| POST | /book/manage/:token/cancel | link token | Cancel a booking |
| POST | /book/manage/:token/reschedule | link token | Reschedule a booking |
Connections (OAuth / social / Twilio)
| Method | Path | Purpose |
|---|---|---|
| POST | /tenants/:id/connections | Start Nango OAuth connect |
| POST | /tenants/:id/connections/sync | Refresh connection status |
| DELETE | /tenants/:id/connections/:provider | Disconnect provider |
| POST | /tenants/:id/connections/twilio | Save Twilio SMS credentials |
| POST | /tenants/:id/slack-install-url | Slack app install URL |
| GET | /tenants/:id/social | Social platform status |
| POST | /tenants/:id/social/connect | Link a social platform |
| POST | /tenants/:id/social/sync | Refresh linked platforms |
| POST | /tenants/:id/social/disconnect | Unlink a platform |
Capabilities (MCP tools)
See Capabilities for product behavior. Catalog ids match MCP_CATALOG in code.
| Method | Path | Purpose |
|---|---|---|
| GET | /tenants/:id/mcp/catalog | Curated catalog (excludes platform-managed) |
| GET | /tenants/:id/mcp/connections | Connected MCP servers + tool manifests |
| POST | /tenants/:id/mcp/connections | Connect catalog entry or arbitrary URL |
| POST | /tenants/:id/mcp/connections/:cid/sync | Re-discover tools; detect drift |
| PATCH | /tenants/:id/mcp/connections/:cid/tools/:tool | Override risk tier / clear poisoning flag |
| POST | /tenants/:id/mcp/connections/:cid/suggest-catalog | Suggest arbitrary URL for catalog review |
| DELETE | /tenants/:id/mcp/connections/:cid | Disconnect |
| GET/POST/DELETE | /tenants/:id/mcp/connections/:cid/watches… | Site-watch poll registrations |
OAuth-protected arbitrary MCP servers complete at GET /oauth/mcp/callback (browser redirect; not bearer-auth).
Hosted sending
| Method | Path | Purpose |
|---|---|---|
| GET | /tenants/:id/sending-identities | Hosted outreach identities |
| PATCH | /tenants/:id/sending-identities/:identityId | Update display name / forward / resume |
| GET/POST | /tenants/:id/sending-domains | BYO brand domains |
| POST | /tenants/:id/sending-domains/:domain/verify | Re-check DNS |
Jobs (missions)
| Method | Path | Purpose |
|---|---|---|
| GET | /tenants/:id/mission-templates | Starter job templates |
| GET/POST | /tenants/:id/missions | List / create jobs |
| GET | /tenants/:id/missions/:mid | Job detail |
| PATCH | /tenants/:id/missions/:mid/brief | Edit brief |
| PATCH | /tenants/:id/missions/:mid/autonomy | Autonomy level |
| PATCH | /tenants/:id/missions/:mid/job-kind | Job kind (outreach / campaign / …) |
| GET/PATCH | /tenants/:id/missions/:mid/todos… | Job todos |
| GET | /tenants/:id/missions/:mid/artifacts | Artifacts (use format=bytes for code bundles) |
| GET | /tenants/:id/missions/:mid/pending-approvals | Pending approvals for this job |
| POST | /tenants/:id/missions/:mid/approve-pending | Batch-approve non-sensitive |
| POST | /tenants/:id/missions/:mid/{pause|resume|kill} | Lifecycle |
| POST | /tenants/:id/missions/:mid/setup/{skip|refresh|seed-text|confirm-webhook|confirm-playbook} | Setup plan actions |
| POST | /tenants/:id/missions/:mid/amendments/{approve|deny} | Brief amendments |
| POST | /tenants/:id/missions/:mid/graph/amendments/{approve|deny} | Graph amendments |
Audience exports
| Method | Path | Purpose |
|---|---|---|
| GET/POST/PATCH/DELETE | /tenants/:id/audience-exports… | Manage exports |
| POST | /tenants/:id/audience-exports/:exportId/run | Run an export |
| POST | /tenants/:id/audience-exports/credentials/s3 | Store S3 credentials (vaulted) |
Examples
Wake the agent with a task:
curl -X POST -H "authorization: Bearer $WG_TOKEN" \
-H "content-type: application/json" \
-d '{"text": "Summarize this week and flag anything odd."}' \
https://waveguide.adwave.com/tenants/ten_.../wake
Connect a curated MCP tool (Apollo):
curl -X POST -H "authorization: Bearer $WG_TOKEN" \
-H "content-type: application/json" \
-d "{\"catalog_id\": \"apollo\", \"secret\": \"$APOLLO_API_KEY\"}" \
https://waveguide.adwave.com/tenants/ten_.../mcp/connections
Create a standing policy (auto-approve budget changes with a delta under $50):
curl -X POST -H "authorization: Bearer $WG_TOKEN" \
-H "content-type: application/json" \
-d '{
"action_type": "campaign.budget_change",
"predicate": {"budget_delta_cents": {"lt": 5000}},
"effect": "auto_approve"
}' \
https://waveguide.adwave.com/tenants/ten_.../policies
Predicates map dotted paths in the tool input to constraints (lt, lte, gt, gte, eq, in), combined with AND
semantics. An empty predicate {} matches every action of that type. Policies apply to T2 only — T3 always requires a
human — and tainted input forces approval regardless of policy.
Kill switch:
curl -X POST -H "authorization: Bearer $WG_TOKEN" \
https://waveguide.adwave.com/tenants/ten_.../kill
Approval links
Approval resolution endpoints (/a/:token/approve, /a/:token/deny) use the signed single-use token carried in the
approval card — they are not access-key-authenticated, because the token itself is the credential. Treat approval links
like passwords: don’t forward them.
Rate limits and errors
Auth endpoints are rate-limited per IP; /wake allows 5 manual runs per hour. Public /book/:slug POSTs are
rate-limited per IP. Errors return JSON ({"error": "message"}) with conventional status codes: 401 bad/expired
credentials, 403 wrong tenant scope, 429 rate-limited, 5xx our problem.
Not in this reference
Agent-runtime callbacks (/runtime/*), provider webhooks (/webhooks/*), and internal/service routes are
platform-internal — sandboxes call them with capability tokens, not your access key. Operator docs:
docs/external-accounts.md, docs/runbook.md, docs/adr/0009-scheduling-service.md.