Skip to content

Gateway

Publish an HTTP or WebSocket API for your application. Point routes at a function or an event bus, then choose who can call them: a Cloud session, an access key, users of your product, or anyone.

The same edge also carries skippr and SDK calls to other Cloud services.

Status: Preview. See the API action reference for the full command list.

At a glance

FactValue
CLIskippr gateway <operation>
Target prefixCloudGateway.
AuthenticationCloud JWT or SigV4 service gateway
Api hostnameReturned as platformHostname
ProtocolsHTTPS request/response and WSS
ContractAPI actions

What you can do

  • Publish HTTP routes backed by a function or event bus.
  • Protect a route with a Skippr Cloud session, an access key, an Auth user pool, or no authorizer for a public route.
  • Open WebSocket connections and send a frame to one ConnectionId.
  • Call supported Skippr Cloud service APIs through the shared edge.

Before you start

You need skippr login or an operator/workload SigV4 key. To complete the HTTP example, create a function named hello first. Your policy must allow the CloudGateway.* operations and access to the integration target.

Create your first HTTP Api

The same Api, integration, authorizer, and route are CLI, Terraform, CDKTF TypeScript, or CDKTF Python. For provider credentials and the shared cloud provider block, see Terraform and CDKTF.

1. Create the Api

bash
skippr gateway create-api --name hello-api --protocol-type HTTP
hcl
resource "cloud_api" "hello" {
  name          = "hello-api"
  protocol_type = "HTTP"
}
ts
import { CloudProvider, CloudApi } from "@skippr/provider-cloud";

const cloud = new CloudProvider(this, "cloud", { region: "eu-central-1" });

const api = new CloudApi(this, "hello", {
  name: "hello-api",
  protocolType: "HTTP",
  provider: cloud,
});
python
from skippr_cdktf import CloudProvider, CloudApi

cloud = CloudProvider(self, "cloud", region="eu-central-1")

api = CloudApi(
    self,
    "hello",
    name="hello-api",
    protocol_type="HTTP",
    provider=cloud,
)

Save the returned apiId and platformHostname.

2. Connect the function

bash
skippr gateway create-integration --api-id '<apiId>' --integration-type FUNCTION --function-name hello
skippr gateway create-authorizer --api-id '<apiId>' --authorizer-type NONE
hcl
resource "cloud_api_integration" "hello" {
  api_id           = cloud_api.hello.api_id
  integration_type = "FUNCTION"
  function_name    = "hello"
}

resource "cloud_api_authorizer" "public" {
  api_id          = cloud_api.hello.api_id
  authorizer_type = "NONE"
}
ts
import { CloudApiAuthorizer, CloudApiIntegration } from "@skippr/provider-cloud";

const integration = new CloudApiIntegration(this, "hello", {
  apiId: api.apiId,
  integrationType: "FUNCTION",
  functionName: "hello",
  provider: cloud,
});

const authorizer = new CloudApiAuthorizer(this, "public", {
  apiId: api.apiId,
  authorizerType: "NONE",
  provider: cloud,
});
python
from skippr_cdktf import CloudApiAuthorizer, CloudApiIntegration

integration = CloudApiIntegration(
    self,
    "hello",
    api_id=api.api_id,
    integration_type="FUNCTION",
    function_name="hello",
    provider=cloud,
)

authorizer = CloudApiAuthorizer(
    self,
    "public",
    api_id=api.api_id,
    authorizer_type="NONE",
    provider=cloud,
)

Save the returned integrationId. Terraform and CDKTF also create a public NONE authorizer so the route can attach it.

3. Create the route

bash
skippr gateway create-route --api-id '<apiId>' --integration-id '<integrationId>' --route-key 'POST /hello'
hcl
resource "cloud_api_route" "hello" {
  api_id         = cloud_api.hello.api_id
  route_key      = "POST /hello"
  integration_id = cloud_api_integration.hello.integration_id
  authorizer_id  = cloud_api_authorizer.public.authorizer_id
}
ts
import { CloudApiRoute } from "@skippr/provider-cloud";

new CloudApiRoute(this, "hello", {
  apiId: api.apiId,
  routeKey: "POST /hello",
  integrationId: integration.integrationId,
  authorizerId: authorizer.authorizerId,
  provider: cloud,
});
python
from skippr_cdktf import CloudApiRoute

CloudApiRoute(
    self,
    "hello",
    api_id=api.api_id,
    route_key="POST /hello",
    integration_id=integration.integration_id,
    authorizer_id=authorizer.authorizer_id,
    provider=cloud,
)

Send POST /hello to the returned platformHostname. Add an authorizer before using the route for protected data.

Understand the Api model

ConceptMeaning
ApiThe primary HTTP or WebSocket resource; there are no stages
RouteMETHOD /path for HTTP, or a route key for WebSocket
IntegrationA FUNCTION or EVENTS_PUT backend; CLOUD_SERVICE is reserved for platform HTTP Apis
AuthorizerJWT, SIGV4, USER_POOL, or NONE
ConnectionIdOpaque identifier for one live WebSocket connection
DomainNameA verified custom hostname attached to one Api

Gateway does not have stages. CreateStage, DeployStage, and stage variables are not part of the product.

Manage HTTP Apis

TaskSupported operations
Manage ApisCreateApi, GetApi, ListApis, UpdateApi, DeleteApi
Manage routesCreateRoute, GetRoute, ListRoutes, UpdateRoute, DeleteRoute
Manage integrationsCreateIntegration, GetIntegration, ListIntegrations, UpdateIntegration, DeleteIntegration
Manage authorizersCreateAuthorizer, GetAuthorizer, ListAuthorizers, DeleteAuthorizer
Execute integrationsExecuteFunctionIntegration, ExecuteEventsPut

FUNCTION invokes a named function and returns the handler payload as the HTTP or WebSocket response body. HTTP status is the function statusCode. Direct skippr functions invoke still returns { "statusCode": 200, "payload": "..." }. EVENTS_PUT writes to an event bus. CLOUD_SERVICE is not an integration option for your Apis.

Add authentication

AuthorizerUse
JWTSomeone signed in to your Skippr Cloud account
SIGV4A signed request from an operator or workload key
USER_POOLA user of your product, from an Auth user pool
NONEA public route

Use WebSocket after HTTP

Create a second Api with protocolType: "WEBSOCKET". WebSocket Apis use the same Api, integration, authorizer, and route operations as HTTP Apis.

Route keyWhen it runs
CONNECTOnce after the WSS upgrade and authorization succeeds
DISCONNECTWhen the connection ends; delivery is best-effort
DEFAULTWhen no custom route matches
A custom keyFor a matching inbound JSON message

Set routeSelectionExpression on CreateApi, such as $request.body.action, when your frames select custom route keys. WebSocket routes support FUNCTION and EVENTS_PUT; they do not support CLOUD_SERVICE.

Connection management operations are supported:

  • PostToConnection sends one UTF-8 JSON frame to one ConnectionId.
  • DisconnectConnection closes one connection.
  • GetConnection and ListConnections return connection data for this Api.

Preview is a managed multi-node service, not a customer-selectable single-node mode. The supported contract is per-connection delivery. There is no broadcast or multicast operation; application fan-out requires one PostToConnection call per recipient.

Hostnames

These hosts are the ones you call from the CLI and SDKs. Check the API action reference before depending on a service that is still coming.

CapabilityHostname
Shared Cloud APIapi.cloud.skippr.io
Gatewaygateway.{region}.cloud.skippr.io
Authauth.cloud.skippr.io
Tables, queue, events, scheduler{service}.{region}.cloud.skippr.io
Secrets, functions, inventory{service}.{region}.cloud.skippr.io
DNS, certificates, sites{service}.{region}.cloud.skippr.io
Logs, metrics, traces, elt{service}.{region}.cloud.skippr.io
Objectsobjects.cloud.skippr.io

streams and machines are not available yet. A reserved hostname does not mean you can call those products. Streams protocol traffic is also not gateway HTTP or WebSocket traffic.

Bind a custom domain

Create the Api, then create a domain name with CLI, Terraform, CDKTF TypeScript, or CDKTF Python. For provider credentials and the shared cloud provider block, see Terraform and CDKTF.

bash
skippr gateway create-domain-name --hostname api.example.com --api-id '<apiId>'
hcl
resource "cloud_api_domain_name" "api" {
  hostname = "api.example.com"
  api_id   = cloud_api.hello.api_id
}
ts
import { CloudApiDomainName } from "@skippr/provider-cloud";

new CloudApiDomainName(this, "api", {
  hostname: "api.example.com",
  apiId: api.apiId,
  provider: cloud,
});
python
from skippr_cdktf import CloudApiDomainName

CloudApiDomainName(
    self,
    "api",
    hostname="api.example.com",
    api_id=api.api_id,
    provider=cloud,
)

The response includes an ownership TXT (_skippr-challenge.{hostname}) and an ACME CNAME target ({token}.validation.skippr.io). Publish these records at your DNS provider together with a traffic CNAME from your hostname to the Api platformHostname ({api_id}.gateway.{region}.cloud.skippr.io). Then:

  1. Call VerifyDomainName.
  2. Request a certificate with the same hostname and acmeDelegationCname.
  3. After the certificate is issued, AttachDomainName with the Api id and certificateId. Terraform can set certificate_id on cloud_api_domain_name once the certificate exists.

Leave the ownership TXT and ACME CNAME in place so renewal can update TXT under validation.skippr.io without another DNS change. Do not proxy a Gateway Api hostname through Cloudflare for SaaS.

A Site custom domain uses a Sites domain binding, not a gateway domain name.

Limits and errors

  • Coarse per-IP and per-credential rate limits apply. A rate-limited request returns 429; wait before retrying.
  • Missing or invalid credentials on a protected route return 401.
  • A valid identity without permission returns 403.
  • PostToConnection returns 410 when the connection is already closed.
  • A request for an Api, domain, or connection that is not yours returns 403.
  • A failed WebSocket authorization returns HTTP 401 or 403 before the upgrade; no connection is opened.

No additional numeric WebSocket quota is part of this public Preview contract. Use the generated operation schemas for required fields and error responses.