Skip to main content

TypeScript SDK Reference

The optropic npm package provides a fully typed, ESM-only SDK for interacting with the Optropic API from TypeScript and JavaScript applications.

Installationโ€‹

Install the package using npm, yarn, or your preferred package manager:

npm install optropic
yarn add optropic
pnpm add optropic

Quick Startโ€‹

import { OptropicClient } from 'optropic';

const client = new OptropicClient({
apiKey: 'optr_live_...'
});

// Use the client
const assets = await client.assets.list();

Client Initializationโ€‹

Create a new client instance with your API key:

import { OptropicClient, type OptropicConfig } from 'optropic';

const client = new OptropicClient({
apiKey: 'optr_live_...'
});

The client accepts an OptropicConfig object during initialization.

Configurationโ€‹

The OptropicConfig interface controls client behavior:

interface OptropicConfig {
apiKey: string;
sandbox?: boolean;
baseUrl?: string;
timeout?: number;
headers?: Record<string, string>;
retry?: RetryConfig;
debug?: boolean;
}

Configuration Optionsโ€‹

OptionTypeDefaultDescription
apiKeystringrequiredYour Optropic API key (format: optr_live_...)
sandboxbooleanfalseUse sandbox environment (for testing)
baseUrlstringhttps://api.optropic.ioCustom API base URL
timeoutnumber30000Request timeout in milliseconds
headersRecord<string, string>{}Custom headers to include in all requests
retryRetryConfigSee belowRetry behavior configuration
debugbooleanfalseEnable debug logging

Retry Configurationโ€‹

The RetryConfig interface controls exponential backoff behavior:

interface RetryConfig {
maxRetries?: number;
baseDelay?: number;
maxDelay?: number;
}
OptionDefaultDescription
maxRetries3Maximum number of retry attempts
baseDelay100Base delay in milliseconds
maxDelay30000Maximum delay cap in milliseconds

Retry uses exponential backoff with jitter: delay = min(baseDelay * (2 ^ attempt) + random_jitter, maxDelay)

Example Configurationโ€‹

const client = new OptropicClient({
apiKey: 'optr_live_...',
timeout: 60000,
debug: true,
retry: {
maxRetries: 5,
baseDelay: 200,
maxDelay: 60000
},
headers: {
'X-Custom-Header': 'value'
}
});

Available Resourcesโ€‹

The client provides access to the following resources. All methods are asynchronous and return Promise types.

Assetsโ€‹

client.assets.list(options?: ListOptions): Promise<ListResponse<Asset>>;
client.assets.create(data: CreateAssetRequest): Promise<Asset>;
client.assets.get(id: string): Promise<Asset>;
client.assets.update(id: string, data: UpdateAssetRequest): Promise<Asset>;
client.assets.delete(id: string): Promise<void>;
client.assets.listAll(options?: ListOptions): AsyncGenerator<Asset>;

Keysโ€‹

client.keys.list(options?: ListOptions): Promise<ListResponse<Key>>;
client.keys.create(data: CreateKeyRequest): Promise<Key>;
client.keys.get(id: string): Promise<Key>;
client.keys.rotate(id: string): Promise<Key>;
client.keys.revoke(id: string): Promise<void>;
client.keys.listAll(options?: ListOptions): AsyncGenerator<Key>;

Keysetsโ€‹

client.keysets.list(options?: ListOptions): Promise<ListResponse<Keyset>>;
client.keysets.create(data: CreateKeysetRequest): Promise<Keyset>;
client.keysets.get(id: string): Promise<Keyset>;
client.keysets.update(id: string, data: UpdateKeysetRequest): Promise<Keyset>;
client.keysets.delete(id: string): Promise<void>;
client.keysets.listAll(options?: ListOptions): AsyncGenerator<Keyset>;

Auditโ€‹

client.audit.list(options?: ListOptions): Promise<ListResponse<AuditLog>>;
client.audit.get(id: string): Promise<AuditLog>;
client.audit.listAll(options?: ListOptions): AsyncGenerator<AuditLog>;

Complianceโ€‹

client.compliance.list(options?: ListOptions): Promise<ListResponse<ComplianceRecord>>;
client.compliance.get(id: string): Promise<ComplianceRecord>;
client.compliance.listAll(options?: ListOptions): AsyncGenerator<ComplianceRecord>;

Schemasโ€‹

client.schemas.list(options?: ListOptions): Promise<ListResponse<Schema>>;
client.schemas.create(data: CreateSchemaRequest): Promise<Schema>;
client.schemas.get(id: string): Promise<Schema>;
client.schemas.update(id: string, data: UpdateSchemaRequest): Promise<Schema>;
client.schemas.delete(id: string): Promise<void>;
client.schemas.validate(data: ValidateSchemaRequest): Promise<ValidationResult>;
client.schemas.listAll(options?: ListOptions): AsyncGenerator<Schema>;

Webhooksโ€‹

client.webhooks.list(options?: ListOptions): Promise<ListResponse<Webhook>>;
client.webhooks.create(data: CreateWebhookRequest): Promise<Webhook>;
client.webhooks.get(id: string): Promise<Webhook>;
client.webhooks.update(id: string, data: UpdateWebhookRequest): Promise<Webhook>;
client.webhooks.delete(id: string): Promise<void>;
client.webhooks.test(id: string): Promise<TestWebhookResult>;
client.webhooks.listAll(options?: ListOptions): AsyncGenerator<Webhook>;

Documentsโ€‹

client.documents.list(options?: ListOptions): Promise<ListResponse<Document>>;
client.documents.create(data: CreateDocumentRequest): Promise<Document>;
client.documents.get(id: string): Promise<Document>;
client.documents.update(id: string, data: UpdateDocumentRequest): Promise<Document>;
client.documents.delete(id: string): Promise<void>;
client.documents.listAll(options?: ListOptions): AsyncGenerator<Document>;

Provenanceโ€‹

client.provenance.list(options?: ListOptions): Promise<ListResponse<ProvenanceRecord>>;
client.provenance.get(id: string): Promise<ProvenanceRecord>;
client.provenance.trace(id: string): Promise<ProvenanceChain>;
client.provenance.listAll(options?: ListOptions): AsyncGenerator<ProvenanceRecord>;

Machine-to-Machine (M2M)โ€‹

client.m2m.authenticate(credentials: M2MCredentials): Promise<M2MToken>;
client.m2m.refresh(token: string): Promise<M2MToken>;
client.m2m.revoke(token: string): Promise<void>;

Asynchronous Operationsโ€‹

All SDK methods are asynchronous and return Promise types. Use async/await or .then() chains:

// Using async/await
const asset = await client.assets.get('ast_123');
console.log(asset.name);

// Using .then()
client.assets.list().then((response) => {
console.log(response.data);
});

Paginationโ€‹

List endpoints return paginated responses with data, count, and next_cursor fields:

const response = await client.assets.list({ limit: 10 });
console.log(response.data); // Asset[]
console.log(response.count); // total count
console.log(response.next_cursor); // pagination cursor or null

Auto-Pagination with AsyncGeneratorโ€‹

Use listAll() to automatically iterate through all pages:

for await (const asset of client.assets.listAll()) {
console.log(asset.name);
}

The listAll() method returns an AsyncGenerator<T> that handles pagination transparently.

Idempotencyโ€‹

POST, PUT, and PATCH requests automatically include an Idempotency-Key header using a UUID. This ensures safe retries without duplicate operations:

// Automatic idempotency key is generated and sent
const asset = await client.assets.create({
name: 'My Asset'
});

// Same request with same payload will not create duplicates
const asset2 = await client.assets.create({
name: 'My Asset'
});

To use a custom idempotency key, pass it in the request options:

const asset = await client.assets.create(
{ name: 'My Asset' },
{ idempotencyKey: 'my-custom-key' }
);

Retry Logicโ€‹

The SDK includes automatic retry with exponential backoff and jitter. Failed requests are retried up to maxRetries times (default: 3).

Retry formula: delay = min(baseDelay * (2 ^ attempt) + random_jitter, maxDelay)

Configure retries during initialization:

const client = new OptropicClient({
apiKey: 'optr_live_...',
retry: {
maxRetries: 5,
baseDelay: 100,
maxDelay: 30000
}
});

Rate Limitingโ€‹

Access rate limit information via the rateLimit property:

const info = client.rateLimit;

if (info) {
console.log(`Remaining requests: ${info.remaining}`);
console.log(`Limit: ${info.limit}`);
console.log(`Reset time: ${info.resetAt}`);
}

The RateLimitInfo interface:

interface RateLimitInfo {
limit: number;
remaining: number;
resetAt: Date;
}

When rate limited, the SDK throws a RateLimitedError. Requests are automatically retried after the reset time if retry is enabled.

Debuggingโ€‹

Enable debug logging during client initialization:

const client = new OptropicClient({
apiKey: 'optr_live_...',
debug: true
});

Debug output is logged to console.log with the [optropic] prefix. Sensitive information (API keys, tokens) is automatically redacted:

[optropic] POST /v1/assets (200 OK, 145ms)
[optropic] Request headers: { Authorization: '***' }
[optropic] Response body: { id: 'ast_...', name: 'My Asset' }

SDK Versionโ€‹

Get the SDK version at runtime:

import { SDK_VERSION } from 'optropic';

console.log(`Using optropic v${SDK_VERSION}`);

Current version: 2.4.0

Error Handlingโ€‹

The SDK provides typed error classes for different failure scenarios:

import {
OptropicError,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitedError,
ServerError
} from 'optropic';

try {
const asset = await client.assets.get('invalid_id');
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key');
} else if (error instanceof NotFoundError) {
console.error('Asset not found');
} else if (error instanceof ValidationError) {
console.error('Validation failed:', error.details);
} else if (error instanceof RateLimitedError) {
console.error('Rate limited, retry after:', error.retryAfter);
} else if (error instanceof OptropicError) {
console.error(`Error [${error.code}]: ${error.message}`);
}
}

Error Classesโ€‹

All error classes extend OptropicError:

class OptropicError extends Error {
code: string;
status: number;
message: string;
}

class AuthenticationError extends OptropicError;
class AuthorizationError extends OptropicError;
class NotFoundError extends OptropicError;
class ConflictError extends OptropicError;
class ValidationError extends OptropicError;
class RateLimitedError extends OptropicError;
class ServerError extends OptropicError;
class TimeoutError extends OptropicError;

TypeScript Supportโ€‹

The package is TypeScript-first with complete type exports. All interfaces and types are available for import:

import type {
OptropicConfig,
Asset,
Key,
Keyset,
AuditLog,
ComplianceRecord,
Schema,
Webhook,
Document,
ProvenanceRecord,
RateLimitInfo,
ListResponse,
ListOptions,
RetryConfig,
// ... and more
} from 'optropic';

Use these types to ensure type safety in your application:

async function processAssets(client: OptropicClient): Promise<void> {
const response: ListResponse<Asset> = await client.assets.list();

for (const asset of response.data) {
const typed: Asset = asset;
console.log(typed.id, typed.name);
}
}

API Pathsโ€‹

Resource methods use versioned API paths with the /v1/ prefix:

POST   /v1/assets
GET /v1/assets
GET /v1/assets/{id}
PUT /v1/assets/{id}
DELETE /v1/assets/{id}

POST /v1/keys
GET /v1/keys
POST /v1/keys/{id}/rotate
POST /v1/keys/{id}/revoke

// ... and so on for other resources

Complete Exampleโ€‹

import { OptropicClient, type Asset } from 'optropic';

async function main() {
const client = new OptropicClient({
apiKey: 'optr_live_...',
timeout: 30000,
debug: false,
retry: {
maxRetries: 3,
baseDelay: 100,
maxDelay: 30000
}
});

try {
// Create an asset
const asset = await client.assets.create({
name: 'Example Asset',
type: 'document'
});
console.log('Created:', asset.id);

// Retrieve the asset
const retrieved = await client.assets.get(asset.id);
console.log('Retrieved:', retrieved.name);

// List all assets with auto-pagination
for await (const a of client.assets.listAll()) {
console.log(`Asset: ${a.id} - ${a.name}`);
}

// Check rate limits
const rateLimit = client.rateLimit;
if (rateLimit) {
console.log(`Remaining: ${rateLimit.remaining}/${rateLimit.limit}`);
}
} catch (error) {
console.error('Error:', error);
}
}

main();

Browser Supportโ€‹

The optropic package is ESM-only and requires a modern JavaScript environment. It is not compatible with CommonJS or older browsers. Use it in:

  • Node.js 16+
  • Modern browsers with ES modules support
  • TypeScript projects (3.8+)
  • Bundlers (Webpack, Vite, esbuild, etc.)

Migration Notesโ€‹

If upgrading from an older version, refer to the CHANGELOG for breaking changes and migration guidance.