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, HTTP endpoints, or mock responses. This guide focuses on four capabilities: mock integrations for testing, Lambda proxy integrations, AWS service integrations, and VPC Link for private resources.
Integrations belong to API Gateway V2 APIs and reference backend infrastructure like Lambda functions, IAM roles, VPC Links, or load balancers. The examples are intentionally small. Combine them with your own API routes, authorizers, and deployment stages.
Create a mock integration for testing
Teams building APIs often start with mock integrations to test routing and response handling before connecting real backends.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.apigatewayv2.Integration("example", {
apiId: exampleAwsApigatewayv2Api.id,
integrationType: "MOCK",
});
import pulumi
import pulumi_aws as aws
example = aws.apigatewayv2.Integration("example",
api_id=example_aws_apigatewayv2_api["id"],
integration_type="MOCK")
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),
IntegrationType: pulumi.String("MOCK"),
})
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,
IntegrationType = "MOCK",
});
});
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())
.integrationType("MOCK")
.build());
}
}
resources:
example:
type: aws:apigatewayv2:Integration
properties:
apiId: ${exampleAwsApigatewayv2Api.id}
integrationType: MOCK
The integrationType of MOCK tells API Gateway to return a static response without invoking any backend. This lets you validate API structure, routes, and response mappings before deploying Lambda functions or other services.
Route requests to Lambda functions
Most serverless APIs route incoming requests to Lambda functions that process the request and return a response.
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 invokes the Lambda function specified by integrationUri (the function’s invoke ARN). The AWS_PROXY integration type passes the full HTTP request to Lambda and expects a formatted response. The integrationMethod specifies the HTTP method API Gateway uses to invoke the integration, and connectionType of INTERNET routes through the public internet.
Integrate with AWS services using service proxies
HTTP APIs can invoke AWS services directly without Lambda as an intermediary, reducing latency and cost for simple operations.
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 of SQS-SendMessage tells API Gateway to send messages to SQS. The requestParameters map extracts values from the incoming request (headers, body) and passes them as SQS parameters. The credentialsArn grants API Gateway permission to invoke SQS on your behalf.
Connect to private resources via VPC Link
Applications with internal load balancers or services in private subnets require VPC Link to route API Gateway traffic into the VPC.
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'
The connectionType of VPC_LINK routes traffic through the VPC Link specified by connectionId. The integrationUri points to a load balancer listener ARN inside your VPC. The tlsConfig verifies the backend’s TLS certificate. The requestParameters and responseParameters transform requests and responses as they pass through the integration, letting you add headers or modify status codes.
Beyond these examples
These snippets focus on specific integration-level features: mock integrations for testing, Lambda proxy integrations, AWS service proxy integrations, 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 and IAM execution roles, and VPC Links, load balancers, and private network infrastructure. They focus on configuring the integration rather than provisioning everything around it.
To keep things focused, common integration patterns are omitted, including:
- Request and response transformation (requestTemplates, Velocity templates)
- Payload format versioning (payloadFormatVersion)
- Timeout configuration (timeoutMilliseconds)
- Content handling strategies (contentHandlingStrategy)
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_PROXY (Lambda and AWS services), HTTP_PROXY (HTTP endpoints and private integrations), MOCK (WebSocket only), AWS (WebSocket only), and HTTP (WebSocket only). For HTTP API private integrations, use HTTP_PROXY.integrationMethod unless integrationType is MOCK. For Lambda integrations, use POST.contentHandlingStrategy, passthroughBehavior, and requestTemplates. HTTP APIs support responseParameters, tlsConfig, and integrationSubtype for AWS service integrations. Some integration types are exclusive to each 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 map service parameters via requestParameters.2.0 provides a simpler structure, while 1.0 (default) maintains backward compatibility.Private Integrations & VPC
connectionType to VPC_LINK and provide connectionId referencing your VPC link. Use integrationType of HTTP_PROXY with integrationUri pointing to your Application Load Balancer, Network Load Balancer, or Cloud Map service ARN.tlsConfig property to specify TLS settings like serverNameToVerify for private HTTP API integrations.Request/Response Transformation
requestParameters to map, append, or overwrite headers, query strings, and paths. For WebSocket APIs, you can also use requestTemplates with Velocity templates based on Content-Type.responseParameters to map response transformations by status code. You can append or overwrite headers and status codes.Timeouts & Limitations
timeoutMilliseconds in your configuration.Immutability & Import
apiId, integrationType, and integrationSubtype properties are immutable. Changing them requires replacing the integration resource.Using a different cloud?
Explore integration guides for other cloud providers: