List webhook subscriptions
Lists webhook subscriptions for the PAT's account.
Lists webhook subscriptions for the PAT's account. Includes both active (is_active=true) and soft-deleted (is_active=false) rows unless filtered.
Sort order is created_at DESC (newest first).
pagination.total counts rows matching the request's filters (account_id + source + is_active), ignoring limit/offset. Use it to determine whether further pages exist.
Never returns the plaintext secret. The plaintext was returned once in the POST 201 response and is unrecoverable from the API afterwards.
Endpoint
GET /api/v1/webhook-subscriptions
Authentication
Bearer Personal Access Token. See Authentication.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Page size (1–100, default 25). |
offset | integer | no | Page start (zero-based, default 0). |
source | enum ("zapier", "dashboard") | no | Filter by source class. |
is_active | boolean | no | Filter to active or soft-deleted rows. |
Example request
curl https://www.voicegram.io/api/v1/webhook-subscriptions \
-H "Authorization: Bearer vg_pat_<your-token>"
Responses
Subscription list with filter-aware pagination total
| Field | Type | Required | Description |
|---|---|---|---|
subscriptions | array of object | yes | |
subscriptions[].id | string (uuid) | yes | |
subscriptions[].url | string (uri) | yes | |
subscriptions[].secret_prefix | string | yes | First 12 characters of the HMAC secret (e.g. vg_whsec_012). Lets customers identify which subscription a logged signature came from without exposing the secret itself. |
subscriptions[].channel_id | string | null | yes | Null when the subscription fires for all channels. |
subscriptions[].channel_type | string | null | yes | Derived from channel_id at creation. Null when channel_id is null. Read-only; cannot be changed after creation. |
subscriptions[].source | enum ("zapier", "dashboard") | yes | |
subscriptions[].zapier_subscription_id | string | null | yes | Populated for source=zapier, null for source=dashboard. |
subscriptions[].is_active | boolean | yes | False once soft-deleted (via DELETE /api/v1/webhook-subscriptions/{id}) or auto-disabled after 5 consecutive failed events. |
subscriptions[].consecutive_failures | integer | yes | Number of consecutive events (full retry cycles) that have failed for this subscription. Resets to 0 on any 2xx delivery. Triggers auto-disable at 5. |
subscriptions[].last_delivery_at | string | null | yes | |
subscriptions[].last_success_at | string | null | yes | |
subscriptions[].last_error | string | null | yes | Most recent error excerpt for ops/support correlation. For URL-redirect failures this carries the literal redirect_blocked: <status> string surfaced by the manual-redirect SSRF guard. |
subscriptions[].created_at | string (date-time) | yes | |
subscriptions[].created_by_user_id | string | null | yes | Populated for source=dashboard rows (the dashboard user who created the row). Null for source=zapier rows because Zapier does not bind to a single human user. The OAuth-style token is account-scoped. |
pagination | object | yes | |
pagination.limit | integer | yes | |
pagination.offset | integer | yes | |
pagination.total | integer | yes | Total row count matching the request's filters (account + source + is_active), ignoring limit/offset. Use to decide whether further pages exist. |
Query parameters failed validation
| Field | Type | Required | Description |
|---|---|---|---|
error | enum ("invalid_token", "plan_required", "validation_error", "invalid_url", "invalid_channel_id", "not_found", "rate_limited", "limit_reached", "conflict", "internal_error") | yes | Stable error code. |
message | string | no | Human-readable error message. |
reason | string | no | Stable diagnostic enum string. Only set on invalid_url responses (e.g. url_must_be_https, url_resolves_to_private_host, url_must_not_contain_credentials). |
issues | array of object | no | Schema-validation issues. Only set on validation_error responses. Each entry has a path array and a message. |
{
"error": "validation_error",
"issues": [
{
"path": [
"limit"
],
"message": "Number must be less than or equal to 100"
}
]
}
The PAT is missing, malformed, expired, or revoked.
See Errors for the shared error response shape.
PAT is valid but the account is on the free plan.
See Errors for the shared error response shape.