CLI reference

Every hookchat command with its usage, flags and examples, generated from docs/cli/reference.md (itself written by hookchat docs generate). Install the binary from the downloads page.

Global flags#

These flags are accepted by every command.

FlagTypeDefaultDescription
--api-keystringAPI key (hookchat_live_... or hookchat_test_...); overrides HOOKCHAT_API_KEY and the profile
--base-urlstringAPI origin; overrides HOOKCHAT_BASE_URL and the profile (default https://hookchat.dev)
--no-colorbooldisable colour even when stdout is a terminal
-o, --outputstringtableoutput format: table, json or yaml
--profilestringconfig profile to use; overrides HOOKCHAT_PROFILE (default "default")
-q, --quietboolprint only ids or values, nothing else on success
--tenantstringtenant slug, required for an operator key; overrides HOOKCHAT_TENANT and the profile
--timeoutduration30sper-request timeout

Commands#

hookchat#

The HookChat command line: Instagram and Messenger DMs as webhooks

Usage
hookchat [command]

hookchat is the command line for the HookChat API. Every /v1 resource has a command: keys, webhooks and their deliveries, conversations, messages, accounts, the audit trail, stats and realtime tickets. It also verifies captured webhook deliveries offline and manages login profiles.

Authentication resolves in this order: the --api-key, --base-url and --tenant flags, then the HOOKCHAT_API_KEY, HOOKCHAT_BASE_URL and HOOKCHAT_TENANT environment variables, then the profile selected by --profile or HOOKCHAT_PROFILE (or the default profile) in the config file written by "hookchat auth login". The config file lives at $HOOKCHAT_CONFIG_DIR/config.json or <user config dir>/hookchat/config.json and is created with mode 0600.

Output is a table by default. --output json prints the API resource (a list is a JSON array, or {"items": [...], "next_cursor": "..."} when a page follows) and --output yaml prints the same shape as YAML. --quiet prints only ids, or the secret for keys create, webhooks create and webhooks rotate. Colour is used only when stdout is a terminal, NO_COLOR is unset and --no-color is not given.

Exit codes
0   success
1   unexpected error
2   usage error: unknown command, flag or argument
3   authentication: unauthorized, forbidden, tenant_required, or no API key configured
4   not found: conversation, message, endpoint, key or delivery
5   invalid_request: a malformed body or parameter
6   send policy: window_closed, human_agent_unavailable or missing_actor
7   rate_limited: the send budget is exhausted or the gateway returned 429
8   send_failed or replay_conflict
9   webhook signature verification failed (verify)
10  network error, timeout or a 5xx without an error envelope
Examples
# Check the gateway and your credentials
hookchat auth login --api-key hookchat_test_... --tenant acme
hookchat ping

# Register a webhook and capture its secret
hookchat webhooks create --url https://example.com/hookchat --output json

# Reply inside the 24 hour window
hookchat messages reply --conversation "CONV#acme#instagram#1#2" --text "On it"

Subcommands

hookchat accounts#

List the tenant's linked channel accounts

Usage
hookchat accounts [command]

The Instagram and Messenger accounts linked to the tenant, with their credential health. An account with a refresh_error needs relinking in the console.

Examples
# Linked accounts
hookchat accounts list

# Only the account keys
hookchat accounts list --quiet

Subcommands

hookchat accounts list#

List linked accounts and their credential health

Usage
hookchat accounts list

Calls GET /v1/accounts. The list is not paginated. Each row carries the platform, the external id, the handle, the status (active, disabled or error) and the last refresh error, if any.

Examples
# Linked accounts as a table
hookchat accounts list

# Find accounts that need relinking
hookchat accounts list --output json | jq '.[] | select(.refresh_error)'

hookchat audit#

Read the tenant's audit trail

Usage
hookchat audit [command]

The audit trail records every administrative action on the tenant: key creation and revocation, webhook changes, replays and sends. Entries never carry message content, tokens or secrets.

Examples
# The most recent 50 entries
hookchat audit list

# Everything, as JSON
hookchat audit list --all --output json

Subcommands

hookchat audit list#

List audit entries, most recent first

Usage
hookchat audit list [flags]

Calls GET /v1/audit. One page is printed by default; the next_cursor goes to stderr in table mode and into the JSON or YAML envelope otherwise. --all walks every page.

Examples
# One page of 20
hookchat audit list --limit 20

# Continue from a cursor
hookchat audit list --cursor eyJ...

# Every entry
hookchat audit list --all

Flags

FlagTypeDefaultDescription
--allboolwalk every page instead of printing one page and its next_cursor
--cursorstringresume from a previous next_cursor
--limitint50page size, 1 to 100 (with --all, the page size used while walking)

hookchat auth#

Log in, inspect and remove credential profiles

Usage
hookchat auth [command]

Profiles store an API key, a base URL and a tenant in the config file so the other commands need no flags. The file is $HOOKCHAT_CONFIG_DIR/config.json or <user config dir>/hookchat/config.json, created with mode 0600. A profile is selected with --profile or HOOKCHAT_PROFILE; "default" is used otherwise. Flags and environment variables always override a profile.

Examples
# Store a key as the default profile
hookchat auth login --api-key hookchat_test_... --tenant acme

# Keep a second workspace in its own profile
hookchat auth login --profile acme --tenant acme --api-key hookchat_live_...
hookchat --profile acme ping

Subcommands

hookchat auth login#

Validate an API key and store it as a profile

Usage
hookchat auth login [flags]

Reads the key from --api-key, or from standard input when the flag is absent (a prompt is shown when stdin is a terminal, so the key never lands in shell history). The key and base URL are validated with a ping, then written to the profile named by --profile (default "default") together with --base-url and --tenant. The first profile written becomes the default profile; pass --set-default to make any later profile the default.

The full key is never printed; status shows a masked prefix only.

Examples
# Store the key with a tenant
hookchat auth login --api-key hookchat_live_... --tenant acme

# Read the key from a secret manager without echoing it
op read op://vault/hookchat/key | hookchat auth login --tenant acme

# A second workspace profile, made the default
hookchat auth login --profile acme --tenant acme --set-default

Flags

FlagTypeDefaultDescription
--set-defaultboolmake this profile the default profile

hookchat auth logout#

Remove a profile from the config file

Usage
hookchat auth logout

Deletes the profile named by --profile (or HOOKCHAT_PROFILE, or the default profile) from the config file. The key itself is not revoked; use "hookchat keys revoke" for that. Removing the default profile makes the next remaining profile the default.

Examples
# Remove the default profile
hookchat auth logout

# Remove a named profile
hookchat auth logout --profile acme

hookchat auth status#

Show the active profile and ping the gateway

Usage
hookchat auth status

Shows which profile is active, where the key came from (flags, environment or the profile), the masked key prefix, the base URL and the tenant, then pings the gateway. The exit code follows the ping, so status doubles as a health check in scripts.

Examples
# Human readable status
hookchat auth status

# Machine readable, including the ping result
hookchat auth status --output json

hookchat completion#

Print a shell completion script

Usage
hookchat completion bash|zsh|fish|powershell

Prints a completion script for the named shell. Load it in your shell's startup file to complete commands and flags:

Output
bash        source <(hookchat completion bash)
zsh         hookchat completion zsh > "${fpath[1]}/_hookchat"
fish        hookchat completion fish > ~/.config/fish/completions/hookchat.fish
powershell  hookchat completion powershell | Out-String | Invoke-Expression
Examples
# Bash, for the current session
source <(hookchat completion bash)

# Zsh, installed permanently
hookchat completion zsh > "${fpath[1]}/_hookchat"

hookchat conversations#

Read the unified inbox

Usage
hookchat conversations [command]

A conversation is one thread between a linked account and a participant. The gateway computes each thread's messaging window (open_24h, human_agent_only or closed) and the can_reply and can_send_as_human_agent flags; consumers never recompute them. Conversation ids contain "#" separators, so quote them in the shell.

Examples
# Threads waiting for an answer
hookchat conversations list --output json | jq '.[] | select(.unanswered)'

# One thread with its recent messages
hookchat conversations get "CONV#acme#instagram#1#2"

Subcommands

hookchat conversations get#

Show one conversation and its recent messages

Usage
hookchat conversations get <id> [flags]

Calls GET /v1/conversations/:id. The id is URL-encoded for you. The table shows the conversation's window and flags followed by its bounded thread history; json and yaml print {"conversation": ..., "messages": [...]}. --include-test adds rows written by test-scope keys.

Examples
# A thread, including test-key rows
hookchat conversations get "CONV#acme#instagram#1#2" --include-test

# Just the window state
hookchat conversations get "CONV#acme#instagram#1#2" --output json | jq -r .conversation.window.state

Flags

FlagTypeDefaultDescription
--include-testboolinclude rows written by test-scope keys

hookchat conversations list#

List conversations, most recently active first

Usage
hookchat conversations list [flags]

Calls GET /v1/conversations. One page is printed by default with the next_cursor on stderr (table) or in the envelope (json, yaml); --all walks every page. The list is the inbox feed: live rows only.

Examples
# The first page of 50
hookchat conversations list

# Every conversation, ids only
hookchat conversations list --all --quiet

# Threads that can still be replied to
hookchat conversations list --output json | jq '.[] | select(.can_reply) | .id'

Flags

FlagTypeDefaultDescription
--allboolwalk every page instead of printing one page and its next_cursor
--cursorstringresume from a previous next_cursor
--limitint50page size, 1 to 100 (with --all, the page size used while walking)

hookchat docs#

Generate and check the command reference

Usage
hookchat docs [command]

The command reference is a single Markdown file generated from the command tree: every command's synopsis, description, examples and flags. It is committed at docs/cli/reference.md and a test fails when it is stale.

Examples
# Regenerate the reference after changing a command
hookchat docs generate --out docs/cli/reference.md

# Fail CI when the committed reference is stale
hookchat docs check

Subcommands

hookchat docs check#

Exit 1 when the committed reference is stale

Usage
hookchat docs check [flags]

Generates the reference in memory and compares it with the file. A difference exits 1 with a message telling you to run "hookchat docs generate".

Examples
# Check the committed file
hookchat docs check

# Check another path
hookchat docs check --file build/reference.md

Flags

FlagTypeDefaultDescription
--filestringdocs/cli/reference.mdthe reference file to compare

hookchat docs generate#

Write the Markdown command reference

Usage
hookchat docs generate [flags]

Walks the command tree and writes one Markdown file with the global flags, then a section per command with its synopsis, description, examples and flags. With --out - the reference is written to stdout.

Examples
# Write the committed reference
hookchat docs generate --out docs/cli/reference.md

# Preview on stdout
hookchat docs generate --out -

Flags

FlagTypeDefaultDescription
--outstringdocs/cli/reference.mdoutput path, or - for stdout

hookchat keys#

Create, list and revoke API keys

Usage
hookchat keys [command]

API keys are bound to a tenant and carry a scope: live keys send real messages, test keys route sends through the mock connection and write rows that reads only see with --include-test. A key inherits the caller's scope unless --scope is given, and a test key cannot mint a live key.

Examples
# Mint a test key for CI
hookchat keys create --label ci --scope test

# Revoke it later
hookchat keys revoke 01ARZ3NDEKTSV4RRFFQ69G5FAV

Subcommands

hookchat keys create#

Mint a new API key

Usage
hookchat keys create [flags]

Calls POST /v1/keys. The plaintext secret is returned exactly once; store it now, no read path returns it again. --quiet prints only the secret, which suits shell capture.

Examples
# A labelled live key
hookchat keys create --label "billing worker" --scope live

# Capture a test key in a script
KEY=$(hookchat keys create --label ci --scope test --quiet)

Flags

FlagTypeDefaultDescription
--labelstringdisplay label (default "key for &lt;tenant&gt;")
--scopestringkey scope: live or test (default: the caller's scope)

hookchat keys list#

List the tenant's API keys

Usage
hookchat keys list

Calls GET /v1/keys. Only the display prefix of each key is returned, never a secret. Revoked keys stay in the list with status revoked.

Examples
# All keys as a table
hookchat keys list

# Only active key ids
hookchat keys list --output json | jq -r '.[] | select(.status == "active") | .id'

hookchat keys revoke#

Revoke an API key

Usage
hookchat keys revoke <id>

Calls DELETE /v1/keys/:id. Revoking an already revoked key succeeds; an unknown or cross-tenant id is key_not_found (exit 4).

Examples
# Revoke by id
hookchat keys revoke 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Revoke every key with a label, quietly
hookchat keys list --output json | jq -r '.[] | select(.label == "ci") | .id' | xargs -n1 hookchat keys revoke --quiet

hookchat messages#

Read the message feed and send replies

Usage
hookchat messages [command]

There are exactly two send paths and no generic send. "reply" works inside the 24 hour window after the participant's last message. "human-agent" works from 24 hours to 7 days and must name the human who wrote the message with --actor. Past 7 days nothing can be sent. The gateway enforces the policy and answers window_closed, human_agent_unavailable or missing_actor (exit 6).

Examples
# Reply inside the window
hookchat messages reply --conversation "CONV#acme#instagram#1#2" --text "Thanks, on it"

# Follow up as a named human after 24 hours
hookchat messages human-agent --conversation "CONV#acme#instagram#1#2" --text "Any update?" --actor user_42

Subcommands

hookchat messages get#

Show one message by its platform id

Usage
hookchat messages get <id> [flags]

Calls GET /v1/messages/:id. The id is the platform's own message id (mid). A message written by a test-scope key is found only with --include-test.

Examples
# One message
hookchat messages get mid_abc123

# A message sent under a test key
hookchat messages get mid_abc123 --include-test --output json

Flags

FlagTypeDefaultDescription
--include-testboolinclude rows written by test-scope keys

hookchat messages human-agent#

Send a human-typed message in the 24 hour to 7 day window

Usage
hookchat messages human-agent [flags]

Calls POST /v1/messages/human-agent. --actor names the human who wrote the message and is required: the gateway refuses a send without it with missing_actor (exit 6). Past 7 days the gateway answers human_agent_unavailable (exit 6) and nothing can be sent.

Examples
# A follow up from a named agent
hookchat messages human-agent --conversation "CONV#acme#instagram#1#2" --text "Any update?" --actor user_42

# With an attachment
hookchat messages human-agent --conversation "CONV#acme#instagram#1#2" --attachment file=https://example.com/quote.pdf --actor user_42

Flags

FlagTypeDefaultDescription
--actorstringid of the human who wrote the message (required)
--attachmentstringsattachment as &lt;type&gt;=&lt;url&gt;; repeatable
--conversationstringconversation id (required)
--reply-tostringplatform message id to reply to
--textstringmessage text

hookchat messages list#

List messages, newest first

Usage
hookchat messages list [flags]

Calls GET /v1/messages, the tenant-wide feed. --conversation narrows it to one thread and --direction to inbound or outbound. Rows written by test-scope keys appear only with --include-test. A filtered page may be short and still carry a next_cursor.

Examples
# The last 50 messages across the tenant
hookchat messages list

# One thread, inbound only, including test rows
hookchat messages list --conversation "CONV#acme#instagram#1#2" --direction inbound --include-test

# Every message in a thread as JSON
hookchat messages list --conversation "CONV#acme#instagram#1#2" --all --output json

Flags

FlagTypeDefaultDescription
--allboolwalk every page instead of printing one page and its next_cursor
--conversationstringrestrict to one conversation id
--cursorstringresume from a previous next_cursor
--directionstringrestrict to one direction: inbound or outbound
--include-testboolinclude rows written by test-scope keys
--limitint50page size, 1 to 100 (with --all, the page size used while walking)

hookchat messages reply#

Send a reply inside the 24 hour window

Usage
hookchat messages reply [flags]

Calls POST /v1/messages/reply. Text, attachments or both may be sent; an attachment is <type>=<url> where type is image, video, audio or file and Meta fetches the URL. Outside the 24 hour window the gateway refuses with window_closed (exit 6); check the conversation's can_send_as_human_agent flag and use "messages human-agent" when it is true.

Examples
# A text reply
hookchat messages reply --conversation "CONV#acme#instagram#1#2" --text "Thanks, on it"

# An image with a caption, replying to a specific message
hookchat messages reply --conversation "CONV#acme#instagram#1#2" --text "Here you go" --attachment image=https://example.com/a.png --reply-to mid_123

# Only the platform message id
hookchat messages reply --conversation "CONV#acme#instagram#1#2" --text "Hi" --quiet

Flags

FlagTypeDefaultDescription
--attachmentstringsattachment as &lt;type&gt;=&lt;url&gt;; repeatable
--conversationstringconversation id (required)
--reply-tostringplatform message id to reply to
--textstringmessage text

hookchat ping#

Check that the gateway is reachable

Usage
hookchat ping

Calls GET /v1/ping and prints the gateway's name, version and clock. The route is unauthenticated, so ping works before any key is configured; when a key is configured it is sent anyway, which makes ping a quick check of the base URL a profile points at.

Examples
# Ping the production gateway
hookchat ping

# Ping a local gateway as JSON
hookchat ping --base-url http://localhost:3000 --output json

hookchat realtime#

Mint websocket connect tickets

Usage
hookchat realtime [command]

A browser cannot set an Authorization header on a websocket upgrade, so the realtime socket is opened with a short-lived, single-use ticket minted here and passed in the socket URL.

Examples
# Mint a ticket
hookchat realtime ticket

# Just the ticket value, for a script
hookchat realtime ticket --quiet

Subcommands

hookchat realtime ticket#

Mint a short-lived websocket connect ticket

Usage
hookchat realtime ticket

Calls POST /v1/realtime/ticket. The ticket is single use, bound to the tenant, and expires within about a minute; open the socket before expires_at.

Examples
# Mint a ticket and show its expiry
hookchat realtime ticket

# Feed the ticket to another tool
TICKET=$(hookchat realtime ticket --quiet)

hookchat stats#

Show the tenant's overview counts

Usage
hookchat stats

Calls GET /v1/stats: messages in the last 24 hours, the DLQ total and the per-endpoint delivered, failed and dlq counts over the reported window.

Examples
# Overview as a table
hookchat stats

# Overview as JSON, for a dashboard
hookchat stats --output json

hookchat verify#

Verify a captured webhook delivery offline

Usage
hookchat verify --secret <whs_...> [--file <path>] [flags]

Checks a delivery's HookChat-Signature header against the signing secret and prints the event it carries. The input is a JSON document of the form {"headers": {...}, "body": "<raw body>"} with lowercased header names, which is what a capture receiver stores, read from --file or standard input. With --raw the input is the raw body itself and the headers are passed with --header "HookChat-Signature: t=...,v1=...".

The signature is HMAC-SHA256 over "<t>.<body>" with the exact body bytes; during a secret rotation the header carries two v1 values and either secret verifies. A timestamp further than --tolerance from now is rejected. A signature failure exits 9; a body that verifies but is not a HookChat event exits 1.

Examples
# A delivery captured as JSON
hookchat verify --secret whs_... --file delivery.json

# Piped from a capture receiver
curl -s http://localhost:4100/deliveries | jq '.[0]' | hookchat verify --secret whs_...

# A raw body with its signature header
hookchat verify --secret whs_... --raw --header "HookChat-Signature: t=1756900000,v1=ab12..." --file body.json

# An old fixture, ignoring the timestamp check
hookchat verify --secret whs_... --file delivery.json --tolerance 87600h

Flags

FlagTypeDefaultDescription
--filestringread the input from this file instead of stdin
--headerstringsa header as "Name: value", repeatable; only with --raw
--rawboolthe input is the raw body; pass headers with --header
--secretstringthe endpoint's whs_ signing secret (required)
--toleranceduration5m0smaximum age of the delivery timestamp

hookchat version#

Print the CLI version

Usage
hookchat version

Prints the hookchat CLI version. With --output json or yaml it also reports the Go toolchain, operating system and CPU architecture the binary was built for, which is useful in a bug report.

Examples
# Just the version
hookchat version

# Version plus build details
hookchat version --output json

hookchat webhooks#

Manage webhook endpoints and their deliveries

Usage
hookchat webhooks [command]

A webhook endpoint is an HTTPS URL the gateway POSTs signed events to. Create returns the whs_ signing secret exactly once; rotate mints a new one while the old one keeps signing for a 24 hour overlap. Test sends a test.event through the real delivery path, and the deliveries subcommands inspect and replay the delivery log.

Examples
# Register an endpoint for two event types
hookchat webhooks create --url https://example.com/hookchat --events message.received,message.failed

# Prove the receiver verifies signatures
hookchat webhooks test 01ARZ3NDEKTSV4RRFFQ69G5FAV
hookchat webhooks deliveries list 01ARZ3NDEKTSV4RRFFQ69G5FAV

Subcommands

hookchat webhooks create#

Register an endpoint and mint its signing secret

Usage
hookchat webhooks create [flags]

Calls POST /v1/webhooks. The URL must be HTTPS on a public host (the gateway rejects private and loopback addresses with invalid_request and the reason in detail). --events restricts the subscription; omit it for every event type. The whs_ signing secret is shown exactly once; --quiet prints only the secret.

Examples
# Every event type
hookchat webhooks create --url https://example.com/hookchat

# Only inbound messages and failures, as JSON to capture id and secret
hookchat webhooks create --url https://example.com/hookchat --events message.received,message.failed --output json

# Capture the secret directly
SECRET=$(hookchat webhooks create --url https://example.com/hookchat --quiet)

Flags

FlagTypeDefaultDescription
--eventsstringsevent types to subscribe to, comma separated (default: all)
--urlstringHTTPS endpoint the gateway POSTs deliveries to (required)

hookchat webhooks delete#

Delete an endpoint

Usage
hookchat webhooks delete <id>

Calls DELETE /v1/webhooks/:id. The endpoint is tombstoned: its signing material is erased while its id and delivery history are kept. A second delete of the same endpoint is a no-op success.

Examples
# Delete by id
hookchat webhooks delete 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Delete every endpoint pointing at a host
hookchat webhooks list --output json | jq -r '.[] | select(.url | contains("old.example.com")) | .id' | xargs -n1 hookchat webhooks delete --quiet

hookchat webhooks deliveries#

Inspect and replay an endpoint's deliveries

Usage
hookchat webhooks deliveries [command]

Every event delivered to an endpoint is logged with its status: pending, attempting, retrying, delivered, failed, blocked or dlq. list pages the log, summary aggregates the failing rows server side, replay re-drives one delivery and replay-all re-drives every failing delivery in a time window. Delivery timestamps are epoch milliseconds in the API; tables show them as RFC 3339.

Examples
# What failed in the last 24 hours
hookchat webhooks deliveries summary 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Re-drive everything that failed since the outage
hookchat webhooks deliveries replay-all 01ARZ3NDEKTSV4RRFFQ69G5FAV --from 6h

Subcommands

hookchat webhooks deliveries list#

List an endpoint's deliveries, newest first

Usage
hookchat webhooks deliveries list <endpointId> [flags]

Calls GET /v1/webhooks/:id/deliveries. One page is printed by default with the next_cursor on stderr (table) or in the envelope (json, yaml); --all walks every page. --status keeps only the named statuses; the filter is applied by the CLI after fetching, so a filtered page may be short. An endpoint id that does not exist under the tenant yields an empty list rather than endpoint_not_found.

Examples
# The latest page
hookchat webhooks deliveries list 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Only failed and dlq rows, across every page
hookchat webhooks deliveries list 01ARZ3NDEKTSV4RRFFQ69G5FAV --status failed,dlq --all

# Delivery ids only, for replay scripts
hookchat webhooks deliveries list 01ARZ3NDEKTSV4RRFFQ69G5FAV --status dlq --all --quiet

Flags

FlagTypeDefaultDescription
--allboolwalk every page instead of printing one page and its next_cursor
--cursorstringresume from a previous next_cursor
--limitint50page size, 1 to 100 (with --all, the page size used while walking)
--statusstringskeep only these statuses, comma separated (pending, attempting, retrying, delivered, failed, blocked, dlq)

hookchat webhooks deliveries replay#

Re-drive one delivery on a fresh attempt budget

Usage
hookchat webhooks deliveries replay <endpointId> <deliveryId> [flags]

Calls POST /v1/webhooks/:id/deliveries/:deliveryId/replay. A delivery that already succeeded is refused with replay_conflict (exit 8) unless --force is given, in which case the receiver sees a duplicate event id (dedupe on it). A delivery that is mid-attempt is always refused.

Examples
# Replay a failed delivery
hookchat webhooks deliveries replay 01ARZ3NDEKTSV4RRFFQ69G5FAV 01J8ZK3M...

# Re-send a delivered one anyway
hookchat webhooks deliveries replay 01ARZ3NDEKTSV4RRFFQ69G5FAV 01J8ZK3M... --force

Flags

FlagTypeDefaultDescription
--forceboolreplay even if the delivery already succeeded

hookchat webhooks deliveries replay-all#

Re-drive every failing delivery in a time window

Usage
hookchat webhooks deliveries replay-all <endpointId> [flags]

Calls POST /v1/webhooks/:id/deliveries/replay. --from is required and --to defaults to now; both accept an RFC 3339 time, a date, a unix epoch or an age such as 6h. The default statuses are dlq and failed; including delivered requires --force (exit 8 otherwise). The batch is bounded: a short page returns a next_cursor, printed on stderr in table mode. --all keeps going until the batch is exhausted and prints the summed counts.

Examples
# Everything that failed in the last 6 hours
hookchat webhooks deliveries replay-all 01ARZ3NDEKTSV4RRFFQ69G5FAV --from 6h

# A precise window, dlq only, walking every batch page
hookchat webhooks deliveries replay-all 01ARZ3NDEKTSV4RRFFQ69G5FAV --from 2026-09-03T00:00:00Z --to 2026-09-03T06:00:00Z --status dlq --all

# Re-send delivered events too (receivers see duplicate event ids)
hookchat webhooks deliveries replay-all 01ARZ3NDEKTSV4RRFFQ69G5FAV --from 1h --status delivered --force

Flags

FlagTypeDefaultDescription
--allboolkeep replaying until the batch is exhausted
--cursorstringcontinue a batch from a previous next_cursor
--forceboolallow delivered deliveries to be re-sent
--fromstringstart of the window: RFC 3339, a date, a unix epoch or an age such as 6h (required)
--limitintbatch page size, 1 to 100 (default: server default)
--statusstringsstatuses to replay, comma separated (default: dlq,failed; delivered needs --force)
--tostringend of the window, same forms as --from (default: now)

hookchat webhooks deliveries summary#

Aggregate an endpoint's failing deliveries

Usage
hookchat webhooks deliveries summary <endpointId> [flags]

Calls GET /v1/webhooks/:id/deliveries/summary. By default it covers the last 24 hours and the statuses dlq, failed, blocked and retrying. --since accepts an RFC 3339 time, a date, a unix epoch or an age such as 6h. When the examined-row cap is hit the result is marked truncated and older failures may be missing.

Examples
# Failures in the last 24 hours
hookchat webhooks deliveries summary 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Only dlq rows from the last 6 hours
hookchat webhooks deliveries summary 01ARZ3NDEKTSV4RRFFQ69G5FAV --since 6h --status dlq

Flags

FlagTypeDefaultDescription
--sincestringstart of the window: RFC 3339, a date, a unix epoch or an age such as 6h (default: 24h)
--statusstringsstatuses to include, comma separated (default: dlq,failed,blocked,retrying)

hookchat webhooks get#

Show one endpoint

Usage
hookchat webhooks get <id>

Calls GET /v1/webhooks/:id. A deleted or cross-tenant id is endpoint_not_found (exit 4).

Examples
# One endpoint
hookchat webhooks get 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Is a rotation overlap still active?
hookchat webhooks get 01ARZ3NDEKTSV4RRFFQ69G5FAV --output json | jq .secondary_active

hookchat webhooks list#

List the tenant's live endpoints

Usage
hookchat webhooks list

Calls GET /v1/webhooks. Deleted endpoints are not listed. No secret is ever returned, only a display prefix of the current one.

Examples
# Endpoints as a table
hookchat webhooks list

# Paused endpoints
hookchat webhooks list --output json | jq '.[] | select(.status == "paused")'

hookchat webhooks rotate#

Mint a new signing secret with a 24 hour overlap

Usage
hookchat webhooks rotate <id>

Calls POST /v1/webhooks/:id/rotate. The new whs_ secret is shown exactly once. The previous secret keeps signing for 24 hours, during which every delivery carries two v1 signatures, so a receiver holding either secret keeps verifying while you roll the new one out.

Examples
# Rotate and show the new secret
hookchat webhooks rotate 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Capture the new secret for a secret manager
NEW=$(hookchat webhooks rotate 01ARZ3NDEKTSV4RRFFQ69G5FAV --quiet)

hookchat webhooks test#

Send a test.event through the real delivery path

Usage
hookchat webhooks test <id>

Calls POST /v1/webhooks/:id/test. The event is signed and delivered asynchronously like any other; poll "webhooks deliveries list" or your receiver for the delivery id printed here. --quiet prints nothing on success.

Examples
# Send a test event
hookchat webhooks test 01ARZ3NDEKTSV4RRFFQ69G5FAV

# Send one and wait for the delivery to settle
hookchat webhooks test 01ARZ3NDEKTSV4RRFFQ69G5FAV --output json | jq -r .delivery_id

hookchat webhooks update#

Change an endpoint's URL or events, or pause and resume it

Usage
hookchat webhooks update <id> [flags]

Calls PATCH /v1/webhooks/:id with only the fields given. --events replaces the subscription filter and --all-events clears it. --disabled pauses deliveries (they queue as pending) and --enabled resumes them. At least one change is required.

Examples
# Move an endpoint to a new URL
hookchat webhooks update 01ARZ3NDEKTSV4RRFFQ69G5FAV --url https://example.com/v2/hookchat

# Pause it during a deploy, then resume
hookchat webhooks update 01ARZ3NDEKTSV4RRFFQ69G5FAV --disabled
hookchat webhooks update 01ARZ3NDEKTSV4RRFFQ69G5FAV --enabled

# Subscribe to everything again
hookchat webhooks update 01ARZ3NDEKTSV4RRFFQ69G5FAV --all-events

Flags

FlagTypeDefaultDescription
--all-eventsboolclear the event filter (subscribe to every event)
--disabledboolpause deliveries (status paused)
--enabledboolresume deliveries (status active)
--eventsstringsnew event type filter, comma separated
--urlstringnew HTTPS endpoint URL