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:

bash
npx openapi-typescript https://api.geopera.com/openapi.json -o kernel-api.d.ts

That gives you an operations map keyed by operation_id, from which you can derive the input and output type of any operation:

ts
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:

ts
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:

ts
// 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.