Skip to content
GridRouterhome

Search

Search providers, capabilities and pages

Docs

TypeScript SDK

The @relaygrid/sdk client for calls, routed runs and the live log.

Not on npm yet

@relaygrid/sdk is not published yet. Until it is, call the REST API with fetch (see the first call). This page documents the client as it stands, so you know what is coming.

The SDK covers calls (one endpoint or a routed capability) and the live log. It runs anywhere with fetch and web streams on the server: Node 20+, Bun, Deno and Workers. Never ship an API key to a browser.

Create a client

import { createGrid } from "@relaygrid/sdk";

const grid = createGrid({ apiKey: process.env.GRID_API_KEY! });
OptionDefault
apiKey—A key with call and run for calls, logs:read for the log
baseUrlhttps://api.gridrouter.io
fetchglobal fetchInject your own (tests, proxies)
userAgent—Sent as User-Agent
app—Sent as X-Grid-App, so calls are attributed to your app in logs
title—Sent as X-Title: your app's display name

Run a capability

run lets GridRouter route: it tries the vendors for a capability in route order and stops at the first hit. The body is the run request.

const result = await grid.run("people.email.find", {
  input: { first_name: "Ada", last_name: "Lovelace", domain: "stripe.com" },
  options: { cost: { max_cost_micro: 50_000 } },
});
console.log(result.provider, result.data);

Call one endpoint

call pins a vendor endpoint. Async endpoints return a Job to poll instead of a result.

const res = await grid.call("hunter/email.find", {
  input: { first_name: "Ada", last_name: "Lovelace", domain: "stripe.com" },
  include_raw: true,
});

Stream the live log

const tail = grid.logs.tail(
  {
    filter: { kinds: "call", capability: "people.email.find", status: "failed" },
    onControl: (frame) => console.error(frame.kind),
    onError: (err) => console.error(err),
  },
  (event) => {
    if (event.kind === "call") console.log(event.row.call_id, event.row.outcome);
  },
);

// later
tail.close();
await tail.done;
console.log(`dropped ${tail.dropped} events`);

filter takes the same keys as the live tail. tail streams over SSE, reconnects with backoff from 0.5 s to 10 s, asks for replay=100 on reconnect and skips events it has already delivered. It stops on a 4xx other than 429 and reports it to onError. Pass signal to stop with an AbortSignal, or reconnect: false to stop at the first disconnect.

Read recent events

const { items } = await grid.logs.recent({ kinds: "call", limit: 20 });

items is newest last, up to 1,000 (default 50).

Errors

Failed requests throw GridApiError, which carries the error envelope's code, message and HTTP status.