AWS Lambda
Amazon API Gateway
POST `Parameters`
Serverless Computing
API Integration

How to pass a params from POST to AWS Lambda from Amazon API Gateway

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When API Gateway triggers a Lambda function from an HTTP POST, the data does not arrive as ordinary function arguments. It arrives inside the Lambda event object. The easiest and most common setup is Lambda proxy integration, where API Gateway forwards the request body, headers, query string parameters, and path parameters in a standard event shape.

The Simplest Model: JSON Body in a POST

Suppose the client sends this request:

bash
1curl -X POST \
2  https://example.execute-api.us-east-1.amazonaws.com/prod/items \
3  -H 'Content-Type: application/json' \
4  -d '{"name":"book","quantity":3}'

With proxy integration enabled, Lambda receives an event that includes a body field containing the raw JSON string.

A Python Lambda handler might look like this:

python
1import json
2
3
4def lambda_handler(event, context):
5    payload = json.loads(event["body"])
6
7    name = payload.get("name")
8    quantity = payload.get("quantity")
9
10    return {
11        "statusCode": 200,
12        "headers": {"Content-Type": "application/json"},
13        "body": json.dumps({
14            "received": {
15                "name": name,
16                "quantity": quantity,
17            }
18        }),
19    }

The important point is that the POST parameters are inside event["body"], not passed directly as top-level Python arguments.

What the Event Usually Contains

With Lambda proxy integration, API Gateway typically sends fields such as:

  • 'body'
  • 'headers'
  • 'queryStringParameters'
  • 'pathParameters'
  • 'httpMethod'
  • 'isBase64Encoded'

That means a single request can carry data in several places.

For example:

python
1import json
2
3
4def lambda_handler(event, context):
5    body = json.loads(event["body"]) if event.get("body") else {}
6    headers = event.get("headers") or {}
7    query = event.get("queryStringParameters") or {}
8    path = event.get("pathParameters") or {}
9
10    return {
11        "statusCode": 200,
12        "body": json.dumps({
13            "body": body,
14            "headers": headers,
15            "query": query,
16            "path": path,
17        }),
18    }

This is useful when your endpoint mixes a JSON body with route parameters or query filters.

Path Parameters and Query Parameters

If the route is something like /users/{id} and the caller also sends ?verbose=true, the Lambda event usually contains:

  • 'event["pathParameters"]["id"]'
  • 'event["queryStringParameters"]["verbose"]'

Example:

python
1import json
2
3
4def lambda_handler(event, context):
5    user_id = event.get("pathParameters", {}).get("id")
6    verbose = event.get("queryStringParameters", {}).get("verbose")
7
8    return {
9        "statusCode": 200,
10        "body": json.dumps({
11            "user_id": user_id,
12            "verbose": verbose,
13        }),
14    }

This is separate from the JSON POST body. API Gateway keeps these sources distinct.

If You Use Form-Encoded POST Data

Not every POST request is JSON. A client may send form data such as:

text
name=book&quantity=3

In that case, the body still arrives as a string, but you parse it differently:

python
1import json
2from urllib.parse import parse_qs
3
4
5def lambda_handler(event, context):
6    raw_body = event.get("body") or ""
7    form = parse_qs(raw_body)
8
9    return {
10        "statusCode": 200,
11        "body": json.dumps({
12            "name": form.get("name", [None])[0],
13            "quantity": form.get("quantity", [None])[0],
14        }),
15    }

So the transport format matters. JSON and form encoding are parsed differently even though both arrive through POST.

Non-Proxy Integration Works Differently

If you are not using Lambda proxy integration, API Gateway can transform the request before Lambda sees it. In that case, you define a mapping template and decide exactly what shape Lambda receives.

For example, a mapping template might build a custom JSON object that pulls from body and query fields. That approach is still valid, but it is more work and usually unnecessary unless you need strict transformation or backward compatibility.

For new serverless APIs, proxy integration is usually the simpler starting point because the event shape is predictable and the Lambda code does the parsing.

Common Pitfalls

The biggest pitfall is expecting POST fields to appear as normal Lambda function parameters. They do not. You always read them from the event.

Another common issue is forgetting to json.loads(event["body"]) when the client sends JSON. The body arrives as a string, not as a parsed Python dictionary.

People also often confuse body parameters with query parameters. In API Gateway they are separate parts of the event, and your code needs to read the right one.

Finally, watch for None values. queryStringParameters and pathParameters may be missing entirely, so defaulting to an empty dictionary makes the handler more robust.

Summary

  • With API Gateway and Lambda proxy integration, POST data arrives inside the Lambda event.
  • JSON POST bodies usually live in event["body"] and must be parsed.
  • Query parameters and path parameters are separate from the body.
  • Form-encoded requests need different parsing than JSON requests.
  • Proxy integration is usually the simplest setup unless you specifically need custom mapping templates.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design