Getting Started with LambdaOpenAPI
Get up and running with LambdaOpenAPI in minutes. This guide walks you through installation, basic configuration, and generating your first OpenAPI specification.
Prerequisites
Before you begin, ensure you have:
- .NET 6.0 or later installed
- AWS Lambda Annotations package in your project
- An existing AWS Lambda project (or create a new one)
If you're new to AWS Lambda Annotations, check out the official AWS documentation to get started.
Installation
Add LambdaOpenAPI to your AWS Lambda project via NuGet:
dotnet add package Oproto.Lambda.OpenApi
That's it! The source generator will automatically integrate with your build process.
Basic Usage
Step 1: Decorate Your Lambda Functions
Add OpenAPI attributes to your Lambda functions to describe your API:
using Amazon.Lambda.Annotations;
using Amazon.Lambda.Annotations.APIGateway;
using Oproto.Lambda.OpenApi.Attributes;
// Assembly-level API info (in AssemblyInfo.cs or any .cs file)
[assembly: OpenApiInfo("My API", "1.0.0", Description = "API for managing resources")]
public class Functions
{
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Get, "/users/{userId}")]
[OpenApiOperation(Summary = "Get user by ID")]
[OpenApiTag("Users")]
public async Task<APIGatewayProxyResponse> GetUser(
[FromRoute] string userId,
[FromQuery] bool includeDetails = false)
{
// Your implementation
return new APIGatewayProxyResponse
{
StatusCode = 200,
Body = JsonSerializer.Serialize(new { UserId = userId })
};
}
}
Step 2: Build Your Project
When you build your project, the OpenAPI specification is automatically generated:
dotnet build
This creates an openapi.json file in your project directory — no manual YAML editing required!
Step 3: View Your Generated Specification
The generated OpenAPI specification includes:
- ✅ Endpoint definitions with paths and HTTP methods
- ✅ Parameter schemas for route, query, header, and body parameters
- ✅ Response schemas based on your return types
- ✅ Tags and descriptions for organization and documentation
Available Attributes
LambdaOpenAPI provides several attributes to customize your API documentation. All attributes are in the Oproto.Lambda.OpenApi.Attributes namespace:
Assembly-Level Attributes
Configure your API at the assembly level (typically in AssemblyInfo.cs or any .cs file):
| Attribute | Purpose |
|---|---|
[OpenApiInfo] | Sets API title, version, description, and metadata |
[OpenApiSecurityScheme] | Defines security schemes (API Key, OAuth2, etc.) |
[OpenApiServer] | Defines server URLs (production, staging, etc.) |
[OpenApiTagDefinition] | Defines tags with descriptions |
[OpenApiTagGroup] | Groups tags for hierarchical navigation (x-tagGroups) |
[OpenApiExternalDocs] | Links to external API documentation |
[OpenApiExampleConfig] | Configures automatic example generation |
[OpenApiOutput] | Specifies output file configuration |
Method-Level Attributes
| Attribute | Purpose |
|---|---|
[OpenApiOperation] | Adds operation metadata (summary, description) |
[OpenApiOperationId] | Custom operation IDs for code generators |
[OpenApiTag] | Groups operations by tags |
[OpenApiResponseType] | Documents response types for IHttpResult methods |
[OpenApiResponseHeader] | Documents response headers |
[OpenApiExample] | Provides request/response examples |
[OpenApiExternalDocs] | Links to external documentation |
Property/Parameter Attributes
| Attribute | Purpose |
|---|---|
[OpenApiSchema] | Customizes type schemas with validation rules |
[OpenApiIgnore] | Excludes properties from schemas |
Important Behaviors
FromServices Parameters Are Excluded
Parameters decorated with [FromServices] are automatically excluded from the OpenAPI specification. These are dependency injection parameters that are not part of the HTTP API contract:
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Get, "/products")]
public async Task<IEnumerable<Product>> GetProducts(
[FromServices] IProductService productService, // Excluded from OpenAPI
[FromQuery] int limit = 10) // Included in OpenAPI
{
return await productService.GetProducts(limit);
}
API Gateway Integration Extension
The generated OpenAPI specification includes the x-amazon-apigateway-integration extension for each operation. This extension is required for deploying to AWS API Gateway:
{
"x-amazon-apigateway-integration": {
"type": "aws_proxy",
"httpMethod": "POST",
"uri": "${LambdaFunctionArn}",
"payloadFormatVersion": "2.0"
}
}
The payloadFormatVersion is automatically set based on the API type:
2.0for HTTP APIs ([HttpApi])1.0for REST APIs ([RestApi])
Async Return Types
The generator automatically unwraps Task<T> and ValueTask<T> return types. For example:
// This method returns Task<Product>
public async Task<Product> GetProduct(string id) { ... }
// The OpenAPI response schema will be for Product, not Task<Product>
Methods returning non-generic Task or ValueTask generate a 204 No Content response.
IHttpResult Return Types
When your Lambda functions return IHttpResult (from Lambda Annotations), the generator cannot infer the actual response type. Use [OpenApiResponseType] to explicitly document responses:
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Get, "/products/{id}")]
[OpenApiResponseType(typeof(Product), 200, Description = "Returns the product")]
[OpenApiResponseType(typeof(ErrorResponse), 404, Description = "Product not found")]
public async Task<IHttpResult> GetProduct(string id)
{
var product = await _service.GetProduct(id);
if (product == null)
return HttpResults.NotFound(new ErrorResponse { Message = "Not found" });
return HttpResults.Ok(product);
}
Deprecation with [Obsolete]
The generator automatically detects the standard .NET [Obsolete] attribute and marks operations as deprecated:
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Delete, "/products/{id}")]
[Obsolete("Use the archive endpoint instead. This will be removed in v2.0.")]
public Task DeleteProduct(string id)
{
// Implementation
}
Response Headers
Document response headers using [OpenApiResponseHeader]:
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Get, "/products")]
[OpenApiResponseHeader("X-Total-Count", Description = "Total products", Type = typeof(int))]
[OpenApiResponseHeader("X-Page-Size", Description = "Page size", Type = typeof(int))]
public Task<IEnumerable<Product>> GetProducts([FromQuery] int page = 1)
{
// Implementation
}
Request and Response Examples
Provide JSON examples using [OpenApiExample]:
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Post, "/products")]
[OpenApiExample("Create Request",
"{\"name\": \"Widget\", \"price\": 19.99}",
IsRequestExample = true)]
[OpenApiExample("Success Response",
"{\"id\": \"123\", \"name\": \"Widget\", \"price\": 19.99}",
StatusCode = 200)]
public Task<Product> CreateProduct([FromBody] CreateProductRequest request)
{
// Implementation
}
Operation IDs
Customize operation IDs for code generators using [OpenApiOperationId]:
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Get, "/products")]
[OpenApiOperationId("listAllProducts")]
public Task<IEnumerable<Product>> GetProducts()
{
// Implementation
}
AOT Compatibility
LambdaOpenAPI fully supports Native AOT builds without any special configuration. The OpenAPI specification is extracted during the Build phase (before AOT compilation) using MetadataLoadContext, so it works seamlessly with AOT projects.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Oproto.Lambda.OpenApi" Version="1.0.0" />
</ItemGroup>
</Project>
See the Configuration Options for more details.
Security Schemes
Security schemes are only added to the OpenAPI specification when you define them using assembly-level attributes:
// In your project (e.g., AssemblyInfo.cs)
[assembly: OpenApiSecurityScheme("apiKey",
Type = OpenApiSecuritySchemeType.ApiKey,
ApiKeyName = "x-api-key",
ApiKeyLocation = ApiKeyLocation.Header)]
OAuth2 Example:
[assembly: OpenApiSecurityScheme("oauth2",
Type = OpenApiSecuritySchemeType.OAuth2,
AuthorizationUrl = "https://auth.example.com/authorize",
TokenUrl = "https://auth.example.com/token",
Scopes = "read:Read access,write:Write access")]
See the Attribute Reference for more details.
Next Steps
Ready to dive deeper? Check out these resources:
- Attribute Reference — Complete documentation for all attributes
- Configuration Options — Advanced MSBuild configuration
LambdaOpenAPI generates your OpenAPI spec at build time using source generators. There's no runtime reflection or scanning, making it perfect for Native AOT deployments with fast cold starts.