SDKs
Native client libraries for recording interactions and querying the Provenance API.
Provenance SDKs provide a native interface for recording interactions via managed queues and querying the full REST API — with type safety, automatic retries, credential caching, and auto-pagination.
Available SDKs
| Language | Package | Status |
|---|---|---|
| Node.js | @stdiolabs/provenance-sdk | Available |
| TypeScript | @stdiolabs/provenance-sdk-ts | Available |
| Python | provenance-sdk | Available |
| Java | dev.provenance:sdk | Available |
| C# / .NET | Provenance.SDK | Coming soon |
All SDKs follow the same pattern: a create() initializer that resolves credentials from the platform, a log() method for queue-based ingestion, and an api() method for the full REST client. Java uses a builder pattern instead of options objects.
Installation
npm install @stdiolabs/provenance-sdkQuick start
Initialize
const { create } = require('@stdiolabs/provenance-sdk');
const provenance = await create({
apiKey: 'your-api-key',
origin: 'my-service',
});The SDK resolves queue credentials and API URL automatically from the platform using your API key. Both are cached for 5 minutes and auto-refresh on token rotation.
Record interactions (queue)
The log() method pushes interactions through a managed queue for reliable async delivery with automatic retries. It returns the generated spanId (a UUID string) which you can use to link child interactions. This is the recommended path for recording interactions in production.
const spanId = await provenance.log({
resourceType: 'user',
resourceId: 'user-123',
action: 'login',
uowId: crypto.randomUUID(),
interaction: { email: 'user@example.com' },
});
// spanId is a UUID string identifying this interaction in the span treeTo link child interactions, pass the returned spanId as parentSpanId:
const parentSpanId = await provenance.log({
resourceType: 'order', resourceId: 'order-789',
action: 'create', uowId,
interaction: { total: 99.99 },
});
await provenance.log({
resourceType: 'payment', resourceId: 'payment-456',
action: 'process', uowId,
parentSpanId,
interaction: { method: 'card' },
});See Unit of Work — Span Hierarchy for the full guide.
Query the API
The api() method returns a client covering all Provenance API endpoints — CRUD operations, analytics, traces, subscriptions, alerts, and more.
const api = await provenance.api();
// List actions
const actions = await api.actions.list();
// Get a trace
const trace = await api.traces.get('user-123');
// Run an analytics query
const data = await api.analytics.query({
metrics: ['count'],
dimensions: ['action'],
timeRange: { type: 'relative', value: '7d' },
});
// Search activity
const results = await api.activity.search({
filters: { action: 'CREATE', resourceType: 'USER' },
});REST API client
The api() method is lazy — the API URL is resolved on first call and cached. The client covers every endpoint in the Provenance API.
CRUD resources
Resources like actions, origins, resource types, dashboards, widgets, subscribers, subscriptions, alerts, and adapter settings all share the same interface:
const api = await provenance.api();
// List (paginated)
const { data, pagination } = await api.actions.list({ page: 1, limit: 25 });
// Get by ID
const action = await api.actions.get('action-uuid');
// Create
const newAction = await api.actions.create({ title: 'Deploy', mnemonic: 'DEPLOY' });
// Update
await api.actions.update('action-uuid', { title: 'Deploy v2' });
// Delete
await api.actions.delete('action-uuid');Auto-pagination
Every CRUD resource includes an async generator that handles pagination automatically:
for await (const action of api.actions.listAll()) {
console.log(action.title);
}
// Custom page size
for await (const origin of api.origins.listAll({}, { pageSize: 50 })) {
console.log(origin.mnemonic);
}Available namespaces
| Namespace | Methods |
|---|---|
actions | list, get, create, update, delete, listAll / list_all |
origins | list, get, create, update, delete, listAll / list_all |
resourceTypes / resource_types | list, get, create, update, delete, listAll / list_all |
interactions | list, get, delete |
interactionFields / interaction_fields | list |
activity | search |
traces | get, timeline, summary |
timeline | get, refresh |
analytics | query, discover |
dashboards | list, get, create, update, delete, listAll / list_all |
widgets | list, get, create, update, delete, listAll / list_all, getData / get_data, previewData / preview_data |
subscribers | list, get, create, update, delete, listAll / list_all, stats |
subscriptions | list, get, create, update, delete, listAll / list_all, pause, resume |
audits | list, create |
queue | stats, process |
templateVariables / template_variables | list |
adapters | list, get |
adapterSettings / adapter_settings | list, get, create, update, delete, listAll / list_all |
alerts | list, get, create, update, delete, listAll / list_all, states, evaluate |
interactionMetrics / interaction_metrics | list, get, create, update, delete, listAll / list_all, types, discover, calculate |
metrics | evaluate, widgetsWithAlerts / widgets_with_alerts |
globalConfig / global_config | get, update |
users | list, get, create, update, delete, listAll / list_all, lock, unlock, roles |
roles | list, get, create, update, delete, listAll / list_all, permissions |
permissions | list |
home | dashboard |
inboundSources / inbound_sources | list, get, create, update, delete, listAll / list_all |
inboundMappings / inbound_mappings | list, get, create, update, delete, listAll / list_all, test |
secrets | list, get, create, update, delete, listAll / list_all, test, envVars / env_vars |
secretProviders / secret_providers | list, get, create, update, delete, listAll / list_all, types |
health() | Health check |
Node.js, TypeScript, and Java use camelCase. Python uses snake_case. Java uses method calls (e.g., api.actions()) instead of property access.
Subscription labels and delivery schedules
The subscriptions namespace supports labels and delivery_schedule parameters on create and update, and label / labels query parameters for filtering. These flow through the existing CRUD methods — no additional SDK methods are needed.
Creating a subscription with labels and a delivery schedule
const api = await provenance.api();
const subscription = await api.subscriptions.create({
actionId: 'action-uuid',
resourceTypeId: 'resource-type-uuid',
subscriberId: 'subscriber-uuid',
labels: ['Production', 'Billing Alerts', 'high-priority'],
delivery_schedule: {
timezone: 'America/New_York',
windows: [
{ days: [1, 2, 3, 4, 5], startTime: '09:00', endTime: '17:00' },
{ days: [6], startTime: '10:00', endTime: '14:00' },
],
},
config: { adapter: 'adapter:slack', webhookUrl: '{{secrets.SLACK_WEBHOOK}}' },
});Filtering subscriptions by label
// Single label — subscriptions containing "Production"
const result = await api.subscriptions.list({ label: 'Production' });
// Multiple labels — subscriptions containing at least one
const result = await api.subscriptions.list({ labels: 'Production,Security' });Alert kind
The alerts namespace supports a kind parameter ("alert" or "goal") on create and update, and as a query parameter for filtering.
Creating a goal-type alert
const api = await provenance.api();
const goal = await api.alerts.create({
title: 'Monthly Revenue Target',
metricId: 'revenue-metric-uuid',
operator: 'gte',
threshold: 100000,
alertActionId: 'goal-reached-action-uuid',
resourceTypeId: 'alert-biz-uuid',
kind: 'goal',
});Filtering alerts by kind
const alerts = await api.alerts.list({ kind: 'alert' });
const goals = await api.alerts.list({ kind: 'goal' });Context layering
Set shared context once, override per call:
const scoped = provenance.addContext({
resourceType: 'order',
userId: 'user-456',
});
// Only provide what's different
await scoped.log({
resourceId: 'order-789',
action: 'create',
uowId: crypto.randomUUID(),
interaction: { total: 99.99 },
});
// api() is shared across parent and children — no extra resolution
const api = await scoped.api();addContext() / add_context() is synchronous and reuses the same queue credentials and API client — no extra network calls.
Propagating parentSpanId via context
You can set parentSpanId in context so all subsequent log() calls on the scoped client are linked as children:
const parentSpanId = await provenance.log({
resourceType: 'order', resourceId: 'order-789',
action: 'create', uowId, interaction: { total: 99.99 },
});
const child = provenance.addContext({ parentSpanId });
await child.log({ resourceId: 'item-1', action: 'reserve', ... });
await child.log({ resourceId: 'item-2', action: 'reserve', ... });Winston transport (Node.js only)
The Node.js SDK includes a Winston transport for drop-in logging integration:
const winston = require('winston');
const { ProvenanceTransport } = require('@stdiolabs/provenance-sdk');
const logger = winston.createLogger({
transports: [
new ProvenanceTransport({
level: 'info',
apiKey: 'your-api-key',
config: { origin: 'my-service' },
})
]
});
logger.info({
resourceType: 'user',
resourceId: 'user-123',
action: 'login',
uowId: '550e8400-e29b-41d4-a716-446655440000',
interaction: { email: 'user@example.com' },
});Self-hosted mode
If you're running Provenance self-hosted with your own queue infrastructure:
const { create } = require('@stdiolabs/provenance-sdk');
const provenance = await create(
{ origin: 'my-service', apiUrl: 'https://your-api.com/api' },
'https://your-queue-url/v2/enqueue/queue-name/destination',
'your-queue-token',
'your-api-key'
);
await provenance.log({ ... });
const api = await provenance.api();In manual mode, apiUrl / api_url is required for the REST client.
Resilience
All SDKs implement the same resilience patterns:
- Lazy resolution — Queue config and API URL fetched on first use, not at
create()time. Your app starts even if the platform is temporarily unreachable. - Retry with backoff — Transient failures (429, 5xx) retried up to 3 times with exponential backoff — for both queue ingestion and REST API calls.
- Auto-refresh — On 401/403 from the queue, credentials are force-refreshed from the platform and the request retried once.
- 5-minute cache — Platform config cached to avoid per-call lookups.
- Shared instances — The API client is shared across
addContext()/add_context()children.
Configuration
| Option | Required | Description |
|---|---|---|
apiKey / api_key | Yes | Your Provenance API key |
origin | Yes | Name of the source system |
platformUrl / platform_url | No | Platform URL (default: https://platform.provenance.dev) |
apiUrl / api_url | No | Override API URL (resolved from platform by default) |
SDK differences
| Node.js | TypeScript | Python | Java | |
|---|---|---|---|---|
| Package | @stdiolabs/provenance-sdk | @stdiolabs/provenance-sdk-ts | provenance-sdk | dev.provenance:sdk |
| Module format | CJS | ESM + CJS (dual) | Python package | Maven JAR |
| Runtime deps | lodash, dayjs, typebox | Zero | httpx | Jackson |
| Async model | Promises | Promises | asyncio / await | Synchronous |
| Naming convention | camelCase | camelCase | snake_case | camelCase |
| Winston transport | Yes | No | No | No |
| Request metadata parsing | Yes (ua-parser-js) | No | No | No |
| Type declarations | Bundled .d.ts | Generated from source | py.typed (PEP 561) | Compiled classes |
| Min runtime | Node 18 | Node 18 | Python 3.10 | Java 11 |
| Package size | ~11 KB | ~24 KB | ~8 KB | ~25 KB |
Auto-instrumentation (Node.js)
The Node.js SDK includes zero-code auto-instrumentation that patches http, http.request/https.request, express, fastify, fetch, prisma, and sequelize to record interactions automatically — with UOW propagation across async boundaries and service calls.
require('@stdiolabs/provenance-sdk/auto').instrument({
apiKey: process.env.PROVENANCE_API_KEY,
origin: 'order-service',
});One line at the top of your app. No changes to application code. See Auto-Instrumentation for the full guide.