API Gateway + Lambda Setup Guide
Complete step-by-step guide to set up API Gateway with Lambda for HashPass API routes.
Prerequisites
- AWS Account with appropriate permissions
- AWS CLI installed and configured
- Node.js 18+ installed
- Project built (
npm run build:mobile)
Step 1: Create IAM Role for Lambda
- Go to IAM Console → Roles → Create Role
- Select: AWS Lambda
- Attach policies:
AWSLambdaBasicExecutionRole(for CloudWatch logs)- Add any other permissions your API needs (e.g., VPC, S3, etc.)
- Name:
hashpass-lambda-execution-role - Note the Role ARN (you'll need it in Step 3)
Step 2: Build and Package Lambda Function
# 1. Build the project
npm run build:mobile
# 2. Create Lambda package directory
mkdir -p lambda-package
cd lambda-package
# 3. Copy Lambda handler
cp ../packages/infra/lambda/index.js .
cp ../packages/infra/lambda/package.json .
# 4. Copy server build (needed by Expo Server)
cp -r ../dist/server ./server
# 5. Install dependencies
npm install --production
# 6. Create deployment package
zip -r ../lambda-deployment.zip . -x "*.git*" "*.DS_Store*"
cd ..
Step 3: Create Lambda Function
# Replace ACCOUNT_ID and ROLE_NAME with your values
aws lambda create-function \
--function-name hashpass-api-handler \
--runtime nodejs20.x \
--role arn:aws:iam::ACCOUNT_ID:role/hashpass-lambda-execution-role \
--handler index.handler \
--zip-file fileb://lambda-deployment.zip \
--timeout 30 \
--memory-size 512 \
--region us-east-1
Or use AWS Console:
- Go to Lambda Console → Create Function
- Name:
hashpass-api-handler - Runtime: Node.js 20.x
- Architecture: x86_64
- Execution role: Use existing role → Select
hashpass-lambda-execution-role - Upload deployment package:
lambda-deployment.zip - Handler:
index.handler - Timeout: 30 seconds
- Memory: 512 MB
Step 4: Create API Gateway REST API
4.1 Create API
aws apigateway create-rest-api \
--name hashpassApi \
--description "HashPass API Gateway" \
--region us-east-1
Or use AWS Console:
- Go to API Gateway Console → Create API
- Choose REST API → Build
- Protocol: REST
- Create new API: New API
- API name:
hashpassApi - Endpoint Type: Regional
- Create API
4.2 Get Root Resource ID
API_ID="YOUR_API_ID" # From previous step
ROOT_RESOURCE_ID=$(aws apigateway get-resources --rest-api-id $API_ID --query 'items[0].id' --output text)
4.3 Create /api Resource
aws apigateway create-resource \
--rest-api-id $API_ID \
--parent-id $ROOT_RESOURCE_ID \
--path-part api \
--region us-east-1
Or use AWS Console:
- In API Gateway → Your API → Resources
- Select "/" (root)
- Actions → Create Resource
- Resource Name:
api - Resource Path:
/api - Create Resource
4.4 Create /api/{proxy+} Resource
API_RESOURCE_ID="YOUR_API_RESOURCE_ID" # From previous step
aws apigateway create-resource \
--rest-api-id $API_ID \
--parent-id $API_RESOURCE_ID \
--path-part "{proxy+}" \
--region us-east-1
Or use AWS Console:
- Select
/apiresource - Actions → Create Resource
- Resource Name:
{proxy+} - Resource Path:
/api/{proxy+} - ✅ Enable Proxy Integration
- Create Resource
4.5 Create ANY Method
PROXY_RESOURCE_ID="YOUR_PROXY_RESOURCE_ID" # From previous step
aws apigateway put-method \
--rest-api-id $API_ID \
--resource-id $PROXY_RESOURCE_ID \
--http-method ANY \
--authorization-type NONE \
--region us-east-1
Or use AWS Console:
- Select
/api/{proxy+}resource - Actions → Create Method → ANY
- Integration type: Lambda Function
- ✅ Use Lambda Proxy Integration
- Lambda Function:
hashpass-api-handler - Region:
us-east-1(or your region) - Save → OK (when prompted to give API Gateway permission)
4.6 Deploy API
aws apigateway create-deployment \
--rest-api-id $API_ID \
--stage-name prod \
--region us-east-1
Or use AWS Console:
- Actions → Deploy API
- Deployment stage:
[New Stage]orprod - Stage name:
prod - Stage description:
Production - Deploy
Note the Invoke URL (e.g., https://YOUR_API_ID.execute-api.us-east-1.amazonaws.com/prod)
Step 5: Configure Custom Domain
5.1 Request ACM Certificate (if not exists)
aws acm request-certificate \
--domain-name "*.hashpass.tech" \
--validation-method DNS \
--region us-east-1
Or use AWS Console:
- Go to ACM Console → Request Certificate
- Domain name:
*.hashpass.tech - Validation method: DNS
- Request
Wait for validation and add DNS records as instructed.
5.2 Create Custom Domain in API Gateway
CERT_ARN="arn:aws:acm:us-east-1:ACCOUNT_ID:certificate/CERT_ID"
aws apigatewayv2 create-domain-name \
--domain-name api.hashpass.tech \
--domain-name-configurations CertificateArn=$CERT_ARN \
--region us-east-1
Or use AWS Console:
- Go to API Gateway → Custom Domain Names → Create
- Domain name:
api.hashpass.tech - Certificate: Select your ACM certificate
- Create
5.3 Create API Mapping
DOMAIN_NAME_ID="YOUR_DOMAIN_NAME_ID" # From previous step
aws apigatewayv2 create-api-mapping \
--domain-name api.hashpass.tech \
--api-id $API_ID \
--stage prod \
--api-mapping-key "" \
--region us-east-1
Or use AWS Console:
- Select
api.hashpass.techdomain - API mappings → Configure API mappings
- API: Select
hashpassApi - Stage:
prod - Path: (leave empty)
- Save
5.4 Get Target Domain
aws apigatewayv2 get-domain-name \
--domain-name api.hashpass.tech \
--query 'DomainNameConfigurations[0].TargetDomainName' \
--output text \
--region us-east-1
Note this domain (e.g., d-xxxxx.execute-api.us-east-1.amazonaws.com)
Step 6: Update DNS
- Go to Route 53 → Hosted Zones →
hashpass.tech - Find or create CNAME record:
- Name:
api - Type:
CNAME - Value: Target domain from Step 5.4
- TTL:
300
- Name:
- Save
Wait for DNS propagation (5-15 minutes, can take up to 48 hours)
Step 7: Test
# Test API Gateway directly
curl https://YOUR_API_ID.execute-api.us-east-1.amazonaws.com/prod/api/config/versions
# Test custom domain (after DNS propagation)
curl https://api.hashpass.tech/api/config/versions
Step 8: Update Lambda Function (when code changes)
# Rebuild and repackage
npm run build:mobile
cd lambda-package
rm -rf node_modules server
cp -r ../dist/server ./server
npm install --production
zip -r ../lambda-deployment.zip . -x "*.git*" "*.DS_Store*"
cd ..
# Update Lambda function
aws lambda update-function-code \
--function-name hashpass-api-handler \
--zip-file fileb://lambda-deployment.zip \
--region us-east-1
Troubleshooting
Lambda Function Errors
- Check CloudWatch Logs: Lambda Console → Function → Monitor → View logs
- Verify
dist/serveris included in deployment package - Check that
@expo/serveris installed
API Gateway 404
- Verify resource path:
/api/{proxy+} - Check method is configured (ANY)
- Verify Lambda integration is set up
- Check API is deployed to a stage
Custom Domain Issues
- Verify ACM certificate is validated
- Check DNS CNAME record is correct
- Wait for DNS propagation
- Verify API mapping is configured
CORS Errors
- Lambda handler already includes CORS headers
- If still issues, configure CORS in API Gateway:
- Enable CORS on
/api/{proxy+}resource - Allow methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
- Allow headers: Content-Type, Authorization
- Enable CORS on
Cost Estimation
- API Gateway: First 1M requests/month free, then $3.50 per million
- Lambda: First 1M requests/month free, then $0.20 per million
- Data Transfer: First 1GB/month free, then $0.09/GB
For most use cases, this should be within the free tier.
Next Steps
After setup is complete:
- Test all API endpoints
- Monitor CloudWatch logs
- Set up CloudWatch alarms for errors
- Configure API Gateway throttling if needed