Skip to content
UpVoiced Docs

API reference

Webhooks

Webhook endpoints, signing secrets, the delivery log, test sends and redelivery.

Set up the SDK client used in the examples

API key or Dashboard session:

import { UpVoiced } from '@upvoiced/sdk';

const apiKey = process.env['UPVOICED_API_KEY']; // uv_live_… (Settings → API keys)
const workspace = process.env['UPVOICED_WORKSPACE_ID']; // sent as X-Workspace
if (!apiKey || !workspace) throw new Error('Set UPVOICED_API_KEY and UPVOICED_WORKSPACE_ID.');
const upvoiced = new UpVoiced({ apiKey, workspace });

curl examples read $UPVOICED_API_KEY and $UPVOICED_WORKSPACE_IDfrom your shell. MCP examples are the tools/call request an MCP client sends to the MCP server with the same API key.

GET/v1/webhooks

Webhook endpoints with status and failure counts; never the secret (owner/admin)

Authentication
API key or Dashboard session; API key scope admin
Operation id
listWebhooks
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
Response 200: 18 fields
Response 200 (application/json)
NameTypeRequired
itemsarray of objectYes
items[].idstring (uuid)Yes
items[].urlstringYes
items[].descriptionstringYes
items[].eventsarray of stringYes
items[].board_idsarray of string (uuid)Yes
items[].activebooleanYes
items[].disabled_reason"consecutive_failures" | nullYes
items[].disabled_atstring (date-time) | nullYes
items[].consecutive_failuresintegervalue ≥ 0Yes
items[].secret_hintstringYes
items[].secret_rotated_atstring (date-time) | nullYes
items[].previous_secret_expires_atstring (date-time) | nullYes
items[].last_success_atstring (date-time) | nullYes
items[].last_failure_atstring (date-time) | nullYes
items[].created_atstring (date-time)Yes
items[].updated_atstring (date-time)Yes
next_cursornullYes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl 'https://api.upvoiced.com/v1/webhooks' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID"
TypeScript SDK
const data = await upvoiced.get('/v1/webhooks');
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

POST/v1/webhooks

Create an endpoint with an events filter and optional board filter; the signing secret is in this response only (webhooks.max)

Authentication
API key or Dashboard session; API key scope admin
Operation id
createWebhook
Idempotency
Send an Idempotency-Key to make retries safe.
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
idempotency-keystringpattern ^[A-Za-z0-9_.:-]{8,128}$No
Request body (JSON)
NameTypeRequired
urlstringlength ≤ 2048pattern ^https?:\/\/[^/?#@:\s]+(?:[/?][^#\s]*)?$Yes
events["*"] | array of "post.created" | "post.updated" | "post.status_changed" | "post.merged" | "post.deleted" | "comment.created" | "vote.created" | "vote.deleted" | "changelog.published" | "end_user.created" | "end_user.deleted"Yes
board_idsarray of string (uuid)items ≤ 50default []No
descriptionstringlength ≤ 200default ""No
activebooleandefault trueNo
Response 201: 17 fields
Response 201 (application/json)
NameTypeRequired
idstring (uuid)Yes
urlstringYes
descriptionstringYes
eventsarray of stringYes
board_idsarray of string (uuid)Yes
activebooleanYes
disabled_reason"consecutive_failures" | nullYes
disabled_atstring (date-time) | nullYes
consecutive_failuresintegervalue ≥ 0Yes
secret_hintstringYes
secret_rotated_atstring (date-time) | nullYes
previous_secret_expires_atstring (date-time) | nullYes
last_success_atstring (date-time) | nullYes
last_failure_atstring (date-time) | nullYes
created_atstring (date-time)Yes
updated_atstring (date-time)Yes
secretstring | nullpattern ^whsec_[0-9A-Za-z]{43}$Yes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl -X POST 'https://api.upvoiced.com/v1/webhooks' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/upvoiced",
  "events": [
    "*"
  ]
}'
TypeScript SDK
const data = await upvoiced.post('/v1/webhooks', {
  body: { url: 'https://example.com/upvoiced', events: ['*'] },
});
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

GET/v1/webhooks/{id}

One webhook endpoint (owner/admin)

Authentication
API key or Dashboard session; API key scope admin
Operation id
getWebhook
Path parameters
NameTypeRequired
idstring (uuid)Yes
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
Response 200: 16 fields
Response 200 (application/json)
NameTypeRequired
idstring (uuid)Yes
urlstringYes
descriptionstringYes
eventsarray of stringYes
board_idsarray of string (uuid)Yes
activebooleanYes
disabled_reason"consecutive_failures" | nullYes
disabled_atstring (date-time) | nullYes
consecutive_failuresintegervalue ≥ 0Yes
secret_hintstringYes
secret_rotated_atstring (date-time) | nullYes
previous_secret_expires_atstring (date-time) | nullYes
last_success_atstring (date-time) | nullYes
last_failure_atstring (date-time) | nullYes
created_atstring (date-time)Yes
updated_atstring (date-time)Yes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl 'https://api.upvoiced.com/v1/webhooks/0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID"
TypeScript SDK
const data = await upvoiced.get('/v1/webhooks/{id}', { path: { id: '0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' } });
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

PATCH/v1/webhooks/{id}

Change URL, events, boards, description or active; active=true re-enables an auto-disabled endpoint

Authentication
API key or Dashboard session; API key scope admin
Operation id
updateWebhook
Path parameters
NameTypeRequired
idstring (uuid)Yes
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
Request body (JSON)
NameTypeRequired
urlstringlength ≤ 2048pattern ^https?:\/\/[^/?#@:\s]+(?:[/?][^#\s]*)?$No
events["*"] | array of "post.created" | "post.updated" | "post.status_changed" | "post.merged" | "post.deleted" | "comment.created" | "vote.created" | "vote.deleted" | "changelog.published" | "end_user.created" | "end_user.deleted"No
board_idsarray of string (uuid)items ≤ 50No
descriptionstringlength ≤ 200No
activebooleanNo
Response 200: 16 fields
Response 200 (application/json)
NameTypeRequired
idstring (uuid)Yes
urlstringYes
descriptionstringYes
eventsarray of stringYes
board_idsarray of string (uuid)Yes
activebooleanYes
disabled_reason"consecutive_failures" | nullYes
disabled_atstring (date-time) | nullYes
consecutive_failuresintegervalue ≥ 0Yes
secret_hintstringYes
secret_rotated_atstring (date-time) | nullYes
previous_secret_expires_atstring (date-time) | nullYes
last_success_atstring (date-time) | nullYes
last_failure_atstring (date-time) | nullYes
created_atstring (date-time)Yes
updated_atstring (date-time)Yes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl -X PATCH 'https://api.upvoiced.com/v1/webhooks/0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/upvoiced"
}'
TypeScript SDK
const data = await upvoiced.patch('/v1/webhooks/{id}', {
  path: { id: '0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' },
  body: { url: 'https://example.com/upvoiced' },
});
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

DELETE/v1/webhooks/{id}

Delete an endpoint and its delivery log

Authentication
API key or Dashboard session; API key scope admin
Operation id
deleteWebhook
Path parameters
NameTypeRequired
idstring (uuid)Yes
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
Response 200: 1 fields
Response 200 (application/json)
NameTypeRequired
oktrueYes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl -X DELETE 'https://api.upvoiced.com/v1/webhooks/0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID"
TypeScript SDK
const data = await upvoiced.delete('/v1/webhooks/{id}', { path: { id: '0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' } });
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

POST/v1/webhooks/{id}/rotate-secret

New signing secret (in this response only); the previous one keeps signing for 24 hours

Authentication
API key or Dashboard session; API key scope admin
Operation id
rotateWebhookSecret
Idempotency
Send an Idempotency-Key to make retries safe.
Path parameters
NameTypeRequired
idstring (uuid)Yes
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
idempotency-keystringpattern ^[A-Za-z0-9_.:-]{8,128}$No
Response 200: 17 fields
Response 200 (application/json)
NameTypeRequired
idstring (uuid)Yes
urlstringYes
descriptionstringYes
eventsarray of stringYes
board_idsarray of string (uuid)Yes
activebooleanYes
disabled_reason"consecutive_failures" | nullYes
disabled_atstring (date-time) | nullYes
consecutive_failuresintegervalue ≥ 0Yes
secret_hintstringYes
secret_rotated_atstring (date-time) | nullYes
previous_secret_expires_atstring (date-time) | nullYes
last_success_atstring (date-time) | nullYes
last_failure_atstring (date-time) | nullYes
created_atstring (date-time)Yes
updated_atstring (date-time)Yes
secretstring | nullpattern ^whsec_[0-9A-Za-z]{43}$Yes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl -X POST 'https://api.upvoiced.com/v1/webhooks/0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d/rotate-secret' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID" \
  -H "Idempotency-Key: $(uuidgen)"
TypeScript SDK
const data = await upvoiced.post('/v1/webhooks/{id}/rotate-secret', { path: { id: '0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' } });
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

GET/v1/webhooks/{id}/deliveries

Delivery log, newest first (14-day retention): attempts, status code, duration, error, response snippet

Authentication
API key or Dashboard session; API key scope admin
Operation id
listWebhookDeliveries
Path parameters
NameTypeRequired
idstring (uuid)Yes
Query parameters
NameTypeRequired
status"pending" | "sending" | "succeeded" | "failed" | "canceled"No
cursorstringlength 1–512No
limitintegervalue 1–100default 25No
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
Response 200: 17 fields
Response 200 (application/json)
NameTypeRequired
itemsarray of objectitems ≤ 100Yes
items[].idstring (uuid)Yes
items[].webhook_idstring (uuid)Yes
items[].event_idstring | nullYes
items[].event_typestringYes
items[].kind"event" | "test" | "redelivery"Yes
items[].status"pending" | "sending" | "succeeded" | "failed" | "canceled"Yes
items[].attemptintegervalue ≥ 0Yes
items[].next_attempt_atstring (date-time) | nullYes
items[].status_codeinteger | nullvalue 100–599Yes
items[].response_msinteger | nullvalue ≥ 0Yes
items[].errorstring | nullYes
items[].response_snippetstring | nullYes
items[].payloadobjectYes
items[].created_atstring (date-time)Yes
items[].completed_atstring (date-time) | nullYes
next_cursorstring | nullYes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl 'https://api.upvoiced.com/v1/webhooks/0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d/deliveries' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID"
TypeScript SDK
const data = await upvoiced.get('/v1/webhooks/{id}/deliveries', { path: { id: '0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' } });
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

POST/v1/webhooks/{id}/test

Queue a signed webhook.test delivery to the endpoint (attempted once; 30/hour)

Authentication
API key or Dashboard session; API key scope admin
Operation id
testWebhook
Idempotency
Send an Idempotency-Key to make retries safe.
Path parameters
NameTypeRequired
idstring (uuid)Yes
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
idempotency-keystringpattern ^[A-Za-z0-9_.:-]{8,128}$No
Response 202: 15 fields
Response 202 (application/json)
NameTypeRequired
idstring (uuid)Yes
webhook_idstring (uuid)Yes
event_idstring | nullYes
event_typestringYes
kind"event" | "test" | "redelivery"Yes
status"pending" | "sending" | "succeeded" | "failed" | "canceled"Yes
attemptintegervalue ≥ 0Yes
next_attempt_atstring (date-time) | nullYes
status_codeinteger | nullvalue 100–599Yes
response_msinteger | nullvalue ≥ 0Yes
errorstring | nullYes
response_snippetstring | nullYes
payloadobjectYes
created_atstring (date-time)Yes
completed_atstring (date-time) | nullYes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl -X POST 'https://api.upvoiced.com/v1/webhooks/0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d/test' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID" \
  -H "Idempotency-Key: $(uuidgen)"
TypeScript SDK
const data = await upvoiced.post('/v1/webhooks/{id}/test', { path: { id: '0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' } });
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.

POST/v1/webhook-deliveries/{id}/redeliver

Replay a logged delivery with the same body and a fresh signature (attempted once; 30/hour)

Authentication
API key or Dashboard session; API key scope admin
Operation id
redeliverWebhookDelivery
Idempotency
Send an Idempotency-Key to make retries safe.
Path parameters
NameTypeRequired
idstring (uuid)Yes
Headers
NameTypeRequired
x-workspacestring (uuid)Yes
idempotency-keystringpattern ^[A-Za-z0-9_.:-]{8,128}$No
Response 202: 15 fields
Response 202 (application/json)
NameTypeRequired
idstring (uuid)Yes
webhook_idstring (uuid)Yes
event_idstring | nullYes
event_typestringYes
kind"event" | "test" | "redelivery"Yes
status"pending" | "sending" | "succeeded" | "failed" | "canceled"Yes
attemptintegervalue ≥ 0Yes
next_attempt_atstring (date-time) | nullYes
status_codeinteger | nullvalue 100–599Yes
response_msinteger | nullvalue ≥ 0Yes
errorstring | nullYes
response_snippetstring | nullYes
payloadobjectYes
created_atstring (date-time)Yes
completed_atstring (date-time) | nullYes

Errors: 400, 401, 403, 404, 409, 413, 422, 429, 500, 503, all in the standard error shape.

curl
curl -X POST 'https://api.upvoiced.com/v1/webhook-deliveries/0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d/redeliver' \
  -H "Authorization: Bearer $UPVOICED_API_KEY" \
  -H "X-Workspace: $UPVOICED_WORKSPACE_ID" \
  -H "Idempotency-Key: $(uuidgen)"
TypeScript SDK
const data = await upvoiced.post('/v1/webhook-deliveries/{id}/redeliver', { path: { id: '0190f5e2-4c1d-7a3b-8c2d-5e6f7a8b9c0d' } });
MCP

No MCP tool for this operation. The MCP server covers the everyday reads and writes.