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
| Target | Maps to | Notes |
|---|---|---|
aws | Lambda + API Gateway v2 (HTTP API) | "Quick create" pattern — single Lambda, $default route, auto-deploying default stage. |
sprintsail-runtime | Deployment + Service + Ingress + in-cluster API-gateway shim | The 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:
| API | WebApp | |
|---|---|---|
| Lifecycle | Per-request | Long-running |
| Cold starts | Possible | No (after minInstances ready) |
| DB connection pools | Recreated per request | Persist |
| Handler signature | (event) => { statusCode, headers, body } | Your own HTTP server |
| AWS mapping | Lambda + API Gateway | ECS Fargate |
| Best for | Webhooks, internal APIs, low-volume endpoints | Express/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.