The aws:apigatewayv2/integration:Integration resource, part of the Pulumi AWS provider, defines how API Gateway V2 routes requests to backend services: Lambda functions, AWS services, or private endpoints. This guide focuses on three capabilities: Lambda proxy integrations, direct AWS service invocation, and VPC Link for private resources.
Integrations connect API Gateway V2 APIs to Lambda functions, AWS services, or load balancers via VPC Links. The examples are intentionally small. Combine them with your own API routes, authorizers, and deployment stages.
Route requests to Lambda functions
Most HTTP APIs route incoming requests to Lambda functions for serverless request handling.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.lambda.Function("example", {
code: new pulumi.asset.FileArchive("example.zip"),
name: "Example",
role: exampleAwsIamRole.arn,
handler: "index.handler",
runtime: aws.lambda.Runtime.NodeJS20dX,
});
const exampleIntegration = new aws.apigatewayv2.Integration("example", {
apiId: exampleAwsApigatewayv2Api.id,
integrationType: "AWS_PROXY",
connectionType: "INTERNET",
contentHandlingStrategy: "CONVERT_TO_TEXT",
description: "Lambda example",
integrationMethod: "POST",
integrationUri: example.invokeArn,
passthroughBehavior: "WHEN_NO_MATCH",
});
import pulumi
import pulumi_aws as aws
example = aws.lambda_.Function("example",
code=pulumi.FileArchive("example.zip"),
name="Example",
role=example_aws_iam_role["arn"],
handler="index.handler",
runtime=aws.lambda_.Runtime.NODE_JS20D_X)
example_integration = aws.apigatewayv2.Integration("example",
api_id=example_aws_apigatewayv2_api["id"],
integration_type="AWS_PROXY",
connection_type="INTERNET",
content_handling_strategy="CONVERT_TO_TEXT",
description="Lambda example",
integration_method="POST",
integration_uri=example.invoke_arn,
passthrough_behavior="WHEN_NO_MATCH")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigatewayv2"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := lambda.NewFunction(ctx, "example", &lambda.FunctionArgs{
Code: pulumi.NewFileArchive("example.zip"),
Name: pulumi.String("Example"),
Role: pulumi.Any(exampleAwsIamRole.Arn),
Handler: pulumi.String("index.handler"),
Runtime: pulumi.String(lambda.RuntimeNodeJS20dX),
})
if err != nil {
return err
}
_, err = apigatewayv2.NewIntegration(ctx, "example", &apigatewayv2.IntegrationArgs{
ApiId: pulumi.Any(exampleAwsApigatewayv2Api.Id),
IntegrationType: pulumi.String("AWS_PROXY"),
ConnectionType: pulumi.String("INTERNET"),
ContentHandlingStrategy: pulumi.String("CONVERT_TO_TEXT"),
Description: pulumi.String("Lambda example"),
IntegrationMethod: pulumi.String("POST"),
IntegrationUri: example.InvokeArn,
PassthroughBehavior: pulumi.String("WHEN_NO_MATCH"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Lambda.Function("example", new()
{
Code = new FileArchive("example.zip"),
Name = "Example",
Role = exampleAwsIamRole.Arn,
Handler = "index.handler",
Runtime = Aws.Lambda.Runtime.NodeJS20dX,
});
var exampleIntegration = new Aws.ApiGatewayV2.Integration("example", new()
{
ApiId = exampleAwsApigatewayv2Api.Id,
IntegrationType = "AWS_PROXY",
ConnectionType = "INTERNET",
ContentHandlingStrategy = "CONVERT_TO_TEXT",
Description = "Lambda example",
IntegrationMethod = "POST",
IntegrationUri = example.InvokeArn,
PassthroughBehavior = "WHEN_NO_MATCH",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.Function;
import com.pulumi.aws.lambda.FunctionArgs;
import com.pulumi.aws.apigatewayv2.Integration;
import com.pulumi.aws.apigatewayv2.IntegrationArgs;
import com.pulumi.asset.FileArchive;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Function("example", FunctionArgs.builder()
.code(new FileArchive("example.zip"))
.name("Example")
.role(exampleAwsIamRole.arn())
.handler("index.handler")
.runtime("nodejs20.x")
.build());
var exampleIntegration = new Integration("exampleIntegration", IntegrationArgs.builder()
.apiId(exampleAwsApigatewayv2Api.id())
.integrationType("AWS_PROXY")
.connectionType("INTERNET")
.contentHandlingStrategy("CONVERT_TO_TEXT")
.description("Lambda example")
.integrationMethod("POST")
.integrationUri(example.invokeArn())
.passthroughBehavior("WHEN_NO_MATCH")
.build());
}
}
resources:
example:
type: aws:lambda:Function
properties:
code:
fn::FileArchive: example.zip
name: Example
role: ${exampleAwsIamRole.arn}
handler: index.handler
runtime: nodejs20.x
exampleIntegration:
type: aws:apigatewayv2:Integration
name: example
properties:
apiId: ${exampleAwsApigatewayv2Api.id}
integrationType: AWS_PROXY
connectionType: INTERNET
contentHandlingStrategy: CONVERT_TO_TEXT
description: Lambda example
integrationMethod: POST
integrationUri: ${example.invokeArn}
passthroughBehavior: WHEN_NO_MATCH
When a request arrives, API Gateway forwards it to the Lambda function specified in integrationUri. The AWS_PROXY integration type passes the full request context (headers, body, query parameters) to your function and expects a structured response. The integrationMethod specifies the HTTP method API Gateway uses when invoking the integration endpoint.
Integrate with AWS services using subtypes
HTTP APIs can invoke AWS services directly without Lambda middleware, translating HTTP requests into service API calls.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.apigatewayv2.Integration("example", {
apiId: exampleAwsApigatewayv2Api.id,
credentialsArn: exampleAwsIamRole.arn,
description: "SQS example",
integrationType: "AWS_PROXY",
integrationSubtype: "SQS-SendMessage",
requestParameters: {
QueueUrl: "$request.header.queueUrl",
MessageBody: "$request.body.message",
},
});
import pulumi
import pulumi_aws as aws
example = aws.apigatewayv2.Integration("example",
api_id=example_aws_apigatewayv2_api["id"],
credentials_arn=example_aws_iam_role["arn"],
description="SQS example",
integration_type="AWS_PROXY",
integration_subtype="SQS-SendMessage",
request_parameters={
"QueueUrl": "$request.header.queueUrl",
"MessageBody": "$request.body.message",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigatewayv2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := apigatewayv2.NewIntegration(ctx, "example", &apigatewayv2.IntegrationArgs{
ApiId: pulumi.Any(exampleAwsApigatewayv2Api.Id),
CredentialsArn: pulumi.Any(exampleAwsIamRole.Arn),
Description: pulumi.String("SQS example"),
IntegrationType: pulumi.String("AWS_PROXY"),
IntegrationSubtype: pulumi.String("SQS-SendMessage"),
RequestParameters: pulumi.StringMap{
"QueueUrl": pulumi.String("$request.header.queueUrl"),
"MessageBody": pulumi.String("$request.body.message"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.ApiGatewayV2.Integration("example", new()
{
ApiId = exampleAwsApigatewayv2Api.Id,
CredentialsArn = exampleAwsIamRole.Arn,
Description = "SQS example",
IntegrationType = "AWS_PROXY",
IntegrationSubtype = "SQS-SendMessage",
RequestParameters =
{
{ "QueueUrl", "$request.header.queueUrl" },
{ "MessageBody", "$request.body.message" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apigatewayv2.Integration;
import com.pulumi.aws.apigatewayv2.IntegrationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Integration("example", IntegrationArgs.builder()
.apiId(exampleAwsApigatewayv2Api.id())
.credentialsArn(exampleAwsIamRole.arn())
.description("SQS example")
.integrationType("AWS_PROXY")
.integrationSubtype("SQS-SendMessage")
.requestParameters(Map.ofEntries(
Map.entry("QueueUrl", "$request.header.queueUrl"),
Map.entry("MessageBody", "$request.body.message")
))
.build());
}
}
resources:
example:
type: aws:apigatewayv2:Integration
properties:
apiId: ${exampleAwsApigatewayv2Api.id}
credentialsArn: ${exampleAwsIamRole.arn}
description: SQS example
integrationType: AWS_PROXY
integrationSubtype: SQS-SendMessage
requestParameters:
QueueUrl: $request.header.queueUrl
MessageBody: $request.body.message
The integrationSubtype property specifies which AWS service action to invoke (here, SQS-SendMessage). The requestParameters map extracts values from the incoming request using variable references like $request.header.queueUrl and $request.body.message, then passes them as parameters to the SQS API. The credentialsArn grants API Gateway permission to call SQS on your behalf.
Connect to private resources via VPC Link
Applications that need to reach internal load balancers or services in private subnets use VPC Link integrations.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.apigatewayv2.Integration("example", {
apiId: exampleAwsApigatewayv2Api.id,
credentialsArn: exampleAwsIamRole.arn,
description: "Example with a load balancer",
integrationType: "HTTP_PROXY",
integrationUri: exampleAwsLbListener.arn,
integrationMethod: "ANY",
connectionType: "VPC_LINK",
connectionId: exampleAwsApigatewayv2VpcLink.id,
tlsConfig: {
serverNameToVerify: "example.com",
},
requestParameters: {
"append:header.authforintegration": "$context.authorizer.authorizerResponse",
"overwrite:path": "staticValueForIntegration",
},
responseParameters: [
{
statusCode: "403",
mappings: {
"append:header.auth": "$context.authorizer.authorizerResponse",
},
},
{
statusCode: "200",
mappings: {
"overwrite:statuscode": "204",
},
},
],
});
import pulumi
import pulumi_aws as aws
example = aws.apigatewayv2.Integration("example",
api_id=example_aws_apigatewayv2_api["id"],
credentials_arn=example_aws_iam_role["arn"],
description="Example with a load balancer",
integration_type="HTTP_PROXY",
integration_uri=example_aws_lb_listener["arn"],
integration_method="ANY",
connection_type="VPC_LINK",
connection_id=example_aws_apigatewayv2_vpc_link["id"],
tls_config={
"server_name_to_verify": "example.com",
},
request_parameters={
"append:header.authforintegration": "$context.authorizer.authorizerResponse",
"overwrite:path": "staticValueForIntegration",
},
response_parameters=[
{
"status_code": "403",
"mappings": {
"append:header.auth": "$context.authorizer.authorizerResponse",
},
},
{
"status_code": "200",
"mappings": {
"overwrite:statuscode": "204",
},
},
])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigatewayv2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := apigatewayv2.NewIntegration(ctx, "example", &apigatewayv2.IntegrationArgs{
ApiId: pulumi.Any(exampleAwsApigatewayv2Api.Id),
CredentialsArn: pulumi.Any(exampleAwsIamRole.Arn),
Description: pulumi.String("Example with a load balancer"),
IntegrationType: pulumi.String("HTTP_PROXY"),
IntegrationUri: pulumi.Any(exampleAwsLbListener.Arn),
IntegrationMethod: pulumi.String("ANY"),
ConnectionType: pulumi.String("VPC_LINK"),
ConnectionId: pulumi.Any(exampleAwsApigatewayv2VpcLink.Id),
TlsConfig: &apigatewayv2.IntegrationTlsConfigArgs{
ServerNameToVerify: pulumi.String("example.com"),
},
RequestParameters: pulumi.StringMap{
"append:header.authforintegration": pulumi.String("$context.authorizer.authorizerResponse"),
"overwrite:path": pulumi.String("staticValueForIntegration"),
},
ResponseParameters: apigatewayv2.IntegrationResponseParameterArray{
&apigatewayv2.IntegrationResponseParameterArgs{
StatusCode: pulumi.String("403"),
Mappings: pulumi.StringMap{
"append:header.auth": pulumi.String("$context.authorizer.authorizerResponse"),
},
},
&apigatewayv2.IntegrationResponseParameterArgs{
StatusCode: pulumi.String("200"),
Mappings: pulumi.StringMap{
"overwrite:statuscode": pulumi.String("204"),
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.ApiGatewayV2.Integration("example", new()
{
ApiId = exampleAwsApigatewayv2Api.Id,
CredentialsArn = exampleAwsIamRole.Arn,
Description = "Example with a load balancer",
IntegrationType = "HTTP_PROXY",
IntegrationUri = exampleAwsLbListener.Arn,
IntegrationMethod = "ANY",
ConnectionType = "VPC_LINK",
ConnectionId = exampleAwsApigatewayv2VpcLink.Id,
TlsConfig = new Aws.ApiGatewayV2.Inputs.IntegrationTlsConfigArgs
{
ServerNameToVerify = "example.com",
},
RequestParameters =
{
{ "append:header.authforintegration", "$context.authorizer.authorizerResponse" },
{ "overwrite:path", "staticValueForIntegration" },
},
ResponseParameters = new[]
{
new Aws.ApiGatewayV2.Inputs.IntegrationResponseParameterArgs
{
StatusCode = "403",
Mappings =
{
{ "append:header.auth", "$context.authorizer.authorizerResponse" },
},
},
new Aws.ApiGatewayV2.Inputs.IntegrationResponseParameterArgs
{
StatusCode = "200",
Mappings =
{
{ "overwrite:statuscode", "204" },
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apigatewayv2.Integration;
import com.pulumi.aws.apigatewayv2.IntegrationArgs;
import com.pulumi.aws.apigatewayv2.inputs.IntegrationTlsConfigArgs;
import com.pulumi.aws.apigatewayv2.inputs.IntegrationResponseParameterArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Integration("example", IntegrationArgs.builder()
.apiId(exampleAwsApigatewayv2Api.id())
.credentialsArn(exampleAwsIamRole.arn())
.description("Example with a load balancer")
.integrationType("HTTP_PROXY")
.integrationUri(exampleAwsLbListener.arn())
.integrationMethod("ANY")
.connectionType("VPC_LINK")
.connectionId(exampleAwsApigatewayv2VpcLink.id())
.tlsConfig(IntegrationTlsConfigArgs.builder()
.serverNameToVerify("example.com")
.build())
.requestParameters(Map.ofEntries(
Map.entry("append:header.authforintegration", "$context.authorizer.authorizerResponse"),
Map.entry("overwrite:path", "staticValueForIntegration")
))
.responseParameters(
IntegrationResponseParameterArgs.builder()
.statusCode("403")
.mappings(Map.of("append:header.auth", "$context.authorizer.authorizerResponse"))
.build(),
IntegrationResponseParameterArgs.builder()
.statusCode("200")
.mappings(Map.of("overwrite:statuscode", "204"))
.build())
.build());
}
}
resources:
example:
type: aws:apigatewayv2:Integration
properties:
apiId: ${exampleAwsApigatewayv2Api.id}
credentialsArn: ${exampleAwsIamRole.arn}
description: Example with a load balancer
integrationType: HTTP_PROXY
integrationUri: ${exampleAwsLbListener.arn}
integrationMethod: ANY
connectionType: VPC_LINK
connectionId: ${exampleAwsApigatewayv2VpcLink.id}
tlsConfig:
serverNameToVerify: example.com
requestParameters:
append:header.authforintegration: $context.authorizer.authorizerResponse
overwrite:path: staticValueForIntegration
responseParameters:
- statusCode: 403
mappings:
append:header.auth: $context.authorizer.authorizerResponse
- statusCode: 200
mappings:
overwrite:statuscode: '204'
Setting connectionType to VPC_LINK and providing a connectionId routes traffic through a VPC Link to private resources. The integrationUri points to a load balancer listener ARN. The tlsConfig block configures TLS verification for the backend connection. The requestParameters and responseParameters properties transform requests and responses as they pass through the integration, using prefixes like append: and overwrite: to control how values are merged.
Beyond these examples
These snippets focus on specific integration features: Lambda proxy integrations, AWS service integrations with subtypes, and VPC Link for private resources. They’re intentionally minimal rather than full API deployments.
The examples reference pre-existing infrastructure such as API Gateway V2 APIs, Lambda functions, IAM roles, and VPC Links or load balancers for private integrations. They focus on configuring the integration rather than provisioning everything around it.
To keep things focused, common integration patterns are omitted, including:
- Mock integrations for testing (integrationType: MOCK)
- Request and response transformation templates (requestTemplates)
- Timeout configuration (timeoutMilliseconds)
- Payload format versioning (payloadFormatVersion)
These omissions are intentional: the goal is to illustrate how each integration feature is wired, not provide drop-in API modules. See the API Gateway V2 Integration resource reference for all available configuration options.
Let's configure AWS API Gateway V2 Integrations
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Integration Types & Configuration
AWS, AWS_PROXY, HTTP, HTTP_PROXY, MOCK. For HTTP APIs: AWS_PROXY, HTTP_PROXY. Use HTTP_PROXY for HTTP API private integrations.integrationType is MOCK. Set integrationMethod to specify the HTTP method (e.g., POST, GET, ANY).contentHandlingStrategy, passthroughBehavior, requestTemplates. HTTP-only: responseParameters, integrationSubtype. Some integrationType values are also restricted by API type.Lambda & AWS Service Integrations
integrationType to AWS_PROXY, integrationMethod to POST, and integrationUri to the Lambda function’s invokeArn. Optionally configure payloadFormatVersion (1.0 or 2.0).integrationType of AWS_PROXY with integrationSubtype (e.g., SQS-SendMessage). Provide credentialsArn for IAM permissions and configure requestParameters to map request data to service parameters.Private Integrations & VPC
connectionType to VPC_LINK, provide the VPC link ID in connectionId, use integrationType of HTTP_PROXY, and set integrationUri to the ARN of your Application Load Balancer listener, Network Load Balancer listener, or AWS Cloud Map service.tlsConfig property to configure TLS settings like serverNameToVerify for HTTP API private integrations.Request & Response Transformation
requestParameters with transformation prefixes like append:header, overwrite:path, or remove:querystring. For WebSocket APIs, requestParameters passes method request parameters to the backend. For HTTP APIs with integrationSubtype, it passes parameters to AWS service integrations.responseParameters (HTTP APIs only) to map status codes to response transformations. You can append headers, overwrite status codes, or modify other response elements.Timeouts & Limits
timeoutMilliseconds when it’s explicitly present in your configuration. Always specify the timeout value if you need drift detection.Immutability & Import Limitations
apiId, integrationType, and integrationSubtype. Changing these requires recreating the integration.Using a different cloud?
Explore integration guides for other cloud providers: