REST API
REST API reference
Every operation of the /v1 API, generated from its OpenAPI document when this page was built. Paths are relative to https://wavefront.adwave.com. Load the OpenAPI document into your API client or code generator for the full request and response schemas.
- Workspaces (5)
- Members (1)
- Context (9)
- Writing rules (2)
- Strategies (8)
- Studio (14)
- Backlog (11)
- Calendar (2)
- Autopilot (2)
- Generations (6)
- Versions (6)
- Reviews & comments (5)
- Publishing (3)
- Schedules (5)
- Destinations (10)
- Imports (4)
- Catalog (1)
- Search data (7)
- Site metrics (2)
- AI visibility (17)
- Suggestions (8)
- Webhooks (11)
- Integrations (8)
- Billing (5)
- Account (1)
- Web app only (60)
Workspaces
Workspaces you can reach, with their settings, overview and activity.
GET /v1/workspaces
List workspaces you can access
An API key sees only its own workspace (role null).
Scope: any (API key or session)
Responses
| Status | Description |
|---|---|
200 | Workspaces |
401 | unauthorized |
GET /v1/workspaces/{ws}/overview
Counts, review queues, your work, recent activity and spend
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Overview |
404 | not_found |
GET /v1/workspaces/{ws}/counts
Queue sizes for navigation badges
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Counts |
404 | not_found |
GET /v1/workspaces/{ws}/activity
Workspace activity, newest first (audit events for owners only)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
cursor | query | string | |
limit | query | integer |
Responses
| Status | Description |
|---|---|
200 | Activity |
400 | invalid_request |
404 | not_found |
GET /v1/workspaces/{ws}
Workspace name, your role, context source and effective spend and concurrency caps
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Workspace |
401 | unauthorized |
404 | not_found |
Members
The people in a workspace, their roles and pending invitations.
GET /v1/workspaces/{ws}/people
Members with names and roles; owners also see pending invitations. API keys get email: null
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | People |
404 | not_found |
Context
The workspace documents every generation reads: brief, voice, rules and references.
GET /v1/workspaces/{ws}/context
Current context manifest with per-document summaries
Scope: context:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Manifest |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
PUT /v1/workspaces/{ws}/context
Push context (multipart: manifest JSON + file:<path> parts for changed files, and an optional base_version field: 409 conflict if another write landed since)
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body (multipart/form-data)
None.
Responses
| Status | Description |
|---|---|
200 | Push result |
400 | invalid_request |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
422 | Unprocessable (see the code) |
GET /v1/workspaces/{ws}/context/file
Read one context document as text or sanitized HTML
Scope: context:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
path required | query | string | |
format | query | "text" | "html" | |
version | query | integer | An earlier context version; omit for the latest |
Responses
| Status | Description |
|---|---|
200 | Document text or HTML |
400 | invalid_request |
404 | not_found |
PUT /v1/workspaces/{ws}/context/file
Create or replace one document as a new context version. workspace.yaml and calendar.json files are validated (400). 422 context_too_large; 409 context_read_only for Git-managed workspaces
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
path required | string | |
body required | string |
Responses
| Status | Description |
|---|---|
200 | Context version |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
422 | Unprocessable (see the code) |
DELETE /v1/workspaces/{ws}/context/file
Remove one document as a new context version (workspace.yaml can't be removed)
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
path required | query | string |
Responses
| Status | Description |
|---|---|
200 | Context version |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/context/versions
Recent context versions
Scope: context:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Versions |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/context/restore
Re-push a prior context snapshot as a new latest version. base_version (optional) is the version the caller last saw: 409 conflict if another write landed since
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
version required | integer | |
base_version | integer |
Responses
| Status | Description |
|---|---|
200 | Push result |
400 | invalid_request |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/context/thread
Context chat thread
Scope: context:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Thread |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/context/chat
Propose and merge context file updates (no wallet charge)
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
message required | string | |
idempotency_key required | string |
Responses
| Status | Description |
|---|---|
200 | Chat turn |
400 | invalid_request |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
Writing rules
Phrases drafts must never use, should avoid or may use, checked on every draft.
GET /v1/workspaces/{ws}/writing-rules
The workspace's copy rules as Settings → Writing rules shows them: never, avoid and allow lists, advanced regexes (owners), and the built-in catalog in numbers
Scope: context:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Writing rules |
400 | invalid_request |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
PUT /v1/workspaces/{ws}/writing-rules
Write the never, avoid and allow lists (and, for owners, advanced regexes) into the copy_checks file as a new context version; other sections are kept
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
never required | array of object | |
avoid required | array of object | |
allow required | array of string | |
advanced | array of object | |
base_version | integer |
Responses
| Status | Description |
|---|---|
200 | Push result |
400 | invalid_request |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Strategies
Content strategies and their plans: pillars, keywords, calendar and cadence.
GET /v1/workspaces/{ws}/strategies
The workspace's strategies, primary first
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
archived | query | "1" | Include archived strategies |
Responses
| Status | Description |
|---|---|
200 | Strategies |
401 | unauthorized |
404 | not_found |
POST /v1/workspaces/{ws}/strategies
Start a strategy from the primary one's brief and voice; `message` starts the strategist at once. If it can't start, the strategy still exists and studio_error says why. A name already in use is 409 slug_exists
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Idempotency-Key | header | string | Retry safely for 7 days: the same key and body replays the original result (200); a different body is 409 idempotency_conflict |
Request body
| Name | Type | Description |
|---|---|---|
name required | string | |
description | string | |
message | string |
Responses
| Status | Description |
|---|---|
200 | Idempotent replay |
201 | Strategy |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/strategies/{sid}
One strategy with plan counts and state
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Responses
| Status | Description |
|---|---|
200 | Strategy |
404 | not_found |
PATCH /v1/workspaces/{ws}/strategies/{sid}
Rename, describe, pause (autopilot skips it) or archive a strategy
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Request body
| Name | Type | Description |
|---|---|---|
name | string | |
description | string | |
status | "active" | "paused" | "archived" |
Responses
| Status | Description |
|---|---|
200 | Strategy |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/strategies/{sid}/plan
The plan draft and its plan_version
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Responses
| Status | Description |
|---|---|
200 | The plan draft |
404 | not_found |
PATCH /v1/workspaces/{ws}/strategies/{sid}/plan
Edit the plan directly, without a strategist turn. Item operations (keywords_add/remove, calendar_upsert/remove, pillars_*, sources_*) change only what they name; brief, voice and calendar.cadence merge field by field; the whole-list fields replace their list. A post with a draft is only dropped by calendar_remove (orphaned_drafts lists them). base_plan_version makes a stale edit a 409 with details.plan_version
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Request body
| Name | Type | Description |
|---|---|---|
patch required | object | |
note | string | |
base_plan_version | integer |
Responses
| Status | Description |
|---|---|
200 | What changed and the studio view |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/studio/plan
The plan draft and its plan_version
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | The plan draft |
404 | not_found |
PATCH /v1/workspaces/{ws}/studio/plan
Edit the plan directly, without a strategist turn. Item operations (keywords_add/remove, calendar_upsert/remove, pillars_*, sources_*) change only what they name; brief, voice and calendar.cadence merge field by field; the whole-list fields replace their list. A post with a draft is only dropped by calendar_remove (orphaned_drafts lists them). base_plan_version makes a stale edit a 409 with details.plan_version
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
patch required | object | |
note | string | |
base_plan_version | integer |
Responses
| Status | Description |
|---|---|
200 | What changed and the studio view |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Studio
The strategist conversation that drafts and edits a strategy's plan.
GET /v1/workspaces/{ws}/studio
The strategist conversation and plan draft
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Studio view |
404 | not_found |
POST /v1/workspaces/{ws}/studio/messages
Send the strategist a message; the turn runs in the background (poll GET). Busy: 409 conflict with details.message_id
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Idempotency-Key | header | string | Retry safely for 7 days: the same key and body replays the original result (200); a different body is 409 idempotency_conflict |
Request body
| Name | Type | Description |
|---|---|---|
message required | string |
Responses
| Status | Description |
|---|---|
200 | Idempotent replay |
202 | Studio view plus message_id (the reply to poll) |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/studio/messages/{mid}/retry
Run a failed reply again; returns the studio view and the new message_id
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
mid required | path | string |
Responses
| Status | Description |
|---|---|
202 | Studio view |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/studio/messages/{mid}/apply
Apply what a strategist reply held for confirmation (held_calendar, or the held_moves still to apply), written as that reply would have written it. 409 plan_conflict once the plan has changed since the reply; 409 invalid_state when nothing is waiting
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
mid required | path | string |
Responses
| Status | Description |
|---|---|
200 | What changed and the studio view |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/studio/messages/{mid}/undo
Undo the latest plan change
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
mid required | path | string |
Responses
| Status | Description |
|---|---|
200 | Studio view |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/studio/reset
Start a fresh conversation; the plan stays
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Studio view |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/studio/save
Save the plan as workspace documents (a new context version)
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Context version, paths and the studio view |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/strategies/{sid}/studio
The strategist conversation and plan draft
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Responses
| Status | Description |
|---|---|
200 | Studio view |
404 | not_found |
POST /v1/workspaces/{ws}/strategies/{sid}/studio/messages
Send the strategist a message; the turn runs in the background (poll GET). Busy: 409 conflict with details.message_id
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Idempotency-Key | header | string | Retry safely for 7 days: the same key and body replays the original result (200); a different body is 409 idempotency_conflict |
Request body
| Name | Type | Description |
|---|---|---|
message required | string |
Responses
| Status | Description |
|---|---|
200 | Idempotent replay |
202 | Studio view plus message_id (the reply to poll) |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/strategies/{sid}/studio/messages/{mid}/retry
Run a failed reply again; returns the studio view and the new message_id
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
mid required | path | string |
Responses
| Status | Description |
|---|---|
202 | Studio view |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/strategies/{sid}/studio/messages/{mid}/apply
Apply what a strategist reply held for confirmation (held_calendar, or the held_moves still to apply), written as that reply would have written it. 409 plan_conflict once the plan has changed since the reply; 409 invalid_state when nothing is waiting
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
mid required | path | string |
Responses
| Status | Description |
|---|---|
200 | What changed and the studio view |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/strategies/{sid}/studio/messages/{mid}/undo
Undo the latest plan change
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
mid required | path | string |
Responses
| Status | Description |
|---|---|
200 | Studio view |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/strategies/{sid}/studio/reset
Start a fresh conversation; the plan stays
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Responses
| Status | Description |
|---|---|
200 | Studio view |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/strategies/{sid}/studio/save
Save the plan as workspace documents (a new context version)
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Responses
| Status | Description |
|---|---|
200 | Context version, paths and the studio view |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Backlog
A strategy's idea backlog, which autopilot draws on to fill the calendar.
GET /v1/workspaces/{ws}/backlog
The idea backlog: counts, the next ideas autopilot takes today, and a page of ideas (status=open|used|skipped, limit up to 500, offset)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
status | query | "open" | "used" | "skipped" | |
limit | query | integer | |
offset | query | integer |
Responses
| Status | Description |
|---|---|
200 | Backlog |
400 | invalid_request |
404 | not_found |
POST /v1/workspaces/{ws}/backlog/ideas
Append ideas to the backlog (created on first use). A bad idea, or an id already there, is left out and listed in warnings; 400 when none are valid
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
ideas required | array of object |
Responses
| Status | Description |
|---|---|
201 | Added |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/backlog/import
Load a backlog from JSON ({defaults?, ideas}). mode merge (default) updates ideas with the same id and appends new ones; replace makes the backlog exactly the import. Bad ideas are left out and listed in warnings
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
mode | "merge" | "replace" | Default merge. |
version | 1 | |
defaults | object | |
ideas required | array of object |
Responses
| Status | Description |
|---|---|
200 | Imported |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/backlog/preview
What autopilot would schedule from the backlog over the next days (default 30, up to 90) and the mix that gives, without writing anything: items with why, shares per dimension against targets, spacing conflicts, unfilled slots and the policy as applied. plan=draft tries the unsaved plan's mix; rebalance=1 previews a rebalance. Without a cadence, one post a day is assumed
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
days | query | integer | |
plan | query | "saved" | "draft" | |
rebalance | query | "0" | "1" |
Responses
| Status | Description |
|---|---|
200 | Preview |
400 | invalid_request |
404 | not_found |
POST /v1/workspaces/{ws}/backlog/rebalance
Re-plan this strategy's autopilot items in the fill window that have no draft yet with the editorial mix: they leave the calendar, their ideas reopen (released), and the slots are filled again (added, with why). Items with any draft stay; nothing is cancelled. 409 invalid_state without a cadence
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | What was released and filled |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/strategies/{sid}/backlog
The idea backlog: counts, the next ideas autopilot takes today, and a page of ideas (status=open|used|skipped, limit up to 500, offset)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
status | query | "open" | "used" | "skipped" | |
limit | query | integer | |
offset | query | integer |
Responses
| Status | Description |
|---|---|
200 | Backlog |
400 | invalid_request |
404 | not_found |
POST /v1/workspaces/{ws}/strategies/{sid}/backlog/ideas
Append ideas to the backlog (created on first use). A bad idea, or an id already there, is left out and listed in warnings; 400 when none are valid
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Request body
| Name | Type | Description |
|---|---|---|
ideas required | array of object |
Responses
| Status | Description |
|---|---|
201 | Added |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/strategies/{sid}/backlog/import
Load a backlog from JSON ({defaults?, ideas}). mode merge (default) updates ideas with the same id and appends new ones; replace makes the backlog exactly the import. Bad ideas are left out and listed in warnings
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Request body
| Name | Type | Description |
|---|---|---|
mode | "merge" | "replace" | Default merge. |
version | 1 | |
defaults | object | |
ideas required | array of object |
Responses
| Status | Description |
|---|---|
200 | Imported |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/strategies/{sid}/backlog/preview
What autopilot would schedule from the backlog over the next days (default 30, up to 90) and the mix that gives, without writing anything: items with why, shares per dimension against targets, spacing conflicts, unfilled slots and the policy as applied. plan=draft tries the unsaved plan's mix; rebalance=1 previews a rebalance. Without a cadence, one post a day is assumed
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
days | query | integer | |
plan | query | "saved" | "draft" | |
rebalance | query | "0" | "1" |
Responses
| Status | Description |
|---|---|
200 | Preview |
400 | invalid_request |
404 | not_found |
POST /v1/workspaces/{ws}/strategies/{sid}/backlog/rebalance
Re-plan this strategy's autopilot items in the fill window that have no draft yet with the editorial mix: they leave the calendar, their ideas reopen (released), and the slots are filled again (added, with why). Items with any draft stay; nothing is cancelled. 409 invalid_state without a cadence
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sid required | path | string | Strategy id or slug |
Responses
| Status | Description |
|---|---|
200 | What was released and filled |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/backlog/fill
Fill open calendar slots from every active strategy's backlog now, as the 30-minute autopilot run does. 409 invalid_state without a cadence
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | What was filled |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Calendar
The saved content calendar, drafting its posts, and personal iCalendar feeds.
GET /v1/workspaces/{ws}/calendar
Every strategy's saved calendar with each post's draft status (?strategy= filters; an unknown strategy is a 404)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
strategy | query | string | Strategy id or slug |
Responses
| Status | Description |
|---|---|
200 | Calendar |
404 | not_found |
POST /v1/workspaces/{ws}/calendar/draft
Draft calendar posts now: item ids, or everything due through a date. Wallet, spend and concurrency limits stop the run early (`stopped`), they are not errors
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
item_ids | array of string | |
strategy | string | |
through | string | |
limit | integer | Default 5. |
Responses
| Status | Description |
|---|---|
200 | Nothing started |
202 | Started |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Autopilot
Automatic drafting, approval and publishing on the calendar's schedule.
PATCH /v1/workspaces/{ws}/autopilot
Owners: switch autopilot on or off, its timing, publishing on the date, and the backlog cadence ({per_day, days})
Scope: autopilot (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
enabled | boolean | |
lead_days | integer | |
per_run | integer | |
publish_on_date | boolean | |
publish_on_approval | boolean | |
destination_id | string | null | |
publish_time | string | |
cadence | object | null |
Responses
| Status | Description |
|---|---|
200 | Autopilot |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
GET /v1/workspaces/{ws}/autopilot/calendar-approval
What approving the calendar for autopilot would trust: every saved item with trusted, via (provenance or approval), its content hash (sha256) and who wrote it; ideas: open backlog ideas no person in the web app wrote, with a hash each; and plan_marks: strategies whose saved plan has an agent's unreviewed plan-wide change, with the sections and a hash to send back
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Calendar approval preview |
404 | not_found |
Generations
Asynchronous generation of articles, images, copy and strategies, and the kinds on offer.
GET /v1/kinds
Generator kinds and their input JSON Schemas
Scope: any (API key or session)
Responses
| Status | Description |
|---|---|
200 | Kinds |
401 | unauthorized |
GET /v1/workspaces/{ws}/generations
List generations (newest first)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
status | query | string | Workflow status, or several comma-separated (e.g. queued,running,needs_input). One of: queued, running, needs_input, ready_for_review, incomplete_budget, failed, cancelled, expired; an unknown one is a 400 |
review_status | query | "pending" | "changes_requested" | "approved" | "superseded" | |
kind | query | string | |
view | query | "awaiting_review" | "mine" | "assigned" | A review queue for the caller |
q | query | string | Search titles and briefs |
latest | query | "1" | One row per piece of content (its newest generation) |
strategy | query | string | Strategy id or slug (404 if unknown): generations whose input.plan.strategy is that strategy, i.e. drafted from its calendar. One-off generations belong to no strategy |
assignment | query | string | Calendar assignment id |
publishing | query | "scheduled" | "published" | "not_scheduled" | Where the content stands at its destinations: scheduled (soonest first), published (newest first) or not_scheduled |
cursor | query | string | next_cursor from the previous page (opaque) |
limit | query | integer |
Responses
| Status | Description |
|---|---|
200 | Page of generations |
400 | invalid_request |
401 | unauthorized |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/generations
Create a generation
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Idempotency-Key | header | string | Retry safely for 7 days: the same key and body replays the original result (200); a different body is 409 idempotency_conflict |
Request body
| Name | Type | Description |
|---|---|---|
kind required | string | |
input | object | Default {}. |
Responses
| Status | Description |
|---|---|
200 | Idempotent replay of the original result (replayed true) |
202 | Accepted: the generation is queued (replayed false) |
400 | invalid_request |
401 | unauthorized |
402 | insufficient_funds (the wallet or credit balance is too low) or plan_required (the workspace needs a plan or add-on for this; details.feature). Both carry details.billing_url |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
422 | Unprocessable (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
GET /v1/workspaces/{ws}/generations/{id}
Generation with events, versions and the content item's version history
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Generation |
404 | not_found |
POST /v1/workspaces/{ws}/generations/{id}/inputs
Answer a needs_input generation
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
answers required | object |
Responses
| Status | Description |
|---|---|
202 | Resuming |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/generations/{id}/cancel
Cancel a queued, running or waiting generation
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Cancelled |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Versions
The versions a generation produces: manifests, files, exports and revisions.
GET /v1/workspaces/{ws}/versions/{vid}
Version manifest, review summary and 15-minute file URLs
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
vid required | path | string | |
text | query | "1" |
Responses
| Status | Description |
|---|---|
200 | Version |
404 | not_found |
GET /v1/workspaces/{ws}/versions/{vid}/diff
Compare this version with an earlier one (`from`), as wavefront_diff_versions does: a unified diff of the article or copy text and the metadata.json keys that changed
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
vid required | path | string | |
from required | query | string | The earlier version's id |
Responses
| Status | Description |
|---|---|
200 | The comparison |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/versions/{vid}/export
Export an article version as clean HTML, Markdown with front matter, portable JSON or a zip. Approved versions for any reader; a draft needs the edit permission (owner or editor session, or a key with generations:write), else 409 not_approved. Images are absolute media URLs; a draft's are 15-minute signed links (x-wavefront-images-expire-at)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
vid required | path | string | |
format | query | "html" | "md" | "json" | "zip" | Default html |
jsonld | query | "1" | html: append the JSON-LD script |
body_only | query | "1" | html, md: leave out the H1 and hero |
front_matter | query | string | md and zip: `none`, or comma-separated `field` or `field:key` (key renames it). Fields: title, h1, slug, seo_title, meta_description, canonical_url, excerpt, date, author, author_url, author_bio, author_job_title, categories, tags, hero_image, hero_alt, version_id, subtitle, keywords, sources, content_type, updated_at |
download | query | "1" | Send as an attachment |
Responses
| Status | Description |
|---|---|
200 | The export (zip: article.html, article.md, article.json, images/) |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/versions/{vid}/revisions
Request a revision (creates the next version)
Specific, local fixes (a corrected figure, a swapped link, a sentence added, removed or reworded) edit the version in place: one edit call, a fact check of the changed sentences only, the parent's images kept. A new angle, structure, section or length reruns the full pipeline. `mode` forces either; the mode used is in the new version's review.json `revision`
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
vid required | path | string | |
Idempotency-Key | header | string | Retry safely for 7 days: the same key and body replays the original result (200); a different body is 409 idempotency_conflict |
Request body
| Name | Type | Description |
|---|---|---|
feedback required | string | |
mode | "auto" | "targeted" | "rewrite" | auto (default): decided from the feedback. targeted: edit the version in place (local fixes; no outline, draft or images). rewrite: rerun the full pipeline Default auto. |
Responses
| Status | Description |
|---|---|
200 | Idempotent replay (replayed true) |
202 | Revision started |
400 | invalid_request |
402 | insufficient_funds (the wallet or credit balance is too low) or plan_required (the workspace needs a plan or add-on for this; details.feature). Both carry details.billing_url |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/versions/{vid}/apply
Apply an approved strategy version to the workspace context
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
vid required | path | string |
Responses
| Status | Description |
|---|---|
200 | Context version created |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/contents/{contentId}/versions
Every version of a piece of content, across its revisions
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
contentId required | path | string |
Responses
| Status | Description |
|---|---|
200 | Versions |
404 | not_found |
Reviews & comments
Review requests, approval decisions and the comment thread on a piece of content.
PATCH /v1/workspaces/{ws}/generations/{id}
Ask an owner or editor to review, or clear the request. The reviewer gets an email (at most one per generation per 10 minutes)
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
assignee_id required | string | null |
Responses
| Status | Description |
|---|---|
200 | Generation |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/generations/{id}/comments
The review thread for this content item, across revisions
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Comments |
404 | not_found |
POST /v1/workspaces/{ws}/generations/{id}/comments
Comment (any member; keys need generations:write)
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string | |
Idempotency-Key | header | string | Retry safely for 7 days: the same key and body replays the original result (200); a different body is 409 idempotency_conflict |
Request body
| Name | Type | Description |
|---|---|---|
body required | string | |
version_id | string |
Responses
| Status | Description |
|---|---|
200 | Idempotent replay |
201 | Comment |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
DELETE /v1/workspaces/{ws}/generations/{id}/comments/{cid}
Delete a comment (its author, or an owner)
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string | |
cid required | path | string |
Responses
| Status | Description |
|---|---|
204 | Deleted |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/versions/{vid}/approve
Approve or request changes
Owners and editors in a web session, or an API key with the opt-in approve scope. A key's decision is recorded with via api_key, the key as the actor and the person who created it as the approver. A version with blockers can't be approved (409 invalid_state), a superseded one can't be decided on, and the approval is bound to the package's manifest SHA-256 (409 approval_mismatch if the stored package changed)
Scope: approve (or an owner or editor session)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
vid required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
decision required | "approved" | "changes_requested" | |
note | string | |
manifest_sha256 | string | The version's manifest_sha256 as you reviewed it; a different one is 409 approval_mismatch |
Responses
| Status | Description |
|---|---|
200 | Decision recorded |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Publishing
Publishing approved versions to destinations, and withdrawing them.
POST /v1/workspaces/{ws}/versions/{vid}/publish
Publish an approved version to a destination
Scope: publish
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
vid required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
destination_id required | string | |
mode | "publish" | "draft" | "schedule" | |
publish_at | string (date-time) | |
send_newsletter | boolean | |
image_version_id | string |
Responses
| Status | Description |
|---|---|
202 | Publication queued |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/publications
Publications, newest first
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
status | query | "queued" | "sending" | "building" | "verifying" | "published" | "draft_created" | "scheduled" | "failed" | … | |
state | query | "queued" | "sending" | "building" | "verifying" | "published" | "draft_created" | "scheduled" | "failed" | … | Generic state; matches legacy statuses too, so published includes staged |
destination_id | query | string | |
content_id | query | string | Every publication of one content item across its versions |
cursor | query | string | next_cursor from the previous page |
limit | query | integer |
Responses
| Status | Description |
|---|---|
200 | Page of publications |
400 | invalid_request |
404 | not_found |
GET /v1/workspaces/{ws}/publications/{id}
Publication status and receipt
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Publication |
404 | not_found |
Schedules
Publishing an approved version at a set time or on its calendar date.
GET /v1/workspaces/{ws}/schedules
Schedules by publish time: active ones, or all with state=all
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
state | query | "active" | "all" | |
content_id | query | string | |
from | query | string (date-time) | publish_at at or after |
to | query | string (date-time) | publish_at before |
limit | query | integer |
Responses
| Status | Description |
|---|---|
200 | Schedules |
400 | invalid_request |
404 | not_found |
POST /v1/workspaces/{ws}/schedules
Schedule an approved version to publish at publish_at, or on its calendar date (on_calendar_date, at time in the workspace's time zone). Native where the destination schedules posts itself; otherwise Wavefront starts it within 5 minutes of the time. 409 schedule_exists when the content already has one there; 409 copy_rejected when the destination's copy_rules would refuse the version
Scope: publish
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
version_id required | string | |
destination_id required | string | |
mode | "publish" | "draft" | |
publish_at | string (date-time) | |
on_calendar_date | boolean | |
time | string |
Responses
| Status | Description |
|---|---|
201 | Scheduled |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/schedules/{id}
A schedule, its publication and its events
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Schedule |
404 | not_found |
PATCH /v1/workspaces/{ws}/schedules/{id}
Move a schedule to a new time; a post the destination holds gets the new time there (an update)
Scope: publish
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
publish_at | string (date-time) | |
on_calendar_date | boolean | |
time | string | |
version_id | string |
Responses
| Status | Description |
|---|---|
200 | Rescheduled |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/schedules/{id}/cancel
Cancel a schedule before its time. A post the destination holds is deleted there (or made a draft where it can't delete); 409 manual_withdraw_required when it can do neither
Scope: publish
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Cancelled |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Destinations
Where content is published (CMSs, sites, webhooks), with their settings and encrypted secrets.
PUT /v1/workspaces/{ws}/destinations/{did}/indexnow
Turn IndexNow on or off for a destination (owner). The first time, a key is generated; the site must host /<key>.txt
Scope: destinations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
did required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
enabled required | boolean |
Responses
| Status | Description |
|---|---|
200 | IndexNow setting and key file instructions |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
PATCH /v1/workspaces/{ws}/destinations/{did}
Edit a destination's name, config (replaced whole; refused while publishing to it), default_mode or secret (owner). Pointing a URL or host field somewhere new needs the whole secret again. When config.copy_rules change, waiting schedules to it are checked against them at once; the answer carries copy_recheck {checked, refused, cleared}
Scope: destinations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
did required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
name | string | |
config | object | |
default_mode | "publish" | "draft" | "schedule" | |
secret | object | |
oauth_grant | string |
Responses
| Status | Description |
|---|---|
200 | Updated |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/destinations/{did}/secret
Rotate a destination's secret (owner): typed fields replace stored ones, or an OAuth grant replaces it all. Never returned
Scope: destinations (or an owner session); owners are emailed when a key adds or redirects a destination
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
did required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
secret | object | |
oauth_grant | string |
Responses
| Status | Description |
|---|---|
200 | Rotated |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/destinations/types
Destination types this deployment can set up: label, icon, capabilities, config and secret JSON Schemas, field help, OAuth and mapping steps
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Types |
404 | not_found |
POST /v1/workspaces/{ws}/destinations/test
Test a destination's settings before saving (owner): runs the adapter's test; 200 with ok, or the stage that failed and why
Scope: destinations (or an owner session); owners are emailed when a key adds or redirects a destination
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
type | string | |
config | object | |
secret | object | |
oauth_grant | string | |
destination_id | string |
Responses
| Status | Description |
|---|---|
200 | Test result |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/destinations/mapping
The field-mapping step (owner): the adapter's targets and remote fields, and Wavefront's fields to map onto them
Scope: destinations (or an owner session); owners are emailed when a key adds or redirects a destination
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
type | string | |
config | object | |
secret | object | |
oauth_grant | string | |
destination_id | string |
Responses
| Status | Description |
|---|---|
200 | Mapping options |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/destinations/{did}/test
Send a test with the stored settings (owner). A webhook gets a signed ping event; returns ok, message and the delivery (status code, timing)
Scope: destinations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
did required | path | string |
Responses
| Status | Description |
|---|---|
200 | Test result |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
429 | Rate, spend or concurrency limit (details.retry_after) |
POST /v1/workspaces/{ws}/destinations/{did}/rotate-secret
A new signing secret for a webhook destination (owner), returned once. The old one also signs for 24 hours unless immediately is true
Scope: destinations (or an owner session); owners are emailed when a key adds or redirects a destination
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
did required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
immediately | boolean |
Responses
| Status | Description |
|---|---|
200 | New secret |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/destinations
List publishing destinations with each adapter's capabilities (secrets never returned)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Destinations |
404 | not_found |
POST /v1/workspaces/{ws}/destinations
Register a destination (owner) with a secret or an OAuth grant; secrets are encrypted at rest. default_mode defaults to draft where the adapter can. A webhook may send an empty secret: the response then carries signing_secret, once
Scope: destinations (or an owner session); owners are emailed when a key adds or redirects a destination
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
type required | string | |
name required | string | |
config required | object | |
secret | object | |
oauth_grant | string | |
default_mode | "publish" | "draft" | "schedule" |
Responses
| Status | Description |
|---|---|
201 | Created |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Imports
Importing documents into context from Google Drive, Notion and Confluence.
GET /v1/workspaces/{ws}/imports
Document import providers (Google Drive, Notion, Confluence) with whether this server has each set up and the workspace's connection, plus every import. Never the tokens; the account name only for sessions
Scope: context:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Providers and imports |
404 | not_found |
PATCH /v1/workspaces/{ws}/imports/{id}
Turn the daily resync on or off
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
resync required | "off" | "daily" |
Responses
| Status | Description |
|---|---|
200 | Import |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
DELETE /v1/workspaces/{ws}/imports/{id}
Stop tracking an import. Its documents stay
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
204 | Removed |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/imports/{id}/sync
Read the import's sources again now. state is updated (one new context version; restore the one before to undo), unchanged or busy. Documents are removed only when the source confirms they are gone
Scope: context:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Resync result |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
422 | Unprocessable (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
502 | Error |
Catalog
The site's catalog feed of products, listings or other entities that drafts can link to.
POST /v1/workspaces/{ws}/catalog/refresh
Refetch the site catalog feed now instead of waiting for catalog.refresh_hours. Returns url, fetched_at, cached, previous_fetched_at, entities per type, added, removed, skipped and problems. A copy younger than a minute is returned as is (cached: true), so repeated calls don't refetch. 409 invalid_state without a catalog; a feed that can't be read leaves the cache unchanged (503 misconfigured)
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | The refreshed copy |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
503 | Error |
Search data
Search Console, Analytics and Bing connections and the search performance they report.
GET /v1/workspaces/{ws}/google
The Search Console and Analytics connection: status, picked properties, last sync. Never the token; the Google email only for sessions
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Connection |
404 | not_found |
POST /v1/workspaces/{ws}/google/sync
Fetch fresh data now (data synced in the last 10 minutes is returned as is). The cron syncs daily
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Sync state |
403 | forbidden, or a missing API key scope (details.missing) |
409 | conflict (see the code) |
502 | Error |
GET /v1/workspaces/{ws}/bing
The Bing Webmaster Tools connection: status, picked site, last sync. Never the API key
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Connection |
404 | not_found |
POST /v1/workspaces/{ws}/bing/sync
Fetch fresh Bing data now (at most one try per 10 minutes: fresh, or too_soon after a failed try). The cron syncs daily
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Sync state |
403 | forbidden, or a missing API key scope (details.missing) |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
502 | Error |
GET /v1/workspaces/{ws}/search-performance
The last syncs: Search Console totals, queries and pages, Analytics totals, landing pages, channels and sources (site-wide and per landing page, with AI assistants), each with the prior 28 days; Bing totals, queries and pages over the latest 4 weeks against the 4 before; and opportunities from both engines
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
limit | query | integer | Rows per list (default 50) |
Responses
| Status | Description |
|---|---|
200 | Search performance |
404 | not_found |
GET /v1/workspaces/{ws}/search-performance/page
One page's Search Console, Analytics and Bing numbers, its top Google queries, where its Analytics sessions come from (AI assistants and search engines by name), a Search Console URL Inspection link, and report: the page's pages-report row (visits by source, AI visits and citations, the Wavefront article), or null
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
url required | query | string (uri) |
Responses
| Status | Description |
|---|---|
200 | Page performance |
400 | invalid_request |
404 | not_found |
GET /v1/workspaces/{ws}/pages-report
How each page is found: one row per page joining Search Console (clicks, position, top queries), Bing, Analytics sessions by source group with AI assistants and search engines by name, AI visits (a floor) and AI citations once measured, and whether Wavefront published it. found_by lists what brings each page traffic, most first. totals, counts per filter and sources_present (which data exists) come with every page
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
sort | query | "sessions" | "google_clicks" | "search_clicks" | "ai_visits" | "ai_citations" | "change" | Default sessions with Analytics, google_clicks with Search Console, else search_clicks (Google plus Bing, each over its own window). change ranks by share, biggest losses first |
filter | query | "published" | "ai" | "ai_visits" | "cited" | "declining" | published: Wavefront published it; ai: AI visits or citations; declining: lost at least 20% of its traffic |
limit | query | integer | Rows per page (default 50) |
cursor | query | string | next_cursor from the previous page, with the same sort and filter. 400 once the data has been synced again |
Responses
| Status | Description |
|---|---|
200 | Pages report |
400 | invalid_request |
404 | not_found |
Site metrics
Site authority and visibility metrics over time.
GET /v1/workspaces/{ws}/site-metrics
Site authority and visibility metrics with history: each provider's state (on, off with what turns it on for owners, or error), and each metric with its definition, latest, previous and baseline values, changes and points for the workspace's registrable domain. ?metrics= (comma-separated ids), ?from= and ?to= (YYYY-MM-DD) narrow the points
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
metrics | query | string | Comma-separated metric ids (tranco.rank,gsc.clicks) |
from | query | string (date) | First day of points |
to | query | string (date) | Last day of points |
Responses
| Status | Description |
|---|---|
200 | Site metrics |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/site-metrics/refresh
Queue a check of every free provider, and keyed ones that are due (never twice in their month). Answers 202 with state queued and the current site_metrics; GET …/site-metrics shows checking: true until the check is done. Once every 10 minutes (429 rate_limited with retry_after); 409 conflict while a check runs
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
202 | Queued |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
AI visibility
What counts as the brand in AI answers, the competitors and the questions AI assistants are asked.
GET /v1/workspaces/{ws}/ai-visibility/imports
The latest imported AI report per source: Search Console's Generative AI report (AI Overviews and AI Mode impressions, one number) and Bing's AI Performance report (Copilot citations, grounding queries). Each has its period, totals, the count of values the report left unknown, and the top 5 pages (and queries); null when nothing was imported
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Imports |
404 | not_found |
POST /v1/workspaces/{ws}/ai-visibility/imports
Import an export of Search Console's Generative AI report or Bing's AI Performance report (multipart: source = search_console | bing, file = a CSV, the ZIP of CSVs Search Console exports, or an XLSX; up to 5 files, 5 MB in all; optional mapping JSON {table?, page | query, value}; Content-Length required). Pages on another registrable domain than the workspace's site are left out (other_site_rows), and an export with none on it is refused. Tables are recognised by their headers; when they aren't, the reply is 200 with needs_mapping, the tables and their columns, and nothing is stored. A value shown as ~ or - (exported by Search Console as 0) is unknown, not zero. The import replaces the source's previous one; 201 with its summary
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body (multipart/form-data)
None.
Responses
| Status | Description |
|---|---|
200 | Columns not recognised: needs_mapping |
201 | Imported |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
DELETE /v1/workspaces/{ws}/ai-visibility/imports/{source}
Delete a source's imported AI report
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
source required | path | "search_console" | "bing" |
Responses
| Status | Description |
|---|---|
204 | Deleted |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/ai-visibility/settings
What counts as the brand in AI answers: brand_terms (the defaults follow the profile's publisher name, the workspace name and the site domain's label until edited), domains (the site_url's registrable domain first), competitors, and the sampling settings: enabled, engines (with engines_available and how each is measured), cadence, phrasings
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Settings |
404 | not_found |
PATCH /v1/workspaces/{ws}/ai-visibility/settings
Owners and editors change brand_terms (null restores the defaults), domains and competitors (at most 10; domains are stored as registrable domains). enabled, cadence (weekly, biweekly, monthly), engines and phrasings (1 to 3) need an owner session (403 otherwise), because sampling uses credits; turning it on needs a plan (402 plan_required)
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
enabled | boolean | |
cadence | "weekly" | "biweekly" | "monthly" | |
engines | array of "chatgpt" | "gemini" | "google_ai_overview" | "google_ai_mode" | "perplexity" | "claude" | |
phrasings | integer | |
brand_terms | array of string | null | |
domains | array of string | |
competitors | array of object |
Responses
| Status | Description |
|---|---|
200 | Settings |
400 | invalid_request |
402 | insufficient_funds (the wallet or credit balance is too low) or plan_required (the workspace needs a plan or add-on for this; details.feature). Both carry details.billing_url |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/ai-visibility/questions
Tracked questions, active first: question, its extra phrasings, topic, source (strategy, search_console, manual), status, and branded (it names the brand, so it measures recall, not discovery). active and limit (50) count active questions
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
status | query | "active" | "paused" | Only this status |
Responses
| Status | Description |
|---|---|
200 | Questions |
400 | invalid_request |
404 | not_found |
POST /v1/workspaces/{ws}/ai-visibility/questions
Track a question (at most 300 characters), or several with {questions: [...]}. Questions are trimmed and checked for repeats; Wavefront writes 2 neutral rewordings unless phrasings are given. One question answers 201 with question and phrasings_missing (true when Wavefront couldn't write its rewordings; edit them in), or 409 conflict when it's already tracked or 50 are active; several answer 201 with added, skipped (each with its reason) and phrasings_missing (ids)
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
question | string | |
topic | string | null | |
source | "strategy" | "search_console" | "manual" | |
phrasings | array of string | |
status | "active" | "paused" | |
questions | array of object |
Responses
| Status | Description |
|---|---|
201 | Added questions |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/ai-visibility/questions/suggest
Up to 20 questions to track, proposed from the strategy's pillar questions and high-priority keywords and from Search Console queries that are already questions, by impressions. Repeats, tracked questions, junk queries and questions naming the brand are left out. Nothing is saved
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
strategy | string | |
limit | integer |
Responses
| Status | Description |
|---|---|
200 | Suggestions |
400 | invalid_request |
404 | not_found |
GET /v1/workspaces/{ws}/ai-visibility/questions/{id}
One tracked question over the last 28 days: its mention, citation and top-3 citation rates overall and per engine (each with k, n, the 95% Wilson range low–high, and enough: n ≥ 10), competitors, the domains cited, and the latest answers (up to 60): engine and how it was measured, the wording asked, status (ok, no_answer, error), mentioned, cited, top3, the site's cited URLs with their rank, an excerpt of the answer and its sources (ours marked), and fan_out_queries (the searches engines ran, with how many answers and which engines). Stored answers are kept 90 days
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Question with its answers |
404 | not_found |
PATCH /v1/workspaces/{ws}/ai-visibility/questions/{id}
Edit a question's wording (new phrasings are written unless given), phrasings, topic or status (active or paused; resuming past 50 active is 409)
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
question | string | |
topic | string | null | |
phrasings | array of string | |
status | "active" | "paused" |
Responses
| Status | Description |
|---|---|
200 | Question |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
DELETE /v1/workspaces/{ws}/ai-visibility/questions/{id}
Stop tracking a question
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
204 | Removed |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/ai-visibility
AI answer sampling results over the last 28 days: mention, citation and top-3 citation rates overall, per engine, per question and engine, and per competitor, each with k, n, the 95% Wilson range (low, high) and enough (n ≥ 10; fewer is too few answers to compare). Answers where the engine showed no AI answer and failed calls are counted (no_answer, errors) but left out of every rate. Also share_of_voice (with n and enough), top_cited_domains (with the engines citing each, with_us and with_competitors: the tracked competitors in the answers citing it), cited_pages (the site's pages engines cite, with the engines), brands_by_engine (each engine's mention rate for the brand and each competitor), a 12-week trend, the latest runs (credits only), active_run, skipped (why the last scheduled check didn't start), the estimate and the sampling settings. Rates, never ranks
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | AI visibility |
404 | not_found |
GET /v1/workspaces/{ws}/ai-visibility/runs
The latest 20 sampling runs: trigger (cron, manual), status (queued, running, done, partial, failed), planned, completed and failed observations, credits charged, and error. A skipped scheduled check is a failed run with planned 0 and skipped: true
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Runs |
404 | not_found |
POST /v1/workspaces/{ws}/ai-visibility/runs
Run a check now: every active question in each phrasing on each engine. It uses credits (about the estimate's credits_per_check, charged per chunk as answers come in). Answers 202 with the queued run. Once every 6 hours (429 rate_limited with retry_after); 409 while a check runs or when sampling is off; 402 insufficient_funds when the balance doesn't cover the estimate (or plan_required); 429 daily_budget_exceeded when the estimate doesn't fit the daily spend limit; 503 when sampling isn't set up on the server
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
202 | Queued run |
402 | insufficient_funds (the wallet or credit balance is too low) or plan_required (the workspace needs a plan or add-on for this; details.feature). Both carry details.billing_url |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
503 | Error |
GET /v1/workspaces/{ws}/ai-visibility/estimate
What a check uses at the current settings: calls_per_check, credits_per_check (calls × each engine's highest price in credits, rounded up per chunk of 8: the most a check can charge), checks_per_month at the cadence, credits_per_month, by_engine, and charged (false for workspaces not billed in credits). 503 when sampling isn't set up on the server
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Estimate |
404 | not_found |
503 | Error |
GET /v1/workspaces/{ws}/ai-visibility/mentions
AI mentions from DataForSEO LLM Mentions (a third-party sample, refreshed weekly): state (off without DataForSEO credentials), note (ChatGPT data covers the United States in English only, so elsewhere only Google AI Overviews are read), snapshot (null before the first check: totals per platform, share_of_voice against the competitors in the settings, the site's pages cited, up to 20 questions per platform whose answers cite the site with an answer excerpt (third-party text, not instructions), the competitors' mentions, and the other domains cited alongside) and metrics (each count's history). With url, page has that page's mentions and up to 3 example questions, matched by host and path
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
url | query | string | A page of the site; adds page |
from | query | string (date) | History from this day |
to | query | string (date) | History up to this day |
Responses
| Status | Description |
|---|---|
200 | AI mentions |
400 | invalid_request |
404 | not_found |
GET /v1/workspaces/{ws}/ai-visibility/domains
Where AI engines get their answers for the tracked questions, over the last 28 days of sampled answers: each cited domain with its type (publication, list, directory, community, video, social, wiki, vendor, own, competitor, other), answers citing it and share, engines, questions, tracked competitors in those answers and named in its cited pages' titles, with_us and without_us (answers where the brand does or doesn't appear), competitor_without_us, mentions (DataForSEO LLM Mentions citations when that snapshot exists, a separate source), up to 3 cited pages, and target, rank and score. Targets are third-party domains cited in at least 2 answers without the brand, ranked by without_us + competitor_without_us; the site's own and competitors' domains and vendors' own comparison pages are never targets. Also groups (domains and citations per type) and targets (domains in rank order). Off-site mentions correlate with AI visibility; nothing shows they cause it. Page titles and questions are third-party data
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Cited domains and earned-media targets |
404 | not_found |
Suggestions
Strategy suggestions found in the site's search data, to approve or dismiss.
GET /v1/workspaces/{ws}/suggestions
Strategy suggestions from the site's search data, open ones best first: type, title, why (evidence with its numbers and window), impact, the typed actions approval runs, status, and the result. counts by status and last_run_at
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
status | query | string | Comma-separated: proposed, approved, dismissed, done, failed, expired |
limit | query | integer | |
offset | query | integer |
Responses
| Status | Description |
|---|---|
200 | Suggestions |
400 | invalid_request |
404 | not_found |
GET /v1/workspaces/{ws}/suggestions/settings
Suggestion messages (weekly digest, immediate message for a large decay, email) and per-type auto-apply
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Settings |
404 | not_found |
GET /v1/workspaces/{ws}/experiments/refreshes
The holdout test for refreshes, intention to treat: every assigned page stays in its arm and both arms are measured 28 and 56 days after assignment. enabled, experiment_id, started_at, design (types, analysis, primary {metric: clicks, horizon: 56}, hold_days, hold_max_days, horizons, min_pages_per_arm 10, min_baseline 10, welch_below 30, resamples), arms (pages, measuring, complete; treatment pending, refreshed, not_refreshed; holdout held, contaminated), strata, primary (the one judged outcome), results (every metric at 28 and 56 days: clicks, impressions, ai_sessions compared as log ratios and reported as shares; mention_rate, citation_rate in points; n per arm, each arm's change, effect, low, high, method welch_t or bootstrap, verdict on the primary only, from sequential looks at 10, 20, 40 and 80 pages per arm with 98.75% intervals, kept once given: too_few_pages, interim, unbalanced_missing (the arms' missing shares differ by over 10 points), higher or lower with decided_look, no_detectable_effect at the last look; exploratory on every other row), looks (each recorded once and never changed), per_protocol (refreshed pages against untouched holdouts, exploratory), caveats, and every page with its arm, stratum, draw, adherence, hold_until, refreshed_at, baseline and outcomes (what couldn't be read is in missing)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Refresh test |
404 | not_found |
POST /v1/workspaces/{ws}/suggestions/detect
Run the detectors on the stored search data now (they also run after every Google and Bing sync). Within 10 minutes of the last run, returns 200 with state fresh and the open suggestions
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | What the run found |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/suggestions/{id}
One suggestion
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Suggestion |
404 | not_found |
PATCH /v1/workspaces/{ws}/suggestions/{id}
Edit a proposed suggestion's actions: the feedback text, the share, the ideas, which posts add links. Each action keeps its type and target; actions can be removed, not added
Scope: generations:write (or an owner or editor); what a key or agent approves never auto-approves
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
actions required | array of object |
Responses
| Status | Description |
|---|---|
200 | Suggestion |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/suggestions/{id}/approve
Approve (optionally with edited actions): Wavefront runs each action through the app's own functions (backlog ideas, revisions, links, plan keywords) and records the result; status becomes done or failed. An action that can't run (a revision already in progress, no budget, a limit) is recorded in result with its error code, and the response is still 200. Ideas and revisions carry the approver's provenance: a person's in the web app, a key's otherwise (never auto-approved). A failed one can be approved again. 409 when already decided
Scope: generations:write (or an owner or editor); what a key or agent approves never auto-approves
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
note | string | null | |
actions | array of object | |
edited_at | string | null |
Responses
| Status | Description |
|---|---|
200 | Suggestion with result |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/suggestions/{id}/dismiss
Dismiss a proposed (or failed) suggestion. The same finding isn't suggested again for 90 days
Scope: generations:write (or an owner or editor); what a key or agent approves never auto-approves
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
note | string | null |
Responses
| Status | Description |
|---|---|
200 | Suggestion |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
Webhooks
Event subscriptions that POST signed events to your URL when things happen in a workspace.
GET /v1/workspaces/{ws}/webhooks
Event subscriptions and the event types they can ask for. Never the signing secrets
Scope: webhooks (or an owner session)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Subscriptions |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/webhooks
Add a webhook: an https URL and the events to send. The response holds the whsec_ signing secret; it is not shown again
Scope: webhooks (or an owner session); subscribing also needs generations:read, and a key changes only subscriptions it created
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
url required | string | |
events required | array of "generation.ready_for_review" | "generation.review_requested" | "generation.needs_input" | "generation.failed" | "version.approved" | "version.changes_requested" | "publication.published" | "publication.failed" | … | |
description | string | null |
Responses
| Status | Description |
|---|---|
201 | Subscription and secret |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/webhooks/sample
Sample bodies for one event type, shaped like deliveries plus the webhook-id as id: the workspace's latest events of that type (source recent), or one made-up example (source example). Keys need generations:read too
Scope: webhooks (or an owner session)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
event required | query | "generation.ready_for_review" | "generation.review_requested" | "generation.needs_input" | "generation.failed" | "version.approved" | "version.changes_requested" | "publication.published" | "publication.failed" | … | |
limit | query | integer | A whole number from 1 to 10; anything else is 400 |
Responses
| Status | Description |
|---|---|
200 | Samples |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/webhooks/{id}
One subscription: status, events, failure run
Scope: webhooks (or an owner session)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Subscription |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
PATCH /v1/workspaces/{ws}/webhooks/{id}
Change the URL, events or description; enabled false pauses it, true turns it back on and clears its failures
Scope: webhooks (or an owner session); subscribing also needs generations:read, and a key changes only subscriptions it created
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Request body
| Name | Type | Description |
|---|---|---|
url | string | |
events | array of "generation.ready_for_review" | "generation.review_requested" | "generation.needs_input" | "generation.failed" | "version.approved" | "version.changes_requested" | "publication.published" | "publication.failed" | … | |
description | string | null | |
enabled | boolean |
Responses
| Status | Description |
|---|---|
200 | Subscription |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
DELETE /v1/workspaces/{ws}/webhooks/{id}
Delete a subscription and its delivery log
Scope: webhooks (or an owner session); subscribing also needs generations:read, and a key changes only subscriptions it created
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
204 | Deleted |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/webhooks/{id}/rotate-secret
Make a new signing secret (returned once). The old one also signs for 24 hours; another rotation in that time is 409
Scope: webhooks (or an owner session); subscribing also needs generations:read, and a key changes only subscriptions it created
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
200 | Subscription and secret |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/webhooks/{id}/test
Send a webhook.test event to this subscription now. Shares a per-workspace limit with redeliver (429)
Scope: webhooks (or an owner session); subscribing also needs generations:read, and a key changes only subscriptions it created
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string |
Responses
| Status | Description |
|---|---|
202 | Delivery |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
GET /v1/workspaces/{ws}/webhooks/{id}/deliveries
The delivery log, newest first, kept 30 days
Scope: webhooks (or an owner session)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string | |
limit | query | integer | |
cursor | query | string | next_cursor from the previous page |
Responses
| Status | Description |
|---|---|
200 | Deliveries |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
GET /v1/workspaces/{ws}/webhooks/{id}/deliveries/{did}
One delivery with the body sent and every attempt. Keys without generations:read get body null
Scope: webhooks (or an owner session)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string | |
did required | path | string |
Responses
| Status | Description |
|---|---|
200 | Delivery |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
POST /v1/workspaces/{ws}/webhooks/{id}/deliveries/{did}/redeliver
Send a finished delivery again: same webhook-id and body, a fresh retry schedule. 409 while it is still being sent or the subscription is off
Scope: webhooks (or an owner session); subscribing also needs generations:read, and a key changes only subscriptions it created
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
id required | path | string | |
did required | path | string |
Responses
| Status | Description |
|---|---|
202 | Delivery |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
Integrations
Slack, Microsoft Teams, Asana and Trello connections.
GET /v1/workspaces/{ws}/task-sync
Project tool sync: which tools this server offers and the workspace's Asana and Trello connections, with the picked project or board, task counts and the last sync. Never a token
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Connections |
404 | not_found |
POST /v1/workspaces/{ws}/task-sync/{provider}/sync
Queue a sync now. Saved plans, drafts, reviews and publishing queue one too, and the cron reconciles daily
Scope: generations:write
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
provider required | path | "asana" | "trello" |
Responses
| Status | Description |
|---|---|
200 | Skipped: a sync started in the last 30 seconds (too_soon) |
202 | Queued |
403 | forbidden, or a missing API key scope (details.missing) |
409 | conflict (see the code) |
GET /v1/workspaces/{ws}/slack
The Slack connection: team, channel, status (active, paused, reconnect), the messages it posts, reviewer DMs and recent deliveries. Never the token
Scope: integrations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Connection |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
PATCH /v1/workspaces/{ws}/slack
Choose which messages go to Slack, turn reviewer DMs on or off, or pause (enabled false) and resume
Scope: integrations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
events | array of "generation.ready_for_review" | "generation.review_requested" | "generation.needs_input" | "version.changes_requested" | "version.approved" | "publication.published" | "publication.failed" | "plan.ready" | … | |
dm_reviewers | boolean | |
enabled | boolean |
Responses
| Status | Description |
|---|---|
200 | Connection |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/slack/test
Post a test message to the connected channel now. Shares the per-workspace webhook send limit (429)
Scope: integrations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
202 | Delivery |
403 | forbidden, or a missing API key scope (details.missing) |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
GET /v1/workspaces/{ws}/microsoft-teams
The Microsoft Teams connection: the webhook URL's host and label, status (active, paused, reconnect), the messages it posts and recent deliveries. Never the URL
Scope: integrations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Connection |
403 | forbidden, or a missing API key scope (details.missing) |
404 | not_found |
PATCH /v1/workspaces/{ws}/microsoft-teams
Choose which messages go to Teams, set the label, or pause (enabled false) and resume
Scope: integrations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Request body
| Name | Type | Description |
|---|---|---|
events | array of "generation.ready_for_review" | "generation.review_requested" | "generation.needs_input" | "version.changes_requested" | "version.approved" | "publication.published" | "publication.failed" | "plan.ready" | … | |
enabled | boolean | |
label | string | null |
Responses
| Status | Description |
|---|---|
200 | Connection |
400 | invalid_request |
403 | forbidden, or a missing API key scope (details.missing) |
409 | conflict (see the code) |
POST /v1/workspaces/{ws}/microsoft-teams/test
Post a test card to Teams now. Shares the per-workspace webhook send limit (429)
Scope: integrations (or an owner)
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
202 | Delivery |
403 | forbidden, or a missing API key scope (details.missing) |
409 | conflict (see the code) |
429 | Rate, spend or concurrency limit (details.retry_after) |
Billing
The plan, the credit balance, credit estimates and public pricing.
GET /v1/pricing
Plans, packs and the trial, with posts a month from the trailing 30-day measured average credits per published post
Scope: none
Responses
| Status | Description |
|---|---|
200 | Pricing |
GET /v1/workspaces/{ws}/billing/balance
The balance alone: credits and plan, by billing mode
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Balance |
404 | not_found |
GET /v1/workspaces/{ws}/billing
The plan, credit balance and history (members)
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Billing |
401 | unauthorized |
404 | not_found |
GET /v1/workspaces/{ws}/billing/estimates
Credit estimates per kind before a run (credits workspaces): the trailing 30-day average and the most a run can hold
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
Responses
| Status | Description |
|---|---|
200 | Estimates |
401 | unauthorized |
404 | not_found |
GET /v1/workspaces/{ws}/billing/checkout/{session}
Confirm a Checkout session and return the updated balance
Scope: generations:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
ws required | path | string | Workspace slug |
session required | path | string |
Responses
| Status | Description |
|---|---|
200 | Fulfillment |
404 | not_found |
Account
You: your profile, browser sessions and invitations.
GET /v1/me
You: profile, memberships, pending invitations. For an API key: its id, scopes and workspace (id, slug, name)
Scope: any (API key or session)
Responses
| Status | Description |
|---|---|
200 | Me |
401 | unauthorized |
Web app only
These operations need a person signed in to the web app (they are marked x-session-only in the OpenAPI document). API keys and MCP tokens are refused. They are listed so you know what exists, not to call.
Show 60 web-app-only operations
| Operation | Summary |
|---|---|
POST /v1/workspaces | Create a workspace (web session) |
POST /v1/workspaces/{ws}/leave | Leave the workspace (the last active owner cannot) |
DELETE /v1/workspaces/{ws}/destinations/{did} | Remove a publishing destination (owner); refused while publishing to it |
POST /v1/workspaces/{ws}/destinations/oauth/start | Start connecting a destination with OAuth (owner, web session): returns the consent URL and a grant id |
GET /v1/workspaces/{ws}/destinations/oauth/{gid} | An OAuth connection you started: whether it connected, and the form it was started with (never the token) |
GET /v1/workspaces/{ws}/social/ayrshare | Social posting through Ayrshare (owner): whether this deployment offers it (and X), the workspace's profile, and the accounts linked to it |
POST /v1/workspaces/{ws}/social/ayrshare/link | A 5-minute Ayrshare page where the owner links the workspace's social accounts (owner, web session). The first call creates the workspace's Ayrshare profile |
PATCH /v1/me | Set your display name (web session) |
POST /v1/me/sessions/revoke-others | Sign out every other browser (web session) |
GET /v1/me/connections | The AI agents connected over MCP as you (web session): each OAuth grant with the client's name, scopes, when it was connected and when it expires. Never tokens |
DELETE /v1/me/connections/{id} | Disconnect an agent (web session): its access and refresh tokens stop working at once |
POST /v1/invitations/{ws}/accept | Accept an invitation sent to your address (web session) |
POST /v1/invitations/{ws}/decline | Decline an invitation sent to your address (web session) |
POST /v1/workspaces/{ws}/publications/{id}/withdraw | Withdraw a publication: the destination deletes the item, Wavefront confirms it is gone, then marks it withdrawn (owner session) |
POST /v1/workspaces/{ws}/publications/{id}/withdrawn | Mark a publication withdrawn after deleting it at the destination by hand, for destinations that can't delete (owner session) |
PATCH /v1/workspaces/{ws} | Rename the workspace (owner); the slug never changes |
GET /v1/workspaces/{ws}/members | List members (owner) |
POST /v1/workspaces/{ws}/members | Add a member by email (owner) |
PATCH /v1/workspaces/{ws}/members/{mid} | Change a member's role (owner) |
DELETE /v1/workspaces/{ws}/members/{mid} | Remove a member (owner) |
GET /v1/workspaces/{ws}/api-keys | List API keys (owner) |
POST /v1/workspaces/{ws}/api-keys | Create an API key (owner); the key is shown once |
DELETE /v1/workspaces/{ws}/api-keys/{kid} | Revoke an API key (owner) |
PATCH /v1/workspaces/{ws}/google | Pick the Search Console site and Analytics property to read (owner), then sync. null clears a pick |
DELETE /v1/workspaces/{ws}/google | Disconnect Google (owner): deletes the token and the synced data. token_revoked is false, with used_by_other_workspaces true, when another workspace still uses the account |
POST /v1/workspaces/{ws}/google/connect | Start connecting Google (owner, web session only). Returns the consent URL to send the browser to. Google's account chooser opens; login_hint preselects an account. Connecting a different account keeps the picks it can read |
GET /v1/workspaces/{ws}/google/accounts | The Google accounts you connected in workspaces you own (owner, web session only;): google_email, granted access and whether it's this workspace's. Never tokens |
POST /v1/workspaces/{ws}/google/account | Switch this workspace to one of your connected Google accounts without a new consent (owner, web session only;). Picks the account can read are kept with their data; others are cleared |
GET /v1/workspaces/{ws}/google/properties | Search Console sites and Analytics properties the connected account can read, with the likely site match |
POST /v1/workspaces/{ws}/bing | Connect Bing with a Bing Webmaster API key (owner, web session only). The key is checked with Bing, stored encrypted and never returned; answers with the verified sites to pick from |
PATCH /v1/workspaces/{ws}/bing | Pick the verified Bing site to read (only the owner who connected), then sync. null clears it |
DELETE /v1/workspaces/{ws}/bing | Disconnect Bing (owner): deletes the stored key and the synced Bing data |
GET /v1/workspaces/{ws}/bing/sites | Sites verified in the connected Bing Webmaster account, with the likely match for the workspace's site |
POST /v1/workspaces/{ws}/imports | Import a preview as one context version (web session; the person who previewed). Documents go under imported/<provider>/. resync daily re-reads the source each day. 409 context_read_only for Git-managed workspaces; 422 context_too_large past the document limit |
POST /v1/workspaces/{ws}/imports/preview | Dry run (web session; the person who connected the provider): reads and converts the picked files, pages, databases or spaces, and lists each document's path, size and status (new or skipped, with renamed_from when a path was taken). Nothing is written. The preview can be imported for an hour |
POST /v1/workspaces/{ws}/imports/{provider}/connect | Start connecting google_drive, notion or confluence (owner, web session only). Returns the consent URL. 503 when the server has no client for it |
DELETE /v1/workspaces/{ws}/imports/{provider}/connection | Disconnect a provider (owner). Its imports stop and are removed; imported documents stay |
GET /v1/workspaces/{ws}/imports/{provider}/browse | What the connected account shares (web session; the person who connected): Notion pages and databases, or Confluence spaces (and a space's pages with parent=<space id>). Google Drive files are picked in the Google Picker instead |
POST /v1/workspaces/{ws}/task-sync/{provider}/connect | Start connecting Asana (OAuth) or Trello (authorize page) as an owner in the web app. Returns {url} to send the browser to |
POST /v1/workspaces/{ws}/task-sync/trello | Finish connecting Trello with the token from the return URL's fragment and the state from its query (owner, the same browser that started) |
GET /v1/workspaces/{ws}/task-sync/{provider}/projects | Asana projects or Trello boards the connected account can see (only the owner who connected) |
PATCH /v1/workspaces/{ws}/task-sync/{provider} | Pick the project or board tasks go to (only the owner who connected), then sync. null stops syncing; links to tasks in an earlier project are forgotten |
DELETE /v1/workspaces/{ws}/task-sync/{provider} | Disconnect (owner): revokes the token and forgets the task links. Tasks already made stay in the tool |
PATCH /v1/workspaces/{ws}/suggestions/settings | Owners in the web app: digest weekly|off, urgent, email, auto_apply (types Wavefront carries out without asking; off by default), auto_apply_published (may revise published posts) and test_refreshes (the holdout test for refreshes; off by default) |
DELETE /v1/workspaces/{ws}/slack | Disconnect Slack: revokes the token and deletes the connection and its log |
POST /v1/workspaces/{ws}/slack/connect | Start Add to Slack (owner, web session only). Returns Slack's install URL, where the installer picks the channel |
PUT /v1/workspaces/{ws}/microsoft-teams | Connect Teams with a Workflows webhook URL (https on powerplatform.com or logic.azure.com), or replace the URL; the chosen messages are kept and it turns back on |
DELETE /v1/workspaces/{ws}/microsoft-teams | Disconnect Teams: deletes the stored URL and the connection's log |
POST /v1/workspaces/{ws}/members/{mid}/invite | Resend a pending invitation (owner) |
PATCH /v1/workspaces/{ws}/settings | Update spend and concurrency caps (owner; app-managed workspaces, 409 context_read_only for Git-managed ones) |
GET /v1/workspaces/{ws}/calendar/feed | Whether you have a calendar feed URL here (id, created_at, last_used_at). The URL itself is shown only when it's made |
POST /v1/workspaces/{ws}/calendar/feed | Make your secret iCalendar feed URL (GET /cal/<token>.ics; ?strategy= and ?published=0 narrow it). Making a new one revokes the old URL. Shown once |
DELETE /v1/workspaces/{ws}/calendar/feed | Turn your calendar feed URL off |
PATCH /v1/workspaces/{ws}/autopilot/approval | Owners in the web app: let autopilot approve its own calendar drafts with zero blockers, and request one automatic revision when they have blockers. API keys and MCP get 403 |
POST /v1/workspaces/{ws}/autopilot/calendar-approval | Owners in the web app: approve calendar items and backlog ideas for autopilot as they stand, each with the sha256 the preview showed, plus every plan_marks entry of their strategies. 409 conflict lists items or ideas that changed or are gone and unreviewed plan marks; nothing is recorded then. Writes autopilot_calendar_approved and emails owners. API keys, MCP and editors get 403 |
POST /v1/workspaces/{ws}/billing/checkout | Start a checkout top-up (owner session) |
POST /v1/workspaces/{ws}/billing/subscribe | Subscribe to the plan in checkout, monthly or annual (owner session) |
POST /v1/workspaces/{ws}/billing/packs | Buy a one-time credit pack in checkout (subscribers, owner session) |
POST /v1/workspaces/{ws}/billing/portal | Open the billing portal: change plan, cancel, card, invoices |
GET /v1/workspaces/{ws}/cost-report | What the workspace's posts cost, in credits (owners): per published post (its draft, revisions, failed revisions, retries and discarded drafts of its calendar item up to when it first went live, withdrawn later or not), per draft and revision (targeted or rewrite), per stage and call purpose, and the share of input read from or written to the prompt cache. ?from= and ?to= (YYYY-MM-DD, inclusive; 30 days by default) and ?kind= (article by default) |