Skip to content
SDK

SDK Documentation

Installation

Install the SDK via npm, yarn, or pnpm. The package includes the client library, CLI tools, and full TypeScript type definitions.

# npm
npm install @aiffinity/provider-platform-sdk

# yarn
yarn add @aiffinity/provider-platform-sdk

# pnpm
pnpm add @aiffinity/provider-platform-sdk

The SDK requires Node.js 20 or later. It ships ESM and CJS dual builds, so it works in any module system.

Client Initialization

Create a ProviderPlatformClient instance with your app credentials. You receive a clientId and clientSecret when you create an app in the developer console.

import { ProviderPlatformClient } from '@aiffinity/provider-platform-sdk';

const client = new ProviderPlatformClient({
  clientId: process.env.AIFFINITY_CLIENT_ID!,
  clientSecret: process.env.AIFFINITY_CLIENT_SECRET!,
});

Configuration options

OptionTypeDefaultDescription
clientIdstringYour app's client ID (required)
clientSecretstringYour app's client secret (required)
baseUrlstringhttps://api.aiffinity.meAPI base URL. Use https://api.staging.aiffinity.me for sandbox.
timeoutnumber30000Request timeout in milliseconds
retriesnumber2Number of automatic retries for transient failures (5xx, network errors)
loggerLoggerconsoleCustom logger instance. Must implement info, warn, error.
// Full configuration example
const client = new ProviderPlatformClient({
  clientId: process.env.AIFFINITY_CLIENT_ID!,
  clientSecret: process.env.AIFFINITY_CLIENT_SECRET!,
  baseUrl: 'https://api.staging.aiffinity.me',
  timeout: 15000,
  retries: 3,
  logger: pino({ level: 'debug' }),
});

client.apps

Manage your provider applications. Each app represents a distinct service on the Aiffinity platform with its own credentials, webhook endpoints, and policy scope.

client.apps

App lifecycle management — create, list, retrieve, update, and delete provider apps.

MethodParametersReturnsDescription
create(opts)CreateAppOptsPromise<App>Register a new app. Returns the app with generated client_id and client_secret.
list()Promise<App[]>List all apps belonging to your developer account.
get(id)stringPromise<App>Retrieve a single app by ID.
update(id, opts)string, UpdateAppOptsPromise<App>Update app name, description, redirect URIs, or webhook URL.
delete(id)stringPromise<void>Delete an app. All associated packages become orphaned.
// Create an app
const app = await client.apps.create({
  name: 'Acme Weather',
  description: 'Real-time weather data and forecasts',
  redirectUris: ['https://acmeweather.com/callback'],
  webhookUrl: 'https://acmeweather.com/webhooks/aiffinity',
});

console.log(app.clientId);   // "prov_abc123..."
console.log(app.clientSecret); // "secret_xyz789..." (shown once)

// List all apps
const apps = await client.apps.list();

// Update an app
await client.apps.update(app.id, {
  description: 'Weather data, forecasts, and severe weather alerts',
});

// Delete an app
await client.apps.delete(app.id);

client.packages

Manage capability packages. A package bundles one or more capability descriptors with listing metadata, risk tier classification, and version history.

client.packages

Full package lifecycle — create, version, validate, submit, and publish.

MethodParametersReturnsDescription
create(opts)CreatePackageOptsPromise<Package>Create a new package with an initial version.
list()Promise<Package[]>List all packages for your account.
get(id)stringPromise<Package>Retrieve a package with its version history.
createVersion(id, opts)string, CreateVersionOptsPromise<PackageVersion>Create a new version of an existing package.
validate(id, versionId)string, stringPromise<ValidationResult>Run the conformance suite against a package version. Returns a score across 6 dimensions.
submit(id, versionId)string, stringPromise<SubmissionResult>Submit a version for review. data_only packages are auto-listed.
publish(id, versionId)string, stringPromise<void>Publish a reviewed version to the catalog.
deprecate(id, versionId)string, stringPromise<void>Deprecate a published version. Existing installs continue working; new installs are blocked.
// Create a package
const pkg = await client.packages.create({
  appId: app.id,
  name: 'Weather Widgets',
  slug: 'acme-weather-widgets',
  description: 'Live weather conditions and forecasts',
  riskTier: 'data_only',
  capabilities: [
    {
      type: 'state',
      name: 'current_weather',
      schema: { /* ... */ },
      surfaceGuidance: {
        intent: 'ambient_context',
        placement: ['home_widgets', 'daily_brief'],
        components: ['stat_row', 'sparkline'],
      },
    },
  ],
});

// Create a new version
const version = await client.packages.createVersion(pkg.id, {
  capabilities: [ /* updated descriptors */ ],
  changelog: 'Added humidity and wind speed fields',
});

// Validate before submission
const result = await client.packages.validate(pkg.id, version.id);
if (result.passed) {
  await client.packages.submit(pkg.id, version.id);
}

// Publish after review approval
await client.packages.publish(pkg.id, version.id);

// Deprecate an old version
await client.packages.deprecate(pkg.id, oldVersionId);

client.runtime

Register capability handlers and start the runtime server. The runtime receives invocation requests from Aiffinity and returns data according to your capability schemas.

client.runtime

Runtime server management — register handlers and manage the server lifecycle.

MethodParametersReturnsDescription
registerHandler(name, handler)string, CapabilityHandlervoidRegister a handler for a named capability. Must match a capability name in your package.
start(opts?)RuntimeStartOptsPromise<void>Start the HTTP server. Listens for invocation requests from Aiffinity.
health()Promise<HealthStatus>Returns the health status of the runtime, including registered handlers and uptime.
import { ProviderPlatformClient, CapabilityHandler } from '@aiffinity/provider-platform-sdk';

const client = new ProviderPlatformClient({
  clientId: process.env.AIFFINITY_CLIENT_ID!,
  clientSecret: process.env.AIFFINITY_CLIENT_SECRET!,
});

const weatherHandler: CapabilityHandler = {
  async execute(request) {
    const weather = await fetchWeatherData(request.params.location);
    return {
      status: 'ok',
      data: {
        location: weather.city,
        temperature_c: weather.temp,
        condition: weather.condition,
      },
      ttl: 900,
    };
  },
};

client.runtime.registerHandler('current_weather', weatherHandler);

await client.runtime.start({ port: 3000 });
// Runtime listening on http://localhost:3000

CapabilityHandler interface

interface CapabilityHandler {
  /** Handle an invocation request and return capability data. */
  execute(request: InvocationRequest): Promise<InvocationResponse>;

  /** Optional: called once when the runtime starts. Use for setup/warmup. */
  init?(): Promise<void>;

  /** Optional: called on graceful shutdown. Use for cleanup. */
  teardown?(): Promise<void>;
}

interface InvocationRequest {
  /** Unique invocation ID for tracing. */
  invocationId: string;
  /** The capability being invoked. */
  capabilityName: string;
  /** Parameters passed by the Aiffinity orchestrator. */
  params: Record<string, unknown>;
  /** Authenticated user context (anonymized). */
  userContext: {
    userId: string;
    locale: string;
    timezone: string;
  };
}

interface InvocationResponse {
  status: 'ok' | 'error' | 'partial';
  data?: Record<string, unknown>;
  error?: { code: string; message: string };
  ttl?: number; // Cache TTL in seconds
}

client.sandbox

Create test scenarios, run conformance tests, and inspect execution traces in an isolated sandbox environment. Use this during development to validate your handlers before submission.

client.sandbox

Sandbox testing — create scenarios, run tests, and inspect traces.

MethodParametersReturnsDescription
createScenario(opts)CreateScenarioOptsPromise<Scenario>Create a test scenario with mock user context and expected inputs.
runTest(scenarioId)stringPromise<TestResult>Execute a scenario against your running handler. Returns pass/fail with detailed assertions.
getTraces(opts?)GetTracesOptsPromise<Trace[]>Retrieve execution traces for debugging. Includes request/response payloads, latency, and errors.
// Create a test scenario
const scenario = await client.sandbox.createScenario({
  capabilityName: 'current_weather',
  params: { location: 'Berlin, DE' },
  userContext: { userId: 'test-user-1', locale: 'en-US', timezone: 'Europe/Berlin' },
  assertions: [
    { path: 'data.location', operator: 'contains', value: 'Berlin' },
    { path: 'data.temperature_c', operator: 'type', value: 'number' },
    { path: 'ttl', operator: 'gte', value: 300 },
  ],
});

// Run the test
const result = await client.sandbox.runTest(scenario.id);
console.log(result.passed);       // true
console.log(result.assertions);   // [{ path: '...', passed: true }, ...]
console.log(result.latencyMs);    // 142

// Inspect traces
const traces = await client.sandbox.getTraces({
  capabilityName: 'current_weather',
  limit: 10,
  since: '2026-04-01T00:00:00Z',
});

for (const trace of traces) {
  console.log(trace.invocationId, trace.status, trace.durationMs);
}

client.certification

Monitor your package's certification status, performance baselines, and quality alerts. Aiffinity continuously evaluates published packages against baseline metrics.

client.certification

Certification monitoring — track quality scores, baselines, and alerts.

MethodParametersReturnsDescription
getCertification(packageId?)stringPromise<Certification>Get the current certification status and scores for a package.
getBaseline(packageId?)stringPromise<Baseline>Get performance baselines: p50/p95/p99 latency, error rate, availability.
listAlerts(opts?)ListAlertsOptsPromise<Alert[]>List active and resolved quality alerts for your packages.
// Check certification status
const cert = await client.certification.getCertification(pkg.id);
console.log(cert.status);    // 'certified' | 'warning' | 'revoked'
console.log(cert.score);     // 94
console.log(cert.dimensions); // { schema: 18, contracts: 16, perf: 15, ... }

// Get performance baselines
const baseline = await client.certification.getBaseline(pkg.id);
console.log(baseline.latency);     // { p50: 120, p95: 340, p99: 890 }
console.log(baseline.errorRate);   // 0.002
console.log(baseline.availability); // 0.9995

// List quality alerts
const alerts = await client.certification.listAlerts({
  status: 'active',
  severity: 'warning',
});

for (const alert of alerts) {
  console.log(alert.type, alert.message, alert.triggeredAt);
}

Widget Helpers

The SDK provides helper functions for building and validating widget surface guidance specs. These ensure your surface guidance payloads conform to the Aiffinity component schema before submission.

createWidgetSpec()

Build a type-safe widget specification object. The function validates the component type and enforces required fields at compile time (TypeScript) and runtime.

import { createWidgetSpec, validateWidgetSpec } from '@aiffinity/provider-platform-sdk';

const spec = createWidgetSpec({
  component: 'stat_row',
  objective: 'inform',
  density: 'compact',
  props: {
    label: 'Temperature',
    value: '24°C',
    trend: { direction: 'up', delta: '+3°' },
  },
});

// spec is typed as WidgetSpec<'stat_row'>

validateWidgetSpec()

Validate a widget spec object against the component schema. Returns a detailed validation result with any errors.

const result = validateWidgetSpec(spec);

if (!result.valid) {
  for (const error of result.errors) {
    console.error(`${error.path}: ${error.message}`);
    // e.g. "props.value: Required field missing"
  }
}

WidgetSpec type definition

interface WidgetSpec<T extends WidgetComponentType = WidgetComponentType> {
  /** Component type identifier. */
  component: T;
  /** What this widget is trying to achieve. */
  objective: WidgetObjective;
  /** Visual density: compact, standard, or expanded. */
  density: WidgetDensity;
  /** Component-specific props. Type varies by component. */
  props: WidgetPropsMap[T];
}

CLI Tools

The SDK includes CLI commands you can run via npx without writing any code. Useful for CI/CD pipelines and quick local checks.

validate

Validate a package version against the conformance suite. Exits with code 1 if the minimum score is not met.

# Validate a remote package version
npx @aiffinity/provider-platform-sdk validate \
  --package-id $PACKAGE_ID \
  --version-id $VERSION_ID

# Validate a local capability descriptor file
npx @aiffinity/provider-platform-sdk validate \
  --local ./capability.json

# Set a minimum passing score (default: 80)
npx @aiffinity/provider-platform-sdk validate \
  --package-id $PACKAGE_ID \
  --version-id $VERSION_ID \
  --min-score 90
FlagTypeDescription
--package-idstringPackage ID to validate (remote mode)
--version-idstringVersion ID to validate (remote mode)
--localpathPath to a local capability descriptor JSON file
--min-scorenumberMinimum passing score (default: 80)
--jsonflagOutput results as JSON instead of human-readable text

submit

Submit a package version for review directly from the command line.

npx @aiffinity/provider-platform-sdk submit \
  --package-id $PACKAGE_ID \
  --version-id $VERSION_ID
FlagTypeDescription
--package-idstringPackage ID to submit (required)
--version-idstringVersion ID to submit (required)
--skip-validationflagSkip automatic pre-submission validation (not recommended)

Both CLI commands read credentials from the environment variables AIFFINITY_CLIENT_ID and AIFFINITY_CLIENT_SECRET. You can also pass --client-id and --client-secret flags directly.

TypeScript Types

The SDK exports all types used in the client API. Import them directly for full type safety in your handlers and configuration.

WidgetComponentType

type WidgetComponentType =
  | 'stat_row'
  | 'sparkline'
  | 'progress_bar'
  | 'ranked_list'
  | 'action_row'
  | 'cta_banner'
  | 'meeting_prep'
  | 'compound_card';

WidgetObjective

type WidgetObjective =
  | 'inform'       // Display data or status
  | 'prepare'      // Pre-meeting or pre-event context
  | 'act'          // Drive a user action
  | 'celebrate'    // Milestone or achievement
  | 'nudge'        // Gentle behavioral prompt
  | 'warn';        // Alert or degraded status

WidgetDensity

type WidgetDensity =
  | 'compact'     // Single line, minimal height
  | 'standard'    // Default card size
  | 'expanded';   // Tall card with extra detail

WidgetSpec

interface WidgetSpec<T extends WidgetComponentType = WidgetComponentType> {
  component: T;
  objective: WidgetObjective;
  density: WidgetDensity;
  props: WidgetPropsMap[T];
}

// WidgetPropsMap maps each component type to its specific props interface.
// See the Widget Components page for per-component prop definitions.

App

interface App {
  id: string;
  clientId: string;
  clientSecret?: string;  // Only returned on create
  name: string;
  description: string;
  redirectUris: string[];
  webhookUrl?: string;
  createdAt: string;
  updatedAt: string;
}

Package & PackageVersion

interface Package {
  id: string;
  appId: string;
  name: string;
  slug: string;
  description: string;
  riskTier: 'data_only' | 'action_capable' | 'high_trust' | 'strategic_surface';
  latestVersionId: string;
  versions: PackageVersion[];
  createdAt: string;
  updatedAt: string;
}

interface PackageVersion {
  id: string;
  packageId: string;
  version: string;       // semver, e.g. "1.2.0"
  status: 'draft' | 'validating' | 'submitted' | 'in_review' | 'approved' | 'published' | 'deprecated';
  capabilities: CapabilityDescriptor[];
  changelog?: string;
  createdAt: string;
}

ValidationResult

interface ValidationResult {
  passed: boolean;
  score: number;          // 0-100
  dimensions: {
    schema: number;       // 0-20 — descriptor schema correctness
    contracts: number;    // 0-20 — capability contract conformance
    performance: number;  // 0-20 — response latency and throughput
    errors: number;       // 0-15 — error handling quality
    security: number;     // 0-15 — auth, input validation, data handling
    docs: number;         // 0-10 — description quality and completeness
  };
  issues: ValidationIssue[];
}

interface ValidationIssue {
  severity: 'error' | 'warning' | 'info';
  code: string;
  message: string;
  path?: string;
}

Error Handling

The SDK wraps all API errors into a typed AiffinityApiError class. This gives you consistent error handling regardless of the failure mode.

import { AiffinityApiError } from '@aiffinity/provider-platform-sdk';

try {
  await client.apps.create({ name: '', description: '' });
} catch (err) {
  if (err instanceof AiffinityApiError) {
    console.error(err.status);       // 422
    console.error(err.code);         // 'VALIDATION_ERROR'
    console.error(err.message);      // 'name: String must contain at least 1 character'
    console.error(err.requestId);    // 'req_abc123' — for support tickets
    console.error(err.retryable);    // false
  }
}

Error codes

CodeHTTP StatusRetryableDescription
VALIDATION_ERROR400 / 422NoInvalid request payload. Check the message for field-level details.
AUTHENTICATION_ERROR401NoInvalid or expired credentials. Verify your client ID and secret.
AUTHORIZATION_ERROR403NoInsufficient permissions. Check your app's scope and risk tier.
NOT_FOUND404NoResource does not exist or is not accessible to your account.
CONFLICT409NoResource already exists (e.g., duplicate slug) or version conflict.
RATE_LIMITED429YesRate limit exceeded. The SDK automatically retries with backoff.
INTERNAL_ERROR500YesServer error. The SDK automatically retries up to retries times.
SERVICE_UNAVAILABLE503YesTemporary outage. The SDK automatically retries with exponential backoff.
TIMEOUTYesRequest timed out. Increase the timeout option or retry.
NETWORK_ERRORYesDNS resolution or TCP connection failure.

Retry behavior

The SDK automatically retries retryable errors using exponential backoff with jitter. The default is 2 retries with base delays of 500ms and 1500ms. Rate-limited responses honor the Retry-After header when present.

// Disable retries
const client = new ProviderPlatformClient({
  clientId: '...',
  clientSecret: '...',
  retries: 0,
});