Skip to content

AWS.ApiGatewayV2 reference

Source: packages/aws/src/ApiGatewayV2/Api.ts

An Amazon API Gateway v2 API — the root of an HTTP API or WebSocket API.

HTTP APIs are the modern, cheaper, faster front door for Lambda functions (compared to REST v1). WebSocket APIs provide two-way real-time messaging backed by Lambda route handlers. Child resources (Integration, Route, Stage, Authorizer) reference the API by passing api in their props.

For the common “HTTP API in front of a Lambda function” case, prefer the high-level HttpApi helper which wires up the integration, route, stage, and invoke permission in one call.

Minimal HTTP API

import * as ApiGatewayV2 from "@alchemy.run/aws/ApiGatewayV2";
const api = yield* ApiGatewayV2.Api("Api", {});

HTTP API with CORS

const api = yield* ApiGatewayV2.Api("Api", {
corsConfiguration: {
AllowOrigins: ["https://example.com"],
AllowMethods: ["GET", "POST"],
AllowHeaders: ["content-type"],
MaxAge: 3600,
},
});
const api = yield* ApiGatewayV2.Api("WsApi", {
protocolType: "WEBSOCKET",
routeSelectionExpression: "$request.body.action",
});
const api = yield* ApiGatewayV2.Api("Api", {
disableExecuteApiEndpoint: true,
});

Api.lookup references a API Alchemy doesn’t manage (created in the console or by another stack), found by apiId or name. It is read during plan/deploy and never created, updated or deleted.

const api = AWS.ApiGatewayV2.Api.lookup({ name: "public" });
const apiId = api.apiId;

Source: packages/aws/src/ApiGatewayV2/ApiMapping.ts

An API Gateway v2 API mapping — serves an API stage under a custom DomainName, optionally at a base path.

ApiMappingResource: Mapping APIs onto a domain

Section titled “ApiMappingResource: Mapping APIs onto a domain”

Map an API at the domain root

yield* ApiGatewayV2.ApiMapping("Root", {
api,
domainName: domain.domainName,
stage: stage.stageName,
});

Map a second API under /v2

yield* ApiGatewayV2.ApiMapping("V2", {
api: apiV2,
domainName: domain.domainName,
stage: "$default",
apiMappingKey: "v2",
});

Source: packages/aws/src/ApiGatewayV2/Authorizer.ts

An API Gateway v2 Authorizer — controls access to HTTP/WebSocket API routes via JWT validation or a Lambda (REQUEST) authorizer.

The common HTTP API authorizer: API Gateway validates the caller’s JWT against the issuer’s JWKS and matches the audience — no Lambda invoked.

const authorizer = yield* ApiGatewayV2.Authorizer("Jwt", {
api,
authorizerType: "JWT",
identitySource: ["$request.header.Authorization"],
jwtConfiguration: {
Issuer: `https://cognito-idp.us-west-2.amazonaws.com/${userPoolId}`,
Audience: [clientId],
},
});
yield* ApiGatewayV2.Route("Secure", {
api,
routeKey: "GET /me",
integration,
authorizationType: "JWT",
authorizerId: authorizer.authorizerId,
});

AuthorizerResource: Lambda (REQUEST) authorizers

Section titled “AuthorizerResource: Lambda (REQUEST) authorizers”
const authorizer = yield* ApiGatewayV2.Authorizer("Lambda", {
api,
authorizerType: "REQUEST",
identitySource: ["$request.header.Authorization"],
authorizerUri: invocationUri,
authorizerPayloadFormatVersion: "2.0",
enableSimpleResponses: true,
});

AuthorizerResource: Looking up an existing authorizer type

Section titled “AuthorizerResource: Looking up an existing authorizer type”

AuthorizerType.lookup references an authorizer type Alchemy doesn’t manage (created in the console or by another stack), found by apiId and authorizerId. It is read during plan/deploy and never created, updated or deleted.

const existing = AWS.ApiGatewayV2.AuthorizerType.lookup({ apiId: "...", authorizerId: "..." });

Source: packages/aws/src/ApiGatewayV2/DomainName.ts

An API Gateway v2 custom domain name.

Requires a validated ACM certificate in the same region. Point DNS (a Route 53 alias or CNAME) at the returned ApiGatewayDomainName target and map APIs onto the domain with ApiMapping.

const domain = yield* ApiGatewayV2.DomainName("Domain", {
domainName: "api.example.com",
domainNameConfigurations: [{
CertificateArn: certificate.certificateArn,
EndpointType: "REGIONAL",
SecurityPolicy: "TLS_1_2",
}],
});
yield* ApiGatewayV2.ApiMapping("Mapping", {
api,
domainName: domain.domainName,
stage: stage.stageName,
});

DomainName: Looking up an existing custom domain name

Section titled “DomainName: Looking up an existing custom domain name”

DomainName.lookup references a custom domain name Alchemy doesn’t manage (created in the console or by another stack), found by domainName. It is read during plan/deploy and never created, updated or deleted.

const domain = AWS.ApiGatewayV2.DomainName.lookup({ domainName: "api.example.com" });

Source: packages/aws/src/ApiGatewayV2/ExportApi.ts

Runtime binding for exporting an HTTP API’s OpenAPI 3.0 definition (apigateway:GET on /apis/{apiId}/exports/{specification}).

Bind an Api inside a function runtime to serve or snapshot the live API definition — e.g. publishing your own /openapi.json route or diffing deployed routes against the source of truth. The response body is a byte Stream of the JSON (or YAML) document. Provide ApiGatewayV2.ExportApiHttp on the Function effect to implement the binding.

// init
const exportApi = yield* ApiGatewayV2.ExportApi(api);
// runtime
const exported = yield* exportApi({ OutputType: "JSON" });
const document = yield* Stream.mkString(Stream.decodeText(exported.body!));

Source: packages/aws/src/ApiGatewayV2/Integration.ts

An API Gateway v2 Integration — the backend target a Route forwards to.

For HTTP APIs the common integration is AWS_PROXY with payload format 2.0, pointing directly at a Lambda function ARN. For WebSocket APIs the integrationUri must be the full Lambda invocation URI.

IntegrationResource: Lambda proxy integration (HTTP API)

Section titled “IntegrationResource: Lambda proxy integration (HTTP API)”
const integration = yield* ApiGatewayV2.Integration("Fn", {
api,
integrationType: "AWS_PROXY",
integrationUri: fn.functionArn,
payloadFormatVersion: "2.0",
});

IntegrationResource: HTTP proxy integration

Section titled “IntegrationResource: HTTP proxy integration”
const integration = yield* ApiGatewayV2.Integration("Upstream", {
api,
integrationType: "HTTP_PROXY",
integrationUri: "https://example.com/{proxy}",
integrationMethod: "ANY",
payloadFormatVersion: "1.0",
});

IntegrationResource: Looking up an existing integration type

Section titled “IntegrationResource: Looking up an existing integration type”

IntegrationType.lookup references an integration type Alchemy doesn’t manage (created in the console or by another stack), found by apiId and integrationId. It is read during plan/deploy and never created, updated or deleted.

const existing = AWS.ApiGatewayV2.IntegrationType.lookup({ apiId: "...", integrationId: "..." });

Source: packages/aws/src/ApiGatewayV2/ManageConnections.ts

Runtime binding for the WebSocket @connections management API (execute-api:ManageConnections).

Bind this to a WebSocket API Stage inside a function runtime to push messages to connected clients — the flagship server-push primitive for WebSocket APIs. The binding grants execute-api:ManageConnections scoped to the stage’s @connections ARN and targets the stage’s callback endpoint (https://{apiId}.execute-api.{region}.amazonaws.com/{stage}).

Provide ApiGatewayV2.ManageConnectionsHttp on the hosting function’s Effect (Effect.provide(ApiGatewayV2.ManageConnectionsHttp)) to satisfy the binding.

const connections = yield* ApiGatewayV2.ManageConnections(stage);
yield* ApiGatewayV2.onWebSocketRoute(api, { routeKey: "$default" }, (event) =>
connections
.postToConnection({
ConnectionId: event.requestContext.connectionId,
Data: `echo:${event.body ?? ""}`,
})
.pipe(
Effect.asVoid,
// The peer may have disconnected between send and receive.
Effect.catchTag("GoneException", () => Effect.void),
Effect.orDie,
),
);
yield* connections.deleteConnection({ ConnectionId: staleConnectionId });

Source: packages/aws/src/ApiGatewayV2/ResetAuthorizersCache.ts

Runtime binding for resetting a stage’s authorizer result cache (apigateway:DELETE on /apis/{apiId}/stages/{stageName}/cache/authorizers).

Bind a Stage inside a function runtime to drop cached Lambda authorizer verdicts — e.g. immediately revoking access after a permission change, without waiting out authorizerResultTtl. Provide ApiGatewayV2.ResetAuthorizersCacheHttp on the Function effect to implement the binding.

// init
const resetAuthorizersCache = yield* ApiGatewayV2.ResetAuthorizersCache(stage);
// runtime
yield* resetAuthorizersCache();

Source: packages/aws/src/ApiGatewayV2/Route.ts

An API Gateway v2 Route — matches incoming requests (or WebSocket messages) and forwards them to an Integration.

Catch-all $default route

yield* ApiGatewayV2.Route("Default", {
api,
routeKey: "$default",
integration,
});

Method + path route

yield* ApiGatewayV2.Route("ListItems", {
api,
routeKey: "GET /items",
integration,
});
yield* ApiGatewayV2.Route("Connect", {
api,
routeKey: "$connect",
integration,
});
yield* ApiGatewayV2.Route("Secure", {
api,
routeKey: "GET /me",
integration,
authorizationType: "JWT",
authorizerId: authorizer.authorizerId,
});

Source: packages/aws/src/ApiGatewayV2/Stage.ts

An API Gateway v2 Stage — the deployed, callable endpoint of an HTTP or WebSocket API.

StageResource: The $default auto-deploy stage

Section titled “StageResource: The $default auto-deploy stage”

The canonical modern setup is a single $default stage with autoDeploy: true — every route/integration change goes live automatically at the API root endpoint, with no Deployment juggling.

const stage = yield* ApiGatewayV2.Stage("Stage", {
api,
autoDeploy: true,
});
// stage.invokeUrl === api.apiEndpoint
const dev = yield* ApiGatewayV2.Stage("Dev", {
api,
stageName: "dev",
autoDeploy: true,
stageVariables: { logLevel: "debug" },
});
const stage = yield* ApiGatewayV2.Stage("Stage", {
api,
autoDeploy: true,
defaultRouteSettings: {
ThrottlingBurstLimit: 100,
ThrottlingRateLimit: 50,
},
});

StageResource: Looking up an existing API gateway V2 stage

Section titled “StageResource: Looking up an existing API gateway V2 stage”

ApiGatewayV2Stage.lookup references an API gateway V2 stage Alchemy doesn’t manage (created in the console or by another stack), found by apiId and stageName. It is read during plan/deploy and never created, updated or deleted.

const existing = AWS.ApiGatewayV2.ApiGatewayV2Stage.lookup({ apiId: "...", stageName: "..." });

Source: packages/aws/src/ApiGatewayV2/VpcLink.ts

An API Gateway v2 VPC link — lets an HTTP API reach private resources (ALB/NLB listeners, Cloud Map services) inside a VPC.

Unlike the v1 VPC link (NLB-only, ~10 min provisioning), the v2 link is subnet/security-group based and provisions in ~1–2 minutes.

const link = yield* ApiGatewayV2.VpcLink("Link", {
subnetIds: [subnetA.subnetId, subnetB.subnetId],
securityGroupIds: [securityGroup.securityGroupId],
});
yield* ApiGatewayV2.Integration("Private", {
api,
integrationType: "HTTP_PROXY",
integrationUri: listener.listenerArn,
integrationMethod: "ANY",
connectionType: "VPC_LINK",
connectionId: link.vpcLinkId,
payloadFormatVersion: "1.0",
});

VpcLink.lookup references a VPC link Alchemy doesn’t manage (created in the console or by another stack), found by vpcLinkId. It is read during plan/deploy and never created, updated or deleted.

const existing = AWS.ApiGatewayV2.VpcLink.lookup({ vpcLinkId: "..." });

Source: packages/aws/src/ApiGatewayV2/WebSocketEventSource.ts

Event source connecting a WebSocket Api route to the hosting Lambda function.

At deploy time the Lambda implementation (Lambda.WebSocketEventSource) materializes the Integration, Route, and invoke Permission for the route; at runtime it dispatches matching WebSocket proxy events to the handler. Subscribe routes with onWebSocketRoute and provide Lambda.WebSocketEventSource on the hosting function.

WebSocketEventSource: Handling WebSocket Routes

Section titled “WebSocketEventSource: Handling WebSocket Routes”
export default MyFunction.make(
{ main: import.meta.url },
Effect.gen(function* () {
const api = yield* ApiGatewayV2.Api("WsApi", {
protocolType: "WEBSOCKET",
routeSelectionExpression: "$request.body.action",
});
const stage = yield* ApiGatewayV2.Stage("WsStage", {
api,
stageName: "prod",
autoDeploy: true,
});
const connections = yield* ApiGatewayV2.ManageConnections(stage);
yield* ApiGatewayV2.onWebSocketRoute(api, { routeKey: "$connect" }, () =>
Effect.succeed({ statusCode: 200 }),
);
yield* ApiGatewayV2.onWebSocketRoute(api, { routeKey: "$default" }, (event) =>
connections
.postToConnection({
ConnectionId: event.requestContext.connectionId,
Data: `echo:${event.body ?? ""}`,
})
.pipe(
Effect.asVoid,
Effect.catchTag("GoneException", () => Effect.void),
Effect.orDie,
),
);
return {};
}).pipe(
Effect.provide(
Layer.mergeAll(
Lambda.WebSocketEventSource,
ApiGatewayV2.ManageConnectionsHttp,
),
),
),
);