TypeScript SDK
The TypeScript client is generated from the kernel’s OpenAPI document — the same document that drives the REST API and the Python SDK. Because the OpenAPI is itself a projection of the operation registry, the generated types track the live API by construction: add an operation, regenerate, and you get a fully-typed method for it.
This is the typed client the Geopera portal uses against its own backend, and you can generate the identical types for your own project from the published OpenAPI.
Generate the types
Use openapi-typescript to turn the
OpenAPI document into a .d.ts of operation types:
npx openapi-typescript https://api.geopera.com/openapi.json -o kernel-api.d.tsThat gives you an operations map keyed by operation_id, from which you can derive the
input and output type of any operation:
import type { operations } from "./kernel-api";
export type KernelOpId = keyof operations;
export type KernelOpInput<K extends KernelOpId> =
operations[K]["requestBody"]["content"]["application/json"];
export type KernelOpOutput<K extends KernelOpId> =
operations[K]["responses"][200]["content"]["application/json"];A typed invoke helper
Wrap the operation endpoint once and every call is type-checked — the body type and the
return type are inferred from the operation_id you pass:
const BASE_URL = "https://api.geopera.com";
/** Error that preserves the RFC-7807 problem+json body. */
export class KernelOpError extends Error {
constructor(public status: number, public problem: unknown) {
super(`kernel op failed (${status})`);
}
}
export async function callKernelOp<K extends KernelOpId>(
op: K,
body: KernelOpInput<K>,
token: string,
extraHeaders: Record<string, string> = {},
): Promise<KernelOpOutput<K>> {
const res = await fetch(`${BASE_URL}/v1/op/${op}`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
...extraHeaders,
},
body: JSON.stringify(body),
});
if (!res.ok) throw new KernelOpError(res.status, await res.json());
return (await res.json()) as KernelOpOutput<K>;
}Use it
The compiler now knows the exact shape of every operation’s input and output:
// Search the catalog — `body` is type-checked against catalog.search's input
const results = await callKernelOp(
"catalog.search",
{ host_name: "earthsearch-aws", collections: ["sentinel-2-l2a"], bbox: [151, -34, 152, -33], limit: 25 },
token,
);
// Place an order with an idempotency key — return type is the order output
const order = await callKernelOp(
"orders.archive.place",
{ projectId, captures: [{ id: "scene-abc", geometry }] },
token,
{ "Idempotency-Key": crypto.randomUUID() },
);
console.log(order.id, order.status, order.totalCredits);If you only need the raw Response (e.g. to stream an NDJSON or binary operation), call
the endpoint directly and skip the JSON parse — the streaming/raw_response operations
are the ones to handle this way.
Authentication
Obtain a token the same way as any other client — the OIDC token endpoint
(client_credentials with an API key, or password for a user). See Authentication. Tokens are short-lived (5 minutes);
refresh with the refresh token rather than re-authenticating.
Errors
callKernelOp throws KernelOpError carrying the application/problem+json body, so you branch on err.status (e.g. 402 for payment, 409 for conflicts) and read err.problem.detail for the specific message.