OrbitPeople.aidocs

TypeScript SDK

npm install @orbit/sdk → typed client with auto-pagination and webhook verification.

Server-side only. API keys (ok_live_…) are workspace secrets — never ship them to a browser or mobile app. Route calls through your backend.

Install

npm install @orbit/sdk
# or: bun add / pnpm add / yarn add

Requires Node ≥ 20 (global fetch + Web Crypto). Zero runtime dependencies. Dual ESM/CJS with full type declarations.

Quickstart

import { OrbitClient } from "@orbit/sdk";

const orbit = new OrbitClient({
  apiKey: process.env.ORBIT_API_KEY!,
  baseUrl: "https://<your-deployment>.convex.site",
});

const { projectId } = await orbit.search({
  brief: "Senior fintech engineers in Berlin with payments experience",
});

const status = await orbit.waitForCompletion(projectId, {
  timeoutMs: 10 * 60 * 1000,
});

if (status.status === "awaiting_input") {
  console.log("Clarification needed:", status.clarificationQuestion);
} else {
  for await (const person of orbit.listAllResults(projectId)) {
    console.log(person.fullName, person.title, person.linkedinUrl);
  }
}

Client API

new OrbitClient({ apiKey, baseUrl, fetch?, maxRetries? })
MethodReturns
orbit.search({ brief, callbackUrl? })Promise<SearchResponse>
orbit.getProject(projectId)Promise<ProjectStatus>
orbit.getResults(projectId, { limit?, offset? })Promise<ResultsResponse>
orbit.listAllResults(projectId)AsyncGenerator<ResultRow>
orbit.exportCsv(projectId)Promise<string>
orbit.waitForCompletion(projectId, opts?)Promise<ProjectStatus>

listAllResults auto-paginates at the 200-item cap until all results are returned.

waitForCompletion polls every pollIntervalMs (default 3 000 ms) until done or awaiting_input; throws OrbitTimeoutError past timeoutMs; honors an AbortSignal.

CSV export

const csv = await orbit.exportCsv(projectId);
// byte-identical to Orbit's in-app export

Webhook verification

import { verifyWebhookSignature, type CallbackEvent } from "@orbit/sdk";

const valid = await verifyWebhookSignature({
  payload: rawBody, // unparsed request body string
  signature: req.headers["x-orbit-signature"], // "sha256=<hex>"
  secret: process.env.ORBIT_WEBHOOK_SECRET!,
});
if (!valid) return new Response("bad signature", { status: 401 });

const event = JSON.parse(rawBody) as CallbackEvent;
// event.projectId, event.status, event.resultsUrl

Error handling

import { OrbitApiError, OrbitTimeoutError } from "@orbit/sdk";

try {
  await orbit.search({ brief });
} catch (err) {
  if (err instanceof OrbitApiError) {
    // err.code: "unauthorized" | "not_found" | "invalid_request" |
    //           "limit_exceeded" | "rate_limited" | "internal_error"
  }
  if (err instanceof OrbitTimeoutError) {
    // waitForCompletion exceeded timeoutMs
  }
}

Transient faults (network errors + 5xx) retry automatically with doubling backoff up to maxRetries (default 2). 4xx never retries.

search retries on network errors, which can create a duplicate project if the server accepted the first request but the response was lost. Set maxRetries: 0 if duplicate projects are worse than a manual retry.

On this page