Skip to content
v2.274.0

Amazon API Gateway Construct Library ​

Amazon API Gateway is a fully managed service that makes it easy for developers to publish, maintain, monitor, and secure APIs at any scale. Create an API to access data, business logic, or functionality from your back-end services, such as applications running on Amazon Elastic Compute Cloud (Amazon EC2), code running on AWS Lambda, or any web application.

Defining APIs ​

APIs are defined as a hierarchy of resources and methods. addResource and addMethod can be used to build this hierarchy. The root resource is api.root.

For example, the following code defines an API that includes the following HTTP endpoints: ANY /, GET /books, POST /books, GET /books/{book_id}, DELETE /books/{book_id}.

ts
const api = new apigateway.RestApi(this, 'books-api');

api.root.addMethod('ANY');

const books = api.root.addResource('books');
books.addMethod('GET');
books.addMethod('POST');

const book = books.addResource('{book_id}');
book.addMethod('GET');
book.addMethod('DELETE');
python
api = apigateway.RestApi(self, "books-api")

api.root.add_method("ANY")

books = api.root.add_resource("books")
books.add_method("GET")
books.add_method("POST")

book = books.add_resource("{book_id}")
book.add_method("GET")
book.add_method("DELETE")
java
RestApi api = new RestApi(this, "books-api");

api.root.addMethod("ANY");

Resource books = api.root.addResource("books");
books.addMethod("GET");
books.addMethod("POST");

Resource book = books.addResource("{book_id}");
book.addMethod("GET");
book.addMethod("DELETE");
csharp
var api = new RestApi(this, "books-api");

api.Root.AddMethod("ANY");

var books = api.Root.AddResource("books");
books.AddMethod("GET");
books.AddMethod("POST");

var book = books.AddResource("{book_id}");
book.AddMethod("GET");
book.AddMethod("DELETE");
go
api := apigateway.NewRestApi(this, jsii.String("books-api"))

api.Root.AddMethod(jsii.String("ANY"))

books := api.Root.AddResource(jsii.String("books"))
books.AddMethod(jsii.String("GET"))
books.AddMethod(jsii.String("POST"))

book := books.AddResource(jsii.String("{book_id}"))
book.AddMethod(jsii.String("GET"))
book.AddMethod(jsii.String("DELETE"))

To give an IAM User or Role permission to invoke a method, use grantExecute:

ts
declare const api: apigateway.RestApi;
declare const user: iam.User;

const method = api.root.addResource('books').addMethod('GET');
method.grantExecute(user);
python
# api: apigateway.RestApi
# user: iam.User


method = api.root.add_resource("books").add_method("GET")
method.grant_execute(user)
java
RestApi api;
User user;


Method method = api.root.addResource("books").addMethod("GET");
method.grantExecute(user);
csharp
RestApi api;
User user;


var method = api.Root.AddResource("books").AddMethod("GET");
method.GrantExecute(user);
go
var api RestApi
var user User


method := api.Root.AddResource(jsii.String("books")).AddMethod(jsii.String("GET"))
method.GrantExecute(user)

Breaking up Methods and Resources across Stacks ​

It is fairly common for REST APIs with a large number of Resources and Methods to hit the CloudFormation limit of 500 resources per stack.

To help with this, Resources and Methods for the same REST API can be re-organized across multiple stacks. A common way to do this is to have a stack per Resource or groups of Resources, but this is not the only possible way. The following example uses sets up two Resources '/pets' and '/books' in separate stacks using nested stacks:

ts
import type { Construct } from 'constructs';
import type { NestedStackProps } from '../../core';
import { App, CfnOutput, NestedStack, Stack } from '../../core';
import type { Method } from '../lib';
import { Deployment, MockIntegration, PassthroughBehavior, RestApi, Stage } from '../lib';

/**
 * This file showcases how to split up a RestApi's Resources and Methods across nested stacks.
 *
 * The root stack 'RootStack' first defines a RestApi.
 * Two nested stacks BooksStack and PetsStack, create corresponding Resources '/books' and '/pets'.
 * They are then deployed to a 'prod' Stage via a third nested stack - DeployStack.
 *
 * To verify this worked, go to the APIGateway
 */

class RootStack extends Stack {
  constructor(scope: Construct) {
    super(scope, 'integ-restapi-import-RootStack');

    const restApi = new RestApi(this, 'RestApi', {
      cloudWatchRole: true,
      deploy: false,
    });
    restApi.root.addMethod('ANY');

    const petsStack = new PetsStack(this, {
      restApiId: restApi.restApiId,
      rootResourceId: restApi.restApiRootResourceId,
    });
    const booksStack = new BooksStack(this, {
      restApiId: restApi.restApiId,
      rootResourceId: restApi.restApiRootResourceId,
    });
    new DeployStack(this, {
      restApiId: restApi.restApiId,
      methods: petsStack.methods.concat(booksStack.methods),
    });

    new CfnOutput(this, 'PetsURL', {
      value: `https://${restApi.restApiId}.execute-api.${this.region}.amazonaws.com/prod/pets`,
    });

    new CfnOutput(this, 'BooksURL', {
      value: `https://${restApi.restApiId}.execute-api.${this.region}.amazonaws.com/prod/books`,
    });
  }
}

interface ResourceNestedStackProps extends NestedStackProps {
  readonly restApiId: string;

  readonly rootResourceId: string;
}

class PetsStack extends NestedStack {
  public readonly methods: Method[] = [];

  constructor(scope: Construct, props: ResourceNestedStackProps) {
    super(scope, 'integ-restapi-import-PetsStack', props);

    const api = RestApi.fromRestApiAttributes(this, 'RestApi', {
      restApiId: props.restApiId,
      rootResourceId: props.rootResourceId,
    });

    const method = api.root.addResource('pets').addMethod('GET', new MockIntegration({
      integrationResponses: [{
        statusCode: '200',
      }],
      passthroughBehavior: PassthroughBehavior.NEVER,
      requestTemplates: {
        'application/json': '{ "statusCode": 200 }',
      },
    }), {
      methodResponses: [{ statusCode: '200' }],
    });

    this.methods.push(method);
  }
}

class BooksStack extends NestedStack {
  public readonly methods: Method[] = [];

  constructor(scope: Construct, props: ResourceNestedStackProps) {
    super(scope, 'integ-restapi-import-BooksStack', props);

    const api = RestApi.fromRestApiAttributes(this, 'RestApi', {
      restApiId: props.restApiId,
      rootResourceId: props.rootResourceId,
    });

    const method = api.root.addResource('books').addMethod('GET', new MockIntegration({
      integrationResponses: [{
        statusCode: '200',
      }],
      passthroughBehavior: PassthroughBehavior.NEVER,
      requestTemplates: {
        'application/json': '{ "statusCode": 200 }',
      },
    }), {
      methodResponses: [{ statusCode: '200' }],
    });

    this.methods.push(method);
  }
}

interface DeployStackProps extends NestedStackProps {
  readonly restApiId: string;

  readonly methods?: Method[];
}

class DeployStack extends NestedStack {
  constructor(scope: Construct, props: DeployStackProps) {
    super(scope, 'integ-restapi-import-DeployStack', props);

    const deployment = new Deployment(this, 'Deployment', {
      api: RestApi.fromRestApiId(this, 'RestApi', props.restApiId),
    });
    if (props.methods) {
      for (const method of props.methods) {
        deployment.node.addDependency(method);
      }
    }
    new Stage(this, 'Stage', { deployment });
  }
}

new RootStack(new App());
python
from aws_cdk.aws_apigateway import IntegrationResponse, MethodResponse, IntegrationResponse, MethodResponse
from constructs import Construct
from aws_cdk import NestedStackProps
from aws_cdk import App, CfnOutput, NestedStack, Stack
from aws_cdk.aws_apigateway import Method
from aws_cdk.aws_apigateway import Deployment, MockIntegration, PassthroughBehavior, RestApi, Stage

#
# This file showcases how to split up a RestApi's Resources and Methods across nested stacks.
#
# The root stack 'RootStack' first defines a RestApi.
# Two nested stacks BooksStack and PetsStack, create corresponding Resources '/books' and '/pets'.
# They are then deployed to a 'prod' Stage via a third nested stack - DeployStack.
#
# To verify this worked, go to the APIGateway
#

class RootStack(Stack):
    def __init__(self, scope):
        super().__init__(scope, "integ-restapi-import-RootStack")

        rest_api = RestApi(self, "RestApi",
            cloud_watch_role=True,
            deploy=False
        )
        rest_api.root.add_method("ANY")

        pets_stack = PetsStack(self,
            rest_api_id=rest_api.rest_api_id,
            root_resource_id=rest_api.rest_api_root_resource_id
        )
        books_stack = BooksStack(self,
            rest_api_id=rest_api.rest_api_id,
            root_resource_id=rest_api.rest_api_root_resource_id
        )
        DeployStack(self,
            rest_api_id=rest_api.rest_api_id,
            methods=pets_stack.methods.concat(books_stack.methods)
        )

        CfnOutput(self, "PetsURL",
            value=f"https://{restApi.restApiId}.execute-api.{this.region}.amazonaws.com/prod/pets"
        )

        CfnOutput(self, "BooksURL",
            value=f"https://{restApi.restApiId}.execute-api.{this.region}.amazonaws.com/prod/books"
        )

class PetsStack(NestedStack):

    def __init__(self, scope, *, restApiId, rootResourceId, parameters=None, timeout=None, notificationArns=None, removalPolicy=None, description=None, suppressTemplateIndentation=None):
        super().__init__(scope, "integ-restapi-import-PetsStack", restApiId=restApiId, rootResourceId=rootResourceId, parameters=parameters, timeout=timeout, notificationArns=notificationArns, removalPolicy=removalPolicy, description=description, suppressTemplateIndentation=suppressTemplateIndentation)

        api = RestApi.from_rest_api_attributes(self, "RestApi",
            rest_api_id=rest_api_id,
            root_resource_id=root_resource_id
        )

        method = api.root.add_resource("pets").add_method("GET", MockIntegration(
            integration_responses=[IntegrationResponse(
                status_code="200"
            )],
            passthrough_behavior=PassthroughBehavior.NEVER,
            request_templates={
                "application/json": "{ \"statusCode\": 200 }"
            }
        ),
            method_responses=[MethodResponse(status_code="200")]
        )

        self.methods.push(method)

class BooksStack(NestedStack):

    def __init__(self, scope, *, restApiId, rootResourceId, parameters=None, timeout=None, notificationArns=None, removalPolicy=None, description=None, suppressTemplateIndentation=None):
        super().__init__(scope, "integ-restapi-import-BooksStack", restApiId=restApiId, rootResourceId=rootResourceId, parameters=parameters, timeout=timeout, notificationArns=notificationArns, removalPolicy=removalPolicy, description=description, suppressTemplateIndentation=suppressTemplateIndentation)

        api = RestApi.from_rest_api_attributes(self, "RestApi",
            rest_api_id=rest_api_id,
            root_resource_id=root_resource_id
        )

        method = api.root.add_resource("books").add_method("GET", MockIntegration(
            integration_responses=[IntegrationResponse(
                status_code="200"
            )],
            passthrough_behavior=PassthroughBehavior.NEVER,
            request_templates={
                "application/json": "{ \"statusCode\": 200 }"
            }
        ),
            method_responses=[MethodResponse(status_code="200")]
        )

        self.methods.push(method)

class DeployStack(NestedStack):
    def __init__(self, scope, *, restApiId, methods=None, parameters=None, timeout=None, notificationArns=None, removalPolicy=None, description=None, suppressTemplateIndentation=None):
        super().__init__(scope, "integ-restapi-import-DeployStack", restApiId=restApiId, methods=methods, parameters=parameters, timeout=timeout, notificationArns=notificationArns, removalPolicy=removalPolicy, description=description, suppressTemplateIndentation=suppressTemplateIndentation)

        deployment = Deployment(self, "Deployment",
            api=RestApi.from_rest_api_id(self, "RestApi", rest_api_id)
        )
        if methods:
            for method in methods:
                deployment.node.add_dependency(method)
        Stage(self, "Stage", deployment=deployment)

RootStack(App())
java
import software.constructs.Construct;
import software.amazon.awscdk.NestedStackProps;
import software.amazon.awscdk.App;
import software.amazon.awscdk.CfnOutput;
import software.amazon.awscdk.NestedStack;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.services.apigateway.Method;
import software.amazon.awscdk.services.apigateway.Deployment;
import software.amazon.awscdk.services.apigateway.MockIntegration;
import software.amazon.awscdk.services.apigateway.PassthroughBehavior;
import software.amazon.awscdk.services.apigateway.RestApi;
import software.amazon.awscdk.services.apigateway.Stage;

/**
 * This file showcases how to split up a RestApi's Resources and Methods across nested stacks.
 *
 * The root stack 'RootStack' first defines a RestApi.
 * Two nested stacks BooksStack and PetsStack, create corresponding Resources '/books' and '/pets'.
 * They are then deployed to a 'prod' Stage via a third nested stack - DeployStack.
 *
 * To verify this worked, go to the APIGateway
 */

public class RootStack extends Stack {
    public RootStack(Construct scope) {
        super(scope, "integ-restapi-import-RootStack");

        RestApi restApi = RestApi.Builder.create(this, "RestApi")
                .cloudWatchRole(true)
                .deploy(false)
                .build();
        restApi.root.addMethod("ANY");

        PetsStack petsStack = new PetsStack(this, new ResourceNestedStackProps()
                .restApiId(restApi.getRestApiId())
                .rootResourceId(restApi.getRestApiRootResourceId())
                );
        BooksStack booksStack = new BooksStack(this, new ResourceNestedStackProps()
                .restApiId(restApi.getRestApiId())
                .rootResourceId(restApi.getRestApiRootResourceId())
                );
        new DeployStack(this, new DeployStackProps()
                .restApiId(restApi.getRestApiId())
                .methods(petsStack.methods.concat(booksStack.getMethods()))
                );

        CfnOutput.Builder.create(this, "PetsURL")
                .value(String.format("https://%s.execute-api.%s.amazonaws.com/prod/pets", restApi.getRestApiId(), this.region))
                .build();

        CfnOutput.Builder.create(this, "BooksURL")
                .value(String.format("https://%s.execute-api.%s.amazonaws.com/prod/books", restApi.getRestApiId(), this.region))
                .build();
    }
}

public class ResourceNestedStackProps extends NestedStackProps {
    private String restApiId;
    public String getRestApiId() {
        return this.restApiId;
    }
    public ResourceNestedStackProps restApiId(String restApiId) {
        this.restApiId = restApiId;
        return this;
    }

    private String rootResourceId;
    public String getRootResourceId() {
        return this.rootResourceId;
    }
    public ResourceNestedStackProps rootResourceId(String rootResourceId) {
        this.rootResourceId = rootResourceId;
        return this;
    }
}

public class PetsStack extends NestedStack {
    public final Method[] methods;

    public PetsStack(Construct scope, ResourceNestedStackProps props) {
        super(scope, "integ-restapi-import-PetsStack", props);

        IRestApi api = RestApi.fromRestApiAttributes(this, "RestApi", RestApiAttributes.builder()
                .restApiId(props.getRestApiId())
                .rootResourceId(props.getRootResourceId())
                .build());

        Method method = api.root.addResource("pets").addMethod("GET", MockIntegration.Builder.create()
                .integrationResponses(List.of(IntegrationResponse.builder()
                        .statusCode("200")
                        .build()))
                .passthroughBehavior(PassthroughBehavior.NEVER)
                .requestTemplates(Map.of(
                        "application/json", "{ \"statusCode\": 200 }"))
                .build(), MethodOptions.builder()
                .methodResponses(List.of(MethodResponse.builder().statusCode("200").build()))
                .build());

        this.methods.push(method);
    }
}

public class BooksStack extends NestedStack {
    public final Method[] methods;

    public BooksStack(Construct scope, ResourceNestedStackProps props) {
        super(scope, "integ-restapi-import-BooksStack", props);

        IRestApi api = RestApi.fromRestApiAttributes(this, "RestApi", RestApiAttributes.builder()
                .restApiId(props.getRestApiId())
                .rootResourceId(props.getRootResourceId())
                .build());

        Method method = api.root.addResource("books").addMethod("GET", MockIntegration.Builder.create()
                .integrationResponses(List.of(IntegrationResponse.builder()
                        .statusCode("200")
                        .build()))
                .passthroughBehavior(PassthroughBehavior.NEVER)
                .requestTemplates(Map.of(
                        "application/json", "{ \"statusCode\": 200 }"))
                .build(), MethodOptions.builder()
                .methodResponses(List.of(MethodResponse.builder().statusCode("200").build()))
                .build());

        this.methods.push(method);
    }
}

public class DeployStackProps extends NestedStackProps {
    private String restApiId;
    public String getRestApiId() {
        return this.restApiId;
    }
    public DeployStackProps restApiId(String restApiId) {
        this.restApiId = restApiId;
        return this;
    }

    private Method[] methods;
    public Method[] getMethods() {
        return this.methods;
    }
    public DeployStackProps methods(Method[] methods) {
        this.methods = methods;
        return this;
    }
}

public class DeployStack extends NestedStack {
    public DeployStack(Construct scope, DeployStackProps props) {
        super(scope, "integ-restapi-import-DeployStack", props);

        Deployment deployment = Deployment.Builder.create(this, "Deployment")
                .api(RestApi.fromRestApiId(this, "RestApi", props.getRestApiId()))
                .build();
        if (props.getMethods()) {
            for (Object method : props.getMethods()) {
                deployment.node.addDependency(method);
            }
        }
        Stage.Builder.create(this, "Stage").deployment(deployment).build();
    }
}

new RootStack(new App());
csharp
using Constructs;
using Amazon.CDK;
using Amazon.CDK.AWS.APIGateway;

/**
 * This file showcases how to split up a RestApi's Resources and Methods across nested stacks.
 *
 * The root stack 'RootStack' first defines a RestApi.
 * Two nested stacks BooksStack and PetsStack, create corresponding Resources '/books' and '/pets'.
 * They are then deployed to a 'prod' Stage via a third nested stack - DeployStack.
 *
 * To verify this worked, go to the APIGateway
 */

class RootStack : Stack
{
    public RootStack(Construct scope) : base(scope, "integ-restapi-import-RootStack")
    {

        var restApi = new RestApi(this, "RestApi", new RestApiProps {
            CloudWatchRole = true,
            Deploy = false
        });
        restApi.Root.AddMethod("ANY");

        var petsStack = new PetsStack(this, new ResourceNestedStackProps {
            RestApiId = restApi.RestApiId,
            RootResourceId = restApi.RestApiRootResourceId
        });
        var booksStack = new BooksStack(this, new ResourceNestedStackProps {
            RestApiId = restApi.RestApiId,
            RootResourceId = restApi.RestApiRootResourceId
        });
        new DeployStack(this, new DeployStackProps {
            RestApiId = restApi.RestApiId,
            Methods = petsStack.Methods.Concat(booksStack.Methods)
        });

        new CfnOutput(this, "PetsURL", new CfnOutputProps {
            Value = $"https://{restApi.restApiId}.execute-api.{this.region}.amazonaws.com/prod/pets"
        });

        new CfnOutput(this, "BooksURL", new CfnOutputProps {
            Value = $"https://{restApi.restApiId}.execute-api.{this.region}.amazonaws.com/prod/books"
        });
    }
}

class ResourceNestedStackProps : NestedStackProps
{
    public string RestApiId { get; set; }

    public string RootResourceId { get; set; }
}

class PetsStack : NestedStack
{
    public readonly Method[] Methods = new [] {  };

    public PetsStack(Construct scope, ResourceNestedStackProps props) : base(scope, "integ-restapi-import-PetsStack", props)
    {

        var api = RestApi.FromRestApiAttributes(this, "RestApi", new RestApiAttributes {
            RestApiId = props.RestApiId,
            RootResourceId = props.RootResourceId
        });

        var method = api.Root.AddResource("pets").AddMethod("GET", new MockIntegration(new IntegrationOptions {
            IntegrationResponses = new [] { new IntegrationResponse {
                StatusCode = "200"
            } },
            PassthroughBehavior = PassthroughBehavior.NEVER,
            RequestTemplates = new Dictionary<string, string> {
                { "application/json", "{ \"statusCode\": 200 }" }
            }
        }), new MethodOptions {
            MethodResponses = new [] { new MethodResponse { StatusCode = "200" } }
        });

        Methods.Push(method);
    }
}

class BooksStack : NestedStack
{
    public readonly Method[] Methods = new [] {  };

    public BooksStack(Construct scope, ResourceNestedStackProps props) : base(scope, "integ-restapi-import-BooksStack", props)
    {

        var api = RestApi.FromRestApiAttributes(this, "RestApi", new RestApiAttributes {
            RestApiId = props.RestApiId,
            RootResourceId = props.RootResourceId
        });

        var method = api.Root.AddResource("books").AddMethod("GET", new MockIntegration(new IntegrationOptions {
            IntegrationResponses = new [] { new IntegrationResponse {
                StatusCode = "200"
            } },
            PassthroughBehavior = PassthroughBehavior.NEVER,
            RequestTemplates = new Dictionary<string, string> {
                { "application/json", "{ \"statusCode\": 200 }" }
            }
        }), new MethodOptions {
            MethodResponses = new [] { new MethodResponse { StatusCode = "200" } }
        });

        Methods.Push(method);
    }
}

class DeployStackProps : NestedStackProps
{
    public string RestApiId { get; set; }

    public Method[]? Methods { get; set; }
}

class DeployStack : NestedStack
{
    public DeployStack(Construct scope, DeployStackProps props) : base(scope, "integ-restapi-import-DeployStack", props)
    {

        var deployment = new Deployment(this, "Deployment", new DeploymentProps {
            Api = RestApi.FromRestApiId(this, "RestApi", props.RestApiId)
        });
        if (props.Methods)
        {
            for (var method in props.Methods)
            {
                deployment.Node.AddDependency(method);
            }
        }
        new Stage(this, "Stage", new StageProps { Deployment = deployment });
    }
}

new RootStack(new App());
go
import "github.com/aws/constructs-go/constructs"
import "github.com/aws/aws-cdk-go/awscdk"
import "github.com/aws/aws-cdk-go/awscdk"
import "github.com/aws/aws-cdk-go/awscdk"
import "github.com/aws/aws-cdk-go/awscdk"

/**
 * This file showcases how to split up a RestApi's Resources and Methods across nested stacks.
 *
 * The root stack 'RootStack' first defines a RestApi.
 * Two nested stacks BooksStack and PetsStack, create corresponding Resources '/books' and '/pets'.
 * They are then deployed to a 'prod' Stage via a third nested stack - DeployStack.
 *
 * To verify this worked, go to the APIGateway
 */

type rootStack struct {
	Stack
}

func newRootStack(scope Construct) *rootStack {
	this := &rootStack{}
	newStack_Override(this, scope, jsii.String("integ-restapi-import-RootStack"))

	restApi := awscdk.NewRestApi(this, jsii.String("RestApi"), &RestApiProps{
		CloudWatchRole: jsii.Boolean(true),
		Deploy: jsii.Boolean(false),
	})
	restApi.Root.AddMethod(jsii.String("ANY"))

	petsStack := NewPetsStack(this, &resourceNestedStackProps{
		restApiId: restApi.RestApiId,
		rootResourceId: restApi.RestApiRootResourceId,
	})
	booksStack := NewBooksStack(this, &resourceNestedStackProps{
		restApiId: restApi.*RestApiId,
		rootResourceId: restApi.*RestApiRootResourceId,
	})
	NewDeployStack(this, &deployStackProps{
		restApiId: restApi.*RestApiId,
		methods: petsStack.methods.concat(booksStack.methods),
	})

	awscdk.NewCfnOutput(this, jsii.String("PetsURL"), &CfnOutputProps{
		Value: fmt.Sprintf("https://%v.execute-api.%v.amazonaws.com/prod/pets", restApi.*RestApiId, this.Region),
	})

	awscdk.NewCfnOutput(this, jsii.String("BooksURL"), &CfnOutputProps{
		Value: fmt.Sprintf("https://%v.execute-api.%v.amazonaws.com/prod/books", restApi.*RestApiId, this.*Region),
	})
	return this
}

type resourceNestedStackProps struct {
	NestedStackProps
	restApiId *string
	rootResourceId *string
}

type petsStack struct {
	NestedStack
	methods []Method
}

func newPetsStack(scope Construct, props resourceNestedStackProps) *petsStack {
	this := &petsStack{}
	newNestedStack_Override(this, scope, jsii.String("integ-restapi-import-PetsStack"), props)

	api := awscdk.RestApi_FromRestApiAttributes(this, jsii.String("RestApi"), &RestApiAttributes{
		RestApiId: props.restApiId,
		RootResourceId: props.rootResourceId,
	})

	method := api.Root.AddResource(jsii.String("pets")).AddMethod(jsii.String("GET"), awscdk.NewMockIntegration(&IntegrationOptions{
		IntegrationResponses: []IntegrationResponse{
			&IntegrationResponse{
				StatusCode: jsii.String("200"),
			},
		},
		PassthroughBehavior: awscdk.PassthroughBehavior_NEVER,
		RequestTemplates: map[string]*string{
			"application/json": jsii.String("{ \"statusCode\": 200 }"),
		},
	}), &MethodOptions{
		MethodResponses: []MethodResponse{
			&MethodResponse{
				StatusCode: jsii.String("200"),
			},
		},
	})

	this.methods.push(method)
	return this
}

type booksStack struct {
	NestedStack
	methods []Method
}

func newBooksStack(scope Construct, props resourceNestedStackProps) *booksStack {
	this := &booksStack{}
	newNestedStack_Override(this, scope, jsii.String("integ-restapi-import-BooksStack"), props)

	api := awscdk.RestApi_FromRestApiAttributes(this, jsii.String("RestApi"), &RestApiAttributes{
		RestApiId: props.restApiId,
		RootResourceId: props.rootResourceId,
	})

	method := api.Root.AddResource(jsii.String("books")).AddMethod(jsii.String("GET"), awscdk.NewMockIntegration(&IntegrationOptions{
		IntegrationResponses: []IntegrationResponse{
			&IntegrationResponse{
				StatusCode: jsii.String("200"),
			},
		},
		PassthroughBehavior: awscdk.PassthroughBehavior_NEVER,
		RequestTemplates: map[string]*string{
			"application/json": jsii.String("{ \"statusCode\": 200 }"),
		},
	}), &MethodOptions{
		MethodResponses: []MethodResponse{
			&MethodResponse{
				StatusCode: jsii.String("200"),
			},
		},
	})

	this.methods.push(method)
	return this
}

type deployStackProps struct {
	NestedStackProps
	restApiId *string
	methods []Method
}

type deployStack struct {
	NestedStack
}

func newDeployStack(scope Construct, props deployStackProps) *deployStack {
	this := &deployStack{}
	newNestedStack_Override(this, scope, jsii.String("integ-restapi-import-DeployStack"), props)

	deployment := awscdk.NewDeployment(this, jsii.String("Deployment"), &DeploymentProps{
		Api: awscdk.RestApi_FromRestApiId(this, jsii.String("RestApi"), props.restApiId),
	})
	if *props.methods {
		for _, method := range *props.methods {
			deployment.Node.AddDependency(method)
		}
	}
	awscdk.NewStage(this, jsii.String("Stage"), &StageProps{
		Deployment: Deployment,
	})
	return this
}

NewRootStack(awscdk.NewApp())

Warning: In the code above, an API Gateway deployment is created during the initial CDK deployment. However, if there are changes to the resources in subsequent CDK deployments, a new API Gateway deployment is not automatically created. As a result, the latest state of the resources is not reflected. To ensure the latest state of the resources is reflected, a manual deployment of the API Gateway is required after the CDK deployment. See Controlled triggering of deployments for more info.

AWS Lambda-backed APIs ​

A very common practice is to use Amazon API Gateway with AWS Lambda as the backend integration. The LambdaRestApi construct makes it easy:

The following code defines a REST API that routes all requests to the specified AWS Lambda function:

ts
declare const backend: lambda.Function;
new apigateway.LambdaRestApi(this, 'myapi', {
  handler: backend,
});
python
# backend: lambda.Function

apigateway.LambdaRestApi(self, "myapi",
    handler=backend
)
java
Function backend;

LambdaRestApi.Builder.create(this, "myapi")
        .handler(backend)
        .build();
csharp
Function backend;

new LambdaRestApi(this, "myapi", new LambdaRestApiProps {
    Handler = backend
});
go
var backend Function

apigateway.NewLambdaRestApi(this, jsii.String("myapi"), &LambdaRestApiProps{
	Handler: backend,
})

You can also supply proxy: false, in which case you will have to explicitly define the API model:

ts
declare const backend: lambda.Function;
const api = new apigateway.LambdaRestApi(this, 'myapi', {
  handler: backend,
  proxy: false
});

const items = api.root.addResource('items');
items.addMethod('GET');  // GET /items
items.addMethod('POST'); // POST /items

const item = items.addResource('{item}');
item.addMethod('GET');   // GET /items/{item}

// the default integration for methods is "handler", but one can
// customize this behavior per method or even a sub path.
item.addMethod('DELETE', new apigateway.HttpIntegration('http://amazon.com'));
python
# backend: lambda.Function

api = apigateway.LambdaRestApi(self, "myapi",
    handler=backend,
    proxy=False
)

items = api.root.add_resource("items")
items.add_method("GET") # GET /items
items.add_method("POST") # POST /items

item = items.add_resource("{item}")
item.add_method("GET") # GET /items/{item}

# the default integration for methods is "handler", but one can
# customize this behavior per method or even a sub path.
item.add_method("DELETE", apigateway.HttpIntegration("http://amazon.com"))
java
Function backend;

LambdaRestApi api = LambdaRestApi.Builder.create(this, "myapi")
        .handler(backend)
        .proxy(false)
        .build();

Resource items = api.root.addResource("items");
items.addMethod("GET"); // GET /items
items.addMethod("POST"); // POST /items

Resource item = items.addResource("{item}");
item.addMethod("GET"); // GET /items/{item}

// the default integration for methods is "handler", but one can
// customize this behavior per method or even a sub path.
item.addMethod("DELETE", new HttpIntegration("http://amazon.com"));
csharp
Function backend;

var api = new LambdaRestApi(this, "myapi", new LambdaRestApiProps {
    Handler = backend,
    Proxy = false
});

var items = api.Root.AddResource("items");
items.AddMethod("GET"); // GET /items
items.AddMethod("POST"); // POST /items

var item = items.AddResource("{item}");
item.AddMethod("GET"); // GET /items/{item}

// the default integration for methods is "handler", but one can
// customize this behavior per method or even a sub path.
item.AddMethod("DELETE", new HttpIntegration("http://amazon.com"));
go
var backend Function

api := apigateway.NewLambdaRestApi(this, jsii.String("myapi"), &LambdaRestApiProps{
	Handler: backend,
	Proxy: jsii.Boolean(false),
})

items := api.Root.AddResource(jsii.String("items"))
items.AddMethod(jsii.String("GET")) // GET /items
items.AddMethod(jsii.String("POST")) // POST /items

item := items.AddResource(jsii.String("{item}"))
item.AddMethod(jsii.String("GET")) // GET /items/{item}

// the default integration for methods is "handler", but one can
// customize this behavior per method or even a sub path.
item.AddMethod(jsii.String("DELETE"), apigateway.NewHttpIntegration(jsii.String("http://amazon.com")))

Additionally, integrationOptions can be supplied to explicitly define options of the Lambda integration:

ts
declare const backend: lambda.Function;

const api = new apigateway.LambdaRestApi(this, 'myapi', {
  handler: backend,
  integrationOptions: {
    allowTestInvoke: false,
    timeout: Duration.seconds(1),
  }
})
python
# backend: lambda.Function


api = apigateway.LambdaRestApi(self, "myapi",
    handler=backend,
    integration_options=apigateway.LambdaIntegrationOptions(
        allow_test_invoke=False,
        timeout=Duration.seconds(1)
    )
)
java
Function backend;


LambdaRestApi api = LambdaRestApi.Builder.create(this, "myapi")
        .handler(backend)
        .integrationOptions(LambdaIntegrationOptions.builder()
                .allowTestInvoke(false)
                .timeout(Duration.seconds(1))
                .build())
        .build();
csharp
Function backend;


var api = new LambdaRestApi(this, "myapi", new LambdaRestApiProps {
    Handler = backend,
    IntegrationOptions = new LambdaIntegrationOptions {
        AllowTestInvoke = false,
        Timeout = Duration.Seconds(1)
    }
});
go
var backend Function


api := apigateway.NewLambdaRestApi(this, jsii.String("myapi"), &LambdaRestApiProps{
	Handler: backend,
	IntegrationOptions: &LambdaIntegrationOptions{
		AllowTestInvoke: jsii.Boolean(false),
		Timeout: awscdk.Duration_Seconds(jsii.Number(1)),
	},
})

AWS StepFunctions backed APIs ​

You can use Amazon API Gateway with AWS Step Functions as the backend integration, specifically Synchronous Express Workflows.

The StepFunctionsRestApi only supports integration with Synchronous Express state machine. The StepFunctionsRestApi construct makes this easy by setting up input, output and error mapping.

The construct sets up an API endpoint and maps the ANY HTTP method and any calls to the API endpoint starts an express workflow execution for the underlying state machine.

Invoking the endpoint with any HTTP method (GET, POST, PUT, DELETE, ...) in the example below will send the request to the state machine as a new execution. On success, an HTTP code 200 is returned with the execution output as the Response Body.

If the execution fails, an HTTP 500 response is returned with the error and cause from the execution output as the Response Body. If the request is invalid (ex. bad execution input) HTTP code 400 is returned.

To disable default response models generation use the useDefaultMethodResponses property:

ts
declare const machine: stepfunctions.IStateMachine;

new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', {
  stateMachine: machine,
  useDefaultMethodResponses: false,
});
python
# machine: stepfunctions.IStateMachine


apigateway.StepFunctionsRestApi(self, "StepFunctionsRestApi",
    state_machine=machine,
    use_default_method_responses=False
)
java
IStateMachine machine;


StepFunctionsRestApi.Builder.create(this, "StepFunctionsRestApi")
        .stateMachine(machine)
        .useDefaultMethodResponses(false)
        .build();
csharp
IStateMachine machine;


new StepFunctionsRestApi(this, "StepFunctionsRestApi", new StepFunctionsRestApiProps {
    StateMachine = machine,
    UseDefaultMethodResponses = false
});
go
var machine IStateMachine


apigateway.NewStepFunctionsRestApi(this, jsii.String("StepFunctionsRestApi"), &StepFunctionsRestApiProps{
	StateMachine: machine,
	UseDefaultMethodResponses: jsii.Boolean(false),
})

The response from the invocation contains only the output field from the StartSyncExecution API. In case of failures, the fields error and cause are returned as part of the response. Other metadata such as billing details, AWS account ID and resource ARNs are not returned in the API response.

By default, a prod stage is provisioned.

In order to reduce the payload size sent to AWS Step Functions, headers are not forwarded to the Step Functions execution input. It is possible to choose whether headers, requestContext, path, querystring, and authorizer are included or not. By default, headers are excluded in all requests.

More details about AWS Step Functions payload limit can be found at https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html#service-limits-task-executions.

The following code defines a REST API that routes all requests to the specified AWS StepFunctions state machine:

ts
const stateMachineDefinition = new stepfunctions.Pass(this, 'PassState');

const stateMachine: stepfunctions.IStateMachine = new stepfunctions.StateMachine(this, 'StateMachine', {
  definition: stateMachineDefinition,
  stateMachineType: stepfunctions.StateMachineType.EXPRESS,
});

new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', {
  deploy: true,
  stateMachine: stateMachine,
});
python
state_machine_definition = stepfunctions.Pass(self, "PassState")

state_machine = stepfunctions.StateMachine(self, "StateMachine",
    definition=state_machine_definition,
    state_machine_type=stepfunctions.StateMachineType.EXPRESS
)

apigateway.StepFunctionsRestApi(self, "StepFunctionsRestApi",
    deploy=True,
    state_machine=state_machine
)
java
Pass stateMachineDefinition = new Pass(this, "PassState");

IStateMachine stateMachine = StateMachine.Builder.create(this, "StateMachine")
        .definition(stateMachineDefinition)
        .stateMachineType(StateMachineType.EXPRESS)
        .build();

StepFunctionsRestApi.Builder.create(this, "StepFunctionsRestApi")
        .deploy(true)
        .stateMachine(stateMachine)
        .build();
csharp
var stateMachineDefinition = new Pass(this, "PassState");

var stateMachine = new StateMachine(this, "StateMachine", new StateMachineProps {
    Definition = stateMachineDefinition,
    StateMachineType = StateMachineType.EXPRESS
});

new StepFunctionsRestApi(this, "StepFunctionsRestApi", new StepFunctionsRestApiProps {
    Deploy = true,
    StateMachine = stateMachine
});
go
stateMachineDefinition := stepfunctions.NewPass(this, jsii.String("PassState"))

stateMachine := stepfunctions.NewStateMachine(this, jsii.String("StateMachine"), &StateMachineProps{
	Definition: stateMachineDefinition,
	StateMachineType: stepfunctions.StateMachineType_EXPRESS,
})

apigateway.NewStepFunctionsRestApi(this, jsii.String("StepFunctionsRestApi"), &StepFunctionsRestApiProps{
	Deploy: jsii.Boolean(true),
	StateMachine: stateMachine,
})

When the REST API endpoint configuration above is invoked using POST, as follows -

bash
curl -X POST -d '{ "customerId": 1 }' https://example.com/

AWS Step Functions will receive the request body in its input as follows:

json
{
  "body": {
    "customerId": 1
  },
  "path": "/",
  "querystring": {}
}

When the endpoint is invoked at path '/users/5' using the HTTP GET method as below:

bash
curl -X GET https://example.com/users/5?foo=bar

AWS Step Functions will receive the following execution input:

json
{
  "body": {},
  "path": {
     "users": "5"
  },
  "querystring": {
    "foo": "bar"
  }
}

Additional information around the request such as the request context, authorizer context, and headers can be included as part of the input forwarded to the state machine. The following example enables headers to be included in the input but not query string.

ts
new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', {
  stateMachine: machine,
  headers: true,
  path: false,
  querystring: false,
  authorizer: false,
  requestContext: {
    caller: true,
    user: true,
  },
});
python
apigateway.StepFunctionsRestApi(self, "StepFunctionsRestApi",
    state_machine=machine,
    headers=True,
    path=False,
    querystring=False,
    authorizer=False,
    request_context=apigateway.RequestContext(
        caller=True,
        user=True
    )
)
java
StepFunctionsRestApi.Builder.create(this, "StepFunctionsRestApi")
        .stateMachine(machine)
        .headers(true)
        .path(false)
        .querystring(false)
        .authorizer(false)
        .requestContext(RequestContext.builder()
                .caller(true)
                .user(true)
                .build())
        .build();
csharp
new StepFunctionsRestApi(this, "StepFunctionsRestApi", new StepFunctionsRestApiProps {
    StateMachine = machine,
    Headers = true,
    Path = false,
    Querystring = false,
    Authorizer = false,
    RequestContext = new RequestContext {
        Caller = true,
        User = true
    }
});
go
apigateway.NewStepFunctionsRestApi(this, jsii.String("StepFunctionsRestApi"), &StepFunctionsRestApiProps{
	StateMachine: machine,
	Headers: jsii.Boolean(true),
	Path: jsii.Boolean(false),
	Querystring: jsii.Boolean(false),
	Authorizer: jsii.Boolean(false),
	RequestContext: &RequestContext{
		Caller: jsii.Boolean(true),
		User: jsii.Boolean(true),
	},
})

In such a case, when the endpoint is invoked as below:

bash
curl -X GET https://example.com/

AWS Step Functions will receive the following execution input:

json
{
  "headers": {
    "Accept": "...",
    "CloudFront-Forwarded-Proto": "...",
  },
  "requestContext": {
     "accountId": "...",
     "apiKey": "...",
  },
  "body": {}
}

Integration Targets ​

Methods are associated with backend integrations, which are invoked when this method is called. API Gateway supports the following integrations:

  • MockIntegration - can be used to test APIs. This is the default integration if one is not specified.
  • AwsIntegration - can be used to invoke arbitrary AWS service APIs.
  • HttpIntegration - can be used to invoke HTTP endpoints.
  • LambdaIntegration - can be used to invoke an AWS Lambda function.
  • SagemakerIntegration - can be used to invoke Sagemaker Endpoints.

The following example shows how to integrate the GET /book/{book_id} method to an AWS Lambda function:

ts
declare const getBookHandler: lambda.Function;
declare const book: apigateway.Resource;

const getBookIntegration = new apigateway.LambdaIntegration(getBookHandler);
book.addMethod('GET', getBookIntegration);
python
# get_book_handler: lambda.Function
# book: apigateway.Resource


get_book_integration = apigateway.LambdaIntegration(get_book_handler)
book.add_method("GET", get_book_integration)
java
Function getBookHandler;
Resource book;


LambdaIntegration getBookIntegration = new LambdaIntegration(getBookHandler);
book.addMethod("GET", getBookIntegration);
csharp
Function getBookHandler;
Resource book;


var getBookIntegration = new LambdaIntegration(getBookHandler);
book.AddMethod("GET", getBookIntegration);
go
var getBookHandler Function
var book Resource


getBookIntegration := apigateway.NewLambdaIntegration(getBookHandler)
book.AddMethod(jsii.String("GET"), getBookIntegration)

Integration options can be optionally be specified:

ts
declare const getBookHandler: lambda.Function;
declare const getBookIntegration: apigateway.LambdaIntegration;

const getBookIntegration = new apigateway.LambdaIntegration(getBookHandler, {
  contentHandling: apigateway.ContentHandling.CONVERT_TO_TEXT, // convert to base64
  credentialsPassthrough: true, // use caller identity to invoke the function
});
python
# get_book_handler: lambda.Function
# get_book_integration: apigateway.LambdaIntegration


get_book_integration = apigateway.LambdaIntegration(get_book_handler,
    content_handling=apigateway.ContentHandling.CONVERT_TO_TEXT,  # convert to base64
    credentials_passthrough=True
)
java
Function getBookHandler;
LambdaIntegration getBookIntegration;


LambdaIntegration getBookIntegration = LambdaIntegration.Builder.create(getBookHandler)
        .contentHandling(ContentHandling.CONVERT_TO_TEXT) // convert to base64
        .credentialsPassthrough(true)
        .build();
csharp
Function getBookHandler;
LambdaIntegration getBookIntegration;


var getBookIntegration = new LambdaIntegration(getBookHandler, new LambdaIntegrationOptions {
    ContentHandling = ContentHandling.CONVERT_TO_TEXT,  // convert to base64
    CredentialsPassthrough = true
});
go
var getBookHandler Function
var getBookIntegration LambdaIntegration


getBookIntegration := apigateway.NewLambdaIntegration(getBookHandler, &LambdaIntegrationOptions{
	ContentHandling: apigateway.ContentHandling_CONVERT_TO_TEXT,
	 // convert to base64
	CredentialsPassthrough: jsii.Boolean(true),
})

Method options can optionally be specified when adding methods:

ts
declare const book: apigateway.Resource;
declare const getBookIntegration: apigateway.LambdaIntegration;

book.addMethod('GET', getBookIntegration, {
  authorizationType: apigateway.AuthorizationType.IAM,
  apiKeyRequired: true
});
python
# book: apigateway.Resource
# get_book_integration: apigateway.LambdaIntegration


book.add_method("GET", get_book_integration,
    authorization_type=apigateway.AuthorizationType.IAM,
    api_key_required=True
)
java
Resource book;
LambdaIntegration getBookIntegration;


book.addMethod("GET", getBookIntegration, MethodOptions.builder()
        .authorizationType(AuthorizationType.IAM)
        .apiKeyRequired(true)
        .build());
csharp
Resource book;
LambdaIntegration getBookIntegration;


book.AddMethod("GET", getBookIntegration, new MethodOptions {
    AuthorizationType = AuthorizationType.IAM,
    ApiKeyRequired = true
});
go
var book Resource
var getBookIntegration LambdaIntegration


book.AddMethod(jsii.String("GET"), getBookIntegration, &MethodOptions{
	AuthorizationType: apigateway.AuthorizationType_IAM,
	ApiKeyRequired: jsii.Boolean(true),
})

It is possible to also integrate with AWS services in a different region. The following code integrates with Amazon SQS in the eu-west-1 region.

ts
const getMessageIntegration = new apigateway.AwsIntegration({
  service: 'sqs',
  path: 'queueName',
  region: 'eu-west-1'
});
python
get_message_integration = apigateway.AwsIntegration(
    service="sqs",
    path="queueName",
    region="eu-west-1"
)
java
AwsIntegration getMessageIntegration = AwsIntegration.Builder.create()
        .service("sqs")
        .path("queueName")
        .region("eu-west-1")
        .build();
csharp
var getMessageIntegration = new AwsIntegration(new AwsIntegrationProps {
    Service = "sqs",
    Path = "queueName",
    Region = "eu-west-1"
});
go
getMessageIntegration := apigateway.NewAwsIntegration(&AwsIntegrationProps{
	Service: jsii.String("sqs"),
	Path: jsii.String("queueName"),
	Region: jsii.String("eu-west-1"),
})

Response Streaming ​

Integrations support response streaming, which allows responses to be streamed back to clients. This is useful for large payloads or when you want to start sending data before the entire response is ready.

To enable response streaming, set ResponseTransferMode.STREAM to the responseTransferMode option:

ts
declare const handler: lambda.Function;
new apigateway.LambdaIntegration(handler, {
  responseTransferMode: apigateway.ResponseTransferMode.STREAM,
});
python
# handler: lambda.Function

apigateway.LambdaIntegration(handler,
    response_transfer_mode=apigateway.ResponseTransferMode.STREAM
)
java
Function handler;

LambdaIntegration.Builder.create(handler)
        .responseTransferMode(ResponseTransferMode.STREAM)
        .build();
csharp
Function handler;

new LambdaIntegration(handler, new LambdaIntegrationOptions {
    ResponseTransferMode = ResponseTransferMode.STREAM
});
go
var handler Function

apigateway.NewLambdaIntegration(handler, &LambdaIntegrationOptions{
	ResponseTransferMode: apigateway.ResponseTransferMode_STREAM,
})

Lambda Integration Permissions ​

By default, creating a LambdaIntegration will add a permission for API Gateway to invoke your AWS Lambda function, scoped to the specific method which uses the integration.

If you reuse the same AWS Lambda function for many integrations, the AWS Lambda permission policy size can be exceeded by adding a separate policy statement for each method which invokes the AWS Lambda function. To avoid this, you can opt to scope permissions to any method on the API by setting scopePermissionToMethod to false, and this will ensure only a single policy statement is added to the AWS Lambda permission policy.

ts
declare const book: apigateway.Resource;
declare const backend: lambda.Function;

const getBookIntegration = new apigateway.LambdaIntegration(backend, {
  scopePermissionToMethod: false,
});
const createBookIntegration = new apigateway.LambdaIntegration(backend, {
  scopePermissionToMethod: false,
});

book.addMethod('GET', getBookIntegration);
book.addMethod('POST', createBookIntegration);
python
# book: apigateway.Resource
# backend: lambda.Function


get_book_integration = apigateway.LambdaIntegration(backend,
    scope_permission_to_method=False
)
create_book_integration = apigateway.LambdaIntegration(backend,
    scope_permission_to_method=False
)

book.add_method("GET", get_book_integration)
book.add_method("POST", create_book_integration)
java
Resource book;
Function backend;


LambdaIntegration getBookIntegration = LambdaIntegration.Builder.create(backend)
        .scopePermissionToMethod(false)
        .build();
LambdaIntegration createBookIntegration = LambdaIntegration.Builder.create(backend)
        .scopePermissionToMethod(false)
        .build();

book.addMethod("GET", getBookIntegration);
book.addMethod("POST", createBookIntegration);
csharp
Resource book;
Function backend;


var getBookIntegration = new LambdaIntegration(backend, new LambdaIntegrationOptions {
    ScopePermissionToMethod = false
});
var createBookIntegration = new LambdaIntegration(backend, new LambdaIntegrationOptions {
    ScopePermissionToMethod = false
});

book.AddMethod("GET", getBookIntegration);
book.AddMethod("POST", createBookIntegration);
go
var book Resource
var backend Function


getBookIntegration := apigateway.NewLambdaIntegration(backend, &LambdaIntegrationOptions{
	ScopePermissionToMethod: jsii.Boolean(false),
})
createBookIntegration := apigateway.NewLambdaIntegration(backend, &LambdaIntegrationOptions{
	ScopePermissionToMethod: jsii.Boolean(false),
})

book.AddMethod(jsii.String("GET"), getBookIntegration)
book.AddMethod(jsii.String("POST"), createBookIntegration)

In the above example, a single permission is added, shared by both getBookIntegration and createBookIntegration.

Note that setting scopePermissionToMethod to false will always allow test invocations, no matter the value specified for allowTestInvoke.

Usage Plan & API Keys ​

A usage plan specifies who can access one or more deployed API stages and methods, and the rate at which they can be accessed. The plan uses API keys to identify API clients and meters access to the associated API stages for each key. Usage plans also allow configuring throttling limits and quota limits that are enforced on individual client API keys.

The following example shows how to create and associate a usage plan and an API key:

ts
declare const integration: apigateway.LambdaIntegration;

const api = new apigateway.RestApi(this, 'hello-api');

const v1 = api.root.addResource('v1');
const echo = v1.addResource('echo');
const echoMethod = echo.addMethod('GET', integration, { apiKeyRequired: true });

const plan = api.addUsagePlan('UsagePlan', {
  name: 'Easy',
  throttle: {
    rateLimit: 10,
    burstLimit: 2
  }
});

const key = api.addApiKey('ApiKey');
plan.addApiKey(key);
python
# integration: apigateway.LambdaIntegration


api = apigateway.RestApi(self, "hello-api")

v1 = api.root.add_resource("v1")
echo = v1.add_resource("echo")
echo_method = echo.add_method("GET", integration, api_key_required=True)

plan = api.add_usage_plan("UsagePlan",
    name="Easy",
    throttle=apigateway.ThrottleSettings(
        rate_limit=10,
        burst_limit=2
    )
)

key = api.add_api_key("ApiKey")
plan.add_api_key(key)
java
LambdaIntegration integration;


RestApi api = new RestApi(this, "hello-api");

Resource v1 = api.root.addResource("v1");
Resource echo = v1.addResource("echo");
Method echoMethod = echo.addMethod("GET", integration, MethodOptions.builder().apiKeyRequired(true).build());

UsagePlan plan = api.addUsagePlan("UsagePlan", UsagePlanProps.builder()
        .name("Easy")
        .throttle(ThrottleSettings.builder()
                .rateLimit(10)
                .burstLimit(2)
                .build())
        .build());

IApiKey key = api.addApiKey("ApiKey");
plan.addApiKey(key);
csharp
LambdaIntegration integration;


var api = new RestApi(this, "hello-api");

var v1 = api.Root.AddResource("v1");
var echo = v1.AddResource("echo");
var echoMethod = echo.AddMethod("GET", integration, new MethodOptions { ApiKeyRequired = true });

var plan = api.AddUsagePlan("UsagePlan", new UsagePlanProps {
    Name = "Easy",
    Throttle = new ThrottleSettings {
        RateLimit = 10,
        BurstLimit = 2
    }
});

var key = api.AddApiKey("ApiKey");
plan.AddApiKey(key);
go
var integration LambdaIntegration


api := apigateway.NewRestApi(this, jsii.String("hello-api"))

v1 := api.Root.AddResource(jsii.String("v1"))
echo := v1.AddResource(jsii.String("echo"))
echoMethod := echo.AddMethod(jsii.String("GET"), integration, &MethodOptions{
	ApiKeyRequired: jsii.Boolean(true),
})

plan := api.AddUsagePlan(jsii.String("UsagePlan"), &UsagePlanProps{
	Name: jsii.String("Easy"),
	Throttle: &ThrottleSettings{
		RateLimit: jsii.Number(10),
		BurstLimit: jsii.Number(2),
	},
})

key := api.AddApiKey(jsii.String("ApiKey"))
plan.addApiKey(key)

To associate a plan to a given RestAPI stage:

ts
declare const plan: apigateway.UsagePlan;
declare const api: apigateway.RestApi;
declare const echoMethod: apigateway.Method;

plan.addApiStage({
  stage: api.deploymentStage,
  throttle: [
    {
      method: echoMethod,
      throttle: {
        rateLimit: 10,
        burstLimit: 2
      }
    }
  ]
});
python
# plan: apigateway.UsagePlan
# api: apigateway.RestApi
# echo_method: apigateway.Method


plan.add_api_stage(
    stage=api.deployment_stage,
    throttle=[apigateway.ThrottlingPerMethod(
        method=echo_method,
        throttle=apigateway.ThrottleSettings(
            rate_limit=10,
            burst_limit=2
        )
    )
    ]
)
java
UsagePlan plan;
RestApi api;
Method echoMethod;


plan.addApiStage(UsagePlanPerApiStage.builder()
        .stage(api.getDeploymentStage())
        .throttle(List.of(ThrottlingPerMethod.builder()
                .method(echoMethod)
                .throttle(ThrottleSettings.builder()
                        .rateLimit(10)
                        .burstLimit(2)
                        .build())
                .build()))
        .build());
csharp
UsagePlan plan;
RestApi api;
Method echoMethod;


plan.AddApiStage(new UsagePlanPerApiStage {
    Stage = api.DeploymentStage,
    Throttle = new [] { new ThrottlingPerMethod {
        Method = echoMethod,
        Throttle = new ThrottleSettings {
            RateLimit = 10,
            BurstLimit = 2
        }
    } }
});
go
var plan UsagePlan
var api RestApi
var echoMethod Method


plan.AddApiStage(&UsagePlanPerApiStage{
	Stage: api.DeploymentStage,
	Throttle: []ThrottlingPerMethod{
		&ThrottlingPerMethod{
			Method: echoMethod,
			Throttle: &ThrottleSettings{
				RateLimit: jsii.Number(10),
				BurstLimit: jsii.Number(2),
			},
		},
	},
})

Existing usage plans can be imported into a CDK app using its id.

ts
const importedUsagePlan = apigateway.UsagePlan.fromUsagePlanId(this, 'imported-usage-plan', '<usage-plan-key-id>');
python
imported_usage_plan = apigateway.UsagePlan.from_usage_plan_id(self, "imported-usage-plan", "<usage-plan-key-id>")
java
IUsagePlan importedUsagePlan = UsagePlan.fromUsagePlanId(this, "imported-usage-plan", "<usage-plan-key-id>");
csharp
var importedUsagePlan = UsagePlan.FromUsagePlanId(this, "imported-usage-plan", "<usage-plan-key-id>");
go
importedUsagePlan := apigateway.UsagePlan_FromUsagePlanId(this, jsii.String("imported-usage-plan"), jsii.String("<usage-plan-key-id>"))

The name and value of the API Key can be specified at creation; if not provided, a name and value will be automatically generated by API Gateway.

ts
declare const api: apigateway.RestApi;
const key = api.addApiKey('ApiKey', {
  apiKeyName: 'myApiKey1',
  value: 'MyApiKeyThatIsAtLeast20Characters',
});
python
# api: apigateway.RestApi

key = api.add_api_key("ApiKey",
    api_key_name="myApiKey1",
    value="MyApiKeyThatIsAtLeast20Characters"
)
java
RestApi api;

IApiKey key = api.addApiKey("ApiKey", ApiKeyOptions.builder()
        .apiKeyName("myApiKey1")
        .value("MyApiKeyThatIsAtLeast20Characters")
        .build());
csharp
RestApi api;

var key = api.AddApiKey("ApiKey", new ApiKeyOptions {
    ApiKeyName = "myApiKey1",
    Value = "MyApiKeyThatIsAtLeast20Characters"
});
go
var api RestApi

key := api.AddApiKey(jsii.String("ApiKey"), &ApiKeyOptions{
	ApiKeyName: jsii.String("myApiKey1"),
	Value: jsii.String("MyApiKeyThatIsAtLeast20Characters"),
})

Existing API keys can also be imported into a CDK app using its id.

ts
const importedKey = apigateway.ApiKey.fromApiKeyId(this, 'imported-key', '<api-key-id>');
python
imported_key = apigateway.ApiKey.from_api_key_id(self, "imported-key", "<api-key-id>")
java
IApiKey importedKey = ApiKey.fromApiKeyId(this, "imported-key", "<api-key-id>");
csharp
var importedKey = ApiKey.FromApiKeyId(this, "imported-key", "<api-key-id>");
go
importedKey := apigateway.ApiKey_FromApiKeyId(this, jsii.String("imported-key"), jsii.String("<api-key-id>"))

The "grant" methods can be used to give prepackaged sets of permissions to other resources. The following code provides read permission to an API key.

ts
declare const importedKey: apigateway.ApiKey;
declare const lambdaFn: lambda.Function;
importedKey.grantRead(lambdaFn);
python
# imported_key: apigateway.ApiKey
# lambda_fn: lambda.Function

imported_key.grant_read(lambda_fn)
java
ApiKey importedKey;
Function lambdaFn;

importedKey.grantRead(lambdaFn);
csharp
ApiKey importedKey;
Function lambdaFn;

importedKey.GrantRead(lambdaFn);
go
var importedKey ApiKey
var lambdaFn Function

importedKey.grantRead(lambdaFn)

Adding an API Key to an imported RestApi ​

API Keys are added to ApiGateway Stages, not to the API itself. When you import a RestApi it does not have any information on the Stages that may be associated with it. Since adding an API Key requires a stage, you should instead add the Api Key to the imported Stage.

ts
declare const restApi: apigateway.IRestApi;
const importedStage = apigateway.Stage.fromStageAttributes(this, 'imported-stage', {
  stageName: 'myStageName',
  restApi,
});

importedStage.addApiKey('MyApiKey');
python
# rest_api: apigateway.IRestApi

imported_stage = apigateway.Stage.from_stage_attributes(self, "imported-stage",
    stage_name="myStageName",
    rest_api=rest_api
)

imported_stage.add_api_key("MyApiKey")
java
IRestApi restApi;

IStage importedStage = Stage.fromStageAttributes(this, "imported-stage", StageAttributes.builder()
        .stageName("myStageName")
        .restApi(restApi)
        .build());

importedStage.addApiKey("MyApiKey");
csharp
IRestApi restApi;

var importedStage = Stage.FromStageAttributes(this, "imported-stage", new StageAttributes {
    StageName = "myStageName",
    RestApi = restApi
});

importedStage.AddApiKey("MyApiKey");
go
var restApi IRestApi

importedStage := apigateway.Stage_FromStageAttributes(this, jsii.String("imported-stage"), &StageAttributes{
	StageName: jsii.String("myStageName"),
	RestApi: RestApi,
})

importedStage.AddApiKey(jsii.String("MyApiKey"))

⚠️ Multiple API Keys ​

It is possible to specify multiple API keys for a given Usage Plan, by calling usagePlan.addApiKey().

When using multiple API keys, a past bug of the CDK prevents API key associations to a Usage Plan to be deleted. If the CDK app had the feature flag - @aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId - enabled when the API keys were created, then the app will not be affected by this bug.

If this is not the case, you will need to ensure that the CloudFormation logical ids of the API keys that are not being deleted remain unchanged. Make note of the logical ids of these API keys before removing any, and set it as part of the addApiKey() method:

ts
declare const usageplan: apigateway.UsagePlan;
declare const apiKey: apigateway.ApiKey;

usageplan.addApiKey(apiKey, {
  overrideLogicalId: '...',
});
python
# usageplan: apigateway.UsagePlan
# api_key: apigateway.ApiKey


usageplan.add_api_key(api_key,
    override_logical_id="..."
)
java
UsagePlan usageplan;
ApiKey apiKey;


usageplan.addApiKey(apiKey, AddApiKeyOptions.builder()
        .overrideLogicalId("...")
        .build());
csharp
UsagePlan usageplan;
ApiKey apiKey;


usageplan.AddApiKey(apiKey, new AddApiKeyOptions {
    OverrideLogicalId = "..."
});
go
var usageplan UsagePlan
var apiKey ApiKey


usageplan.addApiKey(apiKey, &AddApiKeyOptions{
	OverrideLogicalId: jsii.String("..."),
})

Rate Limited API Key ​

In scenarios where you need to create a single api key and configure rate limiting for it, you can use RateLimitedApiKey. This construct lets you specify rate limiting properties which should be applied only to the api key being created. The API key created has the specified rate limits, such as quota and throttles, applied.

The following example shows how to use a rate limited api key :

ts
declare const api: apigateway.RestApi;

const key = new apigateway.RateLimitedApiKey(this, 'rate-limited-api-key', {
  customerId: 'hello-customer',
  apiStages: [{ stage: api.deploymentStage }],
  quota: {
    limit: 10000,
    period: apigateway.Period.MONTH
  }
});
python
# api: apigateway.RestApi


key = apigateway.RateLimitedApiKey(self, "rate-limited-api-key",
    customer_id="hello-customer",
    api_stages=[apigateway.UsagePlanPerApiStage(stage=api.deployment_stage)],
    quota=apigateway.QuotaSettings(
        limit=10000,
        period=apigateway.Period.MONTH
    )
)
java
RestApi api;


RateLimitedApiKey key = RateLimitedApiKey.Builder.create(this, "rate-limited-api-key")
        .customerId("hello-customer")
        .apiStages(List.of(UsagePlanPerApiStage.builder().stage(api.getDeploymentStage()).build()))
        .quota(QuotaSettings.builder()
                .limit(10000)
                .period(Period.MONTH)
                .build())
        .build();
csharp
RestApi api;


var key = new RateLimitedApiKey(this, "rate-limited-api-key", new RateLimitedApiKeyProps {
    CustomerId = "hello-customer",
    ApiStages = new [] { new UsagePlanPerApiStage { Stage = api.DeploymentStage } },
    Quota = new QuotaSettings {
        Limit = 10000,
        Period = Period.MONTH
    }
});
go
var api RestApi


key := apigateway.NewRateLimitedApiKey(this, jsii.String("rate-limited-api-key"), &RateLimitedApiKeyProps{
	CustomerId: jsii.String("hello-customer"),
	ApiStages: []UsagePlanPerApiStage{
		&UsagePlanPerApiStage{
			Stage: api.DeploymentStage,
		},
	},
	Quota: &QuotaSettings{
		Limit: jsii.Number(10000),
		Period: apigateway.Period_MONTH,
	},
})

Working with models ​

When you work with Lambda integrations that are not Proxy integrations, you have to define your models and mappings for the request, response, and integration.

ts
const hello = new lambda.Function(this, 'hello', {
  runtime: lambda.Runtime.NODEJS_LATEST,
  handler: 'hello.handler',
  code: lambda.Code.fromAsset('lambda')
});

const api = new apigateway.RestApi(this, 'hello-api', { });
const resource = api.root.addResource('v1');
python
hello = lambda_.Function(self, "hello",
    runtime=lambda_.Runtime.NODEJS_LATEST,
    handler="hello.handler",
    code=lambda_.Code.from_asset("lambda")
)

api = apigateway.RestApi(self, "hello-api")
resource = api.root.add_resource("v1")
java
Function hello = Function.Builder.create(this, "hello")
        .runtime(Runtime.NODEJS_LATEST)
        .handler("hello.handler")
        .code(Code.fromAsset("lambda"))
        .build();

RestApi api = RestApi.Builder.create(this, "hello-api").build();
Resource resource = api.root.addResource("v1");
csharp
var hello = new Function(this, "hello", new FunctionProps {
    Runtime = Runtime.NODEJS_LATEST,
    Handler = "hello.handler",
    Code = Code.FromAsset("lambda")
});

var api = new RestApi(this, "hello-api", new RestApiProps { });
var resource = api.Root.AddResource("v1");
go
hello := lambda.NewFunction(this, jsii.String("hello"), &FunctionProps{
	Runtime: lambda.Runtime_NODEJS_LATEST(),
	Handler: jsii.String("hello.handler"),
	Code: lambda.Code_FromAsset(jsii.String("lambda")),
})

api := apigateway.NewRestApi(this, jsii.String("hello-api"), &RestApiProps{
})
resource := api.Root.AddResource(jsii.String("v1"))

You can define more parameters on the integration to tune the behavior of API Gateway

ts
declare const hello: lambda.Function;

const integration = new apigateway.LambdaIntegration(hello, {
  proxy: false,
  requestParameters: {
    // You can define mapping parameters from your method to your integration
    // - Destination parameters (the key) are the integration parameters (used in mappings)
    // - Source parameters (the value) are the source request parameters or expressions
    // @see: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
    'integration.request.querystring.who': 'method.request.querystring.who'
  },
  allowTestInvoke: true,
  requestTemplates: {
    // You can define a mapping that will build a payload for your integration, based
    //  on the integration parameters that you have specified
    // Check: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
    'application/json': JSON.stringify({ action: 'sayHello', pollId: "$util.escapeJavaScript($input.params('who'))" })
  },
  // This parameter defines the behavior of the engine is no suitable response template is found
  passthroughBehavior: apigateway.PassthroughBehavior.NEVER,
  integrationResponses: [
    {
      // Successful response from the Lambda function, no filter defined
      //  - the selectionPattern filter only tests the error message
      // We will set the response status code to 200
      statusCode: "200",
      responseTemplates: {
        // This template takes the "message" result from the Lambda function, and embeds it in a JSON response
        // Check https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
        'application/json': JSON.stringify({ state: 'ok', greeting: '$util.escapeJavaScript($input.body)' })
      },
      responseParameters: {
        // We can map response parameters
        // - Destination parameters (the key) are the response parameters (used in mappings)
        // - Source parameters (the value) are the integration response parameters or expressions
        'method.response.header.Content-Type': "'application/json'",
        'method.response.header.Access-Control-Allow-Origin': "'*'",
        'method.response.header.Access-Control-Allow-Credentials': "'true'"
      }
    },
    {
      // For errors, we check if the error message is not empty, get the error data
      selectionPattern: '(\n|.)+',
      // We will set the response status code to 200
      statusCode: "400",
      responseTemplates: {
          'application/json': JSON.stringify({ state: 'error', message: "$util.escapeJavaScript($input.path('$.errorMessage'))" })
      },
      responseParameters: {
          'method.response.header.Content-Type': "'application/json'",
          'method.response.header.Access-Control-Allow-Origin': "'*'",
          'method.response.header.Access-Control-Allow-Credentials': "'true'"
      }
    }
  ]
});
python
# hello: lambda.Function


integration = apigateway.LambdaIntegration(hello,
    proxy=False,
    request_parameters={
        # You can define mapping parameters from your method to your integration
        # - Destination parameters (the key) are the integration parameters (used in mappings)
        # - Source parameters (the value) are the source request parameters or expressions
        # @see: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
        "integration.request.querystring.who": "method.request.querystring.who"
    },
    allow_test_invoke=True,
    request_templates={
        # You can define a mapping that will build a payload for your integration, based
        #  on the integration parameters that you have specified
        # Check: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
        "application/json": JSON.stringify({"action": "sayHello", "poll_id": "$util.escapeJavaScript($input.params('who'))"})
    },
    # This parameter defines the behavior of the engine is no suitable response template is found
    passthrough_behavior=apigateway.PassthroughBehavior.NEVER,
    integration_responses=[apigateway.IntegrationResponse(
        # Successful response from the Lambda function, no filter defined
        #  - the selectionPattern filter only tests the error message
        # We will set the response status code to 200
        status_code="200",
        response_templates={
            # This template takes the "message" result from the Lambda function, and embeds it in a JSON response
            # Check https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
            "application/json": JSON.stringify({"state": "ok", "greeting": "$util.escapeJavaScript($input.body)"})
        },
        response_parameters={
            # We can map response parameters
            # - Destination parameters (the key) are the response parameters (used in mappings)
            # - Source parameters (the value) are the integration response parameters or expressions
            "method.response.header.Content-Type": "'application/json'",
            "method.response.header.Access-Control-Allow-Origin": "'*'",
            "method.response.header.Access-Control-Allow-Credentials": "'true'"
        }
    ), apigateway.IntegrationResponse(
        # For errors, we check if the error message is not empty, get the error data
        selection_pattern="(\n|.)+",
        # We will set the response status code to 200
        status_code="400",
        response_templates={
            "application/json": JSON.stringify({"state": "error", "message": "$util.escapeJavaScript($input.path('$.errorMessage'))"})
        },
        response_parameters={
            "method.response.header.Content-Type": "'application/json'",
            "method.response.header.Access-Control-Allow-Origin": "'*'",
            "method.response.header.Access-Control-Allow-Credentials": "'true'"
        }
    )
    ]
)
java
Function hello;


LambdaIntegration integration = LambdaIntegration.Builder.create(hello)
        .proxy(false)
        .requestParameters(Map.of(
                // You can define mapping parameters from your method to your integration
                // - Destination parameters (the key) are the integration parameters (used in mappings)
                // - Source parameters (the value) are the source request parameters or expressions
                // @see: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
                "integration.request.querystring.who", "method.request.querystring.who"))
        .allowTestInvoke(true)
        .requestTemplates(Map.of(
                // You can define a mapping that will build a payload for your integration, based
                //  on the integration parameters that you have specified
                // Check: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
                "application/json", JSON.stringify(Map.of("action", "sayHello", "pollId", "$util.escapeJavaScript($input.params('who'))"))))
        // This parameter defines the behavior of the engine is no suitable response template is found
        .passthroughBehavior(PassthroughBehavior.NEVER)
        .integrationResponses(List.of(IntegrationResponse.builder()
                // Successful response from the Lambda function, no filter defined
                //  - the selectionPattern filter only tests the error message
                // We will set the response status code to 200
                .statusCode("200")
                .responseTemplates(Map.of(
                        // This template takes the "message" result from the Lambda function, and embeds it in a JSON response
                        // Check https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
                        "application/json", JSON.stringify(Map.of("state", "ok", "greeting", "$util.escapeJavaScript($input.body)"))))
                .responseParameters(Map.of(
                        // We can map response parameters
                        // - Destination parameters (the key) are the response parameters (used in mappings)
                        // - Source parameters (the value) are the integration response parameters or expressions
                        "method.response.header.Content-Type", "'application/json'",
                        "method.response.header.Access-Control-Allow-Origin", "'*'",
                        "method.response.header.Access-Control-Allow-Credentials", "'true'"))
                .build(), IntegrationResponse.builder()
                // For errors, we check if the error message is not empty, get the error data
                .selectionPattern("(\n|.)+")
                // We will set the response status code to 200
                .statusCode("400")
                .responseTemplates(Map.of(
                        "application/json", JSON.stringify(Map.of("state", "error", "message", "$util.escapeJavaScript($input.path('$.errorMessage'))"))))
                .responseParameters(Map.of(
                        "method.response.header.Content-Type", "'application/json'",
                        "method.response.header.Access-Control-Allow-Origin", "'*'",
                        "method.response.header.Access-Control-Allow-Credentials", "'true'"))
                .build()))
        .build();
csharp
Function hello;


var integration = new LambdaIntegration(hello, new LambdaIntegrationOptions {
    Proxy = false,
    RequestParameters = new Dictionary<string, string> {
        // You can define mapping parameters from your method to your integration
        // - Destination parameters (the key) are the integration parameters (used in mappings)
        // - Source parameters (the value) are the source request parameters or expressions
        // @see: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
        { "integration.request.querystring.who", "method.request.querystring.who" }
    },
    AllowTestInvoke = true,
    RequestTemplates = new Dictionary<string, string> {
        // You can define a mapping that will build a payload for your integration, based
        //  on the integration parameters that you have specified
        // Check: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
        { "application/json", JSON.Stringify(new Dictionary<string, string> { { "action", "sayHello" }, { "pollId", "$util.escapeJavaScript($input.params('who'))" } }) }
    },
    // This parameter defines the behavior of the engine is no suitable response template is found
    PassthroughBehavior = PassthroughBehavior.NEVER,
    IntegrationResponses = new [] { new IntegrationResponse {
        // Successful response from the Lambda function, no filter defined
        //  - the selectionPattern filter only tests the error message
        // We will set the response status code to 200
        StatusCode = "200",
        ResponseTemplates = new Dictionary<string, string> {
            // This template takes the "message" result from the Lambda function, and embeds it in a JSON response
            // Check https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
            { "application/json", JSON.Stringify(new Dictionary<string, string> { { "state", "ok" }, { "greeting", "$util.escapeJavaScript($input.body)" } }) }
        },
        ResponseParameters = new Dictionary<string, string> {
            // We can map response parameters
            // - Destination parameters (the key) are the response parameters (used in mappings)
            // - Source parameters (the value) are the integration response parameters or expressions
            { "method.response.header.Content-Type", "'application/json'" },
            { "method.response.header.Access-Control-Allow-Origin", "'*'" },
            { "method.response.header.Access-Control-Allow-Credentials", "'true'" }
        }
    }, new IntegrationResponse {
        // For errors, we check if the error message is not empty, get the error data
        SelectionPattern = @"(
        |.)+",
        // We will set the response status code to 200
        StatusCode = "400",
        ResponseTemplates = new Dictionary<string, string> {
            { "application/json", JSON.Stringify(new Dictionary<string, string> { { "state", "error" }, { "message", "$util.escapeJavaScript($input.path('$.errorMessage'))" } }) }
        },
        ResponseParameters = new Dictionary<string, string> {
            { "method.response.header.Content-Type", "'application/json'" },
            { "method.response.header.Access-Control-Allow-Origin", "'*'" },
            { "method.response.header.Access-Control-Allow-Credentials", "'true'" }
        }
    } }
});
go
var hello Function


integration := apigateway.NewLambdaIntegration(hello, &LambdaIntegrationOptions{
	Proxy: jsii.Boolean(false),
	RequestParameters: map[string]*string{
		// You can define mapping parameters from your method to your integration
		// - Destination parameters (the key) are the integration parameters (used in mappings)
		// - Source parameters (the value) are the source request parameters or expressions
		// @see: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
		"integration.request.querystring.who": jsii.String("method.request.querystring.who"),
	},
	AllowTestInvoke: jsii.Boolean(true),
	RequestTemplates: map[string]*string{
		// You can define a mapping that will build a payload for your integration, based
		//  on the integration parameters that you have specified
		// Check: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
		"application/json": JSON.stringify(map[string]*string{
			"action": jsii.String("sayHello"),
			"pollId": jsii.String("$util.escapeJavaScript($input.params('who'))"),
		}),
	},
	// This parameter defines the behavior of the engine is no suitable response template is found
	PassthroughBehavior: apigateway.PassthroughBehavior_NEVER,
	IntegrationResponses: []IntegrationResponse{
		&IntegrationResponse{
			// Successful response from the Lambda function, no filter defined
			//  - the selectionPattern filter only tests the error message
			// We will set the response status code to 200
			StatusCode: jsii.String("200"),
			ResponseTemplates: map[string]*string{
				// This template takes the "message" result from the Lambda function, and embeds it in a JSON response
				// Check https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
				"application/json": JSON.stringify(map[string]*string{
					"state": jsii.String("ok"),
					"greeting": jsii.String("$util.escapeJavaScript($input.body)"),
				}),
			},
			ResponseParameters: map[string]*string{
				// We can map response parameters
				// - Destination parameters (the key) are the response parameters (used in mappings)
				// - Source parameters (the value) are the integration response parameters or expressions
				"method.response.header.Content-Type": jsii.String("'application/json'"),
				"method.response.header.Access-Control-Allow-Origin": jsii.String("'*'"),
				"method.response.header.Access-Control-Allow-Credentials": jsii.String("'true'"),
			},
		},
		&IntegrationResponse{
			// For errors, we check if the error message is not empty, get the error data
			SelectionPattern: jsii.String("(\n|.)+"),
			// We will set the response status code to 200
			StatusCode: jsii.String("400"),
			ResponseTemplates: map[string]*string{
				"application/json": JSON.stringify(map[string]*string{
					"state": jsii.String("error"),
					"message": jsii.String("$util.escapeJavaScript($input.path('$.errorMessage'))"),
				}),
			},
			ResponseParameters: map[string]*string{
				"method.response.header.Content-Type": jsii.String("'application/json'"),
				"method.response.header.Access-Control-Allow-Origin": jsii.String("'*'"),
				"method.response.header.Access-Control-Allow-Credentials": jsii.String("'true'"),
			},
		},
	},
})

You can define models for your responses (and requests)

ts
declare const api: apigateway.RestApi;

// We define the JSON Schema for the transformed valid response
const responseModel = api.addModel('ResponseModel', {
  contentType: 'application/json',
  modelName: 'ResponseModel',
  schema: {
    schema: apigateway.JsonSchemaVersion.DRAFT4,
    title: 'pollResponse',
    type: apigateway.JsonSchemaType.OBJECT,
    properties: {
      state: { type: apigateway.JsonSchemaType.STRING },
      greeting: { type: apigateway.JsonSchemaType.STRING }
    }
  }
});

// We define the JSON Schema for the transformed error response
const errorResponseModel = api.addModel('ErrorResponseModel', {
  contentType: 'application/json',
  modelName: 'ErrorResponseModel',
  schema: {
    schema: apigateway.JsonSchemaVersion.DRAFT4,
    title: 'errorResponse',
    type: apigateway.JsonSchemaType.OBJECT,
    properties: {
      state: { type: apigateway.JsonSchemaType.STRING },
      message: { type: apigateway.JsonSchemaType.STRING }
    }
  }
});
python
# api: apigateway.RestApi


# We define the JSON Schema for the transformed valid response
response_model = api.add_model("ResponseModel",
    content_type="application/json",
    model_name="ResponseModel",
    schema=apigateway.JsonSchema(
        schema=apigateway.JsonSchemaVersion.DRAFT4,
        title="pollResponse",
        type=apigateway.JsonSchemaType.OBJECT,
        properties={
            "state": apigateway.JsonSchema(type=apigateway.JsonSchemaType.STRING),
            "greeting": apigateway.JsonSchema(type=apigateway.JsonSchemaType.STRING)
        }
    )
)

# We define the JSON Schema for the transformed error response
error_response_model = api.add_model("ErrorResponseModel",
    content_type="application/json",
    model_name="ErrorResponseModel",
    schema=apigateway.JsonSchema(
        schema=apigateway.JsonSchemaVersion.DRAFT4,
        title="errorResponse",
        type=apigateway.JsonSchemaType.OBJECT,
        properties={
            "state": apigateway.JsonSchema(type=apigateway.JsonSchemaType.STRING),
            "message": apigateway.JsonSchema(type=apigateway.JsonSchemaType.STRING)
        }
    )
)
java
RestApi api;


// We define the JSON Schema for the transformed valid response
Model responseModel = api.addModel("ResponseModel", ModelOptions.builder()
        .contentType("application/json")
        .modelName("ResponseModel")
        .schema(JsonSchema.builder()
                .schema(JsonSchemaVersion.DRAFT4)
                .title("pollResponse")
                .type(JsonSchemaType.OBJECT)
                .properties(Map.of(
                        "state", JsonSchema.builder().type(JsonSchemaType.STRING).build(),
                        "greeting", JsonSchema.builder().type(JsonSchemaType.STRING).build()))
                .build())
        .build());

// We define the JSON Schema for the transformed error response
Model errorResponseModel = api.addModel("ErrorResponseModel", ModelOptions.builder()
        .contentType("application/json")
        .modelName("ErrorResponseModel")
        .schema(JsonSchema.builder()
                .schema(JsonSchemaVersion.DRAFT4)
                .title("errorResponse")
                .type(JsonSchemaType.OBJECT)
                .properties(Map.of(
                        "state", JsonSchema.builder().type(JsonSchemaType.STRING).build(),
                        "message", JsonSchema.builder().type(JsonSchemaType.STRING).build()))
                .build())
        .build());
csharp
RestApi api;


// We define the JSON Schema for the transformed valid response
var responseModel = api.AddModel("ResponseModel", new ModelOptions {
    ContentType = "application/json",
    ModelName = "ResponseModel",
    Schema = new JsonSchema {
        Schema = JsonSchemaVersion.DRAFT4,
        Title = "pollResponse",
        Type = JsonSchemaType.OBJECT,
        Properties = new Dictionary<string, JsonSchema> {
            { "state", new JsonSchema { Type = JsonSchemaType.STRING } },
            { "greeting", new JsonSchema { Type = JsonSchemaType.STRING } }
        }
    }
});

// We define the JSON Schema for the transformed error response
var errorResponseModel = api.AddModel("ErrorResponseModel", new ModelOptions {
    ContentType = "application/json",
    ModelName = "ErrorResponseModel",
    Schema = new JsonSchema {
        Schema = JsonSchemaVersion.DRAFT4,
        Title = "errorResponse",
        Type = JsonSchemaType.OBJECT,
        Properties = new Dictionary<string, JsonSchema> {
            { "state", new JsonSchema { Type = JsonSchemaType.STRING } },
            { "message", new JsonSchema { Type = JsonSchemaType.STRING } }
        }
    }
});
go
var api RestApi


// We define the JSON Schema for the transformed valid response
responseModel := api.AddModel(jsii.String("ResponseModel"), &ModelOptions{
	ContentType: jsii.String("application/json"),
	ModelName: jsii.String("ResponseModel"),
	Schema: &JsonSchema{
		Schema: apigateway.JsonSchemaVersion_DRAFT4,
		Title: jsii.String("pollResponse"),
		Type: apigateway.JsonSchemaType_OBJECT,
		Properties: map[string]JsonSchema{
			"state": &JsonSchema{
				"type": apigateway.JsonSchemaType_STRING,
			},
			"greeting": &JsonSchema{
				"type": apigateway.JsonSchemaType_STRING,
			},
		},
	},
})

// We define the JSON Schema for the transformed error response
errorResponseModel := api.AddModel(jsii.String("ErrorResponseModel"), &ModelOptions{
	ContentType: jsii.String("application/json"),
	ModelName: jsii.String("ErrorResponseModel"),
	Schema: &JsonSchema{
		Schema: apigateway.JsonSchemaVersion_DRAFT4,
		Title: jsii.String("errorResponse"),
		Type: apigateway.JsonSchemaType_OBJECT,
		Properties: map[string]JsonSchema{
			"state": &JsonSchema{
				"type": apigateway.JsonSchemaType_STRING,
			},
			"message": &JsonSchema{
				"type": apigateway.JsonSchemaType_STRING,
			},
		},
	},
})

And reference all on your method definition.

ts
declare const integration: apigateway.LambdaIntegration;
declare const resource: apigateway.Resource;
declare const responseModel: apigateway.Model;
declare const errorResponseModel: apigateway.Model;

resource.addMethod('GET', integration, {
  // We can mark the parameters as required
  requestParameters: {
    'method.request.querystring.who': true
  },
  // we can set request validator options like below
  requestValidatorOptions: {
    requestValidatorName: 'test-validator',
    validateRequestBody: true,
    validateRequestParameters: false
  },
  methodResponses: [
    {
      // Successful response from the integration
      statusCode: '200',
      // Define what parameters are allowed or not
      responseParameters: {
        'method.response.header.Content-Type': true,
        'method.response.header.Access-Control-Allow-Origin': true,
        'method.response.header.Access-Control-Allow-Credentials': true
      },
      // Validate the schema on the response
      responseModels: {
        'application/json': responseModel
      }
    },
    {
      // Same thing for the error responses
      statusCode: '400',
      responseParameters: {
        'method.response.header.Content-Type': true,
        'method.response.header.Access-Control-Allow-Origin': true,
        'method.response.header.Access-Control-Allow-Credentials': true
      },
      responseModels: {
        'application/json': errorResponseModel
      }
    }
  ]
});
python
# integration: apigateway.LambdaIntegration
# resource: apigateway.Resource
# response_model: apigateway.Model
# error_response_model: apigateway.Model


resource.add_method("GET", integration,
    # We can mark the parameters as required
    request_parameters={
        "method.request.querystring.who": True
    },
    # we can set request validator options like below
    request_validator_options=apigateway.RequestValidatorOptions(
        request_validator_name="test-validator",
        validate_request_body=True,
        validate_request_parameters=False
    ),
    method_responses=[apigateway.MethodResponse(
        # Successful response from the integration
        status_code="200",
        # Define what parameters are allowed or not
        response_parameters={
            "method.response.header.Content-Type": True,
            "method.response.header.Access-Control-Allow-Origin": True,
            "method.response.header.Access-Control-Allow-Credentials": True
        },
        # Validate the schema on the response
        response_models={
            "application/json": response_model
        }
    ), apigateway.MethodResponse(
        # Same thing for the error responses
        status_code="400",
        response_parameters={
            "method.response.header.Content-Type": True,
            "method.response.header.Access-Control-Allow-Origin": True,
            "method.response.header.Access-Control-Allow-Credentials": True
        },
        response_models={
            "application/json": error_response_model
        }
    )
    ]
)
java
LambdaIntegration integration;
Resource resource;
Model responseModel;
Model errorResponseModel;


resource.addMethod("GET", integration, MethodOptions.builder()
        // We can mark the parameters as required
        .requestParameters(Map.of(
                "method.request.querystring.who", true))
        // we can set request validator options like below
        .requestValidatorOptions(RequestValidatorOptions.builder()
                .requestValidatorName("test-validator")
                .validateRequestBody(true)
                .validateRequestParameters(false)
                .build())
        .methodResponses(List.of(MethodResponse.builder()
                // Successful response from the integration
                .statusCode("200")
                // Define what parameters are allowed or not
                .responseParameters(Map.of(
                        "method.response.header.Content-Type", true,
                        "method.response.header.Access-Control-Allow-Origin", true,
                        "method.response.header.Access-Control-Allow-Credentials", true))
                // Validate the schema on the response
                .responseModels(Map.of(
                        "application/json", responseModel))
                .build(), MethodResponse.builder()
                // Same thing for the error responses
                .statusCode("400")
                .responseParameters(Map.of(
                        "method.response.header.Content-Type", true,
                        "method.response.header.Access-Control-Allow-Origin", true,
                        "method.response.header.Access-Control-Allow-Credentials", true))
                .responseModels(Map.of(
                        "application/json", errorResponseModel))
                .build()))
        .build());
csharp
LambdaIntegration integration;
Resource resource;
Model responseModel;
Model errorResponseModel;


resource.AddMethod("GET", integration, new MethodOptions {
    // We can mark the parameters as required
    RequestParameters = new Dictionary<string, boolean> {
        { "method.request.querystring.who", true }
    },
    // we can set request validator options like below
    RequestValidatorOptions = new RequestValidatorOptions {
        RequestValidatorName = "test-validator",
        ValidateRequestBody = true,
        ValidateRequestParameters = false
    },
    MethodResponses = new [] { new MethodResponse {
        // Successful response from the integration
        StatusCode = "200",
        // Define what parameters are allowed or not
        ResponseParameters = new Dictionary<string, boolean> {
            { "method.response.header.Content-Type", true },
            { "method.response.header.Access-Control-Allow-Origin", true },
            { "method.response.header.Access-Control-Allow-Credentials", true }
        },
        // Validate the schema on the response
        ResponseModels = new Dictionary<string, IModel> {
            { "application/json", responseModel }
        }
    }, new MethodResponse {
        // Same thing for the error responses
        StatusCode = "400",
        ResponseParameters = new Dictionary<string, boolean> {
            { "method.response.header.Content-Type", true },
            { "method.response.header.Access-Control-Allow-Origin", true },
            { "method.response.header.Access-Control-Allow-Credentials", true }
        },
        ResponseModels = new Dictionary<string, IModel> {
            { "application/json", errorResponseModel }
        }
    } }
});
go
var integration LambdaIntegration
var resource Resource
var responseModel Model
var errorResponseModel Model


resource.AddMethod(jsii.String("GET"), integration, &MethodOptions{
	// We can mark the parameters as required
	RequestParameters: map[string]*bool{
		"method.request.querystring.who": jsii.Boolean(true),
	},
	// we can set request validator options like below
	RequestValidatorOptions: &RequestValidatorOptions{
		RequestValidatorName: jsii.String("test-validator"),
		ValidateRequestBody: jsii.Boolean(true),
		ValidateRequestParameters: jsii.Boolean(false),
	},
	MethodResponses: []MethodResponse{
		&MethodResponse{
			// Successful response from the integration
			StatusCode: jsii.String("200"),
			// Define what parameters are allowed or not
			ResponseParameters: map[string]*bool{
				"method.response.header.Content-Type": jsii.Boolean(true),
				"method.response.header.Access-Control-Allow-Origin": jsii.Boolean(true),
				"method.response.header.Access-Control-Allow-Credentials": jsii.Boolean(true),
			},
			// Validate the schema on the response
			ResponseModels: map[string]IModel{
				"application/json": responseModel,
			},
		},
		&MethodResponse{
			// Same thing for the error responses
			StatusCode: jsii.String("400"),
			ResponseParameters: map[string]*bool{
				"method.response.header.Content-Type": jsii.Boolean(true),
				"method.response.header.Access-Control-Allow-Origin": jsii.Boolean(true),
				"method.response.header.Access-Control-Allow-Credentials": jsii.Boolean(true),
			},
			ResponseModels: map[string]IModel{
				"application/json": errorResponseModel,
			},
		},
	},
})

Specifying requestValidatorOptions automatically creates the RequestValidator construct with the given options. However, if you have your RequestValidator already initialized or imported, use the requestValidator option instead.

If you want to use requestValidatorOptions in multiple addMethod() calls then you need to set the @aws-cdk/aws-apigateway:requestValidatorUniqueId feature flag. When this feature flag is set, each RequestValidator will have a unique generated id.

Note if you enable this feature flag when you have already used addMethod() with requestValidatorOptions the Logical Id of the resource will change causing the resource to be replaced.

ts
declare const integration: apigateway.LambdaIntegration;
declare const resource: apigateway.Resource;
declare const responseModel: apigateway.Model;
declare const errorResponseModel: apigateway.Model;

resource.node.setContext('@aws-cdk/aws-apigateway:requestValidatorUniqueId', true);

resource.addMethod('GET', integration, {
  // we can set request validator options like below
  requestValidatorOptions: {
    requestValidatorName: 'test-validator',
    validateRequestBody: true,
    validateRequestParameters: false
  },
});

resource.addMethod('POST', integration, {
  // we can set request validator options like below
  requestValidatorOptions: {
    requestValidatorName: 'test-validator2',
    validateRequestBody: true,
    validateRequestParameters: false
  },
});
python
# integration: apigateway.LambdaIntegration
# resource: apigateway.Resource
# response_model: apigateway.Model
# error_response_model: apigateway.Model


resource.node.set_context("@aws-cdk/aws-apigateway:requestValidatorUniqueId", True)

resource.add_method("GET", integration,
    # we can set request validator options like below
    request_validator_options=apigateway.RequestValidatorOptions(
        request_validator_name="test-validator",
        validate_request_body=True,
        validate_request_parameters=False
    )
)

resource.add_method("POST", integration,
    # we can set request validator options like below
    request_validator_options=apigateway.RequestValidatorOptions(
        request_validator_name="test-validator2",
        validate_request_body=True,
        validate_request_parameters=False
    )
)
java
LambdaIntegration integration;
Resource resource;
Model responseModel;
Model errorResponseModel;


resource.node.setContext("@aws-cdk/aws-apigateway:requestValidatorUniqueId", true);

resource.addMethod("GET", integration, MethodOptions.builder()
        // we can set request validator options like below
        .requestValidatorOptions(RequestValidatorOptions.builder()
                .requestValidatorName("test-validator")
                .validateRequestBody(true)
                .validateRequestParameters(false)
                .build())
        .build());

resource.addMethod("POST", integration, MethodOptions.builder()
        // we can set request validator options like below
        .requestValidatorOptions(RequestValidatorOptions.builder()
                .requestValidatorName("test-validator2")
                .validateRequestBody(true)
                .validateRequestParameters(false)
                .build())
        .build());
csharp
LambdaIntegration integration;
Resource resource;
Model responseModel;
Model errorResponseModel;


resource.Node.SetContext("@aws-cdk/aws-apigateway:requestValidatorUniqueId", true);

resource.AddMethod("GET", integration, new MethodOptions {
    // we can set request validator options like below
    RequestValidatorOptions = new RequestValidatorOptions {
        RequestValidatorName = "test-validator",
        ValidateRequestBody = true,
        ValidateRequestParameters = false
    }
});

resource.AddMethod("POST", integration, new MethodOptions {
    // we can set request validator options like below
    RequestValidatorOptions = new RequestValidatorOptions {
        RequestValidatorName = "test-validator2",
        ValidateRequestBody = true,
        ValidateRequestParameters = false
    }
});
go
var integration LambdaIntegration
var resource Resource
var responseModel Model
var errorResponseModel Model


resource.Node.SetContext(jsii.String("@aws-cdk/aws-apigateway:requestValidatorUniqueId"), jsii.Boolean(true))

resource.AddMethod(jsii.String("GET"), integration, &MethodOptions{
	// we can set request validator options like below
	RequestValidatorOptions: &RequestValidatorOptions{
		RequestValidatorName: jsii.String("test-validator"),
		ValidateRequestBody: jsii.Boolean(true),
		ValidateRequestParameters: jsii.Boolean(false),
	},
})

resource.AddMethod(jsii.String("POST"), integration, &MethodOptions{
	// we can set request validator options like below
	RequestValidatorOptions: &RequestValidatorOptions{
		RequestValidatorName: jsii.String("test-validator2"),
		ValidateRequestBody: jsii.Boolean(true),
		ValidateRequestParameters: jsii.Boolean(false),
	},
})

Default Integration and Method Options ​

The defaultIntegration and defaultMethodOptions properties can be used to configure a default integration at any resource level. These options will be used when defining method under this resource (recursively) with undefined integration or options.

If not defined, the default integration is MockIntegration. See reference documentation for default method options.

The following example defines the booksBackend integration as a default integration. This means that all API methods that do not explicitly define an integration will be routed to this AWS Lambda function.

ts
declare const booksBackend: apigateway.LambdaIntegration;
const api = new apigateway.RestApi(this, 'books', {
  defaultIntegration: booksBackend
});

const books = api.root.addResource('books');
books.addMethod('GET');  // integrated with `booksBackend`
books.addMethod('POST'); // integrated with `booksBackend`

const book = books.addResource('{book_id}');
book.addMethod('GET');   // integrated with `booksBackend`
python
# books_backend: apigateway.LambdaIntegration

api = apigateway.RestApi(self, "books",
    default_integration=books_backend
)

books = api.root.add_resource("books")
books.add_method("GET") # integrated with `booksBackend`
books.add_method("POST") # integrated with `booksBackend`

book = books.add_resource("{book_id}")
book.add_method("GET")
java
LambdaIntegration booksBackend;

RestApi api = RestApi.Builder.create(this, "books")
        .defaultIntegration(booksBackend)
        .build();

Resource books = api.root.addResource("books");
books.addMethod("GET"); // integrated with `booksBackend`
books.addMethod("POST"); // integrated with `booksBackend`

Resource book = books.addResource("{book_id}");
book.addMethod("GET");
csharp
LambdaIntegration booksBackend;

var api = new RestApi(this, "books", new RestApiProps {
    DefaultIntegration = booksBackend
});

var books = api.Root.AddResource("books");
books.AddMethod("GET"); // integrated with `booksBackend`
books.AddMethod("POST"); // integrated with `booksBackend`

var book = books.AddResource("{book_id}");
book.AddMethod("GET");
go
var booksBackend LambdaIntegration

api := apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	DefaultIntegration: booksBackend,
})

books := api.Root.AddResource(jsii.String("books"))
books.AddMethod(jsii.String("GET")) // integrated with `booksBackend`
books.AddMethod(jsii.String("POST")) // integrated with `booksBackend`

book := books.AddResource(jsii.String("{book_id}"))
book.AddMethod(jsii.String("GET"))

A Method can be configured with authorization scopes. Authorization scopes are used in conjunction with an authorizer that uses Amazon Cognito user pools. Read more about authorization scopes here.

Authorization scopes for a Method can be configured using the authorizationScopes property as shown below -

ts
declare const books: apigateway.Resource;

books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
  authorizationType: apigateway.AuthorizationType.COGNITO,
  authorizationScopes: ['Scope1','Scope2']
});
python
# books: apigateway.Resource


books.add_method("GET", apigateway.HttpIntegration("http://amazon.com"),
    authorization_type=apigateway.AuthorizationType.COGNITO,
    authorization_scopes=["Scope1", "Scope2"]
)
java
Resource books;


books.addMethod("GET", new HttpIntegration("http://amazon.com"), MethodOptions.builder()
        .authorizationType(AuthorizationType.COGNITO)
        .authorizationScopes(List.of("Scope1", "Scope2"))
        .build());
csharp
Resource books;


books.AddMethod("GET", new HttpIntegration("http://amazon.com"), new MethodOptions {
    AuthorizationType = AuthorizationType.COGNITO,
    AuthorizationScopes = new [] { "Scope1", "Scope2" }
});
go
var books Resource


books.AddMethod(jsii.String("GET"), apigateway.NewHttpIntegration(jsii.String("http://amazon.com")), &MethodOptions{
	AuthorizationType: apigateway.AuthorizationType_COGNITO,
	AuthorizationScopes: []*string{
		jsii.String("Scope1"),
		jsii.String("Scope2"),
	},
})

Proxy Routes ​

The addProxy method can be used to install a greedy {proxy+} resource on a path. By default, this also installs an "ANY" method:

ts
declare const resource: apigateway.Resource;
declare const handler: lambda.Function;
const proxy = resource.addProxy({
  defaultIntegration: new apigateway.LambdaIntegration(handler),

  // "false" will require explicitly adding methods on the `proxy` resource
  anyMethod: true // "true" is the default
});
python
# resource: apigateway.Resource
# handler: lambda.Function

proxy = resource.add_proxy(
    default_integration=apigateway.LambdaIntegration(handler),

    # "false" will require explicitly adding methods on the `proxy` resource
    any_method=True
)
java
Resource resource;
Function handler;

ProxyResource proxy = resource.addProxy(ProxyResourceOptions.builder()
        .defaultIntegration(new LambdaIntegration(handler))

        // "false" will require explicitly adding methods on the `proxy` resource
        .anyMethod(true)
        .build());
csharp
Resource resource;
Function handler;

var proxy = resource.AddProxy(new ProxyResourceOptions {
    DefaultIntegration = new LambdaIntegration(handler),

    // "false" will require explicitly adding methods on the `proxy` resource
    AnyMethod = true
});
go
var resource Resource
var handler Function

proxy := resource.AddProxy(&ProxyResourceOptions{
	DefaultIntegration: apigateway.NewLambdaIntegration(handler),

	// "false" will require explicitly adding methods on the `proxy` resource
	AnyMethod: jsii.Boolean(true),
})

Authorizers ​

API Gateway supports several different authorization types that can be used for controlling access to your REST APIs.

IAM-based authorizer ​

The following CDK code provides 'execute-api' permission to an IAM user, via IAM policies, for the 'GET' method on the books resource:

ts
declare const books: apigateway.Resource;
declare const iamUser: iam.User;

const getBooks = books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
  authorizationType: apigateway.AuthorizationType.IAM
});

iamUser.attachInlinePolicy(new iam.Policy(this, 'AllowBooks', {
  statements: [
    new iam.PolicyStatement({
      actions: [ 'execute-api:Invoke' ],
      effect: iam.Effect.ALLOW,
      resources: [ getBooks.methodArn ]
    })
  ]
}))
python
# books: apigateway.Resource
# iam_user: iam.User


get_books = books.add_method("GET", apigateway.HttpIntegration("http://amazon.com"),
    authorization_type=apigateway.AuthorizationType.IAM
)

iam_user.attach_inline_policy(iam.Policy(self, "AllowBooks",
    statements=[
        iam.PolicyStatement(
            actions=["execute-api:Invoke"],
            effect=iam.Effect.ALLOW,
            resources=[get_books.method_arn]
        )
    ]
))
java
Resource books;
User iamUser;


Method getBooks = books.addMethod("GET", new HttpIntegration("http://amazon.com"), MethodOptions.builder()
        .authorizationType(AuthorizationType.IAM)
        .build());

iamUser.attachInlinePolicy(Policy.Builder.create(this, "AllowBooks")
        .statements(List.of(
            PolicyStatement.Builder.create()
                    .actions(List.of("execute-api:Invoke"))
                    .effect(Effect.ALLOW)
                    .resources(List.of(getBooks.getMethodArn()))
                    .build()))
        .build());
csharp
Resource books;
User iamUser;


var getBooks = books.AddMethod("GET", new HttpIntegration("http://amazon.com"), new MethodOptions {
    AuthorizationType = AuthorizationType.IAM
});

iamUser.AttachInlinePolicy(new Policy(this, "AllowBooks", new PolicyProps {
    Statements = new [] {
        new PolicyStatement(new PolicyStatementProps {
            Actions = new [] { "execute-api:Invoke" },
            Effect = Effect.ALLOW,
            Resources = new [] { getBooks.MethodArn }
        }) }
}));
go
var books Resource
var iamUser User


getBooks := books.AddMethod(jsii.String("GET"), apigateway.NewHttpIntegration(jsii.String("http://amazon.com")), &MethodOptions{
	AuthorizationType: apigateway.AuthorizationType_IAM,
})

iamUser.AttachInlinePolicy(iam.NewPolicy(this, jsii.String("AllowBooks"), &PolicyProps{
	Statements: []PolicyStatement{
		iam.NewPolicyStatement(&PolicyStatementProps{
			Actions: []*string{
				jsii.String("execute-api:Invoke"),
			},
			Effect: iam.Effect_ALLOW,
			Resources: []*string{
				getBooks.methodArn,
			},
		}),
	},
}))

Lambda-based token authorizer ​

API Gateway also allows lambda functions to be used as authorizers.

This module provides support for token-based Lambda authorizers. When a client makes a request to an API's methods configured with such an authorizer, API Gateway calls the Lambda authorizer, which takes the caller's identity as input and returns an IAM policy as output. A token-based Lambda authorizer (also called a token authorizer) receives the caller's identity in a bearer token, such as a JSON Web Token (JWT) or an OAuth token.

API Gateway interacts with the authorizer Lambda function handler by passing input and expecting the output in a specific format. The event object that the handler is called with contains the authorizationToken and the methodArn from the request to the API Gateway endpoint. The handler is expected to return the principalId (i.e. the client identifier) and a policyDocument stating what the client is authorizer to perform. See here for a detailed specification on inputs and outputs of the Lambda handler.

The following code attaches a token-based Lambda authorizer to the 'GET' Method of the Book resource:

ts
declare const authFn: lambda.Function;
declare const books: apigateway.Resource;

const auth = new apigateway.TokenAuthorizer(this, 'booksAuthorizer', {
  handler: authFn
});

books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
  authorizer: auth
});
python
# auth_fn: lambda.Function
# books: apigateway.Resource


auth = apigateway.TokenAuthorizer(self, "booksAuthorizer",
    handler=auth_fn
)

books.add_method("GET", apigateway.HttpIntegration("http://amazon.com"),
    authorizer=auth
)
java
Function authFn;
Resource books;


TokenAuthorizer auth = TokenAuthorizer.Builder.create(this, "booksAuthorizer")
        .handler(authFn)
        .build();

books.addMethod("GET", new HttpIntegration("http://amazon.com"), MethodOptions.builder()
        .authorizer(auth)
        .build());
csharp
Function authFn;
Resource books;


var auth = new TokenAuthorizer(this, "booksAuthorizer", new TokenAuthorizerProps {
    Handler = authFn
});

books.AddMethod("GET", new HttpIntegration("http://amazon.com"), new MethodOptions {
    Authorizer = auth
});
go
var authFn Function
var books Resource


auth := apigateway.NewTokenAuthorizer(this, jsii.String("booksAuthorizer"), &TokenAuthorizerProps{
	Handler: authFn,
})

books.AddMethod(jsii.String("GET"), apigateway.NewHttpIntegration(jsii.String("http://amazon.com")), &MethodOptions{
	Authorizer: auth,
})

A full working example is shown below.

ts
import * as path from 'path';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
import { App, Stack } from 'aws-cdk-lib';
import { MockIntegration, PassthroughBehavior, RestApi, TokenAuthorizer, Cors } from 'aws-cdk-lib/aws-apigateway';

/// !show
class MyStack extends Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const authorizerFn = new lambda.Function(this, 'MyAuthorizerFunction', {
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler',
      code: lambda.AssetCode.fromAsset(path.join(__dirname, 'integ.token-authorizer.handler')),
    });

    const authorizer = new TokenAuthorizer(this, 'MyAuthorizer', {
      handler: authorizerFn,
    });

    const restapi = new RestApi(this, 'MyRestApi', {
      cloudWatchRole: true,
      defaultMethodOptions: {
        authorizer,
      },
      defaultCorsPreflightOptions: {
        allowOrigins: Cors.ALL_ORIGINS,
      },
    });


    restapi.root.addMethod('ANY', new MockIntegration({
      integrationResponses: [
        { statusCode: '200' },
      ],
      passthroughBehavior: PassthroughBehavior.NEVER,
      requestTemplates: {
        'application/json': '{ "statusCode": 200 }',
      },
    }), {
      methodResponses: [
        { statusCode: '200' },
      ],
    });
  }
}
python
from aws_cdk.aws_apigateway import MethodOptions, CorsOptions, IntegrationResponse, MethodResponse
class MyStack(Stack):
    def __init__(self, scope, id):
        super().__init__(scope, id)

        authorizer_fn = lambda_.Function(self, "MyAuthorizerFunction",
            runtime=lambda_.Runtime.NODEJS_LATEST,
            handler="index.handler",
            code=lambda_.AssetCode.from_asset(path.join(__dirname, "integ.token-authorizer.handler"))
        )

        authorizer = TokenAuthorizer(self, "MyAuthorizer",
            handler=authorizer_fn
        )

        restapi = RestApi(self, "MyRestApi",
            cloud_watch_role=True,
            default_method_options=MethodOptions(
                authorizer=authorizer
            ),
            default_cors_preflight_options=CorsOptions(
                allow_origins=Cors.ALL_ORIGINS
            )
        )

        restapi.root.add_method("ANY", MockIntegration(
            integration_responses=[IntegrationResponse(status_code="200")
            ],
            passthrough_behavior=PassthroughBehavior.NEVER,
            request_templates={
                "application/json": "{ \"statusCode\": 200 }"
            }
        ),
            method_responses=[MethodResponse(status_code="200")
            ]
        )
java
public class MyStack extends Stack {
    public MyStack(Construct scope, String id) {
        super(scope, id);

        Function authorizerFn = Function.Builder.create(this, "MyAuthorizerFunction")
                .runtime(Runtime.NODEJS_LATEST)
                .handler("index.handler")
                .code(AssetCode.fromAsset(join(__dirname, "integ.token-authorizer.handler")))
                .build();

        TokenAuthorizer authorizer = TokenAuthorizer.Builder.create(this, "MyAuthorizer")
                .handler(authorizerFn)
                .build();

        RestApi restapi = RestApi.Builder.create(this, "MyRestApi")
                .cloudWatchRole(true)
                .defaultMethodOptions(MethodOptions.builder()
                        .authorizer(authorizer)
                        .build())
                .defaultCorsPreflightOptions(CorsOptions.builder()
                        .allowOrigins(Cors.ALL_ORIGINS)
                        .build())
                .build();

        restapi.root.addMethod("ANY", MockIntegration.Builder.create()
                .integrationResponses(List.of(IntegrationResponse.builder().statusCode("200").build()))
                .passthroughBehavior(PassthroughBehavior.NEVER)
                .requestTemplates(Map.of(
                        "application/json", "{ \"statusCode\": 200 }"))
                .build(), MethodOptions.builder()
                .methodResponses(List.of(MethodResponse.builder().statusCode("200").build()))
                .build());
    }
}
csharp
class MyStack : Stack
{
    public MyStack(Construct scope, string id) : base(scope, id)
    {

        var authorizerFn = new Function(this, "MyAuthorizerFunction", new FunctionProps {
            Runtime = Runtime.NODEJS_LATEST,
            Handler = "index.handler",
            Code = AssetCode.FromAsset(Join(__dirname, "integ.token-authorizer.handler"))
        });

        var authorizer = new TokenAuthorizer(this, "MyAuthorizer", new TokenAuthorizerProps {
            Handler = authorizerFn
        });

        var restapi = new RestApi(this, "MyRestApi", new RestApiProps {
            CloudWatchRole = true,
            DefaultMethodOptions = new MethodOptions {
                Authorizer = authorizer
            },
            DefaultCorsPreflightOptions = new CorsOptions {
                AllowOrigins = Cors.ALL_ORIGINS
            }
        });

        restapi.Root.AddMethod("ANY", new MockIntegration(new IntegrationOptions {
            IntegrationResponses = new [] { new IntegrationResponse { StatusCode = "200" } },
            PassthroughBehavior = PassthroughBehavior.NEVER,
            RequestTemplates = new Dictionary<string, string> {
                { "application/json", "{ \"statusCode\": 200 }" }
            }
        }), new MethodOptions {
            MethodResponses = new [] { new MethodResponse { StatusCode = "200" } }
        });
    }
}
go
type myStack struct {
	Stack
}

func newMyStack(scope Construct, id *string) *myStack {
	this := &myStack{}
	newStack_Override(this, scope, id)

	authorizerFn := lambda.NewFunction(this, jsii.String("MyAuthorizerFunction"), &FunctionProps{
		Runtime: lambda.Runtime_NODEJS_LATEST(),
		Handler: jsii.String("index.handler"),
		Code: lambda.AssetCode_FromAsset(path.join(__dirname, jsii.String("integ.token-authorizer.handler"))),
	})

	authorizer := awscdk.NewTokenAuthorizer(this, jsii.String("MyAuthorizer"), &TokenAuthorizerProps{
		Handler: authorizerFn,
	})

	restapi := awscdk.NewRestApi(this, jsii.String("MyRestApi"), &RestApiProps{
		CloudWatchRole: jsii.Boolean(true),
		DefaultMethodOptions: &MethodOptions{
			Authorizer: *Authorizer,
		},
		DefaultCorsPreflightOptions: &CorsOptions{
			AllowOrigins: awscdk.Cors_ALL_ORIGINS(),
		},
	})

	restapi.Root.AddMethod(jsii.String("ANY"), awscdk.NewMockIntegration(&IntegrationOptions{
		IntegrationResponses: []IntegrationResponse{
			&IntegrationResponse{
				StatusCode: jsii.String("200"),
			},
		},
		PassthroughBehavior: awscdk.PassthroughBehavior_NEVER,
		RequestTemplates: map[string]*string{
			"application/json": jsii.String("{ \"statusCode\": 200 }"),
		},
	}), &MethodOptions{
		MethodResponses: []MethodResponse{
			&MethodResponse{
				StatusCode: jsii.String("200"),
			},
		},
	})
	return this
}

By default, the TokenAuthorizer looks for the authorization token in the request header with the key 'Authorization'. This can, however, be modified by changing the identitySource property.

Authorizers can also be passed via the defaultMethodOptions property within the RestApi construct or the Method construct. Unless explicitly overridden, the specified defaults will be applied across all Methods across the RestApi or across all Resources, depending on where the defaults were specified.

Lambda-based request authorizer ​

This module provides support for request-based Lambda authorizers. When a client makes a request to an API's methods configured with such an authorizer, API Gateway calls the Lambda authorizer, which takes specified parts of the request, known as identity sources, as input and returns an IAM policy as output. A request-based Lambda authorizer (also called a request authorizer) receives the identity sources in a series of values pulled from the request, from the headers, stage variables, query strings, and the context.

API Gateway interacts with the authorizer Lambda function handler by passing input and expecting the output in a specific format. The event object that the handler is called with contains the body of the request and the methodArn from the request to the API Gateway endpoint. The handler is expected to return the principalId (i.e. the client identifier) and a policyDocument stating what the client is authorizer to perform. See here for a detailed specification on inputs and outputs of the Lambda handler.

The following code attaches a request-based Lambda authorizer to the 'GET' Method of the Book resource:

ts
declare const authFn: lambda.Function;
declare const books: apigateway.Resource;

const auth = new apigateway.RequestAuthorizer(this, 'booksAuthorizer', {
  handler: authFn,
  identitySources: [apigateway.IdentitySource.header('Authorization')]
});

books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
  authorizer: auth
});
python
# auth_fn: lambda.Function
# books: apigateway.Resource


auth = apigateway.RequestAuthorizer(self, "booksAuthorizer",
    handler=auth_fn,
    identity_sources=[apigateway.IdentitySource.header("Authorization")]
)

books.add_method("GET", apigateway.HttpIntegration("http://amazon.com"),
    authorizer=auth
)
java
Function authFn;
Resource books;


RequestAuthorizer auth = RequestAuthorizer.Builder.create(this, "booksAuthorizer")
        .handler(authFn)
        .identitySources(List.of(IdentitySource.header("Authorization")))
        .build();

books.addMethod("GET", new HttpIntegration("http://amazon.com"), MethodOptions.builder()
        .authorizer(auth)
        .build());
csharp
Function authFn;
Resource books;


var auth = new RequestAuthorizer(this, "booksAuthorizer", new RequestAuthorizerProps {
    Handler = authFn,
    IdentitySources = new [] { IdentitySource.Header("Authorization") }
});

books.AddMethod("GET", new HttpIntegration("http://amazon.com"), new MethodOptions {
    Authorizer = auth
});
go
var authFn Function
var books Resource


auth := apigateway.NewRequestAuthorizer(this, jsii.String("booksAuthorizer"), &RequestAuthorizerProps{
	Handler: authFn,
	IdentitySources: []*string{
		apigateway.IdentitySource_Header(jsii.String("Authorization")),
	},
})

books.AddMethod(jsii.String("GET"), apigateway.NewHttpIntegration(jsii.String("http://amazon.com")), &MethodOptions{
	Authorizer: auth,
})

A full working example is shown below.

ts
import * as path from 'path';
import * as lambda from '../../../aws-lambda';
import { App, Stack } from '../../../core';
import { MockIntegration, PassthroughBehavior, RestApi, RequestAuthorizer, IdentitySource } from '../../lib';

// Against the RestApi endpoint from the stack output, run
// `curl -s -o /dev/null -w "%{http_code}" <url>` should return 401
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: deny' <url>?allow=yes` should return 403
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: allow' <url>?allow=yes` should return 200

const app = new App();
const stack = new Stack(app, 'RequestAuthorizerInteg');

const authorizerFn = new lambda.Function(stack, 'MyAuthorizerFunction', {
  runtime: lambda.Runtime.NODEJS_LATEST,
  handler: 'index.handler',
  code: lambda.AssetCode.fromAsset(path.join(__dirname, 'integ.request-authorizer.handler')),
});

const restapi = new RestApi(stack, 'MyRestApi', { cloudWatchRole: true });

const authorizer = new RequestAuthorizer(stack, 'MyAuthorizer', {
  handler: authorizerFn,
  identitySources: [IdentitySource.header('Authorization'), IdentitySource.queryString('allow')],
});

const secondAuthorizer = new RequestAuthorizer(stack, 'MySecondAuthorizer', {
  handler: authorizerFn,
  identitySources: [IdentitySource.header('Authorization'), IdentitySource.queryString('allow')],
});

restapi.root.addMethod('ANY', new MockIntegration({
  integrationResponses: [
    { statusCode: '200' },
  ],
  passthroughBehavior: PassthroughBehavior.NEVER,
  requestTemplates: {
    'application/json': '{ "statusCode": 200 }',
  },
}), {
  methodResponses: [
    { statusCode: '200' },
  ],
  authorizer,
});

restapi.root.resourceForPath('auth').addMethod('ANY', new MockIntegration({
  integrationResponses: [
    { statusCode: '200' },
  ],
  passthroughBehavior: PassthroughBehavior.NEVER,
  requestTemplates: {
    'application/json': '{ "statusCode": 200 }',
  },
}), {
  methodResponses: [
    { statusCode: '200' },
  ],
  authorizer: secondAuthorizer,
});
python
from aws_cdk.aws_apigateway import IntegrationResponse, MethodResponse, IntegrationResponse, MethodResponse
import path as path
import aws_cdk.aws_lambda as lambda_
from aws_cdk import App, Stack
from aws_cdk.aws_apigateway import MockIntegration, PassthroughBehavior, RestApi, RequestAuthorizer, IdentitySource

# Against the RestApi endpoint from the stack output, run
# `curl -s -o /dev/null -w "%{http_code}" <url>` should return 401
# `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: deny' <url>?allow=yes` should return 403
# `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: allow' <url>?allow=yes` should return 200

app = App()
stack = Stack(app, "RequestAuthorizerInteg")

authorizer_fn = lambda_.Function(stack, "MyAuthorizerFunction",
    runtime=lambda_.Runtime.NODEJS_LATEST,
    handler="index.handler",
    code=lambda_.AssetCode.from_asset(path.join(__dirname, "integ.request-authorizer.handler"))
)

restapi = RestApi(stack, "MyRestApi", cloud_watch_role=True)

authorizer = RequestAuthorizer(stack, "MyAuthorizer",
    handler=authorizer_fn,
    identity_sources=[IdentitySource.header("Authorization"), IdentitySource.query_string("allow")]
)

second_authorizer = RequestAuthorizer(stack, "MySecondAuthorizer",
    handler=authorizer_fn,
    identity_sources=[IdentitySource.header("Authorization"), IdentitySource.query_string("allow")]
)

restapi.root.add_method("ANY", MockIntegration(
    integration_responses=[IntegrationResponse(status_code="200")
    ],
    passthrough_behavior=PassthroughBehavior.NEVER,
    request_templates={
        "application/json": "{ \"statusCode\": 200 }"
    }
),
    method_responses=[MethodResponse(status_code="200")
    ],
    authorizer=authorizer
)

restapi.root.resource_for_path("auth").add_method("ANY", MockIntegration(
    integration_responses=[IntegrationResponse(status_code="200")
    ],
    passthrough_behavior=PassthroughBehavior.NEVER,
    request_templates={
        "application/json": "{ \"statusCode\": 200 }"
    }
),
    method_responses=[MethodResponse(status_code="200")
    ],
    authorizer=second_authorizer
)
java
import path.*;
import software.amazon.awscdk.services.lambda.*;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.services.apigateway.MockIntegration;
import software.amazon.awscdk.services.apigateway.PassthroughBehavior;
import software.amazon.awscdk.services.apigateway.RestApi;
import software.amazon.awscdk.services.apigateway.RequestAuthorizer;
import software.amazon.awscdk.services.apigateway.IdentitySource;

// Against the RestApi endpoint from the stack output, run
// `curl -s -o /dev/null -w "%{http_code}" <url>` should return 401
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: deny' <url>?allow=yes` should return 403
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: allow' <url>?allow=yes` should return 200

App app = new App();
Stack stack = new Stack(app, "RequestAuthorizerInteg");

Function authorizerFn = Function.Builder.create(stack, "MyAuthorizerFunction")
        .runtime(Runtime.NODEJS_LATEST)
        .handler("index.handler")
        .code(AssetCode.fromAsset(join(__dirname, "integ.request-authorizer.handler")))
        .build();

RestApi restapi = RestApi.Builder.create(stack, "MyRestApi").cloudWatchRole(true).build();

RequestAuthorizer authorizer = RequestAuthorizer.Builder.create(stack, "MyAuthorizer")
        .handler(authorizerFn)
        .identitySources(List.of(IdentitySource.header("Authorization"), IdentitySource.queryString("allow")))
        .build();

RequestAuthorizer secondAuthorizer = RequestAuthorizer.Builder.create(stack, "MySecondAuthorizer")
        .handler(authorizerFn)
        .identitySources(List.of(IdentitySource.header("Authorization"), IdentitySource.queryString("allow")))
        .build();

restapi.root.addMethod("ANY", MockIntegration.Builder.create()
        .integrationResponses(List.of(IntegrationResponse.builder().statusCode("200").build()))
        .passthroughBehavior(PassthroughBehavior.NEVER)
        .requestTemplates(Map.of(
                "application/json", "{ \"statusCode\": 200 }"))
        .build(), MethodOptions.builder()
        .methodResponses(List.of(MethodResponse.builder().statusCode("200").build()))
        .authorizer(authorizer)
        .build());

restapi.root.resourceForPath("auth").addMethod("ANY", MockIntegration.Builder.create()
        .integrationResponses(List.of(IntegrationResponse.builder().statusCode("200").build()))
        .passthroughBehavior(PassthroughBehavior.NEVER)
        .requestTemplates(Map.of(
                "application/json", "{ \"statusCode\": 200 }"))
        .build(), MethodOptions.builder()
        .methodResponses(List.of(MethodResponse.builder().statusCode("200").build()))
        .authorizer(secondAuthorizer)
        .build());
csharp
using Path;
using Amazon.CDK.AWS.Lambda;
using Amazon.CDK;
using Amazon.CDK.AWS.APIGateway;

// Against the RestApi endpoint from the stack output, run
// `curl -s -o /dev/null -w "%{http_code}" <url>` should return 401
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: deny' <url>?allow=yes` should return 403
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: allow' <url>?allow=yes` should return 200

var app = new App();
var stack = new Stack(app, "RequestAuthorizerInteg");

var authorizerFn = new Function(stack, "MyAuthorizerFunction", new FunctionProps {
    Runtime = Runtime.NODEJS_LATEST,
    Handler = "index.handler",
    Code = AssetCode.FromAsset(Join(__dirname, "integ.request-authorizer.handler"))
});

var restapi = new RestApi(stack, "MyRestApi", new RestApiProps { CloudWatchRole = true });

var authorizer = new RequestAuthorizer(stack, "MyAuthorizer", new RequestAuthorizerProps {
    Handler = authorizerFn,
    IdentitySources = new [] { IdentitySource.Header("Authorization"), IdentitySource.QueryString("allow") }
});

var secondAuthorizer = new RequestAuthorizer(stack, "MySecondAuthorizer", new RequestAuthorizerProps {
    Handler = authorizerFn,
    IdentitySources = new [] { IdentitySource.Header("Authorization"), IdentitySource.QueryString("allow") }
});

restapi.Root.AddMethod("ANY", new MockIntegration(new IntegrationOptions {
    IntegrationResponses = new [] { new IntegrationResponse { StatusCode = "200" } },
    PassthroughBehavior = PassthroughBehavior.NEVER,
    RequestTemplates = new Dictionary<string, string> {
        { "application/json", "{ \"statusCode\": 200 }" }
    }
}), new MethodOptions {
    MethodResponses = new [] { new MethodResponse { StatusCode = "200" } },
    Authorizer = authorizer
});

restapi.Root.ResourceForPath("auth").AddMethod("ANY", new MockIntegration(new IntegrationOptions {
    IntegrationResponses = new [] { new IntegrationResponse { StatusCode = "200" } },
    PassthroughBehavior = PassthroughBehavior.NEVER,
    RequestTemplates = new Dictionary<string, string> {
        { "application/json", "{ \"statusCode\": 200 }" }
    }
}), new MethodOptions {
    MethodResponses = new [] { new MethodResponse { StatusCode = "200" } },
    Authorizer = secondAuthorizer
});
go
import path "github.com/aws-samples/dummy/path"
import "github.com/aws/aws-cdk-go/awscdk"
import "github.com/aws/aws-cdk-go/awscdk"
import "github.com/aws/aws-cdk-go/awscdk"

// Against the RestApi endpoint from the stack output, run
// `curl -s -o /dev/null -w "%{http_code}" <url>` should return 401
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: deny' <url>?allow=yes` should return 403
// `curl -s -o /dev/null -w "%{http_code}" -H 'Authorization: allow' <url>?allow=yes` should return 200

app := awscdk.NewApp()
stack := awscdk.NewStack(app, jsii.String("RequestAuthorizerInteg"))

authorizerFn := lambda.NewFunction(stack, jsii.String("MyAuthorizerFunction"), &FunctionProps{
	Runtime: lambda.Runtime_NODEJS_LATEST(),
	Handler: jsii.String("index.handler"),
	Code: lambda.AssetCode_FromAsset(path.join(__dirname, jsii.String("integ.request-authorizer.handler"))),
})

restapi := awscdk.NewRestApi(stack, jsii.String("MyRestApi"), &RestApiProps{
	CloudWatchRole: jsii.Boolean(true),
})

authorizer := awscdk.NewRequestAuthorizer(stack, jsii.String("MyAuthorizer"), &RequestAuthorizerProps{
	Handler: authorizerFn,
	IdentitySources: []*string{
		awscdk.IdentitySource_Header(jsii.String("Authorization")),
		awscdk.IdentitySource_QueryString(jsii.String("allow")),
	},
})

secondAuthorizer := awscdk.NewRequestAuthorizer(stack, jsii.String("MySecondAuthorizer"), &RequestAuthorizerProps{
	Handler: authorizerFn,
	IdentitySources: []*string{
		awscdk.IdentitySource_*Header(jsii.String("Authorization")),
		awscdk.IdentitySource_*QueryString(jsii.String("allow")),
	},
})

restapi.Root.AddMethod(jsii.String("ANY"), awscdk.NewMockIntegration(&IntegrationOptions{
	IntegrationResponses: []IntegrationResponse{
		&IntegrationResponse{
			StatusCode: jsii.String("200"),
		},
	},
	PassthroughBehavior: awscdk.PassthroughBehavior_NEVER,
	RequestTemplates: map[string]*string{
		"application/json": jsii.String("{ \"statusCode\": 200 }"),
	},
}), &MethodOptions{
	MethodResponses: []MethodResponse{
		&MethodResponse{
			StatusCode: jsii.String("200"),
		},
	},
	Authorizer: Authorizer,
})

restapi.Root.ResourceForPath(jsii.String("auth")).AddMethod(jsii.String("ANY"), awscdk.NewMockIntegration(&IntegrationOptions{
	IntegrationResponses: []IntegrationResponse{
		&IntegrationResponse{
			StatusCode: jsii.String("200"),
		},
	},
	PassthroughBehavior: awscdk.PassthroughBehavior_NEVER,
	RequestTemplates: map[string]*string{
		"application/json": jsii.String("{ \"statusCode\": 200 }"),
	},
}), &MethodOptions{
	MethodResponses: []MethodResponse{
		&MethodResponse{
			StatusCode: jsii.String("200"),
		},
	},
	Authorizer: secondAuthorizer,
})

By default, the RequestAuthorizer does not pass any kind of information from the request. This can, however, be modified by changing the identitySource property, and is required when specifying a value for caching.

Authorizers can also be passed via the defaultMethodOptions property within the RestApi construct or the Method construct. Unless explicitly overridden, the specified defaults will be applied across all Methods across the RestApi or across all Resources, depending on where the defaults were specified.

Cognito User Pools authorizer ​

API Gateway also allows Amazon Cognito user pools as authorizer

The following snippet configures a Cognito user pool as an authorizer:

ts
const userPool = new cognito.UserPool(this, 'UserPool');

const auth = new apigateway.CognitoUserPoolsAuthorizer(this, 'booksAuthorizer', {
  cognitoUserPools: [userPool]
});

declare const books: apigateway.Resource;
books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
  authorizer: auth,
  authorizationType: apigateway.AuthorizationType.COGNITO,
});
python
# books: apigateway.Resource
user_pool = cognito.UserPool(self, "UserPool")

auth = apigateway.CognitoUserPoolsAuthorizer(self, "booksAuthorizer",
    cognito_user_pools=[user_pool]
)
books.add_method("GET", apigateway.HttpIntegration("http://amazon.com"),
    authorizer=auth,
    authorization_type=apigateway.AuthorizationType.COGNITO
)
java
Resource books;
UserPool userPool = new UserPool(this, "UserPool");

CognitoUserPoolsAuthorizer auth = CognitoUserPoolsAuthorizer.Builder.create(this, "booksAuthorizer")
        .cognitoUserPools(List.of(userPool))
        .build();
books.addMethod("GET", new HttpIntegration("http://amazon.com"), MethodOptions.builder()
        .authorizer(auth)
        .authorizationType(AuthorizationType.COGNITO)
        .build());
csharp
Resource books;
var userPool = new UserPool(this, "UserPool");

var auth = new CognitoUserPoolsAuthorizer(this, "booksAuthorizer", new CognitoUserPoolsAuthorizerProps {
    CognitoUserPools = new [] { userPool }
});
books.AddMethod("GET", new HttpIntegration("http://amazon.com"), new MethodOptions {
    Authorizer = auth,
    AuthorizationType = AuthorizationType.COGNITO
});
go
var books Resource
userPool := cognito.NewUserPool(this, jsii.String("UserPool"))

auth := apigateway.NewCognitoUserPoolsAuthorizer(this, jsii.String("booksAuthorizer"), &CognitoUserPoolsAuthorizerProps{
	CognitoUserPools: []IUserPool{
		userPool,
	},
})
books.AddMethod(jsii.String("GET"), apigateway.NewHttpIntegration(jsii.String("http://amazon.com")), &MethodOptions{
	Authorizer: auth,
	AuthorizationType: apigateway.AuthorizationType_COGNITO,
})

Mutual TLS (mTLS) ​

Mutual TLS can be configured to limit access to your API based by using client certificates instead of (or as an extension of) using authorization headers.

ts
declare const acm: any;

new apigateway.DomainName(this, 'domain-name', {
  domainName: 'example.com',
  certificate: acm.Certificate.fromCertificateArn(this, 'cert', 'arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'),
  mtls: {
    bucket: new s3.Bucket(this, 'bucket'),
    key: 'truststore.pem',
    version: 'version',
  },
});
python
# acm: Any


apigateway.DomainName(self, "domain-name",
    domain_name="example.com",
    certificate=acm.Certificate.from_certificate_arn(self, "cert", "arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d"),
    mtls=apigateway.MTLSConfig(
        bucket=s3.Bucket(self, "bucket"),
        key="truststore.pem",
        version="version"
    )
)
java
Object acm;


DomainName.Builder.create(this, "domain-name")
        .domainName("example.com")
        .certificate(acm.Certificate.fromCertificateArn(this, "cert", "arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d"))
        .mtls(MTLSConfig.builder()
                .bucket(new Bucket(this, "bucket"))
                .key("truststore.pem")
                .version("version")
                .build())
        .build();
csharp
var acm;


new DomainName(this, "domain-name", new DomainNameProps {
    DomainName = "example.com",
    Certificate = acm.Certificate.FromCertificateArn(this, "cert", "arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d"),
    Mtls = new MTLSConfig {
        Bucket = new Bucket(this, "bucket"),
        Key = "truststore.pem",
        Version = "version"
    }
});
go
var acm interface{}


apigateway.NewDomainName(this, jsii.String("domain-name"), &DomainNameProps{
	DomainName: jsii.String("example.com"),
	Certificate: acm.certificate_FromCertificateArn(this, jsii.String("cert"), jsii.String("arn:aws:acm:us-east-1:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d")),
	Mtls: &MTLSConfig{
		Bucket: s3.NewBucket(this, jsii.String("bucket")),
		Key: jsii.String("truststore.pem"),
		Version: jsii.String("version"),
	},
})

Instructions for configuring your trust store can be found here.

Deployments ​

By default, the RestApi construct will automatically create an API Gateway Deployment and a "prod" Stage which represent the API configuration you defined in your CDK app. This means that when you deploy your app, your API will have open access from the internet via the stage URL.

The URL of your API can be obtained from the attribute restApi.url, and is also exported as an Output from your stack, so it's printed when you cdk deploy your app:

console
$ cdk deploy
...
books.booksapiEndpointE230E8D5 = https://6lyktd4lpk.execute-api.us-east-1.amazonaws.com/prod/

To disable this behavior, you can set { deploy: false } when creating your API. This means that the API will not be deployed and a stage will not be created for it. You will need to manually define a apigateway.Deployment and apigateway.Stage resources.

Use the deployOptions property to customize the deployment options of your API.

The following example will configure API Gateway to emit logs and data traces to AWS CloudWatch for all API calls:

Note: whether or not this is enabled or disabled by default is controlled by the @aws-cdk/aws-apigateway:disableCloudWatchRole feature flag. When this feature flag is set to false the default behavior will set cloudWatchRole=true

This is controlled via the @aws-cdk/aws-apigateway:disableCloudWatchRole feature flag and is disabled by default. When enabled (or @aws-cdk/aws-apigateway:disableCloudWatchRole=false), an IAM role will be created and associated with API Gateway to allow it to write logs and metrics to AWS CloudWatch.

ts
const api = new apigateway.RestApi(this, 'books', {
  cloudWatchRole: true,
  deployOptions: {
    loggingLevel: apigateway.MethodLoggingLevel.INFO,
    dataTraceEnabled: true
  }
})
python
api = apigateway.RestApi(self, "books",
    cloud_watch_role=True,
    deploy_options=apigateway.StageOptions(
        logging_level=apigateway.MethodLoggingLevel.INFO,
        data_trace_enabled=True
    )
)
java
RestApi api = RestApi.Builder.create(this, "books")
        .cloudWatchRole(true)
        .deployOptions(StageOptions.builder()
                .loggingLevel(MethodLoggingLevel.INFO)
                .dataTraceEnabled(true)
                .build())
        .build();
csharp
var api = new RestApi(this, "books", new RestApiProps {
    CloudWatchRole = true,
    DeployOptions = new StageOptions {
        LoggingLevel = MethodLoggingLevel.INFO,
        DataTraceEnabled = true
    }
});
go
api := apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	CloudWatchRole: jsii.Boolean(true),
	DeployOptions: &StageOptions{
		LoggingLevel: apigateway.MethodLoggingLevel_INFO,
		DataTraceEnabled: jsii.Boolean(true),
	},
})

Note: there can only be a single apigateway.CfnAccount per AWS environment so if you create multiple RestApis with cloudWatchRole=true each new RestApi will overwrite the CfnAccount. It is recommended to set cloudWatchRole=false (the default behavior if @aws-cdk/aws-apigateway:disableCloudWatchRole is enabled) and only create a single CloudWatch role and account per environment.

You can specify the CloudWatch Role and Account sub-resources removal policy with the cloudWatchRoleRemovalPolicy property, which defaults to RemovalPolicy.RETAIN. This option requires cloudWatchRole to be enabled.

ts
import * as cdk from 'aws-cdk-lib/core';

const api = new apigateway.RestApi(this, 'books', {
  cloudWatchRole: true,
  cloudWatchRoleRemovalPolicy: cdk.RemovalPolicy.DESTROY,
});
python
import aws_cdk as cdk


api = apigateway.RestApi(self, "books",
    cloud_watch_role=True,
    cloud_watch_role_removal_policy=cdk.RemovalPolicy.DESTROY
)
java
import software.amazon.awscdk.*;


RestApi api = RestApi.Builder.create(this, "books")
        .cloudWatchRole(true)
        .cloudWatchRoleRemovalPolicy(RemovalPolicy.DESTROY)
        .build();
csharp
using Amazon.CDK;


var api = new RestApi(this, "books", new RestApiProps {
    CloudWatchRole = true,
    CloudWatchRoleRemovalPolicy = RemovalPolicy.DESTROY
});
go
import cdk "github.com/aws/aws-cdk-go/awscdk"


api := apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	CloudWatchRole: jsii.Boolean(true),
	CloudWatchRoleRemovalPolicy: cdk.RemovalPolicy_DESTROY,
})

Deploying to an existing stage ​

Using RestApi ​

If you want to use an existing stage to deploy your RestApi, first set { deploy: false } so the construct doesn't automatically create new Deployment and Stage resources. Then you can manually define a apigateway.Deployment resource and specify the stage name for your existing stage using the stageName property.

Note that as long as the deployment's logical ID doesn't change, it will represent the snapshot in time when the resource was created. To ensure your deployment reflects changes to the RestApi model, see Controlled triggering of deployments.

ts
const restApi = new apigateway.RestApi(this, 'my-rest-api', {
  deploy: false,
});

// Use `stageName` to deploy to an existing stage
const deployment = new apigateway.Deployment(this, 'my-deployment', {
  api: restApi,
  stageName: 'dev',
  retainDeployments: true, // keep old deployments
});
python
rest_api = apigateway.RestApi(self, "my-rest-api",
    deploy=False
)

# Use `stageName` to deploy to an existing stage
deployment = apigateway.Deployment(self, "my-deployment",
    api=rest_api,
    stage_name="dev",
    retain_deployments=True
)
java
RestApi restApi = RestApi.Builder.create(this, "my-rest-api")
        .deploy(false)
        .build();

// Use `stageName` to deploy to an existing stage
Deployment deployment = Deployment.Builder.create(this, "my-deployment")
        .api(restApi)
        .stageName("dev")
        .retainDeployments(true)
        .build();
csharp
var restApi = new RestApi(this, "my-rest-api", new RestApiProps {
    Deploy = false
});

// Use `stageName` to deploy to an existing stage
var deployment = new Deployment(this, "my-deployment", new DeploymentProps {
    Api = restApi,
    StageName = "dev",
    RetainDeployments = true
});
go
restApi := apigateway.NewRestApi(this, jsii.String("my-rest-api"), &RestApiProps{
	Deploy: jsii.Boolean(false),
})

// Use `stageName` to deploy to an existing stage
deployment := apigateway.NewDeployment(this, jsii.String("my-deployment"), &DeploymentProps{
	Api: restApi,
	StageName: jsii.String("dev"),
	RetainDeployments: jsii.Boolean(true),
})

Using SpecRestApi ​

If you want to use an existing stage to deploy your SpecRestApi, first set { deploy: false } so the construct doesn't automatically create new Deployment and Stage resources. Then you can manually define a apigateway.Deployment resource and specify the stage name for your existing stage using the stageName property.

To automatically create a new deployment that reflects the latest API changes, you can use the addToLogicalId() method and pass in your OpenAPI definition.

ts
const myApiDefinition = apigateway.ApiDefinition.fromAsset('path-to-file.json');
const specRestApi = new apigateway.SpecRestApi(this, 'my-specrest-api', {
  deploy: false,
  apiDefinition: myApiDefinition
});

// Use `stageName` to deploy to an existing stage
const deployment = new apigateway.Deployment(this, 'my-deployment', {
  api: specRestApi,
  stageName: 'dev',
  retainDeployments: true, // keep old deployments
});

// Trigger a new deployment on OpenAPI definition updates
deployment.addToLogicalId(myApiDefinition);
python
my_api_definition = apigateway.ApiDefinition.from_asset("path-to-file.json")
spec_rest_api = apigateway.SpecRestApi(self, "my-specrest-api",
    deploy=False,
    api_definition=my_api_definition
)

# Use `stageName` to deploy to an existing stage
deployment = apigateway.Deployment(self, "my-deployment",
    api=spec_rest_api,
    stage_name="dev",
    retain_deployments=True
)

# Trigger a new deployment on OpenAPI definition updates
deployment.add_to_logical_id(my_api_definition)
java
AssetApiDefinition myApiDefinition = ApiDefinition.fromAsset("path-to-file.json");
SpecRestApi specRestApi = SpecRestApi.Builder.create(this, "my-specrest-api")
        .deploy(false)
        .apiDefinition(myApiDefinition)
        .build();

// Use `stageName` to deploy to an existing stage
Deployment deployment = Deployment.Builder.create(this, "my-deployment")
        .api(specRestApi)
        .stageName("dev")
        .retainDeployments(true)
        .build();

// Trigger a new deployment on OpenAPI definition updates
deployment.addToLogicalId(myApiDefinition);
csharp
var myApiDefinition = ApiDefinition.FromAsset("path-to-file.json");
var specRestApi = new SpecRestApi(this, "my-specrest-api", new SpecRestApiProps {
    Deploy = false,
    ApiDefinition = myApiDefinition
});

// Use `stageName` to deploy to an existing stage
var deployment = new Deployment(this, "my-deployment", new DeploymentProps {
    Api = specRestApi,
    StageName = "dev",
    RetainDeployments = true
});

// Trigger a new deployment on OpenAPI definition updates
deployment.AddToLogicalId(myApiDefinition);
go
myApiDefinition := apigateway.ApiDefinition_FromAsset(jsii.String("path-to-file.json"))
specRestApi := apigateway.NewSpecRestApi(this, jsii.String("my-specrest-api"), &SpecRestApiProps{
	Deploy: jsii.Boolean(false),
	ApiDefinition: myApiDefinition,
})

// Use `stageName` to deploy to an existing stage
deployment := apigateway.NewDeployment(this, jsii.String("my-deployment"), &DeploymentProps{
	Api: specRestApi,
	StageName: jsii.String("dev"),
	RetainDeployments: jsii.Boolean(true),
})

// Trigger a new deployment on OpenAPI definition updates
deployment.AddToLogicalId(myApiDefinition)

Note: If the stageName property is set but a stage with the corresponding name does not exist, a new stage resource will be created with the provided stage name.

Note: If you update the stageName property, you should be triggering a new deployment (i.e. with an updated logical ID and API changes). Otherwise, an error will occur during deployment.

Controlled triggering of deployments ​

By default, the RestApi construct deploys changes immediately. If you want to control when deployments happen, set { deploy: false } and create a Deployment construct yourself. Add a revision counter to the construct ID, and update it in your source code whenever you want to trigger a new deployment:

ts
const restApi = new apigateway.RestApi(this, 'my-api', {
  deploy: false,
});

const deploymentRevision = 5; // Bump this counter to trigger a new deployment
new apigateway.Deployment(this, `Deployment${deploymentRevision}`, {
  api: restApi
});
python
rest_api = apigateway.RestApi(self, "my-api",
    deploy=False
)

deployment_revision = 5 # Bump this counter to trigger a new deployment
apigateway.Deployment(self, f"Deployment{deploymentRevision}",
    api=rest_api
)
java
RestApi restApi = RestApi.Builder.create(this, "my-api")
        .deploy(false)
        .build();

Number deploymentRevision = 5; // Bump this counter to trigger a new deployment
 // Bump this counter to trigger a new deployment
Deployment.Builder.create(this, String.format("Deployment%s", deploymentRevision))
        .api(restApi)
        .build();
csharp
var restApi = new RestApi(this, "my-api", new RestApiProps {
    Deploy = false
});

var deploymentRevision = 5; // Bump this counter to trigger a new deployment
 // Bump this counter to trigger a new deployment
new Deployment(this, $"Deployment{deploymentRevision}", new DeploymentProps {
    Api = restApi
});
go
restApi := apigateway.NewRestApi(this, jsii.String("my-api"), &RestApiProps{
	Deploy: jsii.Boolean(false),
})

deploymentRevision := 5 // Bump this counter to trigger a new deployment
 // Bump this counter to trigger a new deployment
apigateway.NewDeployment(this, fmt.Sprintf("Deployment%v", deploymentRevision), &DeploymentProps{
	Api: restApi,
})

Deep dive: Invalidation of deployments ​

API Gateway deployments are an immutable snapshot of the API. This means that we want to automatically create a new deployment resource every time the API model defined in our CDK app changes.

In order to achieve that, the AWS CloudFormation logical ID of the AWS::ApiGateway::Deployment resource is dynamically calculated by hashing the API configuration (resources, methods). This means that when the configuration changes (i.e. a resource or method are added, configuration is changed), a new logical ID will be assigned to the deployment resource. This will cause CloudFormation to create a new deployment resource.

By default, old deployments are deleted. You can set retainDeployments: true to allow users revert the stage to an old deployment manually.

In order to also create a new deployment when changes are made to any authorizer attached to the API, the @aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId feature flag can be enabled. This can be set in the cdk.json file.

json
{
  "context": {
    "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true
  }
}

Custom Domains ​

To associate an API with a custom domain, use the domainName configuration when you define your API:

ts
declare const acmCertificateForExampleCom: any;

const api = new apigateway.RestApi(this, 'MyDomain', {
  domainName: {
    domainName: 'example.com',
    certificate: acmCertificateForExampleCom,
  },
});
python
# acm_certificate_for_example_com: Any


api = apigateway.RestApi(self, "MyDomain",
    domain_name=apigateway.DomainNameOptions(
        domain_name="example.com",
        certificate=acm_certificate_for_example_com
    )
)
java
Object acmCertificateForExampleCom;


RestApi api = RestApi.Builder.create(this, "MyDomain")
        .domainName(DomainNameOptions.builder()
                .domainName("example.com")
                .certificate(acmCertificateForExampleCom)
                .build())
        .build();
csharp
var acmCertificateForExampleCom;


var api = new RestApi(this, "MyDomain", new RestApiProps {
    DomainName = new DomainNameOptions {
        DomainName = "example.com",
        Certificate = acmCertificateForExampleCom
    }
});
go
var acmCertificateForExampleCom interface{}


api := apigateway.NewRestApi(this, jsii.String("MyDomain"), &RestApiProps{
	DomainName: &DomainNameOptions{
		DomainName: jsii.String("example.com"),
		Certificate: acmCertificateForExampleCom,
	},
})

This will define a DomainName resource for you, along with a BasePathMapping from the root of the domain to the deployment stage of the API. This is a common set up.

To route domain traffic to an API Gateway API, use Amazon Route 53 to create an alias record. An alias record is a Route 53 extension to DNS. It's similar to a CNAME record, but you can create an alias record both for the root domain, such as example.com, and for subdomains, such as www.example.com. (You can create CNAME records only for subdomains.)

ts
import * as route53 from 'aws-cdk-lib/aws-route53';
import * as targets from 'aws-cdk-lib/aws-route53-targets';

declare const api: apigateway.RestApi;
declare const hostedZoneForExampleCom: any;

new route53.ARecord(this, 'CustomDomainAliasRecord', {
  zone: hostedZoneForExampleCom,
  target: route53.RecordTarget.fromAlias(new targets.ApiGateway(api))
});
python
import aws_cdk.aws_route53 as route53
import aws_cdk.aws_route53_targets as targets

# api: apigateway.RestApi
# hosted_zone_for_example_com: Any


route53.ARecord(self, "CustomDomainAliasRecord",
    zone=hosted_zone_for_example_com,
    target=route53.RecordTarget.from_alias(targets.ApiGateway(api))
)
java
import software.amazon.awscdk.services.route53.*;
import software.amazon.awscdk.services.route53.targets.*;

RestApi api;
Object hostedZoneForExampleCom;


ARecord.Builder.create(this, "CustomDomainAliasRecord")
        .zone(hostedZoneForExampleCom)
        .target(RecordTarget.fromAlias(new ApiGateway(api)))
        .build();
csharp
using Amazon.CDK.AWS.Route53;
using Amazon.CDK.AWS.Route53.Targets;

RestApi api;
var hostedZoneForExampleCom;


new ARecord(this, "CustomDomainAliasRecord", new ARecordProps {
    Zone = hostedZoneForExampleCom,
    Target = RecordTarget.FromAlias(new ApiGateway(api))
});
go
import "github.com/aws/aws-cdk-go/awscdk"
import targets "github.com/aws/aws-cdk-go/awscdk"

var api RestApi
var hostedZoneForExampleCom interface{}


route53.NewARecord(this, jsii.String("CustomDomainAliasRecord"), &ARecordProps{
	Zone: hostedZoneForExampleCom,
	Target: route53.RecordTarget_FromAlias(targets.NewApiGateway(api)),
})

You can also define a DomainName resource directly in order to customize the default behavior:

ts
declare const acmCertificateForExampleCom: any;

new apigateway.DomainName(this, 'custom-domain', {
  domainName: 'example.com',
  certificate: acmCertificateForExampleCom,
  endpointType: apigateway.EndpointType.EDGE, // default is REGIONAL
  securityPolicy: apigateway.SecurityPolicy.TLS_1_2
});
python
# acm_certificate_for_example_com: Any


apigateway.DomainName(self, "custom-domain",
    domain_name="example.com",
    certificate=acm_certificate_for_example_com,
    endpoint_type=apigateway.EndpointType.EDGE,  # default is REGIONAL
    security_policy=apigateway.SecurityPolicy.TLS_1_2
)
java
Object acmCertificateForExampleCom;


DomainName.Builder.create(this, "custom-domain")
        .domainName("example.com")
        .certificate(acmCertificateForExampleCom)
        .endpointType(EndpointType.EDGE) // default is REGIONAL
        .securityPolicy(SecurityPolicy.TLS_1_2)
        .build();
csharp
var acmCertificateForExampleCom;


new DomainName(this, "custom-domain", new DomainNameProps {
    DomainName = "example.com",
    Certificate = acmCertificateForExampleCom,
    EndpointType = EndpointType.EDGE,  // default is REGIONAL
    SecurityPolicy = SecurityPolicy.TLS_1_2
});
go
var acmCertificateForExampleCom interface{}


apigateway.NewDomainName(this, jsii.String("custom-domain"), &DomainNameProps{
	DomainName: jsii.String("example.com"),
	Certificate: acmCertificateForExampleCom,
	EndpointType: apigateway.EndpointType_EDGE,
	 // default is REGIONAL
	SecurityPolicy: apigateway.SecurityPolicy_TLS_1_2,
})

API Gateway supports both legacy security policies (TLS 1.0, TLS 1.2) and enhanced security policies. Enhanced security policies (those starting with SecurityPolicy_) support TLS 1.3 and provide additional options such as post-quantum cryptography. Use enhanced security policies for regulated workloads, advanced governance, or to use post-quantum cryptography. For more details, see the AWS documentation.

When using enhanced security policies, you must specify endpointAccessMode. STRICT is recommended for production workloads, but BASIC may be needed during migration or for certain application architectures:

ts
declare const acmCertificateForExampleCom: any;

// For regional or private APIs with enhanced security policy
new apigateway.DomainName(this, 'custom-domain-tls13', {
  domainName: 'example.com',
  certificate: acmCertificateForExampleCom,
  securityPolicy: apigateway.SecurityPolicy.TLS13_1_3_2025_09, // TLS 1.3
  endpointAccessMode: apigateway.EndpointAccessMode.STRICT, // Recommended for production
});

// For edge-optimized APIs with enhanced security policy
new apigateway.DomainName(this, 'custom-domain-edge-tls13', {
  domainName: 'example.com',
  certificate: acmCertificateForExampleCom,
  endpointType: apigateway.EndpointType.EDGE,
  securityPolicy: apigateway.SecurityPolicy.TLS13_2025_EDGE, // Enhanced security policy for edge
  endpointAccessMode: apigateway.EndpointAccessMode.STRICT, // Recommended for production
});
python
# acm_certificate_for_example_com: Any


# For regional or private APIs with enhanced security policy
apigateway.DomainName(self, "custom-domain-tls13",
    domain_name="example.com",
    certificate=acm_certificate_for_example_com,
    security_policy=apigateway.SecurityPolicy.TLS13_1_3_2025_09,  # TLS 1.3
    endpoint_access_mode=apigateway.EndpointAccessMode.STRICT
)

# For edge-optimized APIs with enhanced security policy
apigateway.DomainName(self, "custom-domain-edge-tls13",
    domain_name="example.com",
    certificate=acm_certificate_for_example_com,
    endpoint_type=apigateway.EndpointType.EDGE,
    security_policy=apigateway.SecurityPolicy.TLS13_2025_EDGE,  # Enhanced security policy for edge
    endpoint_access_mode=apigateway.EndpointAccessMode.STRICT
)
java
Object acmCertificateForExampleCom;


// For regional or private APIs with enhanced security policy
// For regional or private APIs with enhanced security policy
DomainName.Builder.create(this, "custom-domain-tls13")
        .domainName("example.com")
        .certificate(acmCertificateForExampleCom)
        .securityPolicy(SecurityPolicy.TLS13_1_3_2025_09) // TLS 1.3
        .endpointAccessMode(EndpointAccessMode.STRICT)
        .build();

// For edge-optimized APIs with enhanced security policy
// For edge-optimized APIs with enhanced security policy
DomainName.Builder.create(this, "custom-domain-edge-tls13")
        .domainName("example.com")
        .certificate(acmCertificateForExampleCom)
        .endpointType(EndpointType.EDGE)
        .securityPolicy(SecurityPolicy.TLS13_2025_EDGE) // Enhanced security policy for edge
        .endpointAccessMode(EndpointAccessMode.STRICT)
        .build();
csharp
var acmCertificateForExampleCom;


// For regional or private APIs with enhanced security policy
// For regional or private APIs with enhanced security policy
new DomainName(this, "custom-domain-tls13", new DomainNameProps {
    DomainName = "example.com",
    Certificate = acmCertificateForExampleCom,
    SecurityPolicy = SecurityPolicy.TLS13_1_3_2025_09,  // TLS 1.3
    EndpointAccessMode = EndpointAccessMode.STRICT
});

// For edge-optimized APIs with enhanced security policy
// For edge-optimized APIs with enhanced security policy
new DomainName(this, "custom-domain-edge-tls13", new DomainNameProps {
    DomainName = "example.com",
    Certificate = acmCertificateForExampleCom,
    EndpointType = EndpointType.EDGE,
    SecurityPolicy = SecurityPolicy.TLS13_2025_EDGE,  // Enhanced security policy for edge
    EndpointAccessMode = EndpointAccessMode.STRICT
});
go
var acmCertificateForExampleCom interface{}


// For regional or private APIs with enhanced security policy
// For regional or private APIs with enhanced security policy
apigateway.NewDomainName(this, jsii.String("custom-domain-tls13"), &DomainNameProps{
	DomainName: jsii.String("example.com"),
	Certificate: acmCertificateForExampleCom,
	SecurityPolicy: apigateway.SecurityPolicy_TLS13_1_3_2025_09,
	 // TLS 1.3
	EndpointAccessMode: apigateway.EndpointAccessMode_STRICT,
})

// For edge-optimized APIs with enhanced security policy
// For edge-optimized APIs with enhanced security policy
apigateway.NewDomainName(this, jsii.String("custom-domain-edge-tls13"), &DomainNameProps{
	DomainName: jsii.String("example.com"),
	Certificate: acmCertificateForExampleCom,
	EndpointType: apigateway.EndpointType_EDGE,
	SecurityPolicy: apigateway.SecurityPolicy_TLS13_2025_EDGE,
	 // Enhanced security policy for edge
	EndpointAccessMode: apigateway.EndpointAccessMode_STRICT,
})

Note: Mutual TLS (mTLS) cannot be enabled on a domain name that uses an enhanced security policy.

Once you have a domain, you can map base paths of the domain to APIs. The following example will map the URL <https://example.com/go-to-api1> to the api1 API and <https://example.com/boom> to the api2 API.

ts
declare const domain: apigateway.DomainName;
declare const api1: apigateway.RestApi;
declare const api2: apigateway.RestApi;

domain.addBasePathMapping(api1, { basePath: 'go-to-api1' });
domain.addBasePathMapping(api2, { basePath: 'boom' });
python
# domain: apigateway.DomainName
# api1: apigateway.RestApi
# api2: apigateway.RestApi


domain.add_base_path_mapping(api1, base_path="go-to-api1")
domain.add_base_path_mapping(api2, base_path="boom")
java
DomainName domain;
RestApi api1;
RestApi api2;


domain.addBasePathMapping(api1, BasePathMappingOptions.builder().basePath("go-to-api1").build());
domain.addBasePathMapping(api2, BasePathMappingOptions.builder().basePath("boom").build());
csharp
DomainName domain;
RestApi api1;
RestApi api2;


domain.AddBasePathMapping(api1, new BasePathMappingOptions { BasePath = "go-to-api1" });
domain.AddBasePathMapping(api2, new BasePathMappingOptions { BasePath = "boom" });
go
var domain DomainName
var api1 RestApi
var api2 RestApi


domain.AddBasePathMapping(api1, &BasePathMappingOptions{
	BasePath: jsii.String("go-to-api1"),
})
domain.AddBasePathMapping(api2, &BasePathMappingOptions{
	BasePath: jsii.String("boom"),
})

By default, the base path URL will map to the deploymentStage of the RestApi. You can specify a different API Stage to which the base path URL will map to.

ts
declare const domain: apigateway.DomainName;
declare const restapi: apigateway.RestApi;

const betaDeploy = new apigateway.Deployment(this, 'beta-deployment', {
  api: restapi,
});
const betaStage = new apigateway.Stage(this, 'beta-stage', {
  deployment: betaDeploy,
});
domain.addBasePathMapping(restapi, { basePath: 'api/beta', stage: betaStage });
python
# domain: apigateway.DomainName
# restapi: apigateway.RestApi


beta_deploy = apigateway.Deployment(self, "beta-deployment",
    api=restapi
)
beta_stage = apigateway.Stage(self, "beta-stage",
    deployment=beta_deploy
)
domain.add_base_path_mapping(restapi, base_path="api/beta", stage=beta_stage)
java
DomainName domain;
RestApi restapi;


Deployment betaDeploy = Deployment.Builder.create(this, "beta-deployment")
        .api(restapi)
        .build();
Stage betaStage = Stage.Builder.create(this, "beta-stage")
        .deployment(betaDeploy)
        .build();
domain.addBasePathMapping(restapi, BasePathMappingOptions.builder().basePath("api/beta").stage(betaStage).build());
csharp
DomainName domain;
RestApi restapi;


var betaDeploy = new Deployment(this, "beta-deployment", new DeploymentProps {
    Api = restapi
});
var betaStage = new Stage(this, "beta-stage", new StageProps {
    Deployment = betaDeploy
});
domain.AddBasePathMapping(restapi, new BasePathMappingOptions { BasePath = "api/beta", Stage = betaStage });
go
var domain DomainName
var restapi RestApi


betaDeploy := apigateway.NewDeployment(this, jsii.String("beta-deployment"), &DeploymentProps{
	Api: restapi,
})
betaStage := apigateway.NewStage(this, jsii.String("beta-stage"), &StageProps{
	Deployment: betaDeploy,
})
domain.AddBasePathMapping(restapi, &BasePathMappingOptions{
	BasePath: jsii.String("api/beta"),
	Stage: betaStage,
})

It is possible to create a base path mapping without associating it with a stage by using the attachToStage property. When set to false, the stage must be included in the URL when invoking the API. For example, <https://example.com/myapi/prod> will invoke the stage named prod from the myapi base path mapping.

ts
declare const domain: apigateway.DomainName;
declare const api: apigateway.RestApi;

domain.addBasePathMapping(api, { basePath: 'myapi', attachToStage: false });
python
# domain: apigateway.DomainName
# api: apigateway.RestApi


domain.add_base_path_mapping(api, base_path="myapi", attach_to_stage=False)
java
DomainName domain;
RestApi api;


domain.addBasePathMapping(api, BasePathMappingOptions.builder().basePath("myapi").attachToStage(false).build());
csharp
DomainName domain;
RestApi api;


domain.AddBasePathMapping(api, new BasePathMappingOptions { BasePath = "myapi", AttachToStage = false });
go
var domain DomainName
var api RestApi


domain.AddBasePathMapping(api, &BasePathMappingOptions{
	BasePath: jsii.String("myapi"),
	AttachToStage: jsii.Boolean(false),
})

If you don't specify basePath, all URLs under this domain will be mapped to the API, and you won't be able to map another API to the same domain:

ts
declare const domain: apigateway.DomainName;
declare const api: apigateway.RestApi;
domain.addBasePathMapping(api);
python
# domain: apigateway.DomainName
# api: apigateway.RestApi

domain.add_base_path_mapping(api)
java
DomainName domain;
RestApi api;

domain.addBasePathMapping(api);
csharp
DomainName domain;
RestApi api;

domain.AddBasePathMapping(api);
go
var domain DomainName
var api RestApi

domain.AddBasePathMapping(api)

This can also be achieved through the mapping configuration when defining the domain as demonstrated above.

Base path mappings can also be created with the BasePathMapping resource.

ts
declare const api: apigateway.RestApi;

const domainName = apigateway.DomainName.fromDomainNameAttributes(this, 'DomainName', {
  domainName: 'domainName',
  domainNameAliasHostedZoneId: 'domainNameAliasHostedZoneId',
  domainNameAliasTarget: 'domainNameAliasTarget',
});

new apigateway.BasePathMapping(this, 'BasePathMapping', {
  domainName: domainName,
  restApi: api,
});
python
# api: apigateway.RestApi


domain_name = apigateway.DomainName.from_domain_name_attributes(self, "DomainName",
    domain_name="domainName",
    domain_name_alias_hosted_zone_id="domainNameAliasHostedZoneId",
    domain_name_alias_target="domainNameAliasTarget"
)

apigateway.BasePathMapping(self, "BasePathMapping",
    domain_name=domain_name,
    rest_api=api
)
java
RestApi api;


IDomainName domainName = DomainName.fromDomainNameAttributes(this, "DomainName", DomainNameAttributes.builder()
        .domainName("domainName")
        .domainNameAliasHostedZoneId("domainNameAliasHostedZoneId")
        .domainNameAliasTarget("domainNameAliasTarget")
        .build());

BasePathMapping.Builder.create(this, "BasePathMapping")
        .domainName(domainName)
        .restApi(api)
        .build();
csharp
RestApi api;


var domainName = DomainName.FromDomainNameAttributes(this, "DomainName", new DomainNameAttributes {
    DomainName = "domainName",
    DomainNameAliasHostedZoneId = "domainNameAliasHostedZoneId",
    DomainNameAliasTarget = "domainNameAliasTarget"
});

new BasePathMapping(this, "BasePathMapping", new BasePathMappingProps {
    DomainName = domainName,
    RestApi = api
});
go
var api RestApi


domainName := apigateway.DomainName_FromDomainNameAttributes(this, jsii.String("DomainName"), &DomainNameAttributes{
	DomainName: jsii.String("domainName"),
	DomainNameAliasHostedZoneId: jsii.String("domainNameAliasHostedZoneId"),
	DomainNameAliasTarget: jsii.String("domainNameAliasTarget"),
})

apigateway.NewBasePathMapping(this, jsii.String("BasePathMapping"), &BasePathMappingProps{
	DomainName: domainName,
	RestApi: api,
})

If you wish to setup this domain with an Amazon Route53 alias, use the targets.ApiGatewayDomain:

ts
declare const hostedZoneForExampleCom: any;
declare const domainName: apigateway.DomainName;

import * as route53 from 'aws-cdk-lib/aws-route53';
import * as targets from 'aws-cdk-lib/aws-route53-targets';

new route53.ARecord(this, 'CustomDomainAliasRecord', {
  zone: hostedZoneForExampleCom,
  target: route53.RecordTarget.fromAlias(new targets.ApiGatewayDomain(domainName))
});
python
# hosted_zone_for_example_com: Any
# domain_name: apigateway.DomainName

import aws_cdk.aws_route53 as route53
import aws_cdk.aws_route53_targets as targets


route53.ARecord(self, "CustomDomainAliasRecord",
    zone=hosted_zone_for_example_com,
    target=route53.RecordTarget.from_alias(targets.ApiGatewayDomain(domain_name))
)
java
Object hostedZoneForExampleCom;
DomainName domainName;

import software.amazon.awscdk.services.route53.*;
import software.amazon.awscdk.services.route53.targets.*;


ARecord.Builder.create(this, "CustomDomainAliasRecord")
        .zone(hostedZoneForExampleCom)
        .target(RecordTarget.fromAlias(new ApiGatewayDomain(domainName)))
        .build();
csharp
var hostedZoneForExampleCom;
DomainName domainName;

using Amazon.CDK.AWS.Route53;
using Amazon.CDK.AWS.Route53.Targets;


new ARecord(this, "CustomDomainAliasRecord", new ARecordProps {
    Zone = hostedZoneForExampleCom,
    Target = RecordTarget.FromAlias(new ApiGatewayDomain(domainName))
});
go
var hostedZoneForExampleCom interface{}
var domainName DomainName

import "github.com/aws/aws-cdk-go/awscdk"
import targets "github.com/aws/aws-cdk-go/awscdk"


route53.NewARecord(this, jsii.String("CustomDomainAliasRecord"), &ARecordProps{
	Zone: hostedZoneForExampleCom,
	Target: route53.RecordTarget_FromAlias(targets.NewApiGatewayDomain(domainName)),
})

Custom Domains with multi-level api mapping ​

Additional requirements for creating multi-level path mappings for RestApis:

(both are defaults)

  • Must use SecurityPolicy.TLS_1_2 or higher (TLS 1.0 is not supported for multi-level paths)
  • DomainNames must be EndpointType.REGIONAL
ts
declare const acmCertificateForExampleCom: any;
declare const restApi: apigateway.RestApi;

new apigateway.DomainName(this, 'custom-domain', {
  domainName: 'example.com',
  certificate: acmCertificateForExampleCom,
  mapping: restApi,
  basePath: 'orders/v1/api',
});
python
# acm_certificate_for_example_com: Any
# rest_api: apigateway.RestApi


apigateway.DomainName(self, "custom-domain",
    domain_name="example.com",
    certificate=acm_certificate_for_example_com,
    mapping=rest_api,
    base_path="orders/v1/api"
)
java
Object acmCertificateForExampleCom;
RestApi restApi;


DomainName.Builder.create(this, "custom-domain")
        .domainName("example.com")
        .certificate(acmCertificateForExampleCom)
        .mapping(restApi)
        .basePath("orders/v1/api")
        .build();
csharp
var acmCertificateForExampleCom;
RestApi restApi;


new DomainName(this, "custom-domain", new DomainNameProps {
    DomainName = "example.com",
    Certificate = acmCertificateForExampleCom,
    Mapping = restApi,
    BasePath = "orders/v1/api"
});
go
var acmCertificateForExampleCom interface{}
var restApi RestApi


apigateway.NewDomainName(this, jsii.String("custom-domain"), &DomainNameProps{
	DomainName: jsii.String("example.com"),
	Certificate: acmCertificateForExampleCom,
	Mapping: restApi,
	BasePath: jsii.String("orders/v1/api"),
})

To then add additional mappings to a domain you can use the addApiMapping method.

ts
declare const acmCertificateForExampleCom: any;
declare const restApi: apigateway.RestApi;
declare const secondRestApi: apigateway.RestApi;

const domain = new apigateway.DomainName(this, 'custom-domain', {
  domainName: 'example.com',
  certificate: acmCertificateForExampleCom,
  mapping: restApi,
});

domain.addApiMapping(secondRestApi.deploymentStage, {
  basePath: 'orders/v2/api',
});
python
# acm_certificate_for_example_com: Any
# rest_api: apigateway.RestApi
# second_rest_api: apigateway.RestApi


domain = apigateway.DomainName(self, "custom-domain",
    domain_name="example.com",
    certificate=acm_certificate_for_example_com,
    mapping=rest_api
)

domain.add_api_mapping(second_rest_api.deployment_stage,
    base_path="orders/v2/api"
)
java
Object acmCertificateForExampleCom;
RestApi restApi;
RestApi secondRestApi;


DomainName domain = DomainName.Builder.create(this, "custom-domain")
        .domainName("example.com")
        .certificate(acmCertificateForExampleCom)
        .mapping(restApi)
        .build();

domain.addApiMapping(secondRestApi.getDeploymentStage(), ApiMappingOptions.builder()
        .basePath("orders/v2/api")
        .build());
csharp
var acmCertificateForExampleCom;
RestApi restApi;
RestApi secondRestApi;


var domain = new DomainName(this, "custom-domain", new DomainNameProps {
    DomainName = "example.com",
    Certificate = acmCertificateForExampleCom,
    Mapping = restApi
});

domain.AddApiMapping(secondRestApi.DeploymentStage, new ApiMappingOptions {
    BasePath = "orders/v2/api"
});
go
var acmCertificateForExampleCom interface{}
var restApi RestApi
var secondRestApi RestApi


domain := apigateway.NewDomainName(this, jsii.String("custom-domain"), &DomainNameProps{
	DomainName: jsii.String("example.com"),
	Certificate: acmCertificateForExampleCom,
	Mapping: restApi,
})

domain.AddApiMapping(secondRestApi.DeploymentStage, &ApiMappingOptions{
	BasePath: jsii.String("orders/v2/api"),
})

Access Logging ​

Access logging creates logs every time an API method is accessed. Access logs can have information on who has accessed the API, how the caller accessed the API and what responses were generated. Access logs are configured on a Stage of the RestApi. Access logs can be expressed in a format of your choosing, and can contain any access details, with a minimum that it must include either 'requestId' or 'extendedRequestId'. The list of variables that can be expressed in the access log can be found here. Read more at Setting Up CloudWatch API Logging in API Gateway

ts
// production stage
const prodLogGroup = new logs.LogGroup(this, "PrdLogs");
const api = new apigateway.RestApi(this, 'books', {
  deployOptions: {
    accessLogDestination: new apigateway.LogGroupLogDestination(prodLogGroup),
    accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields(),
  },
});
const deployment = new apigateway.Deployment(this, 'Deployment', {api});

// development stage
const devLogGroup = new logs.LogGroup(this, "DevLogs");
new apigateway.Stage(this, 'dev', {
  deployment,
  accessLogDestination: new apigateway.LogGroupLogDestination(devLogGroup),
  accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields({
    caller: false,
    httpMethod: true,
    ip: true,
    protocol: true,
    requestTime: true,
    resourcePath: true,
    responseLength: true,
    status: true,
    user: true,
  }),
});
python
# production stage
prod_log_group = logs.LogGroup(self, "PrdLogs")
api = apigateway.RestApi(self, "books",
    deploy_options=apigateway.StageOptions(
        access_log_destination=apigateway.LogGroupLogDestination(prod_log_group),
        access_log_format=apigateway.AccessLogFormat.json_with_standard_fields()
    )
)
deployment = apigateway.Deployment(self, "Deployment", api=api)

# development stage
dev_log_group = logs.LogGroup(self, "DevLogs")
apigateway.Stage(self, "dev",
    deployment=deployment,
    access_log_destination=apigateway.LogGroupLogDestination(dev_log_group),
    access_log_format=apigateway.AccessLogFormat.json_with_standard_fields(
        caller=False,
        http_method=True,
        ip=True,
        protocol=True,
        request_time=True,
        resource_path=True,
        response_length=True,
        status=True,
        user=True
    )
)
java
// production stage
LogGroup prodLogGroup = new LogGroup(this, "PrdLogs");
RestApi api = RestApi.Builder.create(this, "books")
        .deployOptions(StageOptions.builder()
                .accessLogDestination(new LogGroupLogDestination(prodLogGroup))
                .accessLogFormat(AccessLogFormat.jsonWithStandardFields())
                .build())
        .build();
Deployment deployment = Deployment.Builder.create(this, "Deployment").api(api).build();

// development stage
LogGroup devLogGroup = new LogGroup(this, "DevLogs");
Stage.Builder.create(this, "dev")
        .deployment(deployment)
        .accessLogDestination(new LogGroupLogDestination(devLogGroup))
        .accessLogFormat(AccessLogFormat.jsonWithStandardFields(JsonWithStandardFieldProps.builder()
                .caller(false)
                .httpMethod(true)
                .ip(true)
                .protocol(true)
                .requestTime(true)
                .resourcePath(true)
                .responseLength(true)
                .status(true)
                .user(true)
                .build()))
        .build();
csharp
// production stage
var prodLogGroup = new LogGroup(this, "PrdLogs");
var api = new RestApi(this, "books", new RestApiProps {
    DeployOptions = new StageOptions {
        AccessLogDestination = new LogGroupLogDestination(prodLogGroup),
        AccessLogFormat = AccessLogFormat.JsonWithStandardFields()
    }
});
var deployment = new Deployment(this, "Deployment", new DeploymentProps { Api = api });

// development stage
var devLogGroup = new LogGroup(this, "DevLogs");
new Stage(this, "dev", new StageProps {
    Deployment = deployment,
    AccessLogDestination = new LogGroupLogDestination(devLogGroup),
    AccessLogFormat = AccessLogFormat.JsonWithStandardFields(new JsonWithStandardFieldProps {
        Caller = false,
        HttpMethod = true,
        Ip = true,
        Protocol = true,
        RequestTime = true,
        ResourcePath = true,
        ResponseLength = true,
        Status = true,
        User = true
    })
});
go
// production stage
prodLogGroup := logs.NewLogGroup(this, jsii.String("PrdLogs"))
api := apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	DeployOptions: &StageOptions{
		AccessLogDestination: apigateway.NewLogGroupLogDestination(prodLogGroup),
		AccessLogFormat: apigateway.AccessLogFormat_JsonWithStandardFields(),
	},
})
deployment := apigateway.NewDeployment(this, jsii.String("Deployment"), &DeploymentProps{
	Api: Api,
})

// development stage
devLogGroup := logs.NewLogGroup(this, jsii.String("DevLogs"))
apigateway.NewStage(this, jsii.String("dev"), &StageProps{
	Deployment: Deployment,
	AccessLogDestination: apigateway.NewLogGroupLogDestination(devLogGroup),
	AccessLogFormat: apigateway.AccessLogFormat_*JsonWithStandardFields(&JsonWithStandardFieldProps{
		Caller: jsii.Boolean(false),
		HttpMethod: jsii.Boolean(true),
		Ip: jsii.Boolean(true),
		Protocol: jsii.Boolean(true),
		RequestTime: jsii.Boolean(true),
		ResourcePath: jsii.Boolean(true),
		ResponseLength: jsii.Boolean(true),
		Status: jsii.Boolean(true),
		User: jsii.Boolean(true),
	}),
})

The following code will generate the access log in the CLF format.

ts
const logGroup = new logs.LogGroup(this, "ApiGatewayAccessLogs");
const api = new apigateway.RestApi(this, 'books', {
  deployOptions: {
    accessLogDestination: new apigateway.LogGroupLogDestination(logGroup),
    accessLogFormat: apigateway.AccessLogFormat.clf(),
  }});
python
log_group = logs.LogGroup(self, "ApiGatewayAccessLogs")
api = apigateway.RestApi(self, "books",
    deploy_options=apigateway.StageOptions(
        access_log_destination=apigateway.LogGroupLogDestination(log_group),
        access_log_format=apigateway.AccessLogFormat.clf()
    )
)
java
LogGroup logGroup = new LogGroup(this, "ApiGatewayAccessLogs");
RestApi api = RestApi.Builder.create(this, "books")
        .deployOptions(StageOptions.builder()
                .accessLogDestination(new LogGroupLogDestination(logGroup))
                .accessLogFormat(AccessLogFormat.clf())
                .build())
        .build();
csharp
var logGroup = new LogGroup(this, "ApiGatewayAccessLogs");
var api = new RestApi(this, "books", new RestApiProps {
    DeployOptions = new StageOptions {
        AccessLogDestination = new LogGroupLogDestination(logGroup),
        AccessLogFormat = AccessLogFormat.Clf()
    }
});
go
logGroup := logs.NewLogGroup(this, jsii.String("ApiGatewayAccessLogs"))
api := apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	DeployOptions: &StageOptions{
		AccessLogDestination: apigateway.NewLogGroupLogDestination(logGroup),
		AccessLogFormat: apigateway.AccessLogFormat_Clf(),
	},
})

You can also configure your own access log format by using the AccessLogFormat.custom() API. AccessLogField provides commonly used fields. The following code configures access log to contain.

ts
const logGroup = new logs.LogGroup(this, "ApiGatewayAccessLogs");
new apigateway.RestApi(this, 'books', {
  deployOptions: {
    accessLogDestination: new apigateway.LogGroupLogDestination(logGroup),
    accessLogFormat: apigateway.AccessLogFormat.custom(
      `${apigateway.AccessLogField.contextRequestId()} ${apigateway.AccessLogField.contextErrorMessage()} ${apigateway.AccessLogField.contextErrorMessageString()}
      ${apigateway.AccessLogField.contextAuthorizerError()} ${apigateway.AccessLogField.contextAuthorizerIntegrationStatus()}`
    )
  }
});
python
log_group = logs.LogGroup(self, "ApiGatewayAccessLogs")
apigateway.RestApi(self, "books",
    deploy_options=apigateway.StageOptions(
        access_log_destination=apigateway.LogGroupLogDestination(log_group),
        access_log_format=apigateway.AccessLogFormat.custom(f"""{apigateway.AccessLogField.contextRequestId()} {apigateway.AccessLogField.contextErrorMessage()} {apigateway.AccessLogField.contextErrorMessageString()}
                  {apigateway.AccessLogField.contextAuthorizerError()} {apigateway.AccessLogField.contextAuthorizerIntegrationStatus()}""")
    )
)
java
LogGroup logGroup = new LogGroup(this, "ApiGatewayAccessLogs");
RestApi.Builder.create(this, "books")
        .deployOptions(StageOptions.builder()
                .accessLogDestination(new LogGroupLogDestination(logGroup))
                .accessLogFormat(AccessLogFormat.custom(String.format("%s %s %s%n      %s %s", AccessLogField.contextRequestId(), AccessLogField.contextErrorMessage(), AccessLogField.contextErrorMessageString(), AccessLogField.contextAuthorizerError(), AccessLogField.contextAuthorizerIntegrationStatus())))
                .build())
        .build();
csharp
var logGroup = new LogGroup(this, "ApiGatewayAccessLogs");
new RestApi(this, "books", new RestApiProps {
    DeployOptions = new StageOptions {
        AccessLogDestination = new LogGroupLogDestination(logGroup),
        AccessLogFormat = AccessLogFormat.Custom($@"{apigateway.AccessLogField.contextRequestId()} {apigateway.AccessLogField.contextErrorMessage()} {apigateway.AccessLogField.contextErrorMessageString()}
              {apigateway.AccessLogField.contextAuthorizerError()} {apigateway.AccessLogField.contextAuthorizerIntegrationStatus()}")
    }
});
go
logGroup := logs.NewLogGroup(this, jsii.String("ApiGatewayAccessLogs"))
apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	DeployOptions: &StageOptions{
		AccessLogDestination: apigateway.NewLogGroupLogDestination(logGroup),
		AccessLogFormat: apigateway.AccessLogFormat_Custom(
		fmt.Sprintf("%v %v %v\n      %v %v", apigateway.AccessLogField_ContextRequestId(), apigateway.AccessLogField_ContextErrorMessage(), apigateway.AccessLogField_ContextErrorMessageString(), apigateway.AccessLogField_ContextAuthorizerError(), apigateway.AccessLogField_ContextAuthorizerIntegrationStatus())),
	},
})

You can use the methodOptions property to configure default method throttling for a stage. The following snippet configures the a stage that accepts 100 requests per minute, allowing burst up to 200 requests per minute.

ts
const api = new apigateway.RestApi(this, 'books');
const deployment = new apigateway.Deployment(this, 'my-deployment', { api });
const stage = new apigateway.Stage(this, 'my-stage', {
  deployment,
  methodOptions: {
    '/*/*': {  // This special path applies to all resource paths and all HTTP methods
      throttlingRateLimit: 100,
      throttlingBurstLimit: 200
    }
  }
});
python
api = apigateway.RestApi(self, "books")
deployment = apigateway.Deployment(self, "my-deployment", api=api)
stage = apigateway.Stage(self, "my-stage",
    deployment=deployment,
    method_options={
        "/*/*": apigateway.MethodDeploymentOptions( # This special path applies to all resource paths and all HTTP methods
            throttling_rate_limit=100,
            throttling_burst_limit=200)
    }
)
java
RestApi api = new RestApi(this, "books");
Deployment deployment = Deployment.Builder.create(this, "my-deployment").api(api).build();
Stage stage = Stage.Builder.create(this, "my-stage")
        .deployment(deployment)
        .methodOptions(Map.of(
                "/*/*", MethodDeploymentOptions.builder() // This special path applies to all resource paths and all HTTP methods
                        .throttlingRateLimit(100)
                        .throttlingBurstLimit(200).build()))
        .build();
csharp
var api = new RestApi(this, "books");
var deployment = new Deployment(this, "my-deployment", new DeploymentProps { Api = api });
var stage = new Stage(this, "my-stage", new StageProps {
    Deployment = deployment,
    MethodOptions = new Dictionary<string, MethodDeploymentOptions> {
        { "/*/*", new MethodDeploymentOptions {  // This special path applies to all resource paths and all HTTP methods
            ThrottlingRateLimit = 100,
            ThrottlingBurstLimit = 200 } }
    }
});
go
api := apigateway.NewRestApi(this, jsii.String("books"))
deployment := apigateway.NewDeployment(this, jsii.String("my-deployment"), &DeploymentProps{
	Api: Api,
})
stage := apigateway.NewStage(this, jsii.String("my-stage"), &StageProps{
	Deployment: Deployment,
	MethodOptions: map[string]MethodDeploymentOptions{
		"/*/*": &MethodDeploymentOptions{
			 // This special path applies to all resource paths and all HTTP methods
			"throttlingRateLimit": jsii.Number(100),
			"throttlingBurstLimit": jsii.Number(200),
		},
	},
})

Configuring methodOptions on the deployOptions of RestApi will set the throttling behaviors on the default stage that is automatically created.

ts
const api = new apigateway.RestApi(this, 'books', {
  deployOptions: {
    methodOptions: {
      '/*/*': {  // This special path applies to all resource paths and all HTTP methods
        throttlingRateLimit: 100,
        throttlingBurstLimit: 1000
      }
    }
  }
});
python
api = apigateway.RestApi(self, "books",
    deploy_options=apigateway.StageOptions(
        method_options={
            "/*/*": apigateway.MethodDeploymentOptions( # This special path applies to all resource paths and all HTTP methods
                throttling_rate_limit=100,
                throttling_burst_limit=1000)
        }
    )
)
java
RestApi api = RestApi.Builder.create(this, "books")
        .deployOptions(StageOptions.builder()
                .methodOptions(Map.of(
                        "/*/*", MethodDeploymentOptions.builder() // This special path applies to all resource paths and all HTTP methods
                                .throttlingRateLimit(100)
                                .throttlingBurstLimit(1000).build()))
                .build())
        .build();
csharp
var api = new RestApi(this, "books", new RestApiProps {
    DeployOptions = new StageOptions {
        MethodOptions = new Dictionary<string, MethodDeploymentOptions> {
            { "/*/*", new MethodDeploymentOptions {  // This special path applies to all resource paths and all HTTP methods
                ThrottlingRateLimit = 100,
                ThrottlingBurstLimit = 1000 } }
        }
    }
});
go
api := apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	DeployOptions: &StageOptions{
		MethodOptions: map[string]MethodDeploymentOptions{
			"/*/*": &MethodDeploymentOptions{
				 // This special path applies to all resource paths and all HTTP methods
				"throttlingRateLimit": jsii.Number(100),
				"throttlingBurstLimit": jsii.Number(1000),
			},
		},
	},
})

To write access log files to a Firehose delivery stream destination use the FirehoseLogDestination class:

ts
const destinationBucket = new s3.Bucket(this, 'Bucket');
const deliveryStreamRole = new iam.Role(this, 'Role', {
  assumedBy: new iam.ServicePrincipal('firehose.amazonaws.com'),
});

const stream = new firehose.CfnDeliveryStream(this, 'MyStream', {
  deliveryStreamName: 'amazon-apigateway-delivery-stream',
  s3DestinationConfiguration: {
    bucketArn: destinationBucket.bucketArn,
    roleArn: deliveryStreamRole.roleArn,
  },
});

const api = new apigateway.RestApi(this, 'books', {
  deployOptions: {
    accessLogDestination: new apigateway.FirehoseLogDestination(stream),
    accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields(),
  },
});
python
destination_bucket = s3.Bucket(self, "Bucket")
delivery_stream_role = iam.Role(self, "Role",
    assumed_by=iam.ServicePrincipal("firehose.amazonaws.com")
)

stream = firehose.CfnDeliveryStream(self, "MyStream",
    delivery_stream_name="amazon-apigateway-delivery-stream",
    s3_destination_configuration=firehose.CfnDeliveryStream.S3DestinationConfigurationProperty(
        bucket_arn=destination_bucket.bucket_arn,
        role_arn=delivery_stream_role.role_arn
    )
)

api = apigateway.RestApi(self, "books",
    deploy_options=apigateway.StageOptions(
        access_log_destination=apigateway.FirehoseLogDestination(stream),
        access_log_format=apigateway.AccessLogFormat.json_with_standard_fields()
    )
)
java
Bucket destinationBucket = new Bucket(this, "Bucket");
Role deliveryStreamRole = Role.Builder.create(this, "Role")
        .assumedBy(new ServicePrincipal("firehose.amazonaws.com"))
        .build();

CfnDeliveryStream stream = CfnDeliveryStream.Builder.create(this, "MyStream")
        .deliveryStreamName("amazon-apigateway-delivery-stream")
        .s3DestinationConfiguration(S3DestinationConfigurationProperty.builder()
                .bucketArn(destinationBucket.getBucketArn())
                .roleArn(deliveryStreamRole.getRoleArn())
                .build())
        .build();

RestApi api = RestApi.Builder.create(this, "books")
        .deployOptions(StageOptions.builder()
                .accessLogDestination(new FirehoseLogDestination(stream))
                .accessLogFormat(AccessLogFormat.jsonWithStandardFields())
                .build())
        .build();
csharp
var destinationBucket = new Bucket(this, "Bucket");
var deliveryStreamRole = new Role(this, "Role", new RoleProps {
    AssumedBy = new ServicePrincipal("firehose.amazonaws.com")
});

var stream = new CfnDeliveryStream(this, "MyStream", new CfnDeliveryStreamProps {
    DeliveryStreamName = "amazon-apigateway-delivery-stream",
    S3DestinationConfiguration = new S3DestinationConfigurationProperty {
        BucketArn = destinationBucket.BucketArn,
        RoleArn = deliveryStreamRole.RoleArn
    }
});

var api = new RestApi(this, "books", new RestApiProps {
    DeployOptions = new StageOptions {
        AccessLogDestination = new FirehoseLogDestination(stream),
        AccessLogFormat = AccessLogFormat.JsonWithStandardFields()
    }
});
go
destinationBucket := s3.NewBucket(this, jsii.String("Bucket"))
deliveryStreamRole := iam.NewRole(this, jsii.String("Role"), &RoleProps{
	AssumedBy: iam.NewServicePrincipal(jsii.String("firehose.amazonaws.com")),
})

stream := firehose.NewCfnDeliveryStream(this, jsii.String("MyStream"), &CfnDeliveryStreamProps{
	DeliveryStreamName: jsii.String("amazon-apigateway-delivery-stream"),
	S3DestinationConfiguration: &S3DestinationConfigurationProperty{
		BucketArn: destinationBucket.bucketArn,
		RoleArn: deliveryStreamRole.roleArn,
	},
})

api := apigateway.NewRestApi(this, jsii.String("books"), &RestApiProps{
	DeployOptions: &StageOptions{
		AccessLogDestination: apigateway.NewFirehoseLogDestination(stream),
		AccessLogFormat: apigateway.AccessLogFormat_JsonWithStandardFields(),
	},
})

Note: The delivery stream name must start with amazon-apigateway-.

Visit Logging API calls to Amazon Data Firehose for more details.

Cross Origin Resource Sharing (CORS) ​

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own.

You can add the CORS preflight OPTIONS HTTP method to any API resource via the defaultCorsPreflightOptions option or by calling the addCorsPreflight on a specific resource.

The following example will enable CORS for all methods and all origins on all resources of the API:

ts
new apigateway.RestApi(this, 'api', {
  defaultCorsPreflightOptions: {
    allowOrigins: apigateway.Cors.ALL_ORIGINS,
    allowMethods: apigateway.Cors.ALL_METHODS // this is also the default
  }
})
python
apigateway.RestApi(self, "api",
    default_cors_preflight_options=apigateway.CorsOptions(
        allow_origins=apigateway.Cors.ALL_ORIGINS,
        allow_methods=apigateway.Cors.ALL_METHODS
    )
)
java
RestApi.Builder.create(this, "api")
        .defaultCorsPreflightOptions(CorsOptions.builder()
                .allowOrigins(Cors.ALL_ORIGINS)
                .allowMethods(Cors.ALL_METHODS)
                .build())
        .build();
csharp
new RestApi(this, "api", new RestApiProps {
    DefaultCorsPreflightOptions = new CorsOptions {
        AllowOrigins = Cors.ALL_ORIGINS,
        AllowMethods = Cors.ALL_METHODS
    }
});
go
apigateway.NewRestApi(this, jsii.String("api"), &RestApiProps{
	DefaultCorsPreflightOptions: &CorsOptions{
		AllowOrigins: apigateway.Cors_ALL_ORIGINS(),
		AllowMethods: apigateway.Cors_ALL_METHODS(),
	},
})

The following example will add an OPTIONS method to the myResource API resource, which only allows GET and PUT HTTP requests from the origin <https://amazon.com.>

ts
declare const myResource: apigateway.Resource;

myResource.addCorsPreflight({
  allowOrigins: [ 'https://amazon.com' ],
  allowMethods: [ 'GET', 'PUT' ]
});
python
# my_resource: apigateway.Resource


my_resource.add_cors_preflight(
    allow_origins=["https://amazon.com"],
    allow_methods=["GET", "PUT"]
)
java
Resource myResource;


myResource.addCorsPreflight(CorsOptions.builder()
        .allowOrigins(List.of("https://amazon.com"))
        .allowMethods(List.of("GET", "PUT"))
        .build());
csharp
Resource myResource;


myResource.AddCorsPreflight(new CorsOptions {
    AllowOrigins = new [] { "https://amazon.com" },
    AllowMethods = new [] { "GET", "PUT" }
});
go
var myResource Resource


myResource.AddCorsPreflight(&CorsOptions{
	AllowOrigins: []*string{
		jsii.String("https://amazon.com"),
	},
	AllowMethods: []*string{
		jsii.String("GET"),
		jsii.String("PUT"),
	},
})

See the CorsOptions API reference for a detailed list of supported configuration options.

You can specify defaults this at the resource level, in which case they will be applied to the entire resource sub-tree:

ts
declare const resource: apigateway.Resource;

const subtree = resource.addResource('subtree', {
  defaultCorsPreflightOptions: {
    allowOrigins: [ 'https://amazon.com' ]
  }
});
python
# resource: apigateway.Resource


subtree = resource.add_resource("subtree",
    default_cors_preflight_options=apigateway.CorsOptions(
        allow_origins=["https://amazon.com"]
    )
)
java
Resource resource;


Resource subtree = resource.addResource("subtree", ResourceOptions.builder()
        .defaultCorsPreflightOptions(CorsOptions.builder()
                .allowOrigins(List.of("https://amazon.com"))
                .build())
        .build());
csharp
Resource resource;


var subtree = resource.AddResource("subtree", new ResourceOptions {
    DefaultCorsPreflightOptions = new CorsOptions {
        AllowOrigins = new [] { "https://amazon.com" }
    }
});
go
var resource Resource


subtree := resource.AddResource(jsii.String("subtree"), &ResourceOptions{
	DefaultCorsPreflightOptions: &CorsOptions{
		AllowOrigins: []*string{
			jsii.String("https://amazon.com"),
		},
	},
})

This means that all resources under subtree (inclusive) will have a preflight OPTIONS added to them.

See #906 for a list of CORS features which are not yet supported.

Endpoint Configuration ​

API gateway allows you to specify an API Endpoint Type. To define an endpoint type for the API gateway, use endpointConfiguration property:

ts
const api = new apigateway.RestApi(this, 'api', {
  endpointConfiguration: {
    types: [ apigateway.EndpointType.EDGE ]
  }
});
python
api = apigateway.RestApi(self, "api",
    endpoint_configuration=apigateway.EndpointConfiguration(
        types=[apigateway.EndpointType.EDGE]
    )
)
java
RestApi api = RestApi.Builder.create(this, "api")
        .endpointConfiguration(EndpointConfiguration.builder()
                .types(List.of(EndpointType.EDGE))
                .build())
        .build();
csharp
var api = new RestApi(this, "api", new RestApiProps {
    EndpointConfiguration = new EndpointConfiguration {
        Types = new [] { EndpointType.EDGE }
    }
});
go
api := apigateway.NewRestApi(this, jsii.String("api"), &RestApiProps{
	EndpointConfiguration: &EndpointConfiguration{
		Types: []EndpointType{
			apigateway.EndpointType_EDGE,
		},
	},
})

You can also configure endpoint IP address type. The default value is IpAddressType.DUAL_STACK for private API, and IpAddressType.IPV4 for regional and edge-optimized API.

ts
const api = new apigateway.RestApi(this, 'api', {
  endpointConfiguration: {
    types: [ apigateway.EndpointType.REGIONAL ],
    ipAddressType: apigateway.IpAddressType.DUAL_STACK,
  }
});
python
api = apigateway.RestApi(self, "api",
    endpoint_configuration=apigateway.EndpointConfiguration(
        types=[apigateway.EndpointType.REGIONAL],
        ip_address_type=apigateway.IpAddressType.DUAL_STACK
    )
)
java
RestApi api = RestApi.Builder.create(this, "api")
        .endpointConfiguration(EndpointConfiguration.builder()
                .types(List.of(EndpointType.REGIONAL))
                .ipAddressType(IpAddressType.DUAL_STACK)
                .build())
        .build();
csharp
var api = new RestApi(this, "api", new RestApiProps {
    EndpointConfiguration = new EndpointConfiguration {
        Types = new [] { EndpointType.REGIONAL },
        IpAddressType = IpAddressType.DUAL_STACK
    }
});
go
api := apigateway.NewRestApi(this, jsii.String("api"), &RestApiProps{
	EndpointConfiguration: &EndpointConfiguration{
		Types: []EndpointType{
			apigateway.EndpointType_REGIONAL,
		},
		IpAddressType: apigateway.IpAddressType_DUAL_STACK,
	},
})

Note: If creating a private API, the IPV4 IP address type is not supported.

You can also create an association between your Rest API and a VPC endpoint. By doing so, API Gateway will generate a new Route53 Alias DNS record which you can use to invoke your private APIs. More info can be found here.

Here is an example:

ts
declare const someEndpoint: ec2.IVpcEndpoint;

const api = new apigateway.RestApi(this, 'api', {
  endpointConfiguration: {
    types: [ apigateway.EndpointType.PRIVATE ],
    vpcEndpoints: [ someEndpoint ]
  }
});
python
# some_endpoint: ec2.IVpcEndpoint


api = apigateway.RestApi(self, "api",
    endpoint_configuration=apigateway.EndpointConfiguration(
        types=[apigateway.EndpointType.PRIVATE],
        vpc_endpoints=[some_endpoint]
    )
)
java
IVpcEndpoint someEndpoint;


RestApi api = RestApi.Builder.create(this, "api")
        .endpointConfiguration(EndpointConfiguration.builder()
                .types(List.of(EndpointType.PRIVATE))
                .vpcEndpoints(List.of(someEndpoint))
                .build())
        .build();
csharp
IVpcEndpoint someEndpoint;


var api = new RestApi(this, "api", new RestApiProps {
    EndpointConfiguration = new EndpointConfiguration {
        Types = new [] { EndpointType.PRIVATE },
        VpcEndpoints = new [] { someEndpoint }
    }
});
go
var someEndpoint IVpcEndpoint


api := apigateway.NewRestApi(this, jsii.String("api"), &RestApiProps{
	EndpointConfiguration: &EndpointConfiguration{
		Types: []EndpointType{
			apigateway.EndpointType_PRIVATE,
		},
		VpcEndpoints: []IVpcEndpoint{
			someEndpoint,
		},
	},
})

By performing this association, we can invoke the API gateway using the following format:

plaintext
https://{rest-api-id}-{vpce-id}.execute-api.{region}.amazonaws.com/{stage}

To restrict access to the API Gateway to only the VPC endpoint, you can use the grantInvokeFromVpcEndpointsOnly method to add resource policies to the API Gateway:

ts
declare const apiGwVpcEndpoint: ec2.IVpcEndpoint;

const api = new apigateway.RestApi(this, 'PrivateApi', {
  endpointConfiguration: {
    types: [ apigateway.EndpointType.PRIVATE ],
    vpcEndpoints: [ apiGwVpcEndpoint ]
  }
});
api.grantInvokeFromVpcEndpointsOnly([apiGwVpcEndpoint]);
python
# api_gw_vpc_endpoint: ec2.IVpcEndpoint


api = apigateway.RestApi(self, "PrivateApi",
    endpoint_configuration=apigateway.EndpointConfiguration(
        types=[apigateway.EndpointType.PRIVATE],
        vpc_endpoints=[api_gw_vpc_endpoint]
    )
)
api.grant_invoke_from_vpc_endpoints_only([api_gw_vpc_endpoint])
java
IVpcEndpoint apiGwVpcEndpoint;


RestApi api = RestApi.Builder.create(this, "PrivateApi")
        .endpointConfiguration(EndpointConfiguration.builder()
                .types(List.of(EndpointType.PRIVATE))
                .vpcEndpoints(List.of(apiGwVpcEndpoint))
                .build())
        .build();
api.grantInvokeFromVpcEndpointsOnly(List.of(apiGwVpcEndpoint));
csharp
IVpcEndpoint apiGwVpcEndpoint;


var api = new RestApi(this, "PrivateApi", new RestApiProps {
    EndpointConfiguration = new EndpointConfiguration {
        Types = new [] { EndpointType.PRIVATE },
        VpcEndpoints = new [] { apiGwVpcEndpoint }
    }
});
api.GrantInvokeFromVpcEndpointsOnly(new [] { apiGwVpcEndpoint });
go
var apiGwVpcEndpoint IVpcEndpoint


api := apigateway.NewRestApi(this, jsii.String("PrivateApi"), &RestApiProps{
	EndpointConfiguration: &EndpointConfiguration{
		Types: []EndpointType{
			apigateway.EndpointType_PRIVATE,
		},
		VpcEndpoints: []IVpcEndpoint{
			apiGwVpcEndpoint,
		},
	},
})
api.GrantInvokeFromVpcEndpointsOnly([]IVpcEndpoint{
	apiGwVpcEndpoint,
})

Private Integrations ​

A private integration makes it simple to expose HTTP/HTTPS resources behind an Amazon VPC for access by clients outside of the VPC. The private integration uses an API Gateway resource of VpcLink to encapsulate connections between API Gateway and targeted VPC resources. The VpcLink is then attached to the Integration of a specific API Gateway Method. The following code sets up a private integration with a network load balancer -

ts
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';

const vpc = new ec2.Vpc(this, 'VPC');
const nlb = new elbv2.NetworkLoadBalancer(this, 'NLB', {
  vpc,
});
const link = new apigateway.VpcLink(this, 'link', {
  targets: [nlb],
});

const integration = new apigateway.Integration({
  type: apigateway.IntegrationType.HTTP_PROXY,
  integrationHttpMethod: 'ANY',
  options: {
    connectionType: apigateway.ConnectionType.VPC_LINK,
    vpcLink: link,
  },
});
python
import aws_cdk.aws_elasticloadbalancingv2 as elbv2


vpc = ec2.Vpc(self, "VPC")
nlb = elbv2.NetworkLoadBalancer(self, "NLB",
    vpc=vpc
)
link = apigateway.VpcLink(self, "link",
    targets=[nlb]
)

integration = apigateway.Integration(
    type=apigateway.IntegrationType.HTTP_PROXY,
    integration_http_method="ANY",
    options=apigateway.IntegrationOptions(
        connection_type=apigateway.ConnectionType.VPC_LINK,
        vpc_link=link
    )
)
java
import software.amazon.awscdk.services.elasticloadbalancingv2.*;


Vpc vpc = new Vpc(this, "VPC");
NetworkLoadBalancer nlb = NetworkLoadBalancer.Builder.create(this, "NLB")
        .vpc(vpc)
        .build();
VpcLink link = VpcLink.Builder.create(this, "link")
        .targets(List.of(nlb))
        .build();

Integration integration = Integration.Builder.create()
        .type(IntegrationType.HTTP_PROXY)
        .integrationHttpMethod("ANY")
        .options(IntegrationOptions.builder()
                .connectionType(ConnectionType.VPC_LINK)
                .vpcLink(link)
                .build())
        .build();
csharp
using Amazon.CDK.AWS.ElasticLoadBalancingV2;


var vpc = new Vpc(this, "VPC");
var nlb = new NetworkLoadBalancer(this, "NLB", new NetworkLoadBalancerProps {
    Vpc = vpc
});
var link = new VpcLink(this, "link", new VpcLinkProps {
    Targets = new [] { nlb }
});

var integration = new Integration(new IntegrationProps {
    Type = IntegrationType.HTTP_PROXY,
    IntegrationHttpMethod = "ANY",
    Options = new IntegrationOptions {
        ConnectionType = ConnectionType.VPC_LINK,
        VpcLink = link
    }
});
go
import elbv2 "github.com/aws/aws-cdk-go/awscdk"


vpc := ec2.NewVpc(this, jsii.String("VPC"))
nlb := elbv2.NewNetworkLoadBalancer(this, jsii.String("NLB"), &NetworkLoadBalancerProps{
	Vpc: Vpc,
})
link := apigateway.NewVpcLink(this, jsii.String("link"), &VpcLinkProps{
	Targets: []INetworkLoadBalancer{
		nlb,
	},
})

integration := apigateway.NewIntegration(&IntegrationProps{
	Type: apigateway.IntegrationType_HTTP_PROXY,
	IntegrationHttpMethod: jsii.String("ANY"),
	Options: &IntegrationOptions{
		ConnectionType: apigateway.ConnectionType_VPC_LINK,
		VpcLink: link,
	},
})

The uri for the private integration, in the case of a VpcLink, will be set to the DNS name of the VPC Link's NLB. If the VPC Link has multiple NLBs or the VPC Link is imported or the DNS name cannot be determined for any other reason, the user is expected to specify the uri property.

Any existing VpcLink resource can be imported into the CDK app via the VpcLink.fromVpcLinkId().

ts
const awesomeLink = apigateway.VpcLink.fromVpcLinkId(this, 'awesome-vpc-link', 'us-east-1_oiuR12Abd');
python
awesome_link = apigateway.VpcLink.from_vpc_link_id(self, "awesome-vpc-link", "us-east-1_oiuR12Abd")
java
IVpcLink awesomeLink = VpcLink.fromVpcLinkId(this, "awesome-vpc-link", "us-east-1_oiuR12Abd");
csharp
var awesomeLink = VpcLink.FromVpcLinkId(this, "awesome-vpc-link", "us-east-1_oiuR12Abd");
go
awesomeLink := apigateway.VpcLink_FromVpcLinkId(this, jsii.String("awesome-vpc-link"), jsii.String("us-east-1_oiuR12Abd"))

Gateway response ​

If the Rest API fails to process an incoming request, it returns to the client an error response without forwarding the request to the integration backend. API Gateway has a set of standard response messages that are sent to the client for each type of error. These error responses can be configured on the Rest API. The list of Gateway responses that can be configured can be found here. Learn more about Gateway Responses.

The following code configures a Gateway Response when the response is 'access denied':

ts
const api = new apigateway.RestApi(this, 'books-api');
api.addGatewayResponse('test-response', {
  type: apigateway.ResponseType.ACCESS_DENIED,
  statusCode: '500',
  responseHeaders: {
    // Note that values must be enclosed within a pair of single quotes
    'Access-Control-Allow-Origin': "'test.com'",
    'test-key': "'test-value'",
  },
  templates: {
    'application/json': '{ "message": $context.error.messageString, "statusCode": "488", "type": "$context.error.responseType" }'
  }
});
python
api = apigateway.RestApi(self, "books-api")
api.add_gateway_response("test-response",
    type=apigateway.ResponseType.ACCESS_DENIED,
    status_code="500",
    response_headers={
        # Note that values must be enclosed within a pair of single quotes
        "Access-Control-Allow-Origin": "'test.com'",
        "test-key": "'test-value'"
    },
    templates={
        "application/json": "{ \"message\": $context.error.messageString, \"statusCode\": \"488\", \"type\": \"$context.error.responseType\" }"
    }
)
java
RestApi api = new RestApi(this, "books-api");
api.addGatewayResponse("test-response", GatewayResponseOptions.builder()
        .type(ResponseType.ACCESS_DENIED)
        .statusCode("500")
        .responseHeaders(Map.of(
                // Note that values must be enclosed within a pair of single quotes
                "Access-Control-Allow-Origin", "'test.com'",
                "test-key", "'test-value'"))
        .templates(Map.of(
                "application/json", "{ \"message\": $context.error.messageString, \"statusCode\": \"488\", \"type\": \"$context.error.responseType\" }"))
        .build());
csharp
var api = new RestApi(this, "books-api");
api.AddGatewayResponse("test-response", new GatewayResponseOptions {
    Type = ResponseType.ACCESS_DENIED,
    StatusCode = "500",
    ResponseHeaders = new Dictionary<string, string> {
        // Note that values must be enclosed within a pair of single quotes
        { "Access-Control-Allow-Origin", "'test.com'" },
        { "test-key", "'test-value'" }
    },
    Templates = new Dictionary<string, string> {
        { "application/json", "{ \"message\": $context.error.messageString, \"statusCode\": \"488\", \"type\": \"$context.error.responseType\" }" }
    }
});
go
api := apigateway.NewRestApi(this, jsii.String("books-api"))
api.AddGatewayResponse(jsii.String("test-response"), &GatewayResponseOptions{
	Type: apigateway.ResponseType_ACCESS_DENIED(),
	StatusCode: jsii.String("500"),
	ResponseHeaders: map[string]*string{
		// Note that values must be enclosed within a pair of single quotes
		"Access-Control-Allow-Origin": jsii.String("'test.com'"),
		"test-key": jsii.String("'test-value'"),
	},
	Templates: map[string]*string{
		"application/json": jsii.String("{ \"message\": $context.error.messageString, \"statusCode\": \"488\", \"type\": \"$context.error.responseType\" }"),
	},
})

OpenAPI Definition ​

CDK supports creating a REST API by importing an OpenAPI definition file. It currently supports OpenAPI v2.0 and OpenAPI v3.0 definition files. Read more about Configuring a REST API using OpenAPI.

The following code creates a REST API using an external OpenAPI definition JSON file -

ts
declare const integration: apigateway.Integration;

const api = new apigateway.SpecRestApi(this, 'books-api', {
  apiDefinition: apigateway.ApiDefinition.fromAsset('path-to-file.json')
});

const booksResource = api.root.addResource('books')
booksResource.addMethod('GET', integration);
python
# integration: apigateway.Integration


api = apigateway.SpecRestApi(self, "books-api",
    api_definition=apigateway.ApiDefinition.from_asset("path-to-file.json")
)

books_resource = api.root.add_resource("books")
books_resource.add_method("GET", integration)
java
Integration integration;


SpecRestApi api = SpecRestApi.Builder.create(this, "books-api")
        .apiDefinition(ApiDefinition.fromAsset("path-to-file.json"))
        .build();

Resource booksResource = api.root.addResource("books");
booksResource.addMethod("GET", integration);
csharp
Integration integration;


var api = new SpecRestApi(this, "books-api", new SpecRestApiProps {
    ApiDefinition = ApiDefinition.FromAsset("path-to-file.json")
});

var booksResource = api.Root.AddResource("books");
booksResource.AddMethod("GET", integration);
go
var integration Integration


api := apigateway.NewSpecRestApi(this, jsii.String("books-api"), &SpecRestApiProps{
	ApiDefinition: apigateway.ApiDefinition_FromAsset(jsii.String("path-to-file.json")),
})

booksResource := api.Root.AddResource(jsii.String("books"))
booksResource.AddMethod(jsii.String("GET"), integration)

It is possible to use the addResource() API to define additional API Gateway Resources.

Note: Deployment will fail if a Resource of the same name is already defined in the Open API specification.

Note: Any default properties configured, such as defaultIntegration, defaultMethodOptions, etc. will only be applied to Resources and Methods defined in the CDK, and not the ones defined in the spec. Use the API Gateway extensions to OpenAPI to configure these.

There are a number of limitations in using OpenAPI definitions in API Gateway. Read the Amazon API Gateway important notes for REST APIs for more details.

Note: When starting off with an OpenAPI definition using SpecRestApi, it is not possible to configure some properties that can be configured directly in the OpenAPI specification file. This is to prevent people duplication of these properties and potential confusion.

However, you can control how API Gateway handles resource updates using the mode property. Valid values are:

  • overwrite - The new API definition replaces the existing one. The existing API identifier remains unchanged.
  • merge - The new API definition is merged with the existing API.

If you don't specify this property, a default value is chosen:

  • For REST APIs created before March 29, 2021, the default is overwrite
  • For REST APIs created after March 29, 2021, the new API definition takes precedence, but any container types such as endpoint configurations and binary media types are merged with the existing API.

Use the default mode to define top-level RestApi properties in addition to using OpenAPI. Generally, it's preferred to use API Gateway's OpenAPI extensions to model these properties.

ts
const api = new apigateway.SpecRestApi(this, 'books-api', {
  apiDefinition: apigateway.ApiDefinition.fromAsset('path-to-file.json'),
  mode: apigateway.RestApiMode.MERGE
});
python
api = apigateway.SpecRestApi(self, "books-api",
    api_definition=apigateway.ApiDefinition.from_asset("path-to-file.json"),
    mode=apigateway.RestApiMode.MERGE
)
java
SpecRestApi api = SpecRestApi.Builder.create(this, "books-api")
        .apiDefinition(ApiDefinition.fromAsset("path-to-file.json"))
        .mode(RestApiMode.MERGE)
        .build();
csharp
var api = new SpecRestApi(this, "books-api", new SpecRestApiProps {
    ApiDefinition = ApiDefinition.FromAsset("path-to-file.json"),
    Mode = RestApiMode.MERGE
});
go
api := apigateway.NewSpecRestApi(this, jsii.String("books-api"), &SpecRestApiProps{
	ApiDefinition: apigateway.ApiDefinition_FromAsset(jsii.String("path-to-file.json")),
	Mode: apigateway.RestApiMode_MERGE,
})

SpecRestApi also supports binary media types, similar to RestApi:

ts
const api = new apigateway.SpecRestApi(this, 'books-api', {
  apiDefinition: apigateway.ApiDefinition.fromAsset('path-to-file.json'),
  binaryMediaTypes: ['image/png', 'application/pdf']
});
python
api = apigateway.SpecRestApi(self, "books-api",
    api_definition=apigateway.ApiDefinition.from_asset("path-to-file.json"),
    binary_media_types=["image/png", "application/pdf"]
)
java
SpecRestApi api = SpecRestApi.Builder.create(this, "books-api")
        .apiDefinition(ApiDefinition.fromAsset("path-to-file.json"))
        .binaryMediaTypes(List.of("image/png", "application/pdf"))
        .build();
csharp
var api = new SpecRestApi(this, "books-api", new SpecRestApiProps {
    ApiDefinition = ApiDefinition.FromAsset("path-to-file.json"),
    BinaryMediaTypes = new [] { "image/png", "application/pdf" }
});
go
api := apigateway.NewSpecRestApi(this, jsii.String("books-api"), &SpecRestApiProps{
	ApiDefinition: apigateway.ApiDefinition_FromAsset(jsii.String("path-to-file.json")),
	BinaryMediaTypes: []*string{
		jsii.String("image/png"),
		jsii.String("application/pdf"),
	},
})

Endpoint configuration ​

By default, SpecRestApi will create an edge optimized endpoint.

This can be modified as shown below:

ts
declare const apiDefinition: apigateway.ApiDefinition;

const api = new apigateway.SpecRestApi(this, 'ExampleRestApi', {
  apiDefinition,
  endpointTypes: [apigateway.EndpointType.PRIVATE]
});
python
# api_definition: apigateway.ApiDefinition


api = apigateway.SpecRestApi(self, "ExampleRestApi",
    api_definition=api_definition,
    endpoint_types=[apigateway.EndpointType.PRIVATE]
)
java
ApiDefinition apiDefinition;


SpecRestApi api = SpecRestApi.Builder.create(this, "ExampleRestApi")
        .apiDefinition(apiDefinition)
        .endpointTypes(List.of(EndpointType.PRIVATE))
        .build();
csharp
ApiDefinition apiDefinition;


var api = new SpecRestApi(this, "ExampleRestApi", new SpecRestApiProps {
    ApiDefinition = apiDefinition,
    EndpointTypes = new [] { EndpointType.PRIVATE }
});
go
var apiDefinition ApiDefinition


api := apigateway.NewSpecRestApi(this, jsii.String("ExampleRestApi"), &SpecRestApiProps{
	ApiDefinition: ApiDefinition,
	EndpointTypes: []EndpointType{
		apigateway.EndpointType_PRIVATE,
	},
})

Note: For private endpoints you will still need to provide the x-amazon-apigateway-policy and x-amazon-apigateway-endpoint-configuration in your openApi file.

Metrics ​

The API Gateway service sends metrics around the performance of Rest APIs to Amazon CloudWatch. These metrics can be referred to using the metric APIs available on the RestApi, Stage and Method constructs. Note that detailed metrics must be enabled for a stage to use the Method metrics. Read more about API Gateway metrics, including enabling detailed metrics. The APIs with the metric prefix can be used to get reference to specific metrics for this API. For example:

ts
const api = new apigateway.RestApi(this, 'my-api');
const stage = api.deploymentStage;
const method = api.root.addMethod('GET');

const clientErrorApiMetric = api.metricClientError();
const serverErrorStageMetric = stage.metricServerError();
const latencyMethodMetric = method.metricLatency(stage);
python
api = apigateway.RestApi(self, "my-api")
stage = api.deployment_stage
method = api.root.add_method("GET")

client_error_api_metric = api.metric_client_error()
server_error_stage_metric = stage.metric_server_error()
latency_method_metric = method.metric_latency(stage)
java
RestApi api = new RestApi(this, "my-api");
Stage stage = api.getDeploymentStage();
Method method = api.root.addMethod("GET");

Metric clientErrorApiMetric = api.metricClientError();
Metric serverErrorStageMetric = stage.metricServerError();
Metric latencyMethodMetric = method.metricLatency(stage);
csharp
var api = new RestApi(this, "my-api");
var stage = api.DeploymentStage;
var method = api.Root.AddMethod("GET");

var clientErrorApiMetric = api.MetricClientError();
var serverErrorStageMetric = stage.MetricServerError();
var latencyMethodMetric = method.MetricLatency(stage);
go
api := apigateway.NewRestApi(this, jsii.String("my-api"))
stage := api.DeploymentStage
method := api.Root.AddMethod(jsii.String("GET"))

clientErrorApiMetric := api.MetricClientError()
serverErrorStageMetric := stage.MetricServerError()
latencyMethodMetric := method.MetricLatency(stage)

APIGateway v2 ​

APIGateway v2 APIs are now moved to its own package named aws-apigatewayv2. Previously, these APIs were marked deprecated but retained for backwards compatibility. The deprecated usage of APIGateway v2 APIs within this module aws-apigateway has now been removed from the codebase.

The reason for the removal of these deprecated Constructs is that CloudFormation team is releasing AWS resources like AWS::APIGateway::DomainNameV2 and this would cause compatibility issue with the deprecated CfnDomainNameV2 resource defined in apigatewayv2.ts file during the L1 generation.

Move to using aws-apigatewayv2 to get the latest APIs and updates.


This module is part of the AWS Cloud Development Kit project.

Types ​

NameKindSummary
ApiKeyConstruct (L2)An API Gateway ApiKey.
AuthorizerConstruct (L2)Base class for all custom authorizers.
BasePathMappingConstruct (L2)This resource creates a base path that clients who call your API must use in the invocation URL.
CognitoUserPoolsAuthorizerConstruct (L2)Cognito user pools based custom authorizer.
DeploymentConstruct (L2)A Deployment of a REST API.
DomainNameConstruct (L2)
GatewayResponseConstruct (L2)Configure the response received by clients, produced from the API Gateway backend.
LambdaRestApiConstruct (L2)Defines an API Gateway REST API with AWS Lambda proxy integration.
MethodConstruct (L2)
ModelConstruct (L2)
ProxyResourceConstruct (L2)Defines a {proxy+} greedy resource and an ANY method on a route.
RateLimitedApiKeyConstruct (L2)An API Gateway ApiKey, for which a rate limiting configuration can be specified.
RequestAuthorizerConstruct (L2)Request-based lambda authorizer that recognizes the caller's identity via request parameters, such as headers, paths, query strings, stage variables, or context variables.
RequestValidatorConstruct (L2)
ResourceConstruct (L2)
ResourceBaseConstruct (L2)
RestApiConstruct (L2)Represents a REST API in Amazon API Gateway.
RestApiBaseConstruct (L2)Base implementation that are common to various implementations of IRestApi.
SpecRestApiConstruct (L2)Represents a REST API in Amazon API Gateway, created with an OpenAPI specification.
StageConstruct (L2)
StageBaseConstruct (L2)Base class for an ApiGateway Stage.
StepFunctionsRestApiConstruct (L2)Defines an API Gateway REST API with a Synchrounous Express State Machine as a proxy integration.
TokenAuthorizerConstruct (L2)Token based lambda authorizer that recognizes the caller's identity as a bearer token, such as a JSON Web Token (JWT) or an OAuth token.
UsagePlanConstruct (L2)
VpcLinkConstruct (L2)Define a new VPC Link Specifies an API Gateway VPC link for a RestApi to access resources in an Amazon Virtual Private Cloud (VPC).
CfnAccountConstruct (L1)The AWS::ApiGateway::Account resource specifies the IAM role that Amazon API Gateway uses to write API logs to Amazon CloudWatch Logs.
CfnApiKeyConstruct (L1)The AWS::ApiGateway::ApiKey resource creates a unique key that you can distribute to clients who are executing API Gateway Method resources that require an API key.
CfnAuthorizerConstruct (L1)The AWS::ApiGateway::Authorizer resource creates an authorization layer that API Gateway activates for methods that have authorization enabled.
CfnBasePathMappingConstruct (L1)The AWS::ApiGateway::BasePathMapping resource creates a base path that clients who call your API must use in the invocation URL.
CfnBasePathMappingV2Construct (L1)The AWS::ApiGateway::BasePathMappingV2 resource creates a base path that clients who call your API must use in the invocation URL.
CfnClientCertificateConstruct (L1)The AWS::ApiGateway::ClientCertificate resource creates a client certificate that API Gateway uses to configure client-side SSL authentication for sending requests to the integration endpoint.
CfnDeploymentConstruct (L1)The AWS::ApiGateway::Deployment resource deploys an API Gateway RestApi resource to a stage so that clients can call the API over the internet.
CfnDocumentationPartConstruct (L1)The AWS::ApiGateway::DocumentationPart resource creates a documentation part for an API.
CfnDocumentationVersionConstruct (L1)The AWS::ApiGateway::DocumentationVersion resource creates a snapshot of the documentation for an API.
CfnDomainNameConstruct (L1)The AWS::ApiGateway::DomainName resource specifies a public custom domain name for your API in API Gateway.
CfnDomainNameAccessAssociationConstruct (L1)The AWS::ApiGateway::DomainNameAccessAssociation resource creates a domain name access association between an access association source and a private custom domain name.
CfnDomainNameV2Construct (L1)The AWS::ApiGateway::DomainNameV2 resource specifies a custom domain name for your private APIs in API Gateway.
CfnGatewayResponseConstruct (L1)The AWS::ApiGateway::GatewayResponse resource creates a gateway response for your API.
CfnMethodConstruct (L1)The AWS::ApiGateway::Method resource creates API Gateway methods that define the parameters and body that clients must send in their requests.
CfnModelConstruct (L1)The AWS::ApiGateway::Model resource defines the structure of a request or response payload for an API method.
CfnRequestValidatorConstruct (L1)The AWS::ApiGateway::RequestValidator resource sets up basic validation rules for incoming requests to your API.
CfnResourceConstruct (L1)The AWS::ApiGateway::Resource resource creates a resource in an API.
CfnRestApiConstruct (L1)The AWS::ApiGateway::RestApi resource creates a REST API.
CfnStageConstruct (L1)The AWS::ApiGateway::Stage resource creates a stage for a deployment.
CfnUsagePlanConstruct (L1)The AWS::ApiGateway::UsagePlan resource creates a usage plan for deployed APIs.
CfnUsagePlanKeyConstruct (L1)The AWS::ApiGateway::UsagePlanKey resource associates an API key with a usage plan.
CfnVpcLinkConstruct (L1)The AWS::ApiGateway::VpcLink resource creates an API Gateway VPC link for a REST API to access resources in an Amazon Virtual Private Cloud (VPC).
AccessLogDestinationConfigStructOptions when binding a log destination to a RestApi Stage.
AccessLogFieldClass$context variables that can be used to customize access log pattern.
AccessLogFormatClassfactory methods for access log format.
AddApiKeyOptionsStructOptions to the UsagePlan.addApiKey() method.
ApiDefinitionClassRepresents an OpenAPI definition asset.
ApiDefinitionConfigStructPost-Binding Configuration for a CDK construct.
ApiDefinitionS3LocationStructS3 location of the API definition file.
ApiKeyGrantsFacadeCollection of grant methods for a IApiKeyRef.
ApiKeyOptionsStructThe options for creating an API Key.
ApiKeyPropsStructApiKey Properties.
ApiKeySourceTypeEnum
ApiMappingOptionsStructOptions for creating an api mapping.
AssetApiDefinitionClassOpenAPI specification from a local file.
AuthorizationTypeEnum
AwsIntegrationClassThis type of integration lets an API expose AWS service actions.
AwsIntegrationPropsStruct
BasePathMappingOptionsStruct
BasePathMappingPropsStruct
CfnAccountPropsStructProperties for defining a CfnAccount.
CfnApiKey.StageKeyPropertyStructStageKey is a property of the AWS::ApiGateway::ApiKey resource that specifies the stage to associate with the API key. This association allows only clients with the key to make requests to methods in that stage.
CfnApiKeyPropsStructProperties for defining a CfnApiKey.
CfnAuthorizerPropsStructProperties for defining a CfnAuthorizer.
CfnBasePathMappingPropsStructProperties for defining a CfnBasePathMapping.
CfnBasePathMappingV2PropsStructProperties for defining a CfnBasePathMappingV2.
CfnClientCertificatePropsStructProperties for defining a CfnClientCertificate.
CfnDeployment.AccessLogSettingPropertyStructThe AccessLogSetting property type specifies settings for logging access in this stage.
CfnDeployment.CanarySettingPropertyStructThe CanarySetting property type specifies settings for the canary deployment in this stage.
CfnDeployment.DeploymentCanarySettingsPropertyStructThe DeploymentCanarySettings property type specifies settings for the canary deployment.
CfnDeployment.MethodSettingPropertyStructThe MethodSetting property type configures settings for all methods in a stage.
CfnDeployment.StageDescriptionPropertyStructStageDescription is a property of the AWS::ApiGateway::Deployment resource that configures a deployment stage.
CfnDeploymentPropsStructProperties for defining a CfnDeployment.
CfnDocumentationPart.LocationPropertyStructThe Location property specifies the location of the Amazon API Gateway API entity that the documentation applies to.
CfnDocumentationPartPropsStructProperties for defining a CfnDocumentationPart.
CfnDocumentationVersionPropsStructProperties for defining a CfnDocumentationVersion.
CfnDomainName.EndpointConfigurationPropertyStructThe EndpointConfiguration property type specifies the endpoint types and IP address types of an Amazon API Gateway domain name.
CfnDomainName.MutualTlsAuthenticationPropertyStructThe mutual TLS authentication configuration for a custom domain name.
CfnDomainNameAccessAssociationPropsStructProperties for defining a CfnDomainNameAccessAssociation.
CfnDomainNamePropsStructProperties for defining a CfnDomainName.
CfnDomainNameV2.EndpointConfigurationPropertyStructThe endpoint configuration to indicate the types of endpoints an API (RestApi) or its custom domain name (DomainName) has and the IP address types that can invoke it.
CfnDomainNameV2PropsStructProperties for defining a CfnDomainNameV2.
CfnGatewayResponsePropsStructProperties for defining a CfnGatewayResponse.
CfnMethod.IntegrationPropertyStructIntegration is a property of the AWS::ApiGateway::Method resource that specifies information about the target backend that a method calls.
CfnMethod.IntegrationResponsePropertyStructIntegrationResponse is a property of the Amazon API Gateway Method Integration property type that specifies the response that API Gateway sends after a method's backend finishes processing a request.
CfnMethod.MethodResponsePropertyStructRepresents a method response of a given HTTP status code returned to the client.
CfnMethodPropsStructProperties for defining a CfnMethod.
CfnModelPropsStructProperties for defining a CfnModel.
CfnRequestValidatorPropsStructProperties for defining a CfnRequestValidator.
CfnResourcePropsStructProperties for defining a CfnResource.
CfnRestApi.EndpointConfigurationPropertyStructThe EndpointConfiguration property type specifies the endpoint types and IP address types of a REST API.
CfnRestApi.S3LocationPropertyStructS3Location is a property of the AWS::ApiGateway::RestApi resource that specifies the Amazon S3 location of a OpenAPI (formerly Swagger) file that defines a set of RESTful APIs in JSON or YAML.
CfnRestApiPropsStructProperties for defining a CfnRestApi.
CfnStage.AccessLogSettingPropertyStructThe AccessLogSetting property type specifies settings for logging access in this stage.
CfnStage.CanarySettingPropertyStructConfiguration settings of a canary deployment.
CfnStage.MethodSettingPropertyStructThe MethodSetting property type configures settings for all methods in a stage.
CfnStagePropsStructProperties for defining a CfnStage.
CfnUsagePlan.ApiStagePropertyStructAPI stage name of the associated API stage in a usage plan.
CfnUsagePlan.QuotaSettingsPropertyStructQuotaSettings is a property of the AWS::ApiGateway::UsagePlan resource that specifies a target for the maximum number of requests users can make to your REST APIs.
CfnUsagePlan.ThrottleSettingsPropertyStructThrottleSettings is a property of the AWS::ApiGateway::UsagePlan resource that specifies the overall request rate (average requests per second) and burst capacity when users call your REST APIs.
CfnUsagePlanKeyPropsStructProperties for defining a CfnUsagePlanKey.
CfnUsagePlanPropsStructProperties for defining a CfnUsagePlan.
CfnVpcLinkPropsStructProperties for defining a CfnVpcLink.
CognitoUserPoolsAuthorizerPropsStructProperties for CognitoUserPoolsAuthorizer.
ConnectionTypeEnum
ContentHandlingEnum
CorsClass
CorsOptionsStruct
DeploymentPropsStruct
DomainNameAttributesStruct
DomainNameOptionsStruct
DomainNamePropsStruct
EndpointAccessModeEnumThe endpoint access mode for the domain name.
EndpointConfigurationStructThe endpoint configuration of a REST API, including VPCs and endpoint types.
EndpointTypeEnum
FirehoseLogDestinationClassUse a Firehose delivery stream as a custom access log destination for API Gateway.
GatewayResponseOptionsStructOptions to add gateway response.
GatewayResponsePropsStructProperties for a new gateway response.
HttpIntegrationClassYou can integrate an API method with an HTTP endpoint using the HTTP proxy integration or the HTTP custom integration,.
HttpIntegrationPropsStruct
IAccessLogDestinationInterfaceAccess log destination for a RestApi Stage.
IApiKeyInterfaceAPI keys are alphanumeric string values that you distribute to app developer customers to grant access to your API.
IAuthorizerInterfaceRepresents an API Gateway authorizer.
IdentitySourceClassRepresents an identity source.
IDomainNameInterface
IGatewayResponseInterfaceRepresents gateway response resource.
IModelInterface
InlineApiDefinitionClassOpenAPI specification from an inline JSON object.
IntegrationClassBase class for backend integrations for an API Gateway method.
IntegrationConfigStructResult of binding an Integration to a Method.
IntegrationOptionsStruct
IntegrationPropsStruct
IntegrationResponseStruct
IntegrationTypeEnum
IpAddressTypeEnumSupported IP Address Types.
IRequestValidatorInterface
IResourceInterface
IRestApiInterface
IStageInterfaceRepresents an APIGateway Stage.
IUsagePlanInterfaceA UsagePlan, either managed by this CDK app, or imported.
IVpcLinkInterfaceRepresents an API Gateway VpcLink.
JsonSchemaStructRepresents a JSON schema definition of the structure of a REST API model.
JsonSchemaTypeEnum
JsonSchemaVersionEnum
JsonWithStandardFieldPropsStructProperties for controlling items output in JSON standard format.
LambdaAuthorizerPropsStructBase properties for all lambda authorizers.
LambdaIntegrationClassIntegrates an AWS Lambda function to an API Gateway method.
LambdaIntegrationOptionsStruct
LambdaRestApiPropsStruct
LogGroupLogDestinationClassUse CloudWatch Logs as a custom access log destination for API Gateway.
MethodDeploymentOptionsStruct
MethodLoggingLevelEnum
MethodOptionsStruct
MethodPropsStruct
MethodResponseStruct
MockIntegrationClassThis type of integration lets API Gateway return a response without sending the request further to the backend.
ModelOptionsStruct
ModelPropsStruct
MTLSConfigStructThe mTLS authentication configuration for a custom domain name.
PassthroughBehaviorEnum
PeriodEnumTime period for which quota settings apply.
ProxyResourceOptionsStruct
ProxyResourcePropsStruct
QuotaSettingsStructSpecifies the maximum number of requests that clients can make to API Gateway APIs.
RateLimitedApiKeyPropsStructRateLimitedApiKey properties.
RequestAuthorizerPropsStructProperties for RequestAuthorizer.
RequestContextStructConfigure what must be included in the requestContext.
RequestValidatorOptionsStruct
RequestValidatorPropsStruct
ResourceAttributesStructAttributes that can be specified when importing a Resource.
ResourceOptionsStruct
ResourcePropsStruct
ResponseTransferModeEnumThe response transfer mode of the integration.
ResponseTypeClassSupported types of gateway responses.
RestApiAttributesStructAttributes that can be specified when importing a RestApi.
RestApiBasePropsStructRepresents the props that all Rest APIs share.
RestApiModeEnumThe Mode that determines how API Gateway handles resource updates when importing an OpenAPI definition.
RestApiPropsStructProps to create a new instance of RestApi.
S3ApiDefinitionClassOpenAPI specification from an S3 archive.
SagemakerIntegrationClassIntegrates an AWS Sagemaker Endpoint to an API Gateway method.
SagemakerIntegrationOptionsStructOptions for SageMakerIntegration.
SecurityPolicyEnumThe minimum version of the SSL protocol that you want API Gateway to use for HTTPS connections.
SpecRestApiPropsStructProps to instantiate a new SpecRestApi.
StageAttributesStructThe attributes of an imported Stage.
StageOptionsStruct
StagePropsStruct
StepFunctionsExecutionIntegrationOptionsStructOptions when configuring Step Functions synchronous integration with Rest API.
StepFunctionsIntegrationClassOptions to integrate with various StepFunction API.
StepFunctionsRestApiPropsStructProperties for StepFunctionsRestApi.
ThrottleSettingsStructContainer for defining throttling parameters to API stages or methods.
ThrottlingPerMethodStructRepresents per-method throttling for a resource.
TokenAuthorizerPropsStructProperties for TokenAuthorizer.
UsagePlanPerApiStageStructRepresents the API stages that a usage plan applies to.
UsagePlanPropsStruct
VpcLinkPropsStructProperties for a VpcLink.