Skip to main content

Lambda API Decorators

Lightweight, CDK-free Python decorators for declaring AWS Lambda API routes and configuration intent. The package records ordered metadata, preserves the original callable, creates no infrastructure, and performs no request routing at runtime. Read the central documentation for the complete architecture.

lambda-api-decorators-cdk can interpret this metadata to create independent Lambda functions and connect them to API Gateway. Sharing a Python module does not create a runtime router or imply one monolithic Lambda.

Installation and compatibility

pip install lambda-api-decorators

The package supports Python 3.9–3.14 and has no runtime dependencies. The CDK consumer is a separate package:

pip install lambda-api-decorators-cdk

The two packages are released and versioned independently.

Quick start

This complete example declares one route, returns a proxy-compatible JSON response, and adds configuration and permission metadata:

import json

from lambda_api_decorators import GET, environment, permission, runtime


@GET("/health")
@runtime("python3.12")
@environment("production")
@permission(actions=["logs:CreateLogGroup"], resources=["*"])
def health(event, context):
    return {
        "statusCode": 200,
        "headers": {"content-type": "application/json"},
        "body": json.dumps({"status": "ok"}),
    }

The decorators leave health callable as a normal Python function. A CDK-aware consumer reads its metadata when synthesizing infrastructure.

Routes

The public HTTP decorators are GET, POST, PUT, DELETE, and ANY. Each handler can declare at most one HTTP route. Applying a second route to the same function raises ValueError.

Several independently decorated functions may share a module:

from lambda_api_decorators import DELETE, GET, POST


@GET("/orders")
def list_orders(event, context):
    return {"statusCode": 200, "body": "[]"}


@POST("/orders")
def create_order(event, context):
    return {"statusCode": 201, "body": "{}"}


@DELETE("/orders/{order_id}")
def delete_order(event, context):
    return {"statusCode": 204, "body": ""}

lambda-api-decorators-cdk can turn these handlers into separate Lambdas. There is no runtime routing layer and sharing a file does not make a single Lambda or a route accumulator.

This is intentionally invalid:

from lambda_api_decorators import GET, POST


@GET("/orders")
@POST("/orders")
def invalid_handler(event, context):
    return {"statusCode": 200, "body": "invalid"}

It raises ValueError while the decorators are applied.

Lambda configuration metadata

The configuration decorators and their public argument shapes are:

from lambda_api_decorators import (
    description,
    environment,
    layer,
    memory_size,
    name,
    role,
    runtime,
    security_group,
    timeout,
    vpc,
)


@runtime("python3.12")
@timeout(30)
@memory_size(512)
@name("orders-handler")
@description("Handles orders")
@role("orders-role")
@vpc("application-vpc")
@environment("production")
@layer("shared")
@security_group("orders-sg")
def configured_handler(event, context):
    return {"statusCode": 200, "body": "ok"}

The logical keys for roles, VPCs, environments, Layers, and security groups are resolved by the infrastructure consumer. The runtime package does not own or expose those registries and does not apply IAM or create AWS resources.

Authentication

Use one authentication declaration per handler:

from lambda_api_decorators import GET, authorizer, public


@GET("/users/me")
@authorizer("users")
def me(event, context):
    return {"statusCode": 200, "body": "{}"}


@GET("/health")
@public
def health(event, context):
    return {"statusCode": 200, "body": "ok"}

@public is used without parentheses. A handler accepts one authentication declaration, and authentication is independent from its route declaration.

current_user

current_user(event) reads claims already placed in an authorized API Gateway event. It supports both shapes:

  • REST API: requestContext.authorizer.claims
  • HTTP API v2 JWT: requestContext.authorizer.jwt.claims

It returns a frozen CurrentUser with subject, optional username, and read-only claims. subject comes from the sub claim. username prefers cognito:username and then username. Malformed or missing identity data raises CurrentUserError.

from lambda_api_decorators import CurrentUser, CurrentUserError, current_user


def identify(event, context):
    try:
        user: CurrentUser = current_user(event)
    except CurrentUserError:
        return {"statusCode": 401, "body": "unauthorized"}
    return {"statusCode": 200, "body": user.subject}

This helper does not verify tokens, authenticate, authorize, or call AWS. It only extracts and validates the supported claim shape.

Permissions

DynamoDB and S3 grants accept a logical registry key or a physical name, and an access value of read or write:

from lambda_api_decorators import grant_dynamodb, grant_s3


@grant_dynamodb("orders", "read")
@grant_dynamodb("orders", "write")
@grant_s3("documents", "read")
def orders(event, context):
    return {"statusCode": 200, "body": "ok"}

The physical-name forms are also valid:

from lambda_api_decorators import grant_dynamodb, grant_s3


@grant_dynamodb(table_name="orders-prod", access="read")
@grant_s3(bucket_name="documents-prod", access="read")
def physical_resources(event, context):
    return {"statusCode": 200, "body": "ok"}

Exactly one of the logical key (resource_key) and physical name must be provided. read is a read grant; write represents the native cumulative read/write grant. There is no third combined access value. These decorators record intent and do not apply IAM by themselves.

For minimal custom IAM statements, use permission:

from lambda_api_decorators import permission


@permission(actions=["events:PutEvents"], resources=["arn:aws:events:*:*:event-bus/orders"])
def publish(event, context):
    return {"statusCode": 202, "body": "accepted"}

Its contract is limited to actions and resources. It does not support conditions, principals, effect, not_actions, or sid.

Metadata model

Declarations are recorded in lexical order as independent invocations, while the original callable and its behavior are preserved. This makes the metadata straightforward to inspect without adding a runtime framework. The package is deliberately CDK-free; infrastructure interpretation belongs to the separate CDK package.

Releases

Tags are the source of the package version through setuptools-scm. Release the runtime package independently from the CDK package:

git switch main
git pull --ff-only
git tag vX.Y.Z
git push origin vX.Y.Z

The release workflow validates the tag and uses PyPI trusted publishing.

Release files for lambda-api-decorators 0.3.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lambda-api-decorators 0.3.3
File Size Uploaded
lambda_api_decorators-0.3.3.tar.gz 23.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lambda-api-decorators 0.3.3
File Interpreter ABI Platform
lambda_api_decorators-0.3.3-py3-none-any.whl Python 3 none any Details

Total release size: 33.4 kB

Release files / lambda_api_decorators-0.3.3.tar.gz

Download URL lambda_api_decorators-0.3.3.tar.gz
Size 23.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c623c695bab8d711bfed0edf937587ebf27a27a100f50cdd85212242ad2ec28f
BLAKE2b-256 checksum
How to use checksums
19a71293fb0bd6319926998aeed5087d86de1652515a6a5d96b28a09333824ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / lambda_api_decorators-0.3.3-py3-none-any.whl

Download URL lambda_api_decorators-0.3.3-py3-none-any.whl
Size 9.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f936d5aabc6eda68eadebf4d7a564f65739d325d530429eefca6ddc53c3a9e8d
BLAKE2b-256 checksum
How to use checksums
159e3be591346e5f927c27fa893a2741457bdd35467bddb89ba0d205b81e6cd4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.3 This release

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page