I need help setting up webhook validation for my Shopify store using AWS Lambda and Node.js.
My Setup
I created a webhook in my Shopify admin under Settings > Notifications > Webhooks for new orders. The webhook points to my AWS API Gateway endpoint which triggers a Lambda function. I’m using a proxy integration to get the full HTTP request.
The Problem
I’m trying to use the Shopify Node.js SDK to validate incoming webhooks, but I’m confused about a few things:
How do I get the raw request and response objects in Lambda? In Express I would use req and res but I’m not using Express here.
Where should I use the webhook signing secret that Shopify gave me? Is this the ACCESS_TOKEN or something else?
My Current Code
import "@shopify/shopify-api/adapters/node";
import { shopifyApi } from "@shopify/shopify-api";
const STORE_DOMAIN = 'my-store-name';
const API_TOKEN = 'my_api_token';
const shopifyClient = shopifyApi({
shopName: STORE_DOMAIN,
accessToken: API_TOKEN
});
exports.handler = async (event, context) => {
const {isValid, topic, domain} = await shopifyClient.webhooks.validate({
rawBody: ??, // how to get request body as string?
rawRequest: ??, // what goes here in Lambda?
rawResponse: ?? // what goes here in Lambda?
});
if (!isValid) {
return {
statusCode: 401
};
}
// handle webhook data here
}
The validation method needs three parameters but I’m not sure how to provide them in the Lambda environment. Any examples would be really helpful!
Been down this rabbit hole way too many times with Lambda webhooks. Yeah, manual validation works, but there’s a much cleaner approach.
Skip wrestling with Lambda event objects and custom wrappers - I automated the entire webhook pipeline with Latenode. It hooks straight into Shopify webhooks without decoding event.body or messing with API Gateway configs.
Latenode handles HMAC validation automatically using your webhook secret (different from your API token - check individual webhook settings). No more header parsing or base64 encoding headaches.
I build flows that catch Shopify webhooks, validate them, process data, and trigger whatever actions I need. Takes 10 minutes instead of hours debugging Lambda event structures.
Best part? Requirements change? Just modify the flow instead of redeploying functions. Way more flexible than hardcoded validation.
lambda’s event structure is completely different from express. you don’t get req/res objects - everything comes through the event parameter. use event.body for rawBody, but api gateway might base64 encode it depending on your setup. for rawRequest, just pass the event itself or build an object with headers from event.headers. set rawResponse to null in lambda context. that signing secret isn’t your access token - it’s a separate webhook-specific secret you’ll find on the webhook config page.
Hit this exact issue last month migrating our webhook processor. The rawRequest parameter wants a Node.js IncomingMessage-like object, but Lambda gives you an event structure instead. I built a simple wrapper that maps event.headers to headers property and event.body to the body.
The webhook secret’s completely separate from your API credentials - you’ll find it under ‘Webhook details’ when you edit the webhook in Shopify admin.
What got me was making sure the Content-Type in API Gateway binary media types matches exactly what Shopify sends. If it doesn’t, the body gets mangled during base64 encoding.
Also heads up - the validation method’s super strict about header formatting. You might need to normalize header names since API Gateway sometimes lowercases them while Shopify expects specific casing for HMAC calculation.
Had the exact same headache when I moved my webhook handlers to Lambda. The key thing is Lambda doesn’t give you Express-style request/response objects - you’ve got to pull everything from the event parameter API Gateway sends. For rawBody, use event.body but make sure API Gateway isn’t parsing it as JSON. You need the raw string for HMAC validation. Build rawRequest from event.headers and other event properties. For rawResponse, just pass null or an empty object since Lambda handles responses differently. Gotcha that bit me: the webhook secret lives in your individual webhook config in Shopify admin, not your app credentials. Look for ‘Webhook signature’ or something similar when editing the webhook. Also check your API Gateway integration type. With proxy integration, the body might come base64 encoded depending on content-type settings. I ended up writing a helper function to normalize Lambda events so the Shopify SDK could use them.
I encountered a similar issue transitioning from Express to Lambda a while ago. Remember, the webhook signing secret is not your API token; you can find it in the webhook settings after setting it up. In Lambda, you will need to manually construct the request and response objects. For the rawBody, use event.body, ensuring that binary media types are configured in API Gateway. Gather rawRequest headers from event.headers, and you can leave rawResponse empty since Lambda processes responses differently. Be cautious as API Gateway may base64 encode the body based on your content-type settings, so decoding may be necessary before validation. Also, ensure you’re correctly capturing the X-Shopify-Hmac-Sha256 header because API Gateway sometimes changes header names to lowercase. Once you align Lambda’s event structure with what the SDK requires, the validation process should become more straightforward. I even created a simple wrapper function to simplify this conversion.