Lesson 8 of 21
Building REST APIs with API Gateway
Build serverless REST APIs with AWS API Gateway — resources, methods, Lambda integration, authorization, throttling, and deployment stages.
What you'll learn
- ✓How API Gateway creates serverless HTTP APIs
- ✓REST API vs HTTP API — when to use which
- ✓Lambda proxy integration
- ✓Authorization, throttling, and CORS
Prerequisites
- •AWS Lambda basics
- •Understanding of REST API concepts
API Gateway is a fully managed service that creates, publishes, and manages REST APIs. Combined with Lambda, it gives you a serverless backend that scales automatically.
REST API vs HTTP API
AWS offers two types:
| Feature | REST API | HTTP API |
|---|---|---|
| Cost | $3.50/million | $1.00/million |
| Features | Full (caching, WAF, usage plans) | Basic |
| Latency | ~30ms overhead | ~10ms overhead |
| Auth | IAM, Cognito, Lambda authorizers | IAM, JWT |
Use HTTP API for simple Lambda-backed APIs. Use REST API when you need caching, request validation, or API keys.
Creating a REST API with SAM
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
Handler: app.handler
Runtime: python3.12
Events:
GetUsers:
Type: Api
Properties:
Path: /users
Method: get
CreateUser:
Type: Api
Properties:
Path: /users
Method: post
GetUser:
Type: Api
Properties:
Path: /users/{userId}
Method: get
Lambda proxy integration
With proxy integration, API Gateway passes the full HTTP request to Lambda and expects a specific response format.
import json
def handler(event, context):
method = event["httpMethod"]
path = event["path"]
path_params = event.get("pathParameters") or {}
if method == "GET" and path == "/users":
return response(200, {"users": get_all_users()})
if method == "GET" and "userId" in path_params:
user = get_user(path_params["userId"])
if not user:
return response(404, {"error": "User not found"})
return response(200, user)
if method == "POST" and path == "/users":
body = json.loads(event.get("body") or "{}")
user = create_user(body)
return response(201, user)
return response(404, {"error": "Not found"})
def response(status_code, body):
return {
"statusCode": status_code,
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
"body": json.dumps(body),
}
CORS
Enable CORS for browser clients:
# SAM template
Globals:
Api:
Cors:
AllowMethods: "'GET,POST,PUT,DELETE'"
AllowHeaders: "'Content-Type,Authorization'"
AllowOrigin: "'https://myapp.com'"
Or handle it in Lambda:
def response(status_code, body):
return {
"statusCode": status_code,
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,PUT,DELETE",
"Access-Control-Allow-Headers": "Content-Type,Authorization",
},
"body": json.dumps(body),
}
Authorization
Cognito authorizer
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
Auth:
DefaultAuthorizer: CognitoAuthorizer
Authorizers:
CognitoAuthorizer:
UserPoolArn: !GetAtt UserPool.Arn
Lambda authorizer
def authorizer(event, context):
token = event.get("authorizationToken", "")
if validate_token(token):
return generate_policy("user", "Allow", event["methodArn"])
else:
return generate_policy("user", "Deny", event["methodArn"])
def generate_policy(principal, effect, resource):
return {
"principalId": principal,
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": effect,
"Resource": resource,
}],
},
}
Request validation
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
Models:
CreateUserModel:
type: object
required: [name, email]
properties:
name:
type: string
email:
type: string
format: email
Throttling
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
MethodSettings:
- HttpMethod: '*'
ResourcePath: '/*'
ThrottlingBurstLimit: 100
ThrottlingRateLimit: 50
Deployment stages
# Deploy to staging
sam deploy --stack-name my-api-staging --parameter-overrides Stage=staging
# Deploy to production
sam deploy --stack-name my-api-prod --parameter-overrides Stage=prod
Summary
API Gateway + Lambda gives you a serverless REST API that scales from zero to millions of requests. Use proxy integration for simplicity, Cognito or Lambda authorizers for security, and SAM templates for infrastructure as code. Start with HTTP API for cost efficiency and switch to REST API when you need advanced features.
Progress is saved locally to your browser.