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
| Option | Type | Default | Description |
|---|---|---|---|
| clientId | string | — | Your app's client ID (required) |
| clientSecret | string | — | Your app's client secret (required) |
| baseUrl | string | https://api.aiffinity.me | API base URL. Use https://api.staging.aiffinity.me for sandbox. |
| timeout | number | 30000 | Request timeout in milliseconds |
| retries | number | 2 | Number of automatic retries for transient failures (5xx, network errors) |
| logger | Logger | console | Custom 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.
| Method | Parameters | Returns | Description |
|---|---|---|---|
| create(opts) | CreateAppOpts | Promise<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) | string | Promise<App> | Retrieve a single app by ID. |
| update(id, opts) | string, UpdateAppOpts | Promise<App> | Update app name, description, redirect URIs, or webhook URL. |
| delete(id) | string | Promise<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.
| Method | Parameters | Returns | Description |
|---|---|---|---|
| create(opts) | CreatePackageOpts | Promise<Package> | Create a new package with an initial version. |
| list() | — | Promise<Package[]> | List all packages for your account. |
| get(id) | string | Promise<Package> | Retrieve a package with its version history. |
| createVersion(id, opts) | string, CreateVersionOpts | Promise<PackageVersion> | Create a new version of an existing package. |
| validate(id, versionId) | string, string | Promise<ValidationResult> | Run the conformance suite against a package version. Returns a score across 6 dimensions. |
| submit(id, versionId) | string, string | Promise<SubmissionResult> | Submit a version for review. data_only packages are auto-listed. |
| publish(id, versionId) | string, string | Promise<void> | Publish a reviewed version to the catalog. |
| deprecate(id, versionId) | string, string | Promise<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.
| Method | Parameters | Returns | Description |
|---|---|---|---|
| registerHandler(name, handler) | string, CapabilityHandler | void | Register a handler for a named capability. Must match a capability name in your package. |
| start(opts?) | RuntimeStartOpts | Promise<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.
| Method | Parameters | Returns | Description |
|---|---|---|---|
| createScenario(opts) | CreateScenarioOpts | Promise<Scenario> | Create a test scenario with mock user context and expected inputs. |
| runTest(scenarioId) | string | Promise<TestResult> | Execute a scenario against your running handler. Returns pass/fail with detailed assertions. |
| getTraces(opts?) | GetTracesOpts | Promise<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.
| Method | Parameters | Returns | Description |
|---|---|---|---|
| getCertification(packageId?) | string | Promise<Certification> | Get the current certification status and scores for a package. |
| getBaseline(packageId?) | string | Promise<Baseline> | Get performance baselines: p50/p95/p99 latency, error rate, availability. |
| listAlerts(opts?) | ListAlertsOpts | Promise<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
| Flag | Type | Description |
|---|---|---|
| --package-id | string | Package ID to validate (remote mode) |
| --version-id | string | Version ID to validate (remote mode) |
| --local | path | Path to a local capability descriptor JSON file |
| --min-score | number | Minimum passing score (default: 80) |
| --json | flag | Output 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
| Flag | Type | Description |
|---|---|---|
| --package-id | string | Package ID to submit (required) |
| --version-id | string | Version ID to submit (required) |
| --skip-validation | flag | Skip 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
| Code | HTTP Status | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 / 422 | No | Invalid request payload. Check the message for field-level details. |
| AUTHENTICATION_ERROR | 401 | No | Invalid or expired credentials. Verify your client ID and secret. |
| AUTHORIZATION_ERROR | 403 | No | Insufficient permissions. Check your app's scope and risk tier. |
| NOT_FOUND | 404 | No | Resource does not exist or is not accessible to your account. |
| CONFLICT | 409 | No | Resource already exists (e.g., duplicate slug) or version conflict. |
| RATE_LIMITED | 429 | Yes | Rate limit exceeded. The SDK automatically retries with backoff. |
| INTERNAL_ERROR | 500 | Yes | Server error. The SDK automatically retries up to retries times. |
| SERVICE_UNAVAILABLE | 503 | Yes | Temporary outage. The SDK automatically retries with exponential backoff. |
| TIMEOUT | — | Yes | Request timed out. Increase the timeout option or retry. |
| NETWORK_ERROR | — | Yes | DNS 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,
});