Configure AWS API Gateway Integrations

The aws:apigateway/integration:Integration resource, part of the Pulumi AWS provider, connects API Gateway methods to backend services: Lambda functions, HTTP endpoints, AWS services, or mock responses. This guide focuses on three capabilities: Lambda proxy and streaming integrations, VPC Link for private backend access, and mock integrations for testing.

Integrations require a REST API, resource, and method to exist first, and reference backend services like Lambda functions or load balancers. The examples are intentionally small. Combine them with your own API structure and backend infrastructure.

Route requests to Lambda functions with proxy integration

Most serverless APIs route HTTP requests directly to Lambda functions, letting the function handle request parsing and response formatting.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";

const current = aws.getCallerIdentity({});
const currentGetRegion = aws.getRegion({});
const currentGetPartition = aws.getPartition({});
// API Gateway
const api = new aws.apigateway.RestApi("api", {name: "myapi"});
const resource = new aws.apigateway.Resource("resource", {
    pathPart: "resource",
    parentId: api.rootResourceId,
    restApi: api.id,
});
const method = new aws.apigateway.Method("method", {
    restApi: api.id,
    resourceId: resource.id,
    httpMethod: "GET",
    authorization: "NONE",
});
// IAM
const assumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["lambda.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const role = new aws.iam.Role("role", {
    name: "myrole",
    assumeRolePolicy: assumeRole.then(assumeRole => assumeRole.json),
});
const lambda = new aws.lambda.Function("lambda", {
    code: new pulumi.asset.FileArchive("lambda.zip"),
    name: "mylambda",
    role: role.arn,
    handler: "lambda.lambda_handler",
    runtime: aws.lambda.Runtime.Python3d12,
    sourceCodeHash: std.filebase64sha256({
        input: "lambda.zip",
    }).then(invoke => invoke.result),
});
const integration = new aws.apigateway.Integration("integration", {
    restApi: api.id,
    resourceId: resource.id,
    httpMethod: method.httpMethod,
    integrationHttpMethod: "POST",
    type: "AWS_PROXY",
    uri: lambda.invokeArn,
});
// Lambda
const apigwLambda = new aws.lambda.Permission("apigw_lambda", {
    statementId: "AllowExecutionFromAPIGateway",
    action: "lambda:InvokeFunction",
    "function": lambda.name,
    principal: "apigateway.amazonaws.com",
    sourceArn: pulumi.all([currentGetPartition, currentGetRegion, current, api.id, method.httpMethod, resource.path]).apply(([currentGetPartition, currentGetRegion, current, id, httpMethod, path]) => `arn:${currentGetPartition.partition}:execute-api:${currentGetRegion.region}:${current.accountId}:${id}/*/${httpMethod}${path}`),
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std

current = aws.get_caller_identity()
current_get_region = aws.get_region()
current_get_partition = aws.get_partition()
# API Gateway
api = aws.apigateway.RestApi("api", name="myapi")
resource = aws.apigateway.Resource("resource",
    path_part="resource",
    parent_id=api.root_resource_id,
    rest_api=api.id)
method = aws.apigateway.Method("method",
    rest_api=api.id,
    resource_id=resource.id,
    http_method="GET",
    authorization="NONE")
# IAM
assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["lambda.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
role = aws.iam.Role("role",
    name="myrole",
    assume_role_policy=assume_role.json)
lambda_ = aws.lambda_.Function("lambda",
    code=pulumi.FileArchive("lambda.zip"),
    name="mylambda",
    role=role.arn,
    handler="lambda.lambda_handler",
    runtime=aws.lambda_.Runtime.PYTHON3D12,
    source_code_hash=std.filebase64sha256(input="lambda.zip").result)
integration = aws.apigateway.Integration("integration",
    rest_api=api.id,
    resource_id=resource.id,
    http_method=method.http_method,
    integration_http_method="POST",
    type="AWS_PROXY",
    uri=lambda_.invoke_arn)
# Lambda
apigw_lambda = aws.lambda_.Permission("apigw_lambda",
    statement_id="AllowExecutionFromAPIGateway",
    action="lambda:InvokeFunction",
    function=lambda_.name,
    principal="apigateway.amazonaws.com",
    source_arn=pulumi.Output.all(
        id=api.id,
        http_method=method.http_method,
        path=resource.path
).apply(lambda resolved_outputs: f"arn:{current_get_partition.partition}:execute-api:{current_get_region.region}:{current.account_id}:{resolved_outputs['id']}/*/{resolved_outputs['http_method']}{resolved_outputs['path']}")
)
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigateway"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		currentGetRegion, err := aws.GetRegion(ctx, &aws.GetRegionArgs{}, nil)
		if err != nil {
			return err
		}
		currentGetPartition, err := aws.GetPartition(ctx, &aws.GetPartitionArgs{}, nil)
		if err != nil {
			return err
		}
		// API Gateway
		api, err := apigateway.NewRestApi(ctx, "api", &apigateway.RestApiArgs{
			Name: pulumi.String("myapi"),
		})
		if err != nil {
			return err
		}
		resource, err := apigateway.NewResource(ctx, "resource", &apigateway.ResourceArgs{
			PathPart: pulumi.String("resource"),
			ParentId: api.RootResourceId,
			RestApi:  api.ID(),
		})
		if err != nil {
			return err
		}
		method, err := apigateway.NewMethod(ctx, "method", &apigateway.MethodArgs{
			RestApi:       api.ID(),
			ResourceId:    resource.ID(),
			HttpMethod:    pulumi.String("GET"),
			Authorization: pulumi.String("NONE"),
		})
		if err != nil {
			return err
		}
		// IAM
		assumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"lambda.amazonaws.com",
							},
						},
					},
					Actions: []string{
						"sts:AssumeRole",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		role, err := iam.NewRole(ctx, "role", &iam.RoleArgs{
			Name:             pulumi.String("myrole"),
			AssumeRolePolicy: pulumi.String(assumeRole.Json),
		})
		if err != nil {
			return err
		}
		invokeFilebase64sha256, err := std.Filebase64sha256(ctx, &std.Filebase64sha256Args{
			Input: "lambda.zip",
		}, nil)
		if err != nil {
			return err
		}
		lambda, err := lambda.NewFunction(ctx, "lambda", &lambda.FunctionArgs{
			Code:           pulumi.NewFileArchive("lambda.zip"),
			Name:           pulumi.String("mylambda"),
			Role:           role.Arn,
			Handler:        pulumi.String("lambda.lambda_handler"),
			Runtime:        pulumi.String(lambda.RuntimePython3d12),
			SourceCodeHash: pulumi.String(invokeFilebase64sha256.Result),
		})
		if err != nil {
			return err
		}
		_, err = apigateway.NewIntegration(ctx, "integration", &apigateway.IntegrationArgs{
			RestApi:               api.ID(),
			ResourceId:            resource.ID(),
			HttpMethod:            method.HttpMethod,
			IntegrationHttpMethod: pulumi.String("POST"),
			Type:                  pulumi.String("AWS_PROXY"),
			Uri:                   lambda.InvokeArn,
		})
		if err != nil {
			return err
		}
		// Lambda
		_, err = lambda.NewPermission(ctx, "apigw_lambda", &lambda.PermissionArgs{
			StatementId: pulumi.String("AllowExecutionFromAPIGateway"),
			Action:      pulumi.String("lambda:InvokeFunction"),
			Function:    lambda.Name,
			Principal:   pulumi.String("apigateway.amazonaws.com"),
			SourceArn: pulumi.All(api.ID(), method.HttpMethod, resource.Path).ApplyT(func(_args []interface{}) (string, error) {
				id := _args[0].(string)
				httpMethod := _args[1].(string)
				path := _args[2].(string)
				return fmt.Sprintf("arn:%v:execute-api:%v:%v:%v/*/%v%v", currentGetPartition.Partition, currentGetRegion.Region, current.AccountId, id, httpMethod, path), nil
			}).(pulumi.StringOutput),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var currentGetRegion = Aws.GetRegion.Invoke();

    var currentGetPartition = Aws.GetPartition.Invoke();

    // API Gateway
    var api = new Aws.ApiGateway.RestApi("api", new()
    {
        Name = "myapi",
    });

    var resource = new Aws.ApiGateway.Resource("resource", new()
    {
        PathPart = "resource",
        ParentId = api.RootResourceId,
        RestApi = api.Id,
    });

    var method = new Aws.ApiGateway.Method("method", new()
    {
        RestApi = api.Id,
        ResourceId = resource.Id,
        HttpMethod = "GET",
        Authorization = "NONE",
    });

    // IAM
    var assumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "lambda.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var role = new Aws.Iam.Role("role", new()
    {
        Name = "myrole",
        AssumeRolePolicy = assumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var lambda = new Aws.Lambda.Function("lambda", new()
    {
        Code = new FileArchive("lambda.zip"),
        Name = "mylambda",
        Role = role.Arn,
        Handler = "lambda.lambda_handler",
        Runtime = Aws.Lambda.Runtime.Python3d12,
        SourceCodeHash = Std.Filebase64sha256.Invoke(new()
        {
            Input = "lambda.zip",
        }).Apply(invoke => invoke.Result),
    });

    var integration = new Aws.ApiGateway.Integration("integration", new()
    {
        RestApi = api.Id,
        ResourceId = resource.Id,
        HttpMethod = method.HttpMethod,
        IntegrationHttpMethod = "POST",
        Type = "AWS_PROXY",
        Uri = lambda.InvokeArn,
    });

    // Lambda
    var apigwLambda = new Aws.Lambda.Permission("apigw_lambda", new()
    {
        StatementId = "AllowExecutionFromAPIGateway",
        Action = "lambda:InvokeFunction",
        Function = lambda.Name,
        Principal = "apigateway.amazonaws.com",
        SourceArn = Output.Tuple(currentGetPartition, currentGetRegion, current, api.Id, method.HttpMethod, resource.Path).Apply(values =>
        {
            var currentGetPartition = values.Item1;
            var currentGetRegion = values.Item2;
            var current = values.Item3;
            var id = values.Item4;
            var httpMethod = values.Item5;
            var path = values.Item6;
            return $"arn:{currentGetPartition.Apply(getPartitionResult => getPartitionResult.Partition)}:execute-api:{currentGetRegion.Apply(getRegionResult => getRegionResult.Region)}:{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:{id}/*/{httpMethod}{path}";
        }),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.inputs.GetRegionArgs;
import com.pulumi.aws.inputs.GetPartitionArgs;
import com.pulumi.aws.apigateway.RestApi;
import com.pulumi.aws.apigateway.RestApiArgs;
import com.pulumi.aws.apigateway.Resource;
import com.pulumi.aws.apigateway.ResourceArgs;
import com.pulumi.aws.apigateway.Method;
import com.pulumi.aws.apigateway.MethodArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.lambda.Function;
import com.pulumi.aws.lambda.FunctionArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.Filebase64sha256Args;
import com.pulumi.aws.apigateway.Integration;
import com.pulumi.aws.apigateway.IntegrationArgs;
import com.pulumi.aws.lambda.Permission;
import com.pulumi.aws.lambda.PermissionArgs;
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) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        final var currentGetRegion = AwsFunctions.getRegion(GetRegionArgs.builder()
            .build());

        final var currentGetPartition = AwsFunctions.getPartition(GetPartitionArgs.builder()
            .build());

        // API Gateway
        var api = new RestApi("api", RestApiArgs.builder()
            .name("myapi")
            .build());

        var resource = new Resource("resource", ResourceArgs.builder()
            .pathPart("resource")
            .parentId(api.rootResourceId())
            .restApi(api.id())
            .build());

        var method = new Method("method", MethodArgs.builder()
            .restApi(api.id())
            .resourceId(resource.id())
            .httpMethod("GET")
            .authorization("NONE")
            .build());

        // IAM
        final var assumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("lambda.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var role = new Role("role", RoleArgs.builder()
            .name("myrole")
            .assumeRolePolicy(assumeRole.json())
            .build());

        var lambda = new Function("lambda", FunctionArgs.builder()
            .code(new FileArchive("lambda.zip"))
            .name("mylambda")
            .role(role.arn())
            .handler("lambda.lambda_handler")
            .runtime("python3.12")
            .sourceCodeHash(StdFunctions.filebase64sha256(Filebase64sha256Args.builder()
                .input("lambda.zip")
                .build()).result())
            .build());

        var integration = new Integration("integration", IntegrationArgs.builder()
            .restApi(api.id())
            .resourceId(resource.id())
            .httpMethod(method.httpMethod())
            .integrationHttpMethod("POST")
            .type("AWS_PROXY")
            .uri(lambda.invokeArn())
            .build());

        // Lambda
        var apigwLambda = new Permission("apigwLambda", PermissionArgs.builder()
            .statementId("AllowExecutionFromAPIGateway")
            .action("lambda:InvokeFunction")
            .function(lambda.name())
            .principal("apigateway.amazonaws.com")
            .sourceArn(Output.tuple(api.id(), method.httpMethod(), resource.path()).applyValue(values -> {
                var id = values.t1;
                var httpMethod = values.t2;
                var path = values.t3;
                return String.format("arn:%s:execute-api:%s:%s:%s/*/%s%s", currentGetPartition.partition(),currentGetRegion.region(),current.accountId(),id,httpMethod,path);
            }))
            .build());

    }
}
resources:
  # API Gateway
  api:
    type: aws:apigateway:RestApi
    properties:
      name: myapi
  resource:
    type: aws:apigateway:Resource
    properties:
      pathPart: resource
      parentId: ${api.rootResourceId}
      restApi: ${api.id}
  method:
    type: aws:apigateway:Method
    properties:
      restApi: ${api.id}
      resourceId: ${resource.id}
      httpMethod: GET
      authorization: NONE
  integration:
    type: aws:apigateway:Integration
    properties:
      restApi: ${api.id}
      resourceId: ${resource.id}
      httpMethod: ${method.httpMethod}
      integrationHttpMethod: POST
      type: AWS_PROXY
      uri: ${lambda.invokeArn}
  # Lambda
  apigwLambda:
    type: aws:lambda:Permission
    name: apigw_lambda
    properties:
      statementId: AllowExecutionFromAPIGateway
      action: lambda:InvokeFunction
      function: ${lambda.name}
      principal: apigateway.amazonaws.com
      sourceArn: arn:${currentGetPartition.partition}:execute-api:${currentGetRegion.region}:${current.accountId}:${api.id}/*/${method.httpMethod}${resource.path}
  lambda:
    type: aws:lambda:Function
    properties:
      code:
        fn::FileArchive: lambda.zip
      name: mylambda
      role: ${role.arn}
      handler: lambda.lambda_handler
      runtime: python3.12
      sourceCodeHash:
        fn::invoke:
          function: std:filebase64sha256
          arguments:
            input: lambda.zip
          return: result
  role:
    type: aws:iam:Role
    properties:
      name: myrole
      assumeRolePolicy: ${assumeRole.json}
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}
  currentGetRegion:
    fn::invoke:
      function: aws:getRegion
      arguments: {}
  currentGetPartition:
    fn::invoke:
      function: aws:getPartition
      arguments: {}
  # IAM
  assumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - lambda.amazonaws.com
            actions:
              - sts:AssumeRole

The type property set to AWS_PROXY enables Lambda proxy integration, where API Gateway forwards the entire request as a JSON event. The uri points to the Lambda function’s invoke ARN. The integrationHttpMethod must be POST for Lambda invocations. The lambda.Permission grants API Gateway permission to invoke the function, using a source ARN that restricts access to this specific API and method.

Stream Lambda responses for large payloads

When Lambda functions return large responses or need to stream data incrementally, response streaming avoids buffering the entire payload in API Gateway.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const integration = new aws.apigateway.Integration("integration", {
    restApi: api.id,
    resourceId: resource.id,
    httpMethod: method.httpMethod,
    integrationHttpMethod: "POST",
    type: "AWS_PROXY",
    uri: lambda.responseStreamingInvokeArn,
    responseTransferMode: "STREAM",
    timeoutMilliseconds: 900000,
});
import pulumi
import pulumi_aws as aws

integration = aws.apigateway.Integration("integration",
    rest_api=api["id"],
    resource_id=resource["id"],
    http_method=method["httpMethod"],
    integration_http_method="POST",
    type="AWS_PROXY",
    uri=lambda_["responseStreamingInvokeArn"],
    response_transfer_mode="STREAM",
    timeout_milliseconds=900000)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigateway"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := apigateway.NewIntegration(ctx, "integration", &apigateway.IntegrationArgs{
			RestApi:               pulumi.Any(api.Id),
			ResourceId:            pulumi.Any(resource.Id),
			HttpMethod:            pulumi.Any(method.HttpMethod),
			IntegrationHttpMethod: pulumi.String("POST"),
			Type:                  pulumi.String("AWS_PROXY"),
			Uri:                   pulumi.Any(lambda.ResponseStreamingInvokeArn),
			ResponseTransferMode:  pulumi.String("STREAM"),
			TimeoutMilliseconds:   pulumi.Int(900000),
		})
		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 integration = new Aws.ApiGateway.Integration("integration", new()
    {
        RestApi = api.Id,
        ResourceId = resource.Id,
        HttpMethod = method.HttpMethod,
        IntegrationHttpMethod = "POST",
        Type = "AWS_PROXY",
        Uri = lambda.ResponseStreamingInvokeArn,
        ResponseTransferMode = "STREAM",
        TimeoutMilliseconds = 900000,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apigateway.Integration;
import com.pulumi.aws.apigateway.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 integration = new Integration("integration", IntegrationArgs.builder()
            .restApi(api.id())
            .resourceId(resource.id())
            .httpMethod(method.httpMethod())
            .integrationHttpMethod("POST")
            .type("AWS_PROXY")
            .uri(lambda.responseStreamingInvokeArn())
            .responseTransferMode("STREAM")
            .timeoutMilliseconds(900000)
            .build());

    }
}
resources:
  integration:
    type: aws:apigateway:Integration
    properties:
      restApi: ${api.id}
      resourceId: ${resource.id}
      httpMethod: ${method.httpMethod}
      integrationHttpMethod: POST
      type: AWS_PROXY
      uri: ${lambda.responseStreamingInvokeArn}
      responseTransferMode: STREAM
      timeoutMilliseconds: 900000

Setting responseTransferMode to STREAM enables response streaming. The uri references responseStreamingInvokeArn instead of the standard invoke ARN. The timeoutMilliseconds can be extended up to 900,000 (15 minutes) for streaming mode, compared to 300,000 for buffered responses. Your Lambda function must be configured to support response streaming.

Applications that need to reach internal services or databases use VPC Link to route API Gateway requests through a Network Load Balancer into a VPC.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const config = new pulumi.Config();
const name = config.requireObject<any>("name");
const subnetId = config.requireObject<any>("subnetId");
const test = new aws.lb.LoadBalancer("test", {
    name: name,
    internal: true,
    loadBalancerType: "network",
    subnets: [subnetId],
});
const testVpcLink = new aws.apigateway.VpcLink("test", {
    name: name,
    targetArn: test.arn,
});
const testRestApi = new aws.apigateway.RestApi("test", {name: name});
const testResource = new aws.apigateway.Resource("test", {
    restApi: testRestApi.id,
    parentId: testRestApi.rootResourceId,
    pathPart: "test",
});
const testMethod = new aws.apigateway.Method("test", {
    restApi: testRestApi.id,
    resourceId: testResource.id,
    httpMethod: "GET",
    authorization: "NONE",
    requestModels: {
        "application/json": "Error",
    },
});
const testIntegration = new aws.apigateway.Integration("test", {
    restApi: testRestApi.id,
    resourceId: testResource.id,
    httpMethod: testMethod.httpMethod,
    requestTemplates: {
        "application/json": "",
        "application/xml": `#set(inputRoot = input.path(''))
{ }`,
    },
    requestParameters: {
        "integration.request.header.X-Authorization": "'static'",
        "integration.request.header.X-Foo": "'Bar'",
    },
    type: "HTTP",
    uri: "https://www.google.de",
    integrationHttpMethod: "GET",
    passthroughBehavior: "WHEN_NO_MATCH",
    contentHandling: "CONVERT_TO_TEXT",
    connectionType: "VPC_LINK",
    connectionId: testVpcLink.id,
});
import pulumi
import pulumi_aws as aws

config = pulumi.Config()
name = config.require_object("name")
subnet_id = config.require_object("subnetId")
test = aws.lb.LoadBalancer("test",
    name=name,
    internal=True,
    load_balancer_type="network",
    subnets=[subnet_id])
test_vpc_link = aws.apigateway.VpcLink("test",
    name=name,
    target_arn=test.arn)
test_rest_api = aws.apigateway.RestApi("test", name=name)
test_resource = aws.apigateway.Resource("test",
    rest_api=test_rest_api.id,
    parent_id=test_rest_api.root_resource_id,
    path_part="test")
test_method = aws.apigateway.Method("test",
    rest_api=test_rest_api.id,
    resource_id=test_resource.id,
    http_method="GET",
    authorization="NONE",
    request_models={
        "application/json": "Error",
    })
test_integration = aws.apigateway.Integration("test",
    rest_api=test_rest_api.id,
    resource_id=test_resource.id,
    http_method=test_method.http_method,
    request_templates={
        "application/json": "",
        "application/xml": """#set($inputRoot = $input.path('$'))
{ }""",
    },
    request_parameters={
        "integration.request.header.X-Authorization": "'static'",
        "integration.request.header.X-Foo": "'Bar'",
    },
    type="HTTP",
    uri="https://www.google.de",
    integration_http_method="GET",
    passthrough_behavior="WHEN_NO_MATCH",
    content_handling="CONVERT_TO_TEXT",
    connection_type="VPC_LINK",
    connection_id=test_vpc_link.id)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigateway"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		cfg := config.New(ctx, "")
		name := cfg.RequireObject("name")
		subnetId := cfg.RequireObject("subnetId")
		test, err := lb.NewLoadBalancer(ctx, "test", &lb.LoadBalancerArgs{
			Name:             pulumi.Any(name),
			Internal:         pulumi.Bool(true),
			LoadBalancerType: pulumi.String("network"),
			Subnets: pulumi.StringArray{
				subnetId,
			},
		})
		if err != nil {
			return err
		}
		testVpcLink, err := apigateway.NewVpcLink(ctx, "test", &apigateway.VpcLinkArgs{
			Name:      pulumi.Any(name),
			TargetArn: test.Arn,
		})
		if err != nil {
			return err
		}
		testRestApi, err := apigateway.NewRestApi(ctx, "test", &apigateway.RestApiArgs{
			Name: pulumi.Any(name),
		})
		if err != nil {
			return err
		}
		testResource, err := apigateway.NewResource(ctx, "test", &apigateway.ResourceArgs{
			RestApi:  testRestApi.ID(),
			ParentId: testRestApi.RootResourceId,
			PathPart: pulumi.String("test"),
		})
		if err != nil {
			return err
		}
		testMethod, err := apigateway.NewMethod(ctx, "test", &apigateway.MethodArgs{
			RestApi:       testRestApi.ID(),
			ResourceId:    testResource.ID(),
			HttpMethod:    pulumi.String("GET"),
			Authorization: pulumi.String("NONE"),
			RequestModels: pulumi.StringMap{
				"application/json": pulumi.String("Error"),
			},
		})
		if err != nil {
			return err
		}
		_, err = apigateway.NewIntegration(ctx, "test", &apigateway.IntegrationArgs{
			RestApi:    testRestApi.ID(),
			ResourceId: testResource.ID(),
			HttpMethod: testMethod.HttpMethod,
			RequestTemplates: pulumi.StringMap{
				"application/json": pulumi.String(""),
				"application/xml":  pulumi.String("#set($inputRoot = $input.path('$'))\n{ }"),
			},
			RequestParameters: pulumi.StringMap{
				"integration.request.header.X-Authorization": pulumi.String("'static'"),
				"integration.request.header.X-Foo":           pulumi.String("'Bar'"),
			},
			Type:                  pulumi.String("HTTP"),
			Uri:                   pulumi.String("https://www.google.de"),
			IntegrationHttpMethod: pulumi.String("GET"),
			PassthroughBehavior:   pulumi.String("WHEN_NO_MATCH"),
			ContentHandling:       pulumi.String("CONVERT_TO_TEXT"),
			ConnectionType:        pulumi.String("VPC_LINK"),
			ConnectionId:          testVpcLink.ID(),
		})
		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 config = new Config();
    var name = config.RequireObject<dynamic>("name");
    var subnetId = config.RequireObject<dynamic>("subnetId");
    var test = new Aws.LB.LoadBalancer("test", new()
    {
        Name = name,
        Internal = true,
        LoadBalancerType = "network",
        Subnets = new[]
        {
            subnetId,
        },
    });

    var testVpcLink = new Aws.ApiGateway.VpcLink("test", new()
    {
        Name = name,
        TargetArn = test.Arn,
    });

    var testRestApi = new Aws.ApiGateway.RestApi("test", new()
    {
        Name = name,
    });

    var testResource = new Aws.ApiGateway.Resource("test", new()
    {
        RestApi = testRestApi.Id,
        ParentId = testRestApi.RootResourceId,
        PathPart = "test",
    });

    var testMethod = new Aws.ApiGateway.Method("test", new()
    {
        RestApi = testRestApi.Id,
        ResourceId = testResource.Id,
        HttpMethod = "GET",
        Authorization = "NONE",
        RequestModels = 
        {
            { "application/json", "Error" },
        },
    });

    var testIntegration = new Aws.ApiGateway.Integration("test", new()
    {
        RestApi = testRestApi.Id,
        ResourceId = testResource.Id,
        HttpMethod = testMethod.HttpMethod,
        RequestTemplates = 
        {
            { "application/json", "" },
            { "application/xml", @"#set($inputRoot = $input.path('$'))
{ }" },
        },
        RequestParameters = 
        {
            { "integration.request.header.X-Authorization", "'static'" },
            { "integration.request.header.X-Foo", "'Bar'" },
        },
        Type = "HTTP",
        Uri = "https://www.google.de",
        IntegrationHttpMethod = "GET",
        PassthroughBehavior = "WHEN_NO_MATCH",
        ContentHandling = "CONVERT_TO_TEXT",
        ConnectionType = "VPC_LINK",
        ConnectionId = testVpcLink.Id,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.LoadBalancerArgs;
import com.pulumi.aws.apigateway.VpcLink;
import com.pulumi.aws.apigateway.VpcLinkArgs;
import com.pulumi.aws.apigateway.RestApi;
import com.pulumi.aws.apigateway.RestApiArgs;
import com.pulumi.aws.apigateway.Resource;
import com.pulumi.aws.apigateway.ResourceArgs;
import com.pulumi.aws.apigateway.Method;
import com.pulumi.aws.apigateway.MethodArgs;
import com.pulumi.aws.apigateway.Integration;
import com.pulumi.aws.apigateway.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) {
        final var config = ctx.config();
        final var name = config.require("name");
        final var subnetId = config.require("subnetId");
        var test = new LoadBalancer("test", LoadBalancerArgs.builder()
            .name(name)
            .internal(true)
            .loadBalancerType("network")
            .subnets(subnetId)
            .build());

        var testVpcLink = new VpcLink("testVpcLink", VpcLinkArgs.builder()
            .name(name)
            .targetArn(test.arn())
            .build());

        var testRestApi = new RestApi("testRestApi", RestApiArgs.builder()
            .name(name)
            .build());

        var testResource = new Resource("testResource", ResourceArgs.builder()
            .restApi(testRestApi.id())
            .parentId(testRestApi.rootResourceId())
            .pathPart("test")
            .build());

        var testMethod = new Method("testMethod", MethodArgs.builder()
            .restApi(testRestApi.id())
            .resourceId(testResource.id())
            .httpMethod("GET")
            .authorization("NONE")
            .requestModels(Map.of("application/json", "Error"))
            .build());

        var testIntegration = new Integration("testIntegration", IntegrationArgs.builder()
            .restApi(testRestApi.id())
            .resourceId(testResource.id())
            .httpMethod(testMethod.httpMethod())
            .requestTemplates(Map.ofEntries(
                Map.entry("application/json", ""),
                Map.entry("application/xml", """
#set($inputRoot = $input.path('$'))
{ }                """)
            ))
            .requestParameters(Map.ofEntries(
                Map.entry("integration.request.header.X-Authorization", "'static'"),
                Map.entry("integration.request.header.X-Foo", "'Bar'")
            ))
            .type("HTTP")
            .uri("https://www.google.de")
            .integrationHttpMethod("GET")
            .passthroughBehavior("WHEN_NO_MATCH")
            .contentHandling("CONVERT_TO_TEXT")
            .connectionType("VPC_LINK")
            .connectionId(testVpcLink.id())
            .build());

    }
}
configuration:
  name:
    type: dynamic
  subnetId:
    type: dynamic
resources:
  test:
    type: aws:lb:LoadBalancer
    properties:
      name: ${name}
      internal: true
      loadBalancerType: network
      subnets:
        - ${subnetId}
  testVpcLink:
    type: aws:apigateway:VpcLink
    name: test
    properties:
      name: ${name}
      targetArn: ${test.arn}
  testRestApi:
    type: aws:apigateway:RestApi
    name: test
    properties:
      name: ${name}
  testResource:
    type: aws:apigateway:Resource
    name: test
    properties:
      restApi: ${testRestApi.id}
      parentId: ${testRestApi.rootResourceId}
      pathPart: test
  testMethod:
    type: aws:apigateway:Method
    name: test
    properties:
      restApi: ${testRestApi.id}
      resourceId: ${testResource.id}
      httpMethod: GET
      authorization: NONE
      requestModels:
        application/json: Error
  testIntegration:
    type: aws:apigateway:Integration
    name: test
    properties:
      restApi: ${testRestApi.id}
      resourceId: ${testResource.id}
      httpMethod: ${testMethod.httpMethod}
      requestTemplates:
        application/json: ""
        application/xml: |-
          #set($inputRoot = $input.path('$'))
          { }          
      requestParameters:
        integration.request.header.X-Authorization: '''static'''
        integration.request.header.X-Foo: '''Bar'''
      type: HTTP
      uri: https://www.google.de
      integrationHttpMethod: GET
      passthroughBehavior: WHEN_NO_MATCH
      contentHandling: CONVERT_TO_TEXT
      connectionType: VPC_LINK
      connectionId: ${testVpcLink.id}

The connectionType property set to VPC_LINK enables private integration. The connectionId references a VpcLink resource that connects to a Network Load Balancer. The type can be HTTP or HTTP_PROXY depending on whether you need request transformation. The VPC Link handles network connectivity; your backend service must be reachable from the NLB.

VPC Link V2 supports Application Load Balancers, enabling API Gateway to route to containerized or EC2-based services with advanced routing rules.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.apigatewayv2.VpcLink("example", {
    name: "example",
    securityGroupIds: [exampleAwsSecurityGroup.id],
    subnetIds: exampleAwsSubnet.map(__item => __item.id),
});
const exampleLoadBalancer = new aws.lb.LoadBalancer("example", {
    name: "example-alb",
    internal: true,
    loadBalancerType: "application",
    securityGroups: [exampleAwsSecurityGroup.id],
    subnets: exampleAwsSubnet.map(__item => __item.id),
});
const exampleListener = new aws.lb.Listener("example", {
    loadBalancerArn: exampleLoadBalancer.arn,
    port: 80,
    protocol: "HTTP",
    defaultActions: [{
        type: "fixed-response",
        fixedResponse: {
            contentType: "text/plain",
            messageBody: "OK",
            statusCode: "200",
        },
    }],
});
const exampleRestApi = new aws.apigateway.RestApi("example", {name: "example"});
const exampleResource = new aws.apigateway.Resource("example", {
    restApi: exampleRestApi.id,
    parentId: exampleRestApi.rootResourceId,
    pathPart: "example",
});
const exampleMethod = new aws.apigateway.Method("example", {
    restApi: exampleRestApi.id,
    resourceId: exampleResource.id,
    httpMethod: "GET",
    authorization: "NONE",
});
const exampleIntegration = new aws.apigateway.Integration("example", {
    restApi: exampleRestApi.id,
    resourceId: exampleResource.id,
    httpMethod: exampleMethod.httpMethod,
    integrationHttpMethod: "GET",
    type: "HTTP_PROXY",
    connectionType: "VPC_LINK",
    connectionId: example.id,
    integrationTarget: exampleLoadBalancer.arn,
    uri: "http://example.com",
});
import pulumi
import pulumi_aws as aws

example = aws.apigatewayv2.VpcLink("example",
    name="example",
    security_group_ids=[example_aws_security_group["id"]],
    subnet_ids=[__item["id"] for __item in example_aws_subnet])
example_load_balancer = aws.lb.LoadBalancer("example",
    name="example-alb",
    internal=True,
    load_balancer_type="application",
    security_groups=[example_aws_security_group["id"]],
    subnets=[__item["id"] for __item in example_aws_subnet])
example_listener = aws.lb.Listener("example",
    load_balancer_arn=example_load_balancer.arn,
    port=80,
    protocol="HTTP",
    default_actions=[{
        "type": "fixed-response",
        "fixed_response": {
            "content_type": "text/plain",
            "message_body": "OK",
            "status_code": "200",
        },
    }])
example_rest_api = aws.apigateway.RestApi("example", name="example")
example_resource = aws.apigateway.Resource("example",
    rest_api=example_rest_api.id,
    parent_id=example_rest_api.root_resource_id,
    path_part="example")
example_method = aws.apigateway.Method("example",
    rest_api=example_rest_api.id,
    resource_id=example_resource.id,
    http_method="GET",
    authorization="NONE")
example_integration = aws.apigateway.Integration("example",
    rest_api=example_rest_api.id,
    resource_id=example_resource.id,
    http_method=example_method.http_method,
    integration_http_method="GET",
    type="HTTP_PROXY",
    connection_type="VPC_LINK",
    connection_id=example.id,
    integration_target=example_load_balancer.arn,
    uri="http://example.com")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigateway"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigatewayv2"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
var splat0 []interface{}
for _, val0 := range exampleAwsSubnet {
splat0 = append(splat0, val0.Id)
}
example, err := apigatewayv2.NewVpcLink(ctx, "example", &apigatewayv2.VpcLinkArgs{
Name: pulumi.String("example"),
SecurityGroupIds: pulumi.StringArray{
exampleAwsSecurityGroup.Id,
},
SubnetIds: toPulumiArray(splat0),
})
if err != nil {
return err
}
var splat1 []interface{}
for _, val0 := range exampleAwsSubnet {
splat1 = append(splat1, val0.Id)
}
exampleLoadBalancer, err := lb.NewLoadBalancer(ctx, "example", &lb.LoadBalancerArgs{
Name: pulumi.String("example-alb"),
Internal: pulumi.Bool(true),
LoadBalancerType: pulumi.String("application"),
SecurityGroups: pulumi.StringArray{
exampleAwsSecurityGroup.Id,
},
Subnets: toPulumiArray(splat1),
})
if err != nil {
return err
}
_, err = lb.NewListener(ctx, "example", &lb.ListenerArgs{
LoadBalancerArn: exampleLoadBalancer.Arn,
Port: pulumi.Int(80),
Protocol: pulumi.String("HTTP"),
DefaultActions: lb.ListenerDefaultActionArray{
&lb.ListenerDefaultActionArgs{
Type: pulumi.String("fixed-response"),
FixedResponse: &lb.ListenerDefaultActionFixedResponseArgs{
ContentType: pulumi.String("text/plain"),
MessageBody: pulumi.String("OK"),
StatusCode: pulumi.String("200"),
},
},
},
})
if err != nil {
return err
}
exampleRestApi, err := apigateway.NewRestApi(ctx, "example", &apigateway.RestApiArgs{
Name: pulumi.String("example"),
})
if err != nil {
return err
}
exampleResource, err := apigateway.NewResource(ctx, "example", &apigateway.ResourceArgs{
RestApi: exampleRestApi.ID(),
ParentId: exampleRestApi.RootResourceId,
PathPart: pulumi.String("example"),
})
if err != nil {
return err
}
exampleMethod, err := apigateway.NewMethod(ctx, "example", &apigateway.MethodArgs{
RestApi: exampleRestApi.ID(),
ResourceId: exampleResource.ID(),
HttpMethod: pulumi.String("GET"),
Authorization: pulumi.String("NONE"),
})
if err != nil {
return err
}
_, err = apigateway.NewIntegration(ctx, "example", &apigateway.IntegrationArgs{
RestApi: exampleRestApi.ID(),
ResourceId: exampleResource.ID(),
HttpMethod: exampleMethod.HttpMethod,
IntegrationHttpMethod: pulumi.String("GET"),
Type: pulumi.String("HTTP_PROXY"),
ConnectionType: pulumi.String("VPC_LINK"),
ConnectionId: example.ID(),
IntegrationTarget: exampleLoadBalancer.Arn,
Uri: pulumi.String("http://example.com"),
})
if err != nil {
return err
}
return nil
})
}
func toPulumiArray(arr []) pulumi.Array {
var pulumiArr pulumi.Array
for _, v := range arr {
pulumiArr = append(pulumiArr, pulumi.(v))
}
return pulumiArr
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.ApiGatewayV2.VpcLink("example", new()
    {
        Name = "example",
        SecurityGroupIds = new[]
        {
            exampleAwsSecurityGroup.Id,
        },
        SubnetIds = exampleAwsSubnet.Select(__item => __item.Id).ToList(),
    });

    var exampleLoadBalancer = new Aws.LB.LoadBalancer("example", new()
    {
        Name = "example-alb",
        Internal = true,
        LoadBalancerType = "application",
        SecurityGroups = new[]
        {
            exampleAwsSecurityGroup.Id,
        },
        Subnets = exampleAwsSubnet.Select(__item => __item.Id).ToList(),
    });

    var exampleListener = new Aws.LB.Listener("example", new()
    {
        LoadBalancerArn = exampleLoadBalancer.Arn,
        Port = 80,
        Protocol = "HTTP",
        DefaultActions = new[]
        {
            new Aws.LB.Inputs.ListenerDefaultActionArgs
            {
                Type = "fixed-response",
                FixedResponse = new Aws.LB.Inputs.ListenerDefaultActionFixedResponseArgs
                {
                    ContentType = "text/plain",
                    MessageBody = "OK",
                    StatusCode = "200",
                },
            },
        },
    });

    var exampleRestApi = new Aws.ApiGateway.RestApi("example", new()
    {
        Name = "example",
    });

    var exampleResource = new Aws.ApiGateway.Resource("example", new()
    {
        RestApi = exampleRestApi.Id,
        ParentId = exampleRestApi.RootResourceId,
        PathPart = "example",
    });

    var exampleMethod = new Aws.ApiGateway.Method("example", new()
    {
        RestApi = exampleRestApi.Id,
        ResourceId = exampleResource.Id,
        HttpMethod = "GET",
        Authorization = "NONE",
    });

    var exampleIntegration = new Aws.ApiGateway.Integration("example", new()
    {
        RestApi = exampleRestApi.Id,
        ResourceId = exampleResource.Id,
        HttpMethod = exampleMethod.HttpMethod,
        IntegrationHttpMethod = "GET",
        Type = "HTTP_PROXY",
        ConnectionType = "VPC_LINK",
        ConnectionId = example.Id,
        IntegrationTarget = exampleLoadBalancer.Arn,
        Uri = "http://example.com",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apigatewayv2.VpcLink;
import com.pulumi.aws.apigatewayv2.VpcLinkArgs;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.LoadBalancerArgs;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionFixedResponseArgs;
import com.pulumi.aws.apigateway.RestApi;
import com.pulumi.aws.apigateway.RestApiArgs;
import com.pulumi.aws.apigateway.Resource;
import com.pulumi.aws.apigateway.ResourceArgs;
import com.pulumi.aws.apigateway.Method;
import com.pulumi.aws.apigateway.MethodArgs;
import com.pulumi.aws.apigateway.Integration;
import com.pulumi.aws.apigateway.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 VpcLink("example", VpcLinkArgs.builder()
            .name("example")
            .securityGroupIds(exampleAwsSecurityGroup.id())
            .subnetIds(exampleAwsSubnet.stream().map(element -> element.id()).collect(toList()))
            .build());

        var exampleLoadBalancer = new LoadBalancer("exampleLoadBalancer", LoadBalancerArgs.builder()
            .name("example-alb")
            .internal(true)
            .loadBalancerType("application")
            .securityGroups(exampleAwsSecurityGroup.id())
            .subnets(exampleAwsSubnet.stream().map(element -> element.id()).collect(toList()))
            .build());

        var exampleListener = new Listener("exampleListener", ListenerArgs.builder()
            .loadBalancerArn(exampleLoadBalancer.arn())
            .port(80)
            .protocol("HTTP")
            .defaultActions(ListenerDefaultActionArgs.builder()
                .type("fixed-response")
                .fixedResponse(ListenerDefaultActionFixedResponseArgs.builder()
                    .contentType("text/plain")
                    .messageBody("OK")
                    .statusCode("200")
                    .build())
                .build())
            .build());

        var exampleRestApi = new RestApi("exampleRestApi", RestApiArgs.builder()
            .name("example")
            .build());

        var exampleResource = new Resource("exampleResource", ResourceArgs.builder()
            .restApi(exampleRestApi.id())
            .parentId(exampleRestApi.rootResourceId())
            .pathPart("example")
            .build());

        var exampleMethod = new Method("exampleMethod", MethodArgs.builder()
            .restApi(exampleRestApi.id())
            .resourceId(exampleResource.id())
            .httpMethod("GET")
            .authorization("NONE")
            .build());

        var exampleIntegration = new Integration("exampleIntegration", IntegrationArgs.builder()
            .restApi(exampleRestApi.id())
            .resourceId(exampleResource.id())
            .httpMethod(exampleMethod.httpMethod())
            .integrationHttpMethod("GET")
            .type("HTTP_PROXY")
            .connectionType("VPC_LINK")
            .connectionId(example.id())
            .integrationTarget(exampleLoadBalancer.arn())
            .uri("http://example.com")
            .build());

    }
}

This configuration uses apigatewayv2.VpcLink (V2) instead of the V1 VPC Link. The integrationTarget property specifies the ALB ARN, while uri sets the Host header for the backend request. The type HTTP_PROXY forwards requests without transformation. VPC Link V2 requires security groups that allow traffic from the VPC Link to the ALB.

Test API behavior with mock integrations

During development, mock integrations let you test API Gateway configuration without deploying backend services.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const myDemoAPI = new aws.apigateway.RestApi("MyDemoAPI", {
    name: "MyDemoAPI",
    description: "This is my API for demonstration purposes",
});
const myDemoResource = new aws.apigateway.Resource("MyDemoResource", {
    restApi: myDemoAPI.id,
    parentId: myDemoAPI.rootResourceId,
    pathPart: "mydemoresource",
});
const myDemoMethod = new aws.apigateway.Method("MyDemoMethod", {
    restApi: myDemoAPI.id,
    resourceId: myDemoResource.id,
    httpMethod: "GET",
    authorization: "NONE",
});
const myDemoIntegration = new aws.apigateway.Integration("MyDemoIntegration", {
    restApi: myDemoAPI.id,
    resourceId: myDemoResource.id,
    httpMethod: myDemoMethod.httpMethod,
    type: "MOCK",
    cacheKeyParameters: ["method.request.path.param"],
    cacheNamespace: "foobar",
    timeoutMilliseconds: 29000,
    requestParameters: {
        "integration.request.header.X-Authorization": "'static'",
    },
    requestTemplates: {
        "application/xml": `{
   \\"body\\" : input.json('')
}
`,
    },
});
import pulumi
import pulumi_aws as aws

my_demo_api = aws.apigateway.RestApi("MyDemoAPI",
    name="MyDemoAPI",
    description="This is my API for demonstration purposes")
my_demo_resource = aws.apigateway.Resource("MyDemoResource",
    rest_api=my_demo_api.id,
    parent_id=my_demo_api.root_resource_id,
    path_part="mydemoresource")
my_demo_method = aws.apigateway.Method("MyDemoMethod",
    rest_api=my_demo_api.id,
    resource_id=my_demo_resource.id,
    http_method="GET",
    authorization="NONE")
my_demo_integration = aws.apigateway.Integration("MyDemoIntegration",
    rest_api=my_demo_api.id,
    resource_id=my_demo_resource.id,
    http_method=my_demo_method.http_method,
    type="MOCK",
    cache_key_parameters=["method.request.path.param"],
    cache_namespace="foobar",
    timeout_milliseconds=29000,
    request_parameters={
        "integration.request.header.X-Authorization": "'static'",
    },
    request_templates={
        "application/xml": """{
   \"body\" : $input.json('$')
}
""",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigateway"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		myDemoAPI, err := apigateway.NewRestApi(ctx, "MyDemoAPI", &apigateway.RestApiArgs{
			Name:        pulumi.String("MyDemoAPI"),
			Description: pulumi.String("This is my API for demonstration purposes"),
		})
		if err != nil {
			return err
		}
		myDemoResource, err := apigateway.NewResource(ctx, "MyDemoResource", &apigateway.ResourceArgs{
			RestApi:  myDemoAPI.ID(),
			ParentId: myDemoAPI.RootResourceId,
			PathPart: pulumi.String("mydemoresource"),
		})
		if err != nil {
			return err
		}
		myDemoMethod, err := apigateway.NewMethod(ctx, "MyDemoMethod", &apigateway.MethodArgs{
			RestApi:       myDemoAPI.ID(),
			ResourceId:    myDemoResource.ID(),
			HttpMethod:    pulumi.String("GET"),
			Authorization: pulumi.String("NONE"),
		})
		if err != nil {
			return err
		}
		_, err = apigateway.NewIntegration(ctx, "MyDemoIntegration", &apigateway.IntegrationArgs{
			RestApi:    myDemoAPI.ID(),
			ResourceId: myDemoResource.ID(),
			HttpMethod: myDemoMethod.HttpMethod,
			Type:       pulumi.String("MOCK"),
			CacheKeyParameters: pulumi.StringArray{
				pulumi.String("method.request.path.param"),
			},
			CacheNamespace:      pulumi.String("foobar"),
			TimeoutMilliseconds: pulumi.Int(29000),
			RequestParameters: pulumi.StringMap{
				"integration.request.header.X-Authorization": pulumi.String("'static'"),
			},
			RequestTemplates: pulumi.StringMap{
				"application/xml": pulumi.String("{\n   \\\"body\\\" : $input.json('$')\n}\n"),
			},
		})
		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 myDemoAPI = new Aws.ApiGateway.RestApi("MyDemoAPI", new()
    {
        Name = "MyDemoAPI",
        Description = "This is my API for demonstration purposes",
    });

    var myDemoResource = new Aws.ApiGateway.Resource("MyDemoResource", new()
    {
        RestApi = myDemoAPI.Id,
        ParentId = myDemoAPI.RootResourceId,
        PathPart = "mydemoresource",
    });

    var myDemoMethod = new Aws.ApiGateway.Method("MyDemoMethod", new()
    {
        RestApi = myDemoAPI.Id,
        ResourceId = myDemoResource.Id,
        HttpMethod = "GET",
        Authorization = "NONE",
    });

    var myDemoIntegration = new Aws.ApiGateway.Integration("MyDemoIntegration", new()
    {
        RestApi = myDemoAPI.Id,
        ResourceId = myDemoResource.Id,
        HttpMethod = myDemoMethod.HttpMethod,
        Type = "MOCK",
        CacheKeyParameters = new[]
        {
            "method.request.path.param",
        },
        CacheNamespace = "foobar",
        TimeoutMilliseconds = 29000,
        RequestParameters = 
        {
            { "integration.request.header.X-Authorization", "'static'" },
        },
        RequestTemplates = 
        {
            { "application/xml", @"{
   \""body\"" : $input.json('$')
}
" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apigateway.RestApi;
import com.pulumi.aws.apigateway.RestApiArgs;
import com.pulumi.aws.apigateway.Resource;
import com.pulumi.aws.apigateway.ResourceArgs;
import com.pulumi.aws.apigateway.Method;
import com.pulumi.aws.apigateway.MethodArgs;
import com.pulumi.aws.apigateway.Integration;
import com.pulumi.aws.apigateway.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 myDemoAPI = new RestApi("myDemoAPI", RestApiArgs.builder()
            .name("MyDemoAPI")
            .description("This is my API for demonstration purposes")
            .build());

        var myDemoResource = new Resource("myDemoResource", ResourceArgs.builder()
            .restApi(myDemoAPI.id())
            .parentId(myDemoAPI.rootResourceId())
            .pathPart("mydemoresource")
            .build());

        var myDemoMethod = new Method("myDemoMethod", MethodArgs.builder()
            .restApi(myDemoAPI.id())
            .resourceId(myDemoResource.id())
            .httpMethod("GET")
            .authorization("NONE")
            .build());

        var myDemoIntegration = new Integration("myDemoIntegration", IntegrationArgs.builder()
            .restApi(myDemoAPI.id())
            .resourceId(myDemoResource.id())
            .httpMethod(myDemoMethod.httpMethod())
            .type("MOCK")
            .cacheKeyParameters("method.request.path.param")
            .cacheNamespace("foobar")
            .timeoutMilliseconds(29000)
            .requestParameters(Map.of("integration.request.header.X-Authorization", "'static'"))
            .requestTemplates(Map.of("application/xml", """
{
   \"body\" : $input.json('$')
}
            """))
            .build());

    }
}
resources:
  myDemoAPI:
    type: aws:apigateway:RestApi
    name: MyDemoAPI
    properties:
      name: MyDemoAPI
      description: This is my API for demonstration purposes
  myDemoResource:
    type: aws:apigateway:Resource
    name: MyDemoResource
    properties:
      restApi: ${myDemoAPI.id}
      parentId: ${myDemoAPI.rootResourceId}
      pathPart: mydemoresource
  myDemoMethod:
    type: aws:apigateway:Method
    name: MyDemoMethod
    properties:
      restApi: ${myDemoAPI.id}
      resourceId: ${myDemoResource.id}
      httpMethod: GET
      authorization: NONE
  myDemoIntegration:
    type: aws:apigateway:Integration
    name: MyDemoIntegration
    properties:
      restApi: ${myDemoAPI.id}
      resourceId: ${myDemoResource.id}
      httpMethod: ${myDemoMethod.httpMethod}
      type: MOCK
      cacheKeyParameters:
        - method.request.path.param
      cacheNamespace: foobar
      timeoutMilliseconds: 29000
      requestParameters:
        integration.request.header.X-Authorization: '''static'''
      requestTemplates:
        application/xml: |
          {
             \"body\" : $input.json('$')
          }          

The type MOCK returns static responses without calling a backend. The requestTemplates transform incoming requests into the response format. The requestParameters map method request headers to integration request headers. The cacheKeyParameters define which request parameters affect caching. Mock integrations are useful for validating API structure before backend deployment.

Beyond these examples

These snippets focus on specific integration-level features: Lambda proxy and streaming integrations, VPC Link for private backend access, and mock integrations for testing. They’re intentionally minimal rather than full API deployments.

The examples reference pre-existing infrastructure such as REST API, resources, and methods, Lambda functions with execution roles, VPC infrastructure (subnets, security groups, load balancers), and VPC Link resources (V1 for NLB, V2 for ALB). They focus on configuring the integration rather than provisioning the surrounding API structure.

To keep things focused, common integration patterns are omitted, including:

  • Request and response transformation (requestTemplates, requestParameters)
  • Caching configuration (cacheKeyParameters, cacheNamespace)
  • IAM credentials and authorization (credentials property)
  • TLS configuration for backend connections (tlsConfig)
  • Content type handling (contentHandling, passthroughBehavior)

These omissions are intentional: the goal is to illustrate how each integration type is wired, not provide drop-in API modules. See the API Gateway Integration resource reference for all available configuration options.

Let's configure AWS API Gateway Integrations

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Integration Types & Lambda
Why can't I invoke my Lambda function through API Gateway?
Lambda functions can only be invoked via POST. Set integrationHttpMethod to POST when using type AWS_PROXY or AWS with Lambda.
What's the difference between AWS and AWS_PROXY integration types?
AWS_PROXY passes the entire request to Lambda and expects a specific response format, while AWS allows custom request/response transformations. For Lambda, AWS_PROXY is typically simpler and recommended.
What parameters are required for different integration types?
For AWS, AWS_PROXY, HTTP, or HTTP_PROXY types, you must specify both integrationHttpMethod and uri. For VPC_LINK connections, you must also provide connectionId.
How do I give API Gateway permission to invoke my Lambda function?
Create an aws.lambda.Permission resource with principal set to apigateway.amazonaws.com and sourceArn pointing to your API Gateway execution ARN.
VPC & Private Integrations
How do I connect API Gateway to private VPC resources?
Set connectionType to VPC_LINK and provide the VPC Link ID via connectionId. For VPC Link V2 with Application Load Balancers, also set integrationTarget to the load balancer ARN.
What's the difference between VPC Link V1 and V2?
VPC Link V1 uses Network Load Balancers and only requires connectionId. VPC Link V2 supports Application Load Balancers and uses integrationTarget to specify the load balancer ARN, while uri sets the Host header.
What does the uri parameter do in private integrations?
For private integrations, uri is not used for routing requests to your endpoint. Instead, it’s used for setting the Host header and for certificate validation.
Timeouts & Streaming
What are the timeout limits and how do I increase them?
The default timeout is 29,000 milliseconds (29 seconds). The minimum is 50ms. For BUFFERED mode, the maximum is 300,000ms (5 minutes), but you need to raise a Service Quota Ticket to increase beyond 29,000ms. For STREAM mode, the maximum is 900,000ms (15 minutes).
How do I enable Lambda response streaming?
Set responseTransferMode to STREAM, use your Lambda function’s responseStreamingInvokeArn for uri, and set timeoutMilliseconds to 900000. You may also need to adjust your Lambda function’s timeout.
Can I switch back to BUFFERED mode after using STREAM?
Yes, but once responseTransferMode is set to BUFFERED, you must explicitly specify BUFFERED rather than removing the argument.
Request Configuration
When do I need to specify passthroughBehavior?
passthroughBehavior is required if you use requestTemplates. Valid values are WHEN_NO_MATCH, WHEN_NO_TEMPLATES, or NEVER.
How do I pass caller identity through to my backend?
For AWS integrations, set credentials to arn:aws:iam::*:user/* to pass through the caller’s identity from the request. Alternatively, specify an IAM Role ARN for API Gateway to assume.
Immutability & Lifecycle
What properties are immutable after creation?
The following properties cannot be changed after creation: httpMethod, resourceId, restApi, type, passthroughBehavior, integrationHttpMethod, and credentials.

Using a different cloud?

Explore integration guides for other cloud providers: