Skip to main content

API

An API is request-driven HTTP — a single handler that receives every request, dispatches internally on event.rawPath, and returns { statusCode, headers, body }. Same model as AWS Lambda + API Gateway v2's $default catch-all.

Contrast with WebApp (long-running HTTP server, persistent state across requests) and Function (event-driven, not necessarily HTTP).

Quick example

import { Project, API, Secret } from '@sprintsail/sdk';

export const app = new Project('orders');
export const apiKey = new Secret(app, 'api-key', {});

export const gateway = new API(app, 'gateway', {
handler: './src/handler.ts',
memory: 512,
bindings: { apiKey },
});

Your handler:

import { apiKey } from '../infra.js';

interface ApiGatewayV2Event {
rawPath: string;
rawQueryString: string;
headers: Record<string, string>;
body?: string;
requestContext: { http: { method: string; path: string } };
}

export default async function handler(event: ApiGatewayV2Event) {
const { method } = event.requestContext.http;
const path = event.rawPath;

if (method === 'GET' && path === '/health') {
return { statusCode: 200, body: 'ok' };
}
if (method === 'GET' && path === '/whoami') {
const key = await apiKey.value();
return {
statusCode: 200,
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ keyPrefix: key.slice(0, 6) }),
};
}
return { statusCode: 404, body: 'Not Found' };
}

Config

interface APIConfig {
handler: string;
runtime?: 'nodejs22' | 'nodejs20' | 'python3.12';
memory?: number; // MB, default 512
timeout?: number; // seconds, default 30
env?: Record<string, string>;
bindings?: Record<string, Database | Bucket | Secret | Queue>;
}

Target mapping

TargetMaps toNotes
awsLambda + API Gateway v2 (HTTP API)"Quick create" pattern — single Lambda, $default route, auto-deploying default stage.
sprintsail-runtimeDeployment + Service + Ingress + in-cluster API-gateway shimThe shim adapts incoming HTTP into the API Gateway v2 event shape. Catch-all Ingress to the shim. Handler code is identical to AWS.

API vs. WebApp

Both run HTTP. The split:

APIWebApp
LifecyclePer-requestLong-running
Cold startsPossibleNo (after minInstances ready)
DB connection poolsRecreated per requestPersist
Handler signature(event) => { statusCode, headers, body }Your own HTTP server
AWS mappingLambda + API GatewayECS Fargate
Best forWebhooks, internal APIs, low-volume endpointsExpress/FastAPI/Next.js, anything stateful

TLS & Ingress

Same as WebApp — HTTPS via cert-manager when a sail-issuer ClusterIssuer exists; configure host suffix via SAIL_INGRESS_DOMAIN.

Path routing

API has one Ingress with path: /. All routing is in your handler. This intentionally matches the AWS $default model — same handler code on both targets.