Skip to main content
@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

OptionTypeRequiredDescription
apiKeystringYesBearer token issued for your organization (pi_live_…).
baseUrlstringYesBase URL of your deployed Pi API instance.
providerKeysProviderKeysNoBYOK credentials forwarded to third-party providers.
fetchImpltypeof fetchNoCustom 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,
  },
});

Provider key headers

providerKeys fieldRequest header
geminiX-Gemini-Api-Key
firecrawlX-Firecrawl-Api-Key
livekit.apiKeyX-LiveKit-Api-Key
livekit.apiSecretX-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

PropertyTypeDescription
statusnumberHTTP status code returned by the server.
codestring | undefinedMachine-readable error code.
typestring | undefinedError category string.
requestIdstring | undefinedRequest ID for tracing and support.
detailsRecord<string, unknown> | undefinedAdditional error context.
messagestringHuman-readable error message.

Available namespaces

The client exposes these namespaces:
NamespaceAccessed viaWhat it does
brandspi.brandsExtract brand DNA, list brands, retrieve a brand, project brand context.
jobspi.jobsRetrieve a job by ID, poll until completion.
imagespi.imagesGenerate images and campaign ads (image-namespace alias).
adspi.adsGenerate branded ad creatives.
campaignspi.campaignsGenerate, edit, and localize campaign ads.
avatarspi.avatarsGenerate, save, list, and retrieve AI avatars.
voicepi.voiceManage voice agents, sessions, and voices.
healthpi.healthClinical triage, decision support, medication checks, scan analysis, and more.
neuropi.neuroDecode EEG/neural signals.
surveillancepi.surveillanceAnalyze video streams, manage policies, and consume incident events via SSE.
robotspi.robotsRun agentic robotics tasks, issue commands, and stream robot events via SSE.
runspi.runsCreate and retrieve multi-step agentic runs.
webhookspi.webhooksList, 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.