@roadie/sdk is the first-party TypeScript SDK for the Roadie data plane. It is isomorphic — it runs on Node 20+, browsers, and React Native / Expo over the WHATWG fetch + streams standard — and ships with zero runtime dependencies. It wraps the data plane with typed errors, automatic retries, idempotency, timeouts, and streaming.
Prefer to keep your existing OpenAI code? Point the official OpenAI SDK at Roadie instead — see Using OpenAI SDKs. Both hit the same gateway.

Install

Roadie is pre-1.0 (0.x); changes inside /v1 are additive.

Authentication

The client is constructed in exactly one of two modes — supplying both, or neither, throws a RoadieConfigurationError.
A secret key (rd_sk_…) grants full access to your project’s data plane. Constructing the client with one in a browser-like environment (where window is defined) throws immediately — pass dangerouslyAllowBrowser: true only if you are certain the code runs server-side. Client apps must authenticate with a tokenProvider; see Client tokens and Authentication.

Client options

Both modes accept these options (plus exactly one of apiKey / tokenProvider):

Quickstart

roadie.chat.create returns the normalized response — the assistant message, finish_reason, token usage, an estimated cost, and the gateway requestId.
model accepts an explicit provider/model id (like openai/gpt-4o) or a project alias you configure (like smart) that fails over across providers. See Models, aliases & fallback.

Method surface

Every resource method accepts a trailing options object with signal?: AbortSignal and timeoutMs?: number (streaming also accepts framing?: 'sse' | 'ndjson'). ChatParams is a chat request minus stream: model, messages, and the optional temperature, max_output_tokens, response_format, tools, tool_choice, user, metadata, and provider_options. EmbeddingsParams is model, input (a string or string array), and the optional dimensions, user, metadata, provider_options.

Response metadata

Every result carries the gateway requestId and a rateLimit snapshot as non-enumerable properties, so JSON.stringify(res) still yields exactly the wire body:

Streaming

roadie.chat.stream(...) returns a ChatStream synchronously; the HTTP connection is opened lazily on the first for await step. Iterate the unified frames — content_delta carries incremental text and the terminal message_end carries the final usage and cost:
Frame types are message_start, content_delta, tool_call_delta, usage, message_end, and a terminal error frame for a mid-stream failure (nothing follows it). Cancel a stream (or any call) with an AbortSignal; breaking out of the loop closes the socket. NDJSON framing is available via { framing: 'ndjson' }. See Streaming.

Feedback

roadie.feedback.submit rates a prior response by its gateway requestId:
rating is 'up' or 'down'. (The endpoint also accepts a 1–5 numeric score, but the SDK deliberately exposes only thumbs.)

Client tokens

Client apps never hold a secret key. Supply a tokenProvider — a () => string | Promise<string> the SDK caches and refreshes (at 80% of the token’s TTL, single-flighting concurrent refreshes).
  • Path A (backend mint). Your backend mints a client token; the app fetches it. The provider is just the fetch: tokenProvider: async () => (await fetch('/api/roadie-token')).text().
  • Path B (federated identity, no backend). Exchange your existing IdP token (Firebase, Auth0, Supabase, Cognito, …) plus your publishable key for a client token with the federatedTokenProvider helper:
TokenManager and the TokenProvider type are exported for advanced cases. See Client tokens and the zero-backend federated identity tutorial.

Error handling

Every failure is a RoadieError subclass carrying a stable code, the requestId, the HTTP status, and (for rate limits) retryAfter. Branch on the class, or use isRoadieError(err) and read err.type / err.code.
Envelope-mapped classes (one per gateway error type): InvalidRequestError, AuthenticationError, PermissionError, NotFoundError, RateLimitError, QuotaError, BudgetError, ProviderError, IdempotencyError, InternalError. Client-side classes: APIConnectionError, APIConnectionTimeoutError (the request exceeded its timeoutMs), APIUserAbortError (the caller aborted via its own AbortSignal), and RoadieConfigurationError. The SDK already retries transient failures (network errors, 429, 5xx) before they reach you, honoring Retry-After, and reuses one auto Idempotency-Key across those retries so a retried create is de-duplicated by the gateway. See Errors & retries and the full error reference.

Not included

This SDK is a focused client for the data-plane runtime surface. It intentionally does not cover:
  • Model catalog — there is no roadie.models.list. Aliases and provider/model ids resolve server-side; browse the catalog via the raw GET /v1/models endpoint or the Python SDK.
  • Request cancellation endpoint — there is no cancel method. Abort an in-flight request client-side with an AbortSignal.
  • Images — no image resource. Generate images through the OpenAI-compatible surface (or RoadieKit on iOS).
  • Backend client-token minting (Path A) — there is no roadie.client_tokens.create. Mint tokens from your backend with the Python SDK or POST /v1/client-tokens; this SDK covers the Path-B exchange via federatedTokenProvider.
  • Control-plane management (projects, keys, budgets). That is the separate management API.

Next steps

Node quickstart

A 10-minute server integration, every snippet run in CI.

Next.js quickstart

Wrap the SDK in a server-side route.

Client tokens

Authenticate browser and mobile apps safely.

Error reference

Every error type and code, with how to handle each.