VOTPort
Let’s talk
Menu

Connect signed events and reliable webhooks

Inspect signed delivery events, configure persistent webhook delivery, replay failures, and retain verifiable audit records.

On this page

Delivery jobs emit signed events for workflow activity and recipient evidence. Use them to update a production tracker, notify a coordinator of a missed acceptance deadline, or retain the handoff record in your archive.

Open Workflows > Activity for signed event history. Load more activity appends records; Export signed records downloads the records loaded so far, so load the required history before exporting. Workflows > Webhooks contains receiver configuration, delivery attempts, and Replay event actions. GET /api/workflows/events exposes the signed history to authorized operators and agents. Follow its returned next cursor as after, including when a scope-filtered page is empty but its cursor advances. When next equals the previous cursor, you are caught up; stop or wait before polling again.

Configure a receiver

An administrator configures the webhook endpoint and retains its displayed signing secret. VOTPort sends the signed event JSON with these headers:

Header Meaning
X-Votport-Event-Id Stable event ID for deduplication.
X-Votport-Timestamp Unix seconds for this delivery attempt.
X-Votport-Signature sha256= followed by HMAC-SHA256 of timestamp + "." + raw_body, using the displayed secret as UTF-8 bytes.

Verify the raw body before parsing or reserializing it, enforce an appropriate timestamp freshness window, and verify the event's Ed25519 signature against a separately trusted server receipt public key. Persist the event before returning a success response. Only HTTP 2xx acknowledges delivery; redirects are not followed.

The Node.js receiver example uses only the standard library. It checks HMAC freshness and the pinned issuer, then atomically archives an event before acknowledging it. Run it behind an HTTPS endpoint on a POSIX host with a precreated private event directory:

VOTPORT_EVENT_ISSUER='<trusted server receipt public key>' \
VOTPORT_WEBHOOK_SECRET='<displayed webhook signing secret>' \
VOTPORT_EVENT_DIRECTORY=/srv/mam-events PORT=8090 \
node examples/delivery-event-receiver.mjs

Use job IDs from archived events to query package metadata, checks, manifests, and recipient evidence. This is an integration surface for your MAM or production system, not a preinstalled vendor-specific connector.

Retry and replay

Webhook attempts persist across restarts. Failures use bounded exponential retries and become dead after 12 failed attempts. Inspect the response or error, correct the receiver, and replay the event. Receivers must deduplicate by event ID/hash and tolerate out-of-order arrival.

Changing webhook configuration rotates its secret and supersedes pending attempts under the old revision. Automatic delivery starts from the new configuration's event. Explicitly replay older events when the new receiver needs them.

Operator endpoints are GET /api/workflows/webhook/attempts and POST /api/workflows/webhook/replay/{id}. Agent tokens can inspect permitted signed events; webhook configuration and replay are operator actions, not MCP tools.

Preserve audit evidence

Each event contains the previous event hash for its tenant. With a trusted issuer and checkpoint, a complete tenant chain can reveal changed, missing, or reordered records. A project-filtered view can contain legitimate gaps, so do not treat it as a complete tenant export.

The receiver example also checks exported event arrays:

VOTPORT_EVENT_ISSUER='<trusted server receipt public key>' \
node examples/delivery-event-receiver.mjs verify events.json [previous-hash]

Retain signed exports, the trusted public key, and checkpoints independently when audit records must withstand changes by a deployment administrator. Signatures and chaining do not make a database physically immutable. Keep recipient acceptance distinct from transfer activity and job readiness in downstream reports.

Read as Markdown