Skip to main content

Webhooks

Webhooks let DriftWise receive events from your VCS / CI system and post analysis results back as merge-request comments. For endpoint shapes on webhook config management, see the webhooks tag of the API reference.

info

This page covers inbound webhooks — an external system sending events to DriftWise. For outbound notifications (DriftWise alerting you when scheduled scans fail or are auto-disabled), see Scheduled Scans.

For plan analysis from your CI pipeline (GitHub Actions, GitLab CI script: steps, Atlantis run: steps), use POST /api/v2/orgs/:id/analyze with an API key — it enqueues the analysis and your pipeline polls for the result — see GitHub Actions, GitLab CI, and Atlantis. The /webhooks/ endpoint described below is a separate integration path for event-driven flows: Atlantis plan events and GitLab merge-request / comment events.

Supported sources​

Two webhook sources are registered at the /webhooks/ endpoint:

SourceURL segmentAuth modelSignature header
AtlantisatlantisHMAC-SHA-256 over bodyX-Atlantis-Signature (or X-Hub-Signature-256)
GitLab native webhookgitlabConstant shared secretX-Gitlab-Token

Any other :provider segment returns 404 unknown provider.

The two auth models differ:

  • Atlantis signs each request with HMAC-SHA-256 of the raw body using the webhook secret. Either header carries an sha256=<hex> value; X-Atlantis-Signature takes priority.
  • GitLab sends the shared secret verbatim in X-Gitlab-Token — exactly the behavior of GitLab's native "Secret token" field in Settings → Webhooks. DriftWise does a constant-time compare against the stored secret. This is not an HMAC; do not hash the secret before sending it.

How it works​

  1. The source system POSTs an event to DriftWise.
  2. DriftWise validates the signature / token, parses the event, and returns 202 Accepted immediately.
  3. For Atlantis plan events, DriftWise runs analysis and posts a comment back to the PR via the GitHub App.
  4. For GitLab merge-request events, DriftWise observes the MR and comments via the stored API token when /driftwise commands arrive.

Comment-back requires an installed GitHub App (Atlantis path) or a stored GitLab API token (GitLab path). See each source's setup guide.

Creating a webhook config​

Create GitLab webhook configs through the dashboard's Settings → GitLab Integration card (the wizard creates the config for you); Atlantis configs are created via the API only. On creation you'll get a raw_secret field in the response — save this immediately. It's shown once and required to sign inbound requests from the source.

Creation is gated to owner/admin because a viewer setting up a webhook with a known-bad secret could effectively DoS real integrations that share the org's webhook gateway.

GitLab webhook configs additionally accept an API token that DriftWise live-validates against the target GitLab instance before saving. Expired tokens, wrong-scope tokens, and tokens for unreachable instances fail at save time with a specific 400 message — no token ever lands in the DB as "active but actually broken." Tokens without an expiration date are rejected: create a Personal or Group Access Token with an explicit expiry.

Webhook URL​

Your source posts events to:

https://api.driftwise.ai/webhooks/<source>/<org_id>

For example:

https://api.driftwise.ai/webhooks/atlantis/1478fe16-d292-4f0f-95fa-d249dda3d7ab

This is not a /api/v2/ endpoint — it lives outside the v2 auth middleware by design, because the source authenticates with the webhook secret, not an API key or OIDC token.

Source setup​

Atlantis​

Add a webhook in your Atlantis server config pointing to DriftWise:

atlantis.yaml
webhooks:
- event: plan
workspace-regex: ".*"
url: "https://api.driftwise.ai/webhooks/atlantis/<org_id>"
secret: "<raw_secret from webhook config>"

Atlantis computes an HMAC-SHA-256 of the body with the shared secret and sends it in X-Atlantis-Signature: sha256=<hex>. DriftWise validates this against every enabled atlantis config for the org and accepts if any secret matches.

See Atlantis Integration for the full workflow setup.

GitLab native webhook​

In your GitLab project, open Settings → Webhooks. Add a new webhook:

  • URL: https://api.driftwise.ai/webhooks/gitlab/<org_id>
  • Secret token: paste the raw_secret returned when you created the webhook config in DriftWise (value starts with whsec_)
  • Trigger: enable Merge request events and Comments
  • Save

GitLab sends the secret token verbatim in X-Gitlab-Token on each delivery. DriftWise compares it (constant-time) against every enabled gitlab config for the org.

See GitLab CI Integration for the full setup including the optional API token for comment-back.

Updating a webhook config​

The PATCH endpoint accepts {enabled, api_token} — at least one field is required (empty body returns 400, not a no-op). Token rotations re-validate against the target GitLab instance before persisting, same as on create. Failures return a 400 with an actionable message that never contains the raw token itself. api_token is only supported on gitlab configs.

Security​

  • Secrets are encrypted at rest with AES-256-GCM. Only a 14-char identifier prefix (whsec_ + 8 hex chars) is stored in plaintext for lookup / display.
  • Signature validation on every inbound webhook. Atlantis: HMAC-SHA-256 over the raw body. GitLab: constant-time compare of X-Gitlab-Token against the stored secret. Both fail closed — missing headers, DB errors, decrypt failures, or zero enabled configs all reject with 401.
  • Body size cap of 5 MB at the gateway. Larger payloads are rejected with 413 before any validation work runs.
  • Replay protection — duplicate payloads (same body hash) are deduplicated to prevent double-processing.
  • Repo cross-check — when a matching webhook config has a repo_path set, the event body's repo must match it or the request is rejected with 403. Prevents a tenant member with a valid token from forging events from a different repo in the same org.
  • Async processing — webhooks return 202 immediately, so the source doesn't block on analysis.
  • provider_base_url is SSRF-validated (must be public HTTPS) before save, for GitLab configs pointing at self-hosted instances.

Endpoint reference​

Webhook config CRUD is under the webhooks tag of the API reference.