Skip to content

Webhooks

ordyn-webhooks lets external systems trigger endpoint jobs and infrastructure jobs through HTTP webhooks.

The webhook service receives public HTTP requests, authenticates them according to each webhook definition, and makes normalized request data available to the triggered job.

Use webhooks when another application should start an Ordyn job, for example:

  • a monitoring system detects a condition and asks Ordyn to remediate the affected machine
  • a CI or deployment platform starts an infrastructure build or administration job
  • a company portal starts a controlled endpoint action without giving the caller direct Ordyn server access
  • another automation tool passes structured data into an Ordyn job

Webhooks are available in Administration > Services on the Webhooks tab.

How it works

At a high level:

  1. An admin creates a webhook service client in Ordyn.
  2. An admin issues a service-client enrollment token scoped to that webhook service client.
  3. The ordyn-webhooks service enrolls through the configured Edge service by using the scoped token once.
  4. An admin creates a webhook definition with endpoint or infrastructure scope.
  5. External systems call the public webhook URL.
  6. The webhook service validates and normalizes the request.
  7. Ordyn records the event and starts matching endpoint automations or infrastructure job automations.

The webhook service accepts public ingress traffic. It does not require external callers to reach the Ordyn server directly.

The webhook service connects outbound to its assigned Edge service for enrollment and Ordyn communication.

Service clients

A webhook service client represents one running ordyn-webhooks instance.

Create it in Administration > Services on the Webhooks tab by selecting Create client.

The service client needs:

  • name
  • edge service
  • public base URL
  • enabled state

The public base URL is the externally reachable base address for that webhook service, for example:

text
https://ordyn-webhooks.example.com

Ordyn uses this value to display the full URL for each webhook. The service accepts webhook calls under:

text
<public base URL>/v1/hooks/<webhook slug>

After creating a service client, issue a service-client enrollment token for it from the enrollment tokens page. Run the service enrollment command with that token. The command stores the service-client certificate state on disk, and the token is only needed for that enrollment.

Each webhook service client has a detail page that shows connection state, version, current certificate serial, certificate expiration, enrollment timestamps, and the configured public base URL. Admins can enable or disable the service client and revoke the current certificate from the detail page. After revocation, follow the forced stop, enroll, and start workflow below before the service can connect. See service-client certificate lifetime and renewal for the renewal workflow.

Runtime configuration

The service needs these values at runtime:

Environment variablePurpose
ORDYN_WEBHOOK_EDGE_HOSTEdge host used for service-client enrollment and the service-client websocket.
ORDYN_WEBHOOK_SERVICE_CLIENT_IDThe service client ID from Ordyn.
ORDYN_WEBHOOK_PUBLIC_BASE_URLPublic base URL shown in Ordyn for webhook URLs.

Configure these values before following the installation and enrollment workflow below. Enrollment state is stored in /data/service-client-v1 on the persistent webhooks-data volume.

Common optional values:

Environment variablePurpose
ORDYN_WEBHOOK_BODY_LIMITMaximum accepted request body size.

Backend webhook event retention is configured separately:

Environment variablePurpose
ORDYN_WEBHOOK_EVENT_RETENTION_DAYSNumber of days to keep stored webhook event payloads in Ordyn. Defaults to 30. Set to 0 or lower to disable pruning.

Installation

Prerequisites:

Checkout the webhook deployment folder from the Ordyn compose repository:

bash
if [ ! -d /opt/ordyn-compose/.git ]; then
  git clone --filter=blob:none --sparse https://github.com/ordyn-project/compose.git /opt/ordyn-compose
fi
cd /opt/ordyn-compose
git sparse-checkout add webhooks

Create the environment file:

bash
cd /opt/ordyn-compose/webhooks
cp .env.example .env

Set these values in .env:

dotenv
SERVICE_DOMAIN=ordyn-webhooks.example.com
ORDYN_WEBHOOK_EDGE_HOST=ordyn-edge.example.com
ORDYN_WEBHOOK_SERVICE_CLIENT_ID=<service-client-id>
ORDYN_WEBHOOK_PUBLIC_BASE_URL=https://ordyn-webhooks.example.com

Pull and verify the service image:

bash
docker compose pull
python3 /opt/cosign-docker-verify/verify.py

Continue only when the webhook image verifies successfully and no failed verification message appears. Issue a service-client enrollment token for the webhook service client in Ordyn, stop any running service container, and enroll the persistent service state:

bash
docker compose stop webhooks
printf '%s' '<enrollment-token>' | docker compose run --rm -T --no-deps webhooks npm run enroll -- --token-stdin

After enrollment succeeds, start the service:

bash
docker compose up -d webhooks

To renew, recover, or replace its service-client certificate, issue a new token and run forced enrollment while the service is stopped:

bash
docker compose stop webhooks
printf '%s' '<enrollment-token>' | docker compose run --rm -T --no-deps webhooks npm run enroll -- --token-stdin --force

Run docker compose up -d webhooks only after forced enrollment succeeds. Do not use docker compose exec for enrollment.

The webhook service needs public HTTPS ingress for /v1/hooks/. The provided compose file routes that path through Traefik.

Public ingress

The service exposes incoming webhook calls at:

text
/v1/hooks/:slug

The slug is generated by Ordyn when the webhook is created. It is part of the copied webhook URL.

Only that ingress path needs to be publicly reachable. Service-client enrollment and control traffic are outbound from the webhook service to edge.

Source-IP authentication uses caller addresses forwarded by Traefik.

Configure rate limiting on public webhook routes when a webhook endpoint is exposed to untrusted networks or high-volume callers.

Webhook definitions

A webhook definition belongs to one webhook service client and has either endpoint or infrastructure scope.

Create it in Administration > Services on the Webhooks tab by selecting Create webhook.

A webhook has:

  • service client
  • scope
  • endpoint when the scope is Endpoint
  • name
  • allowed HTTP methods
  • authentication mode
  • optional source IP allowlist
  • optional job variable mappings
  • enabled state

An endpoint-scoped webhook is bound to one approved endpoint and can match endpoint automations for that endpoint. An infrastructure-scoped webhook has no endpoint and can match automations configured on infrastructure jobs.

The scope and endpoint cannot be changed while an automation references the webhook. Remove those references before changing its scope or endpoint. A referenced webhook also cannot be deleted.

The incoming request does not select an endpoint, infrastructure job, Runner pool, or Runner.

Disabled webhooks are not accepted by the ingress service and do not trigger jobs.

Allowed methods

Each webhook can allow one or more HTTP methods:

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE

The default method is POST.

If a request uses a method that is not allowed, the service rejects it before forwarding an event to Ordyn.

Authentication

Webhook authentication is configured per webhook definition.

Supported modes:

ModeBehavior
UnauthenticatedNo token is required. Use only for trusted networks or low-risk integrations.
Bearer tokenThe caller sends Authorization: Bearer <token>.
Header tokenThe caller sends the token in the configured header, for example X-Ordyn-Webhook-Token.
Source IP allowlistThe caller source IP must match one configured IP address or CIDR range.

Bearer-token and header-token values are hashed before they are stored in Ordyn. Tokens are not shown again after saving.

Source IP allowlists support individual IP addresses and CIDR ranges, for example:

text
203.0.113.10
203.0.113.0/24
2001:db8::/32

Source-IP checks use the caller address forwarded by Traefik.

Request payloads

The webhook service stores and forwards a normalized request shape.

It records:

  • webhook ID and slug
  • receive timestamp
  • HTTP method
  • source IP
  • content type
  • sanitized headers
  • query parameters
  • parsed body
  • raw body

JSON request bodies are parsed as JSON. application/x-www-form-urlencoded bodies are parsed into fields. Other body types are forwarded as text in the normalized request.

Sensitive caller tokens are used for authentication and should not be treated as job input.

Connect Webhooks To Jobs

The webhook scope determines where it can be selected.

Endpoint Jobs

Configure an endpoint event automation with:

  • event Webhook received
  • an endpoint-scoped webhook definition
  • the endpoint job to run
  • an optional maximum random delay

The automation matches only when:

  • the webhook definition is active
  • the webhook's endpoint is approved
  • the automation is enabled
  • the automation resolves to the webhook's endpoint
  • the automation references the received webhook

When multiple matching automations exist for the endpoint, Ordyn evaluates them in their configured order. The optional random delay can spread bursts when an external system sends many events.

Infrastructure Jobs

  1. Create a webhook definition with scope Infrastructure.
  2. Open Operations > Infrastructure Jobs.
  3. Select the job that should run and open its Automations tab.
  4. Add an event automation with event Webhook received.
  5. Select the webhook and configure an optional maximum random delay.

Each matching automation starts the infrastructure job that owns it. The job runs once using the Runner pool selected in its overview. It does not create endpoint targets.

Job validity windows apply when the webhook event is processed. An event outside the job's allowed start window does not start a run.

See Infrastructure Jobs for the complete workflow.

Job variables

Triggered jobs receive webhook trigger details under:

text
trigger.webhook

The run also has trigger.type set to webhook_received and trigger.source set to webhook. See Variables for the full trigger field list.

Webhook definitions can also map selected request values to short job variables under:

text
webhook.<name>

For example, a mapping with:

NamePath
build_idbody.build.id

makes the value available as:

text
{{ webhook.build_id }}

Mapping paths are evaluated against the normalized request, so useful prefixes are usually:

  • body
  • query
  • headers
  • source_ip
  • method
  • content_type

Use mappings for values that job authors should consume directly. Use trigger.webhook.* when a job needs the full request context.

Example

An external system sends:

bash
curl -X POST \
  https://ordyn-webhooks.example.com/v1/hooks/3d72... \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  --data '{"build":{"id":"2026.06.25.1"},"action":"restart-service"}'

With a variable mapping:

NamePath
build_idbody.build.id
actionbody.action

the triggered job can use:

text
{{ webhook.build_id }}
{{ webhook.action }}
{{ trigger.webhook.source_ip }}

Events and diagnostics

Ordyn stores each received webhook event with the normalized request, mapped variables, matching automations, dispatched automations, and any dispatch error.

Webhook events are retained for 30 days by default. Ordyn removes events outside the retention window according to ORDYN_WEBHOOK_EVENT_RETENTION_DAYS.

The webhook definition shows the last receive timestamp and last error. Common last-error causes are:

  • the webhook's endpoint is not approved
  • no enabled endpoint automation matched the webhook and endpoint
  • no enabled infrastructure automation matched the webhook
  • the webhook was received while the definition was inactive

Service-client connection state is shown on the Webhooks page. It includes connection status, version, certificate serial, last enrollment, last connection, last seen time, and last error.

Support bundles

Webhook service clients participate in service-client log bundles.

Use support bundles when troubleshooting:

  • webhook service enrollment problems
  • service-client connection loss
  • runtime configuration not reaching the service
  • received requests not triggering jobs
  • authentication failures reported by the webhook service

Select the webhook service client as a log source when creating a service-client log bundle.

Security recommendations

Use token authentication or source-IP allowlists for production webhooks.

Prefer:

  • HTTPS on public webhook routes
  • long random bearer or header tokens
  • source-IP allowlists when the caller has stable egress addresses
  • one webhook per integration purpose
  • endpoint scope for integrations that should act on one approved endpoint
  • infrastructure scope for integrations that should start infrastructure jobs
  • narrowly configured automations for the intended jobs
  • mapped variables for the specific fields a job needs

Avoid:

  • unauthenticated public webhooks
  • passing secrets in request bodies unless the job genuinely requires them
  • using a shared webhook for unrelated external systems
  • exposing service-client control paths publicly

Permissions

  • Webhooks Read views webhook service clients, definitions, URLs, and events.
  • Webhooks Create, Webhooks Update, and Webhooks Delete manage webhook definitions.
  • Endpoint automation permissions control endpoint webhook automations.
  • Jobs Run, Runners Execute, and Webhooks Read are required to manage infrastructure webhook automations.

Limitations

Limitations:

  • an endpoint-scoped webhook targets one approved endpoint
  • an infrastructure-scoped webhook does not target an endpoint
  • the webhook scope and endpoint are fixed while the webhook is referenced by an automation
  • the incoming payload does not select the endpoint, job, Runner pool, or Runner
  • authentication is configured per webhook definition, not per automation
  • request bodies are normalized for job input, but Ordyn does not transform arbitrary payload formats beyond JSON and form parsing

Use variable mappings to adapt different caller payload shapes into stable job variables.