Skip to main content
Every namespace is a property of the object returned by createPiClient(). Methods map directly to Pi API endpoints, validate inputs with Zod before sending, and parse responses through typed contracts.
import { createPiClient } from '@pi-api/sdk';

const pi = createPiClient({
  apiKey: process.env.PI_API_KEY!,
  baseUrl: process.env.PI_BASE_URL!,
});

Extract brand DNA from a URL or images, list saved brands, retrieve a single brand, or project its identity into a structured use-case context.Import
import { createPiClient } from '@pi-api/sdk';
const pi = createPiClient({ apiKey: '...', baseUrl: '...' });
// Access via: pi.brands
Methods
// Queue a brand DNA extraction job
pi.brands.extract(
  input: unknown,                                         // { url?, logoBase64?, imagesBase64?, location? }
  options?: { providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// List saved brands
pi.brands.list(params?: {
  query?: string;
  limit?: number;
  offset?: number;
  expand?: 'latest_job';
  include?: 'latest_job';
}): Promise<BrandList>

// Retrieve a single brand by ID
pi.brands.retrieve(
  id: string,
  params?: { expand?: 'latest_job'; include?: 'latest_job' }
): Promise<BrandRetrieve>

// Project brand DNA into a use-case-specific context
pi.brands.project(
  id: string,
  input: { use_case: string }
): Promise<BrandProjectionResponse>
Example
// Extract → wait → project
const queued = await pi.brands.extract({ url: 'https://example.com' });
const job = await pi.jobs.waitForCompletion(queued.data.job_id);

const brands = await pi.brands.list({ limit: 10 });
const brand = await pi.brands.retrieve(brands.data.data[0].id);

const projected = await pi.brands.project(brand.data.id, {
  use_case: 'Generate design tokens for a SaaS dashboard.',
});
console.log(projected.data.payload);
Retrieve a job by ID or poll until it reaches a terminal state (completed, failed, or cancelled).Methods
// Retrieve a job (single fetch)
pi.jobs.retrieve(
  id: string,
  params?: {
    expand?: 'brand' | 'avatar' | 'ad' | 'diagnostics';
    include?: 'brand' | 'avatar' | 'ad' | 'diagnostics';
    wait_for_completion?: boolean;
    timeout_seconds?: number;
  }
): Promise<JobRetrieve>

// Poll until the job reaches a terminal state
pi.jobs.waitForCompletion(
  id: string,
  options?: {
    timeout_seconds?: number;   // default: 120
    poll_interval_ms?: number;  // default: 1000
    include?: RequestOptions['query'];
  }
): Promise<JobRetrieve | unknown>
Example
// Queue any async job, then wait
const queued = await pi.brands.extract({ url: 'https://example.com' });

const completed = await pi.jobs.waitForCompletion(queued.data.job_id, {
  timeout_seconds: 60,
  poll_interval_ms: 2000,
});
waitForCompletion returns the parsed job envelope when the job finishes. If the timeout expires before the job completes, it returns the last-known job state.
Generate ad images or campaign images. Both methods are async and return a job_id for polling.Methods
// Generate a branded image (maps to POST /api/v1/images/generations)
pi.images.generate(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Generate a campaign ad image (maps to POST /api/v1/images/campaigns)
pi.images.campaigns(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>
Example
const queued = await pi.images.campaigns(
  {
    prompt: 'Premium Gen Z static ad for a soft drink',
    output: { aspect_ratio: '4:5', resolution: '1K' },
  },
  { idempotencyKey: 'my-campaign-run-001' },
);

const job = await pi.jobs.waitForCompletion(queued.data.job_id);
pi.images.campaigns() and pi.campaigns.generate() call equivalent backend routes and accept the same input schema. Use whichever naming fits your codebase conventions.
Generate a branded ad creative in a single async call.Methods
// Generate an ad creative (maps to POST /api/v1/ads/generate)
pi.ads.generate(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>
Example
const queued = await pi.ads.generate({
  brand_id: 'brand-uuid-here',
  prompt: 'Bold product ad for a summer launch',
  output: { aspect_ratio: '1:1', resolution: '2K' },
});

const job = await pi.jobs.waitForCompletion(queued.data.job_id);
Generate campaign ads, edit existing ads, and localize ads for different markets. All three methods are async and return a job_id.Methods
// Generate a new campaign ad
pi.campaigns.generate(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Edit an existing campaign ad
pi.campaigns.edit(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Localize a campaign ad for a different market
pi.campaigns.localizeAd(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>
Example
// Generate
const gen = await pi.campaigns.generate({
  prompt: 'Premium Gen Z static ad for a soft drink',
  output: { aspect_ratio: '4:5', resolution: '1K' },
});
await pi.jobs.waitForCompletion(gen.data.job_id);

// Edit
const edit = await pi.campaigns.edit({
  ad_id: 'ad-uuid-here',
  instructions: 'Make the background darker and add a city skyline.',
});
await pi.jobs.waitForCompletion(edit.data.job_id);

// Localize
const localized = await pi.campaigns.localizeAd({
  ad_id: 'ad-uuid-here',
  target_locale: 'fr-FR',
});
await pi.jobs.waitForCompletion(localized.data.job_id);
Generate, save, list, and retrieve AI avatar images.Methods
// Queue an avatar generation job
pi.avatars.generate(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Save a generated avatar for reuse
pi.avatars.save(input: unknown): Promise<SavedAvatarEnvelope>

// List saved avatars
pi.avatars.list(params?: {
  limit?: number;
  offset?: number;
}): Promise<SavedAvatarListEnvelope>

// Retrieve a saved avatar by ID
pi.avatars.retrieve(id: string): Promise<SavedAvatarRetrieveEnvelope>
Example
// Generate and then save
const queued = await pi.avatars.generate({
  prompt: 'Professional headshot, neutral background, confident expression',
});
const job = await pi.jobs.waitForCompletion(queued.data.job_id);

const saved = await pi.avatars.save({
  image_url: job.data.job_result.image_url,
  label: 'Brand spokesperson avatar',
});

const list = await pi.avatars.list({ limit: 20 });
const avatar = await pi.avatars.retrieve(saved.data.id);
Create and manage reusable voice agents, start LiveKit sessions, and complete sessions when a call ends.Methods
// --- Agents ---

// List all voice agents
pi.voice.agents.list(): Promise<VoiceAgentListResponse>

// Create a new voice agent
pi.voice.agents.create(input: unknown): Promise<VoiceAgentCreateResponse>

// Retrieve a voice agent by ID
pi.voice.agents.retrieve(id: string): Promise<VoiceAgentRetrieveResponse>

// Update a voice agent
pi.voice.agents.update(id: string, input: unknown): Promise<VoiceAgentRetrieveResponse>

// Delete a voice agent
pi.voice.agents.delete(id: string): Promise<VoiceAgentDeleteResponse>

// Preview a voice agent (test its voice and configuration)
pi.voice.agents.preview(id: string, input?: unknown): Promise<unknown>

// --- Sessions ---

// Create a new voice session (returns LiveKit token)
pi.voice.sessions.create(
  input: unknown,
  options?: { providerKeys?: ProviderKeys }
): Promise<unknown>

// Retrieve a voice session by ID
pi.voice.sessions.retrieve(id: string): Promise<unknown>

// Mark a session as complete
pi.voice.sessions.complete(id: string, input: unknown): Promise<unknown>

// --- Voices ---

// List available voices
pi.voice.voices.list(): Promise<unknown>
Example
// Create a voice agent
const agent = await pi.voice.agents.create({
  name: 'Support Agent',
  voice_id: 'en-US-neural-1',
  system_prompt: 'You are a helpful customer support agent.',
});

// Start a session using that agent
const session = await pi.voice.sessions.create(
  { agent_id: agent.data.id },
  { providerKeys: { livekit: { apiKey: '...', apiSecret: '...' } } },
);

// Complete the session when the call ends
await pi.voice.sessions.complete(session.data.id, {
  summary: 'User resolved billing question.',
});

// List all agents
const agents = await pi.voice.agents.list();
Voice sessions require LiveKit credentials. Pass them via providerKeys.livekit either at client initialization or per-call in the options argument.
Nine async methods covering the full clinical intelligence surface: triage, decision support, medication checks, clinical notes structuring, adherence analysis, patient risk prioritization, scan analysis, research assistance, and cognitive wellness.Methods
// Health triage — analyze symptoms and suggest urgency
pi.health.analyze(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Clinical decision support
pi.health.decisionSupport(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Medication interaction and safety check
pi.health.medicationCheck(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Structure free-text clinical notes
pi.health.notesStructure(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Medication adherence analysis
pi.health.adherence(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Patient risk prioritization
pi.health.riskPriority(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Medical image / scan analysis
pi.health.scanAnalysis(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Research assistance (literature lookup, evidence synthesis)
pi.health.researchAssist(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Cognitive wellness assessment
pi.health.wellness(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>
Example
// Run a triage analysis
const queued = await pi.health.analyze({
  patient_id: 'p-001',
  chief_complaint: 'Chest pain, onset 2 hours ago, radiating to left arm.',
  vitals: { bp: '140/90', hr: 102, temp: 37.1 },
});
const result = await pi.jobs.waitForCompletion(queued.data.job_id);

// Check medication interactions
const medCheck = await pi.health.medicationCheck({
  medications: ['warfarin 5mg', 'aspirin 81mg', 'ibuprofen 400mg'],
  patient_context: { age: 68, weight_kg: 78 },
});
await pi.jobs.waitForCompletion(medCheck.data.job_id);
Health API outputs are decision-support tools, not replacements for professional clinical judgment. Always validate results with qualified clinicians before acting on them in care settings.
Decode EEG or other neural signal data asynchronously.Methods
// Decode neural/EEG signals
pi.neuro.decode(
  input: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>
Example
const queued = await pi.neuro.decode({
  signal_type: 'eeg',
  data: eegBuffer, // your raw signal data
  channel_count: 64,
  sample_rate_hz: 256,
});

const result = await pi.jobs.waitForCompletion(queued.data.job_id);
Create video streams, manage detection policies, and consume real-time incident events over SSE.Methods
// --- Streams ---

// Register a new video stream for analysis
pi.surveillance.streams.create(
  body: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// --- Policies ---

// List detection policies, optionally filtered by stream
pi.surveillance.policies.list(
  params?: { stream_id?: string }
): Promise<SurveillancePoliciesListResponse>

// Create or update a detection policy
pi.surveillance.policies.upsert(body: unknown): Promise<SurveillancePolicyUpsertResponse>

// --- Events (SSE) ---

// Open an SSE stream of real-time incident events
pi.surveillance.events(
  params: {
    stream_id: string;
    severity?: 'info' | 'warning' | 'critical';
  },
  options?: { providerKeys?: ProviderKeys }
): AsyncIterable<{ event?: string; data: string }>
Example
// Register a stream
await pi.surveillance.streams.create({
  stream_url: 'rtsp://camera.example.com/feed1',
  label: 'Front entrance camera',
});

// Set a policy
await pi.surveillance.policies.upsert({
  stream_id: 'cam-1',
  rules: [{ type: 'person_detection', threshold: 0.85 }],
});

// Consume live incident events
for await (const msg of pi.surveillance.events({ stream_id: 'cam-1', severity: 'critical' })) {
  const event = msg.event ?? 'message';
  const data = JSON.parse(msg.data);
  console.log(event, data);
}
surveillance.events() returns an AsyncIterable. Use for await…of to consume the SSE stream. The loop runs until the server closes the connection or you break out of it.
Submit robotics runs, query robot status, issue real-time commands, manage zones and behaviors, and stream live robot events over SSE.
The client exposes this namespace as pi.robots (not pi.robotics).
Methods
// --- Core ---

// Queue an agentic robotics run
pi.robots.run(
  body: unknown,
  options?: { idempotencyKey?: string; providerKeys?: ProviderKeys }
): Promise<ExtractJobQueued>

// Get the current status of a robot
pi.robots.status(id: string): Promise<unknown>

// Send a real-time command to a robot
pi.robots.command(id: string, body: unknown): Promise<unknown>

// --- Zones ---

// List geographic or logical zones
pi.robots.zones.list(params?: { robot_id?: string }): Promise<RobotZonesListResponse>

// Create or update zones (1–200 zones per request)
pi.robots.zones.upsert(body: unknown): Promise<RobotZonesCreateResponse>

// --- Behaviors ---

// List behavior rules
pi.robots.behaviors.list(params?: { robot_id?: string }): Promise<RobotBehaviorsListResponse>

// Create or update a behavior rule
pi.robots.behaviors.upsert(body: unknown): Promise<RobotBehaviorsCreateResponse>

// --- Actions ---

// List action rules
pi.robots.actions.list(params?: { behavior_id?: string }): Promise<RobotActionsListResponse>

// Create or update an action rule
pi.robots.actions.upsert(body: unknown): Promise<RobotActionsCreateResponse>

// --- Events (SSE) ---

// Open an SSE stream of live robot telemetry events
pi.robots.events(
  options?: { providerKeys?: ProviderKeys }
): AsyncIterable<{ event?: string; data: string }>
Example
// Dispatch a run
const queued = await pi.robots.run({
  robot_id: 'robot-uuid-here',
  task: 'Navigate to zone B and perform inspection.',
});
await pi.jobs.waitForCompletion(queued.data.job_id);

// Check status
const status = await pi.robots.status('robot-uuid-here');

// Issue a stop command
await pi.robots.command('robot-uuid-here', { action: 'stop' });

// Stream live telemetry
for await (const msg of pi.robots.events()) {
  const event = msg.event ?? 'message';
  const data = JSON.parse(msg.data);
  console.log(event, data);
}
Create and retrieve multi-step agentic runs that orchestrate multiple Pi capabilities together.Methods
// Create a new agentic run
pi.runs.create(input: unknown): Promise<RunCreateResponse>

// Retrieve a run by ID
pi.runs.retrieve(
  id: string,
  params?: {
    wait_for_completion?: boolean;
    timeout_seconds?: number;
  }
): Promise<RunRetrieve>

// Create a run and poll until it completes
pi.runs.createAndWait(
  input: unknown,
  options?: {
    timeout_seconds?: number;   // default: 120
    poll_interval_ms?: number;  // default: 1000
  }
): Promise<RunRetrieve>
Example
// Fire-and-poll in one call
const run = await pi.runs.createAndWait(
  {
    steps: [
      { namespace: 'brands', method: 'extract', input: { url: 'https://example.com' } },
      { namespace: 'campaigns', method: 'generate', input: { prompt: 'Launch ad' } },
    ],
  },
  { timeout_seconds: 180 },
);

// Or create and retrieve separately
const created = await pi.runs.create({ steps: [] });
const retrieved = await pi.runs.retrieve(created.data.run_id, {
  wait_for_completion: true,
  timeout_seconds: 60,
});
Register, list, and update webhook endpoints that Pi will call when async jobs complete.Methods
// List all registered webhooks
pi.webhooks.list(): Promise<WebhookListResponse>

// Register a new webhook endpoint
pi.webhooks.create(input: unknown): Promise<WebhookResponse>

// Update an existing webhook
pi.webhooks.update(id: string, input: unknown): Promise<WebhookResponse>
Example
// Register a webhook
const webhook = await pi.webhooks.create({
  url: 'https://yourapp.example.com/webhooks/pi',
  events: ['job.completed', 'job.failed'],
  secret: process.env.WEBHOOK_SECRET,
});

// List all webhooks
const all = await pi.webhooks.list();

// Update (e.g. rotate secret or change events)
await pi.webhooks.update(webhook.data.id, {
  events: ['job.completed', 'job.failed', 'job.cancelled'],
});
Use webhook events to avoid polling altogether. Register a job.completed webhook and let Pi push results to your server as soon as each job finishes.