Skip to content

TypeScript SDK

The @kanoniv/sdk package is a zero-dependency TypeScript client for the Kanoniv Cloud API. It uses native fetch (Node 18+ and modern browsers) and provides full type definitions for all resources.

Installation

bash
npm install @kanoniv/sdk

Quick start

typescript
import { KanonivClient } from '@kanoniv/sdk';

const client = new KanonivClient({ apiKey: 'kn_...' });

// Resolve an identity
const entity = await client.resolve({ system: 'crm', externalId: 'sf_123' });

// Real-time resolve
const result = await client.resolveRt.realtime({
  sourceName: 'crm',
  externalId: 'cus_456',
  data: { email: '[email protected]', name: 'Jane Doe' },
});

// Batch ingest
await client.ingest('crm', [
  { external_id: '1', email: '[email protected]', name: 'Alice' },
  { external_id: '2', email: '[email protected]', name: 'Bob' },
]);

client.close();

Configuration

typescript
const client = new KanonivClient({
  apiKey: 'kn_...',              // API key (kn_ for prod, kn_test_ for sandbox)
  // accessToken: 'jwt_...',     // Or use JWT bearer token
  baseUrl: 'https://api.kanoniv.com',  // Default
  timeout: 30000,                // Request timeout in ms (default: 30s)
  maxRetries: 2,                 // Retries on transient errors (default: 2)
});

Sub-resources

The client exposes 12 sub-resources matching the API surface:

PropertyClassPurpose
client.entitiesEntitiesResourceSearch, get, link, lock, revert entities
client.sourcesSourcesResourceCRUD data sources, sync, preview, mappings
client.resolveRtResolveResourceReal-time and bulk identity resolution
client.jobsJobsResourceList, run, cancel reconciliation jobs
client.rulesRulesResourceList, create, view history of matching rules
client.reviewsReviewsResourceList and decide on pending match reviews
client.overridesOverridesResourceForce merge or split via manual overrides
client.auditAuditResourceView audit trail and entity event history
client.specsSpecsResourceList, get, upload identity specs
client.feedbackFeedbackResourceActive learning feedback labels
client.webhooksWebhooksResourceOutbound webhook management
client.sandboxSandboxResourceSandbox status and reset

Top-level methods

typescript
// Resolve by source + ID or free-text query
await client.resolve({ system: 'crm', externalId: 'sf_123' });
await client.resolve({ query: '[email protected]' });

// Batch ingest records
await client.ingest('source_name', records, { entityType: 'person' });

// Dashboard statistics
await client.stats();

Entities

typescript
// Search entities
const { data, total } = await client.entities.search({
  q: 'jane',
  entityType: 'person',
  limit: 20,
});

// Get canonical entity
const entity = await client.entities.get('entity-uuid');

// Get entity with linked records
const linked = await client.entities.getLinked('entity-uuid');

// Bulk linked entities (max 1000)
const bulk = await client.entities.getLinkedBulk(['id1', 'id2']);

// Entity history
const history = await client.entities.history('entity-uuid');

// Lock entity
await client.entities.lock('entity-uuid');

// Revert to previous state
await client.entities.revert('entity-uuid', 'event-uuid');

Real-time resolution

typescript
// Single record resolve
const result = await client.resolveRt.realtime({
  sourceName: 'crm',
  externalId: 'cus_123',
  data: { email: '[email protected]', name: 'Jane' },
});
// result.entity_id, result.is_new, result.confidence

// Bulk resolve (max 1000 lookups)
const bulk = await client.resolveRt.bulk([
  { source: 'crm', id: 'cus_123' },
  { source: 'erp', id: 'emp_456' },
]);
// bulk.resolved, bulk.not_found, bulk.results

Webhooks

typescript
// Create (signing secret returned only on creation)
const webhook = await client.webhooks.create({
  url: 'https://your-server.com/hook',
  eventTypes: ['entity.merged', 'reconciliation.completed'],
});

// List, get, delete, test
const all = await client.webhooks.list();
const one = await client.webhooks.get('wh-id');
await client.webhooks.delete('wh-id');
await client.webhooks.test('wh-id');

// Delivery history
const deliveries = await client.webhooks.deliveries('wh-id', { limit: 50 });

Sandbox

typescript
const status = await client.sandbox.status();
// { is_sandbox: true, entity_count: 42, entity_limit: 1000, source_count: 3 }

const reset = await client.sandbox.reset();
// { message: "...", entities_deleted: 42 }

Error handling

All errors extend KanonivError. Catch specific types for targeted handling:

typescript
import {
  KanonivError,
  ValidationError,
  AuthenticationError,
  NotFoundError,
  RateLimitError,
  ServerError,
} from '@kanoniv/sdk';

try {
  await client.entities.get('nonexistent');
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log('Entity not found');
  } else if (err instanceof RateLimitError) {
    console.log(`Retry after ${err.retryAfter}s`);
  } else if (err instanceof KanonivError) {
    console.log(`API error ${err.statusCode}: ${err.message}`);
  }
}
Error classHTTP statusWhen
ValidationError400Invalid request body
AuthenticationError401Missing or invalid credentials
ForbiddenError403Insufficient permissions
NotFoundError404Resource not found
ConflictError409Duplicate resource
RateLimitError429Rate or quota limit hit
ServerError5xxServer-side issue

Automatic retries

The SDK automatically retries on transient errors (408, 429, 502, 503, 504) with exponential backoff. Rate limit responses honor the Retry-After header. Configure with maxRetries (default: 2).

Requirements

  • Node.js 18+ (uses native fetch)
  • Or any modern browser with fetch support
  • Zero runtime dependencies

The identity and delegation layer for AI agents.