
Receive Stripe, GitHub and generic webhooks on a Lambda Web Function, verify HMAC-SHA256 signatures and store each event once in DynamoDB.
POST /webhooks/{provider} runs four steps. First it verifies the signature with the provider's scheme: Stripe's stripe-signature header (timestamp plus HMAC-SHA256 over t.body), GitHub's x-hub-signature-256 header (sha256= prefix), or a generic x-webhook-signature hex digest. All comparisons use crypto.timingSafeEqual, and a missing or wrong signature returns 401 before the body is parsed. Second it parses the JSON. Third it derives a stable event id per provider (GitHub's x-github-delivery header, otherwise the payload id). Fourth it writes the event with a conditional PutItem on attribute_not_exists(eventId): the first delivery is stored and later redeliveries return 200 with duplicate: true, so provider retries are idempotent. A TTL attribute expires events after 30 days.NoEcho template parameters mapped to environment variables; in production load them from AWS Secrets Manager or SSM Parameter Store instead. POST /test/fire builds a correctly signed sample request for any provider so the flow can be exercised without an external account. It signs with the real secret, so it is gated by the EnableTestEndpoint parameter, which defaults to false. GET /events and GET /events/{eventId} read back what was stored.AWS::Serverless::WebFunction resource expands into AWS::Lambda::WebFunction, an immutable AWS::Lambda::WebFunctionRevision and an AWS::Lambda::WebFunctionEndpoint. The endpoint uses AuthType ApplicationManaged because providers cannot SigV4-sign their calls; the HMAC signature is the authentication. The explicit execution role carries CloudWatch Logs plus PutItem, GetItem and Scan scoped to the table ARN.git clone https://github.com/aws-samples/serverless-patterns/cd serverless-patterns/lambda-web-webhooks/nodejs/samSee the GitHub repo for deployment instructions.sam delete --stack-name lambda-web-webhooks-sam.