AWS Lambda lets you run code without managing servers. Deploy a webhook handler that processes InstantDM events, scales automatically, and costs nearly nothing at low volume.
Why AWS Lambda?
- Zero infrastructure - no servers to manage, patch, or scale
- Pay per request - first 1M requests/month are free
- Auto-scaling - handles traffic spikes without configuration
- AWS ecosystem - easy integration with DynamoDB, SES, SQS, and more
What You'll Need
| Requirement | Details |
|---|---|
| InstantDM account | Trendsetter+ plan with API access |
| AWS account | Free tier eligible |
| AWS CLI | Installed and configured |
Lambda Function
// index.mjs
export const handler = async (event) => {
const body = JSON.parse(event.body);
const { event: eventType, timestamp, data } = body;
console.log(`Event: ${eventType} from @${data.username}`);
if (eventType === 'flow_completed') {
const name = data.response_variables?.full_name || 'there';
// Send a follow-up DM
await fetch('https://api.instantdm.com/api-webhook', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.INSTANTDM_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'send_message',
type: 'text',
recipient_id: data.instagram_user_id,
message: `Thanks ${name}! We'll follow up shortly.`,
}),
});
// Save to DynamoDB (optional)
// await saveToDynamoDB(data);
}
return { statusCode: 200, body: JSON.stringify({ status: 'ok' }) };
};
Setup with API Gateway
- Create the Lambda function in AWS Console.
- Add an API Gateway trigger (HTTP API).
- Copy the API Gateway URL.
- Paste it into InstantDM Settings → API → Webhook URL.
- Set the
INSTANTDM_API_KEYenvironment variable in Lambda.
Using SAM (Serverless Application Model)
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
WebhookFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs20.x
Timeout: 30
Environment:
Variables:
INSTANTDM_API_KEY: !Ref InstantDMApiKey
Events:
Webhook:
Type: HttpApi
Properties:
Path: /webhook
Method: POST
Parameters:
InstantDMApiKey:
Type: String
NoEcho: true
Deploy:
sam build && sam deploy --guided
Saving to DynamoDB
import { DynamoDBClient, PutItemCommand } from '@aws-sdk/client-dynamodb';
const dynamo = new DynamoDBClient({});
async function saveToDynamoDB(data) {
await dynamo.send(new PutItemCommand({
TableName: 'instagram-leads',
Item: {
id: { S: `${data.instagram_user_id}-${Date.now()}` },
username: { S: data.username },
email: { S: data.response_variables?.email || '' },
flow_name: { S: data.flow_name || '' },
timestamp: { S: new Date().toISOString() },
},
}));
}
Troubleshooting
| Issue | Solution |
|---|---|
| Lambda timing out | Increase timeout to 30 seconds. Check that external API calls aren't hanging. |
| 502 Bad Gateway | Lambda must return { statusCode, body } format. Check the response structure. |
| Environment variable empty | Set it in Lambda Configuration → Environment variables, not in code. |
| Cold start latency | Use provisioned concurrency for consistent response times, or accept 1-2s cold starts. |
What's Next
- Deploy to Vercel for a simpler serverless option.
- Use Cloudflare Workers for edge computing.
- Read the Node.js backend guide for a traditional server.
- Explore the full API docs at instantdm.com/instagram-api-docs.