Skip to content
Latchkey

How to Test Webhooks in CI

A webhook handler is just a POST route, so a test signs a sample payload and posts it to the endpoint.

Compute the provider's HMAC signature over a fixture payload, POST it with the signature header, then assert the handler returned success and did its side effect.

Steps

  • Save a realistic sample payload as a fixture.
  • Compute the HMAC signature over the raw body.
  • POST it with the signature header and assert the response.

Workflow

.github/workflows/ci.yml
steps:
  - run: |
      npm start &
      npx wait-on http://localhost:3000/health
  - run: |
      BODY=$(cat fixtures/order.created.json)
      SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}')"
      curl -sf -X POST http://localhost:3000/webhooks \
        -H "content-type: application/json" \
        -H "x-signature: $SIG" \
        --data "$BODY" -o /dev/null -w '%{http_code}' | grep -q 200
    env:
      WEBHOOK_SECRET: ${{ secrets.WEBHOOK_SECRET }}

Gotchas

  • Sign the exact raw bytes the handler verifies; reserializing JSON changes the signature.
  • Test the rejection path too: send a bad signature and assert the handler returns 401.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →