@pi-api/sdk is the official TypeScript client for Pi API. It wraps all Pi endpoints — brand intelligence, visual commerce, voice, health, neuro, surveillance, and robotics — into a single typed client you initialize once and use everywhere.
Entry point
Call createPiClient() to create the client. Every namespace hangs off the returned object.
import { createPiClient } from '@pi-api/sdk';
const pi = createPiClient({
apiKey: process.env.PI_API_KEY!,
baseUrl: 'https://api.example.com',
});
CreatePiClientOptions
| Option | Type | Required | Description |
|---|
apiKey | string | Yes | Bearer token issued for your organization (pi_live_…). |
baseUrl | string | Yes | Base URL of your deployed Pi API instance. |
providerKeys | ProviderKeys | No | BYOK credentials forwarded to third-party providers. |
fetchImpl | typeof fetch | No | Custom fetch implementation (defaults to global fetch). |
BYOK — bring your own keys
Pi API supports bring your own keys for third-party providers. Pass a providerKeys object when you create the client, and the SDK forwards each key as a request header automatically.
const pi = createPiClient({
apiKey: process.env.PI_API_KEY!,
baseUrl: 'https://api.example.com',
providerKeys: {
gemini: process.env.GEMINI_API_KEY,
firecrawl: process.env.FIRECRAWL_API_KEY,
livekit: process.env.LIVEKIT_API_KEY
? {
apiKey: process.env.LIVEKIT_API_KEY,
apiSecret: process.env.LIVEKIT_API_SECRET!,
}
: undefined,
},
});
providerKeys field | Request header |
|---|
gemini | X-Gemini-Api-Key |
firecrawl | X-Firecrawl-Api-Key |
livekit.apiKey | X-LiveKit-Api-Key |
livekit.apiSecret | X-LiveKit-Api-Secret |
You can also pass providerKeys per-call on any method that accepts an options parameter. Per-call keys override the client-level keys for that request only.
Error handling
All errors thrown by the SDK are instances of PiApiError. Catch it to access structured error details.
import { createPiClient, PiApiError } from '@pi-api/sdk';
try {
const job = await pi.brands.extract({ url: 'https://example.com' });
} catch (err) {
if (err instanceof PiApiError) {
console.error(err.status); // HTTP status code (number)
console.error(err.code); // Machine-readable error code
console.error(err.type); // Error category
console.error(err.requestId); // Request ID for support
console.error(err.message); // Human-readable message
}
}
PiApiError properties
| Property | Type | Description |
|---|
status | number | HTTP status code returned by the server. |
code | string | undefined | Machine-readable error code. |
type | string | undefined | Error category string. |
requestId | string | undefined | Request ID for tracing and support. |
details | Record<string, unknown> | undefined | Additional error context. |
message | string | Human-readable error message. |
Available namespaces
The client exposes these namespaces:
| Namespace | Accessed via | What it does |
|---|
brands | pi.brands | Extract brand DNA, list brands, retrieve a brand, project brand context. |
jobs | pi.jobs | Retrieve a job by ID, poll until completion. |
images | pi.images | Generate images and campaign ads (image-namespace alias). |
ads | pi.ads | Generate branded ad creatives. |
campaigns | pi.campaigns | Generate, edit, and localize campaign ads. |
avatars | pi.avatars | Generate, save, list, and retrieve AI avatars. |
voice | pi.voice | Manage voice agents, sessions, and voices. |
health | pi.health | Clinical triage, decision support, medication checks, scan analysis, and more. |
neuro | pi.neuro | Decode EEG/neural signals. |
surveillance | pi.surveillance | Analyze video streams, manage policies, and consume incident events via SSE. |
robots | pi.robots | Run agentic robotics tasks, issue commands, and stream robot events via SSE. |
runs | pi.runs | Create and retrieve multi-step agentic runs. |
webhooks | pi.webhooks | List, register, and update webhook endpoints. |
End-to-end example
Extract a brand and wait for the job to complete:
import { createPiClient, PiApiError } from '@pi-api/sdk';
const pi = createPiClient({
apiKey: process.env.PI_API_KEY!,
baseUrl: 'https://api.example.com',
providerKeys: {
gemini: process.env.GEMINI_API_KEY,
firecrawl: process.env.FIRECRAWL_API_KEY,
},
});
async function extractBrand(url: string) {
// 1. Queue the extraction job
const queued = await pi.brands.extract({ url });
// 2. Poll until completed (default timeout: 120 s)
const job = await pi.jobs.waitForCompletion(queued.data.job_id);
return job;
}
const result = await extractBrand('https://example.com');
console.log(result);
jobs.waitForCompletion() polls on a 1-second interval by default. Pass poll_interval_ms and timeout_seconds to tune the behavior for your use case.