Tutorial: Creating a webhook endpoint using a Lambda function URL
In this tutorial, you create a Lambda function URL to implement a webhook endpoint. A webhook is a lightweight, event-driven communication that automatically sends data between applications using HTTP. You can use a webhook to receive immediate updates about events happening in another system, such as when a new customer signs up on a website, a payment is processed, or a file is uploaded.
With Lambda, webhooks can be implemented using either Lambda function URLs or API Gateway. Function URLs are a good choice for simple webhooks that don't require features like advanced authorization or request validation.
Tip
If you're not sure which solution is best for your particular use case, see Select a method to invoke your Lambda function using an HTTP request.
Prerequisites
To complete this tutorial, you must have either Python (version 3.8 or later) or Node.js (version 18 or later) installed on your local machine.
To test the endpoint using an HTTP request, the tutorial uses curl
Create the Lambda function
First create the Lambda function that runs when an HTTP request is sent to your webhook endpoint. In this example, the sending application sends an update whenever a payment is submitted and indicates in the body of the HTTP request whether the payment was successful. The Lambda function parses the request and takes action according to the status of the payment. In this example, the code just prints the order ID for the payment, but in a real application, you might add the order to a database or send a notification.
The function also implements the most common authentication method used for webhooks, hash-based message authentication (HMAC). With this method, both the sending and receiving applications share a secret key. The sending application uses a hashing algorithm to generate a unique signature using this key together with the message content, and includes the signature in the webhook request as an HTTP header. The receiving application then repeats this step, generating the signature using the secret key, and compares the resulting value with the signature sent in the request header. If the result matches, the request is considered legitimate.
Create the function using the Lambda console with either the Python or Node.js runtime.
Create the secret key
For the Lambda function to authenticate the webhook request, it uses a secret key which it shares with the calling application. In this example, the key is stored in an environment variable. In a production application, we recommend that you use AWS Secrets Manager as a more secure option. To learn more about using Secrets Manager to store secret keys, see Create an AWS Secrets Manager secret and Get secrets from AWS Secrets Manager in the AWS Secrets Manager User Guide.
Create and store the webhook secret key
-
Generate a long, random string using a cryptographically secure random number generator. You can use the following code snippets in Python or Node.js to generate and print a 32-character secret, or use your own preferred method.
-
Store your generated string as an environment variable for your function by doing the following:
-
In the Configuration tab for your function, select Environment variables.
-
Choose Edit.
-
Choose Add environment variable.
-
For Key, enter
WEBHOOK_SECRET
, then for Value, enter the secret you generated in the previous step. -
Choose Save.
-
You'll need to use this secret again later in the tutorial to test your function, so make a note of it now.
Create the function URL endpoint
Create an endpoint for your webhook using a Lambda function URL. Beacuse you use the auth type of NONE
to create an endpoint with public access,
anyone with the URL can invoke your function. To learn more about controlling access to function URLs, see Control access to Lambda function URLs.
If you need more advanced authentication options for your webhook, consider using API Gateway.
Create the function URL endpoint
-
In the Configuration tab for your function, select Function URL.
-
Choose Create function URL.
-
For Auth type, select NONE.
-
Choose Save.
The endpoint for the function URL you just created is displayed in the Function URL pane. Copy the endpoint to use later in the tutorial.
Test the function in the console
Before using an HTTP request to invoke your function using the URL endpoint, test it in the console to confirm your code is working as expected.
To verify the function in the console, you first calculate a webhook signature using the secret you generated earlier in the tutorial with the following test JSON payload:
{ "type": "payment.success", "orderId": "1234", "amount": "99.99" }
Use either of the following Python or Node.js code examples to calculate the webhook signature using your own secret.
You can now test your function code using a test HTTP request in the console.
Test the function in the console
-
Select the Code tab for your function.
-
In the TEST EVENTS section, choose Create new test event
-
For Event Name, enter
myEvent
. -
Replace the existing JSON by copying and pasting the following into the Event JSON pane. Replace the webhook signature with the value you calculated in the previous step.
{ "headers": { "Content-Type": "application/json", "x-webhook-signature": "
2d672e7a0423fab740fbc040e801d1241f2df32d2ffd8989617a599486553e2a
" }, "body": "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}" } -
Choose Save.
-
Choose Invoke.
You should see output similar to the following:
Test the function using an HTTP request
Use the curl command line tool to test your webhook endpoint.
Test the function using HTTP requests
-
In a terminal or shell program, run the following curl command. Replace the URL with the value for your own function URL endpoint and replace the webhook signature with the signature you calculated using your own secret key.
curl -X POST
https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/
\ -H "Content-Type: application/json" \ -H "x-webhook-signature:d5f52b76ffba65ff60ea73da67bdf1fc5825d4db56b5d3ffa0b64b7cb85ef48b
" \ -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'You should see the following output:
{"received": true}
-
Inspect the CloudWatch logs for your function to confirm it parsed the payload correctly by doing the following:
-
Open the Logs group
page in the Amazon CloudWatch console. -
Select your function's log group (
/aws/lambda/myLambdaWebhook
). -
Select the most recent log stream.
You should see output similar to the following in your function's logs:
-
-
Confirm that your code detects an invalid signature by running the following curl command. Replace the URL with your own function URL endpoint.
curl -X POST
https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/
\ -H "Content-Type: application/json" \ -H "x-webhook-signature: abcdefg" \ -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'You should see the following output:
{"error": "Invalid signature"}
Clean up your resources
You can now delete the resources that you created for this tutorial, unless you want to retain them. By deleting AWS resources that you're no longer using, you prevent unnecessary charges to your AWS account.
To delete the Lambda function
-
Open the Functions page
of the Lambda console. -
Select the function that you created.
-
Choose Actions, Delete.
-
Type
confirm
in the text input field and choose Delete.
When you created the Lambda function in the console, Lambda also created an execution role for your function.
To delete the execution role
-
Open the Roles page
of the IAM console. -
Select the execution role that Lambda created. The role has the name format
myLambdaWebhook-role-<random string>
. -
Choose Delete.
-
Enter the name of the role in the text input field and choose Delete.