# Outgoing update webhooks

Deliver a signed public update to your own HTTPS receiver and inspect its delivery receipt.

## Configure a destination

Open Sources, choose the project and configure its outgoing webhook. The endpoint must use public HTTPS without URL credentials, a query string or a fragment. Private and local network addresses are rejected. Configuration does not turn on the output: select the separate webhook output switch when you are ready.

Save the one-time signing secret securely. Status reads and exports show only the destination origin, and never return its private path or signing material. Changing the endpoint or rotating the secret creates a new generation. Previously prepared publications are not replayed to the new destination.

## Public event contract

The event type is update.published. Its stable id is indielogs:update: followed by the published update ID. The envelope contains created_at, a public project id/name/slug, the maker username, and the update id, sanitized body_html, public URL, published_at and optional public image/video URLs. It contains no repository evidence, email, provider credentials or private draft context.

History reconstructed during onboarding is excluded from outgoing delivery. Pro entitlement, current output selection, ownership, moderation and account status are rechecked before sending. A delivery acknowledgement does not change the public journal publication.

## Verify the signature

Read the raw UTF-8 body before parsing JSON. The headers are x-indielogs-event-id, x-indielogs-timestamp (Unix seconds) and x-indielogs-signature (sha256= followed by a lowercase hexadecimal HMAC). Decode the part after ilwh_ in the saved secret as base64url bytes. Compute HMAC-SHA256 over eventId + a dot + timestamp + a dot + the raw body, then compare with the supplied digest using a timing-safe comparison.

Reject old timestamps (a five-minute tolerance is a reasonable receiver policy), malformed signatures and event IDs that do not match the body. Deduplicate the stable event ID before applying work. Return a 2xx response only after accepting the event. Redirects are never followed.

## Receipts and retries

Output delivery shows Acknowledged only after the receiver returns 2xx. Failures before the send boundary can be retried explicitly after resolving the configuration or content problem. A timeout, redirect or error after dispatch is uncertain and is not resent automatically; inspect the receiver before taking further action.

Retries retain the first payload snapshot. A successful HTTP request is never repeated merely because saving its local receipt failed. Disconnecting or rotating stops new sends; a request already dispatched may still finish and its actual receipt can settle.

## API, CLI and MCP access

sources.webhook-status is a project-scoped sources:read operation. outputs.list and outputs.retry use the same delivery service in the web app, API, CLI and MCP; retry accepts channel webhook and requires updates:publish. Existing tokens gain no new scopes.

sources.webhook-configure and sources.webhook-disconnect require a signed-in browser session. An agent cannot grant a new external destination by presenting a bearer token. Public operation references document all three contracts, including their browser-only access mode.