Agent skill

Terraform Webhooks Skill

Receive and verify HCP Terraform (Terraform Cloud) and Terraform Enterprise notification webhooks. Use when setting up Terraform run notification handlers, debugging X-TFE-Notification-Signature verification, or handling triggers like run:completed, run:errored, run:needs_attention, and assessment:drifted.

Install this skill

npx skills add hookdeck/webhook-skills --skill terraform-webhooks


HCP Terraform (formerly Terraform Cloud) and Terraform Enterprise send workspace notifications to any HTTP endpoint using the generic destination type. This skill covers that destination only; Slack, Microsoft Teams, and email use their own formats.

When to Use This Skill

  • How do I receive HCP Terraform / Terraform Cloud run notification webhooks?
  • How do I verify the X-TFE-Notification-Signature header?
  • How do I handle run:completed, run:errored, or run:needs_attention notifications?
  • How do I react to drift detection (assessment:drifted) or failed health assessments?
  • Why is my Terraform notification configuration failing verification or not enabling?

Verification (core)

The signature is the hex HMAC-SHA512 of the raw request body, keyed with the notification configuration's token, sent in X-TFE-Notification-Signature. The token is optional in HCP Terraform: if you don't set one, no signature is sent, so set one and reject unsigned requests.

const crypto = require('crypto');

function verifyTerraformSignature(rawBody, signatureHeader, token) {
  if (!signatureHeader || !token) return false;
  const expected = crypto.createHmac('sha512', token).update(rawBody).digest('hex');
  try {
    const received = Buffer.from(signatureHeader.toLowerCase());
    const expectedBuf = Buffer.from(expected);
    return received.length === expectedBuf.length && crypto.timingSafeEqual(received, expectedBuf);
  } catch {
    return false;
  }
}
import hmac, hashlib

def verify_terraform_signature(raw_body: bytes, signature_header: str, token: str) -> bool:
    if not signature_header or not token:
        return False
    expected = hmac.new(token.encode(), raw_body, hashlib.sha512).hexdigest()
    return hmac.compare_digest(signature_header.lower().encode(), expected.encode())

In Express, read the body with express.raw({ type: '*/*' }) so the signature verifies whatever Content-Type the request carries.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Verification Request

When you save a configuration with Enabled on, or click Send a test, HCP Terraform POSTs a test payload whose notifications[0].trigger is "verification" (run fields are null). Return any 2xx; the configuration can't be enabled otherwise. The request is signed like any other when a token is set, so the token must already be configured in your handler.

Triggers

Run payloads (payload_version: 1) carry the trigger in notifications[].trigger. Workspace payloads (payload_version: "2") carry it in a top-level trigger.

TriggerFires When
run:createdA run is created and enters the Pending stage
run:planningA run acquires the lock and starts executing
run:needs_attentionA plan has changes and needs approval or a policy override
run:applyingA run enters the Apply stage
run:completedA run completes successfully
run:erroredA run ends early from an error or cancellation
assessment:driftedDrift detected (health assessments enabled)
assessment:check_failureContinuous validation checks failed
assessment:failedA health assessment itself failed
workspace:auto_destroy_reminderAn automatic destroy run is imminent
workspace:auto_destroy_run_resultsAn automatic destroy run was attempted
workspace:deletedA workspace was deleted
verificationTest request sent on enable / "Send a test"

Run payload fields: payload_version, notification_configuration_id, run_url, run_id, run_message, run_created_at, run_created_by, workspace_id, workspace_name, organization_name, and notifications[] (message, trigger, run_status, run_updated_at, run_updated_by).

For the full payload reference, see Notification configurations API.

Important Headers

HeaderDescription
X-TFE-Notification-SignatureHex HMAC-SHA512 of the raw body (only when a token is set)

Environment Variables

# The token entered on the notification configuration (cannot be viewed after saving)
TERRAFORM_NOTIFICATION_TOKEN=your_notification_token

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 terraform --path /webhooks/terraform

Use the tunnel URL as the Webhook URL of a generic notification configuration. Enabling the configuration sends the verification request through it.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 4, 2026

View on GitHub →