Skip to content

Reference

alter webhooks

Register and operate the outbound webhook endpoints that receive approval lifecycle events.

An application can register HTTPS endpoints that Alter calls when a held request is created, decided, expires, executes or fails. These commands manage them. See Outbound webhooks for the event payloads and how to verify a delivery.

alter webhooks event-types --app <app-id-or-name>
alter webhooks list --app <app-id-or-name>
alter webhooks show --app <app-id-or-name> --endpoint <id>
alter webhooks create --app <app-id-or-name> --url <url> --events <types> [--description <text>] [--header-file <path|->] [--header "Name: value"]...
alter webhooks update --app <app-id-or-name> --endpoint <id> [--url <url>] [--events <types>] [--description <text>] [--enable | --disable] [--header-file <path|->] [--header "Name: value"]... | [--clear-headers]
alter webhooks delete --app <app-id-or-name> --endpoint <id> [--confirm <endpoint-id> | --yes]
alter webhooks rotate-secret --app <app-id-or-name> --endpoint <id> [--expire-previous] [--confirm <endpoint-id> | --yes]
alter webhooks test --app <app-id-or-name> --endpoint <id>
alter webhooks deliveries --app <app-id-or-name> --endpoint <id> [--status <status>] [--limit <n>] [--offset <n>]
alter webhooks resend --app <app-id-or-name> --endpoint <id> --delivery <id>
alter webhooks recover --app <app-id-or-name> --endpoint <id> --since <iso-8601>

Every command takes --app <id> (or the app’s name), or link a workspace / set ALTER_APP_ID.

Scopes: dashboard_app_webhooks:read for event-types, list, show and deliveries (show prints the full URL only to a token whose owner is an organization admin and that holds dashboard_app_webhooks:write or dashboard_app_webhooks:admin as well); dashboard_app_webhooks:write for update, test, resend and recover; dashboard_app_webhooks:admin for delete; and dashboard_app_webhooks:rotate for anything that returns the signing secret or points an endpoint somewhere new — create (which needs write as well), update --url (which needs write as well) and rotate-secret. rotate is literal-only: neither * nor dashboard_app_webhooks:* grants it, so type it at alter auth login --scopes .... A default alter auth login grants read and write but not rotate; when the token lacks it, create and update --url refuse before sending anything, exit 7, and print the full alter auth login --scopes ... command that keeps the default set and adds dashboard_app_webhooks:rotate.

Every command that changes an endpoint — create, update, delete, rotate-secret, test, resend and recover — is also admin-only: the token’s owner must be an organization admin at the time of the call, whatever scopes the token holds (the same rule as keys mint, and as GitHub’s admin:repo_hook). A member’s token gets a 403, exit 7, and the CLI prints webhook changes require an organization admin. The reads stay open to every member.

The event types an endpoint can subscribe to, the current payload api_version, and a payload_example.

Terminal window
alter webhooks event-types --app <app-id-or-name>

List the app’s endpoints: URL, subscribed events, whether each is enabled (and why not — consecutive_failures or continuous_failure when Alter disabled it), the failure counter and the last delivery time. The signing secret is never returned. On stderr the CLI prints how many of the app’s max_endpoints are registered and the auto-disable thresholds (brake: the consecutive failed messages and the days of failure after which Alter disables an endpoint), which the list carries beside its rows. Each url is redacted to its scheme, host and port plus the endpoint’s own id, with no path or query (https://hooks.example.com#ep_1a2b3c4d), and a host label that looks random is masked (https://***.m.pipedream.net#ep_1a2b3c4d). The row carries url_redacted: true. This is because a receiver URL can carry its own secret in the path or the host. The id suffix tells endpoints on the same host apart, and nothing derived from the URL is shown; show prints the full URL to a token that also holds dashboard_app_webhooks:write. The CLI notes this on stderr.

Terminal window
alter webhooks list --app <app-id-or-name>

One endpoint’s metadata, never its secret. The url is full (url_redacted: false) only when the token’s owner is an organization admin and the token holds dashboard_app_webhooks:write or dashboard_app_webhooks:admin — the caller that may change the endpoint. Any other token — one with only dashboard_app_webhooks:read, or one owned by a member, whatever its scopes — gets the same redacted url as list (url_redacted: true), and the CLI notes on stderr that the full URL needs an organization admin’s token holding dashboard_app_webhooks:write or dashboard_app_webhooks:admin. has_custom_headers says whether custom request headers are stored; their values are write-only.

Terminal window
alter webhooks show --app <app-id-or-name> --endpoint <endpoint-id>

Register an endpoint. The answer carries the endpoint’s signing secret in the signing_secret field — once. Store it where the receiver verifies deliveries; it cannot be retrieved later, only rotated.

FlagRequiredDescription
--url <url>yesAbsolute https:// URL of the receiver (at most 2048 characters; no embedded credentials, no ?query and no #fragment — a receiver credential or tenant id travels as a --header). Alter resolves and validates the host when it saves the endpoint and again on every delivery; a private, loopback or link-local address is refused.
--events <types>yesComma-separated, at least one of approval.requested, approval.decided, approval.expired, approval.executed, approval.failed. webhook.test is not subscribable: test delivers it to the endpoint whatever it subscribes to. An endpoint subscribed to nothing is refused locally (exit 2) and by the backend (webhook_event_types_required).
--description <text>noA label (at most 255 characters).
--header-file <path>noCustom request headers read from a file, or from stdin with -: one Name: value per line, blank lines ignored. This keeps header values (often receiver credentials) out of argv and shell history.
--header "Name: value"noA custom request header sent with every delivery — an Authorization header the receiver checks, a tenant id. Repeatable; combined with --header-file, at most 10 in all. The value lands in argv, so the CLI warns and --header-file is preferred.

A refused header is named by its position (--header #2, --header-file line 3) and, once its name is valid, by that name; its value is never printed. Header names are HTTP tokens (letters, digits and !#$%&'*+.^_`|~-), at most 128 characters, and a name may appear only once in any letter case. Host, Content-Type, Content-Length, Transfer-Encoding, Connection and the webhook-* names are reserved. A value is 1–1024 characters of visible ASCII, spaces and tabs; an empty value is refused (“header value must not be empty”). Headers are stored in Alter’s secret store and never shown again.

Terminal window
alter webhooks create --app <app-id-or-name> \
--url https://bot.example.com/alter/webhooks \
--events approval.requested,approval.decided,approval.expired \
--header-file /run/secrets/receiver-headers \
--output json > endpoint.json # the signing_secret field is in this file, once

An app may hold at most 10 endpoints: the CLI reads the list first and refuses at the limit with exit 5 before sending anything (the backend’s own refusal is webhook_endpoint_limit, a conflict, the same exit code).

Change the URL, the subscribed events or the description, replace or clear the custom headers, or enable / disable the endpoint. --enable and --disable are mutually exclusive, as are --header / --header-file and --clear-headers; --description "" clears the description. Changing --url re-points the endpoint, so it needs dashboard_app_webhooks:rotate as well as dashboard_app_webhooks:write. The CLI reads the token’s own scopes first and, when rotate is missing, refuses before sending anything; otherwise the backend’s refusal is printed. Either way the command exits 7 and names the missing scope. Re-enabling resets the failure counters: the next failure starts a new run.

Terminal window
alter webhooks update --app <app-id-or-name> --endpoint <endpoint-id> --events approval.decided,approval.failed
alter webhooks update --app <app-id-or-name> --endpoint <endpoint-id> --enable

Delete an endpoint. Its delivery history is deleted with it and cannot be recovered; pending deliveries to it are dropped; the signing secret and custom headers are removed from the secret store. The endpoint itself can be registered again (with a new secret). On a terminal the CLI states that and asks you to type the endpoint ID back; without one, pass --confirm <endpoint-id> (the same ID as --endpoint) or --yes, or the command exits 8. A --confirm that names another endpoint exits 2.

Terminal window
alter webhooks delete --app <app-id-or-name> --endpoint <endpoint-id> --confirm <endpoint-id>

Mint a new signing secret; the answer carries it in the signing_secret field — once — with previous_secret_valid_until. Deliveries during the following 24 hours carry a signature for each secret, so a receiver that verifies with either keeps working while the new one is rolled out. --expire-previous stops signing with the previous secret at once, with no overlap — for a secret that leaked; receivers still on it fail verification immediately. It is confirmed like delete: type the endpoint ID on a terminal, or pass --confirm <endpoint-id> or --yes. Two rotations racing each other are refused rather than silently overwriting: the loser exits 5 with webhook_rotation_conflict; read the endpoint and rotate again.

Terminal window
alter webhooks rotate-secret --app <app-id-or-name> --endpoint <endpoint-id> --confirm <endpoint-id> --output json

Queue a webhook.test event to the endpoint — delivered whatever events it subscribes to — and print its message_id and delivery_id. Follow it with deliveries. A disabled endpoint is refused before anything is queued (exit 5, naming disabled_reason and the code webhook_endpoint_disabled, the same code the backend’s own 409 carries): update --enable it first.

Terminal window
alter webhooks test --app <app-id-or-name> --endpoint <endpoint-id>

The endpoint’s delivery log, newest first: the event, the status (pending, delivered, exhausted, failed, skipped_disabled), the attempt count, the last HTTP status or typed error (status:503, transport:timeout, blocked:blocked_destination), the next attempt time while pending, and the delivery id resend takes. Response bodies are never stored.

Terminal window
alter webhooks deliveries --app <app-id-or-name> --endpoint <endpoint-id> --status exhausted
  • --status — filter by delivery status.
  • --limit / --offset — pagination (1–200 per page, default 50). When another page exists, the CLI prints the next --offset on stderr.

Queue a fresh delivery of one message (a new attempt row; the original keeps its history).

Terminal window
alter webhooks resend --app <app-id-or-name> --endpoint <endpoint-id> --delivery <delivery-id>

After an outage of the receiver: queue a fresh delivery of every message since --since whose latest delivery to this endpoint did not succeed. --since must be in the past. Bounded to 1,000 messages per call; the answer’s queued counts what was queued and next_since, when present, is the --since to pass on the next call.

Terminal window
alter webhooks recover --app <app-id-or-name> --endpoint <endpoint-id> --since 2026-11-01T00:00:00Z

An endpoint is disabled by Alter when 20 events in a row exhaust every delivery attempt with no success in between, or when every attempt has failed for 5 days: enabled turns false with disabled_reason set, the organization’s administrators are emailed, and an audit row webhook_endpoint.auto_disabled is written. Fix the receiver, update --enable, then recover what was missed.

Report an issue with this page

Necessary

Required for sign-in, security, authorization, and remembering your choices.

Always active

Analytics

Helps us understand which product and documentation features are useful.

Performance diagnostics

Uses performance tracing and privacy-masked session replay to diagnose problems.

You can change these choices at any time from Cookie settings.