API guides
Authentication
Every operator call carries an API key as a bearer token and names its workspace in X-Workspace. Keys are secrets: use them from your server, never from a browser or a mobile app.
curl https://api.upvoiced.com/v1/posts?limit=10 \
-H "Authorization: Bearer $UPVOICED_API_KEY" \
-H "X-Workspace: $UPVOICED_WORKSPACE_ID"Create a key
- In the dashboard, open Settings → API keys (owners and admins).
- Name the key, pick a scope and, optionally, an expiry of up to 366 days.
- Copy the key. It is shown once: UpVoiced keeps only a keyed hash. Production keys start with
uv_live_, keys of test environments withuv_test_, and neither works in the other environment. - Put your workspace id in
UPVOICED_WORKSPACE_ID: it is the Audience shown under Settings → Single sign-on.
Revoke a key on the same page; it stops working on the next request.
Scopes
Scopes are cumulative: admin includes write, which includes read.
| Scope | Allows | Operations |
|---|---|---|
read | Every read (GET). | 31 |
write | Creating and changing posts, comments, notes, votes, changelog entries and other content. | 36 |
admin | Workspace configuration: settings, SSO settings, members and invitations, branding, boards, statuses and tags, billing changes, webhooks, imports and exports. | 70 |
Each operation in the API reference names the scope it needs. A key without it gets 403 insufficient_scope before anything runs:
HTTP/1.1 403 Forbidden
{
"error": {
"code": "insufficient_scope",
"message": "This API key needs the write scope.",
"details": [{ "path": "scope", "code": "write" }]
}
}The workspace header
Send X-Workspace: <workspace id> on every workspace call. A key belongs to the workspace it was created in. A key created with All workspaces I administer is operator-wide: it can name any workspace its creator administers. A key bound to one workspace that names another gets 403 workspace_not_allowed.
A key acts as the person who created it. If that person leaves the workspace or stops being an owner or admin, the key stops working there. Keys without the admin scope act with member permissions.
Dashboard-only operations
Some operations need a signed-in person in the dashboard and refuse every key with 403 session_required: managing API keys (a leaked key can never mint a replacement), creating or deleting a workspace, accepting invitations and rotating the SSO secret. They are marked “Dashboard session only” in the reference:
GET /v1/workspacesPOST /v1/workspacesPOST /v1/invitations/acceptPOST /v1/workspace/switchPOST /v1/workspace/sso/rotatePOST /v1/workspace/deletionGET /v1/api-keysPOST /v1/api-keysDELETE /v1/api-keys/{id}PUT /v1/ai/credentials/anthropicDELETE /v1/ai/credentials/anthropicPOST /v1/ai/credentials/openrouter/connectPOST /v1/ai/credentials/openrouter/callbackDELETE /v1/ai/credentials/openrouter
Plans
On the Free plan keys are read-only: write calls answer 403 plan_required, also for keys created before a downgrade. The number of keys per workspace depends on the plan.
Other callers
- Public reads (Public portal API) need no credentials:
X-Workspace: <slug>picks the workspace and only public content is returned. - The widget (Widget API) uses an end-user session. To sign your own users in, see single sign-on.
- MCP clients use the same API keys: see the MCP server.
Authentication failures
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated | No key, an unknown, revoked or expired key, or a key of another environment. |
| 403 | insufficient_scope | The key’s scope is too low for the operation. |
| 403 | workspace_not_allowed | A workspace-bound key named another workspace. |
| 403 | session_required | The operation is Dashboard-only. |
| 403 | plan_required | The plan does not allow it (for example writes on Free). |