Waveguide
Docs navigation

API

Everything the dashboard does goes through a JSON API you can call yourself. 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 are relative to /tenants/:id unless noted. :id is your tenant id (ten_…).

MethodPathPurpose
GET/tenants/:idTenant status + connections
GET/tenants/:id/spendMonth-to-date model spend by category
GET/tenants/:id/sessionsRecent agent sessions
GET/tenants/:id/auditAudit log (most recent 200)
GET/tenants/:id/approvalsPending approvals
GET/POST/tenants/:id/soulRead / replace SOUL.md
POST/tenants/:id/policiesCreate a standing policy
POST/tenants/:id/wakeWake the agent with a message (rate-limited)
POST/tenants/:id/killKill switch
POST/tenants/:id/resumeResume after pause/kill
POST/tenants/:id/rotate-keyRotate the access key (returned once)
POST/tenants/:id/exportFull data export → returns a bundle key
POST/tenants/:id/deletePermanent delete (irreversible)
GET/tenants/:id/channelsList channel bindings
GET/tenants/:id/billing-portalStripe customer portal URL

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

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 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. Errors return JSON ({"error": "message"}) with conventional status codes: 401 bad/expired credentials, 403 wrong tenant scope, 429 rate-limited, 5xx our problem.