@helix-tools/sdk-typescript
v3.12.0
Published
TypeScript/Node.js SDK for Helix Connect Platform
Maintainers
Readme
Helix Connect TypeScript SDK
Official TypeScript SDK for the Helix Connect data marketplace platform.
Overview
The Helix Connect SDK gives data producers and consumers programmatic access to the Helix Connect data marketplace. Producers upload and price datasets, manage partner access, and track earnings; consumers browse, subscribe to, and download the datasets they have access to. Every dataset is encrypted in transit and at rest, with encryption, compression, and decryption handled automatically by the SDK.
Installation
npm install @helix-tools/sdk-typescriptRequires Node.js 18 or later (see engines in package.json).
Authentication & Credentials
Every SDK call is authenticated with three values: HELIX_CUSTOMER_ID,
AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY. You get these from the
Helix Connect portal (https://portal.helix.tools) — sign in and open the
Credentials page, where they're revealed only once you're authenticated.
The SDK does not read these from the environment for you; your application
reads them (e.g. from env vars or a secrets manager) and passes them into
the client config, as shown throughout this README. The one variable the SDK
does resolve automatically is HELIX_API_ENDPOINT, used as a fallback for
apiEndpoint when it's omitted; it otherwise defaults to
https://api-go.helix.tools.
const producer = new HelixProducer({
customerId: process.env.HELIX_CUSTOMER_ID!,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID!,
awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
});STS session credentials (opt-in)
By default, the SDK signs every request with the long-lived AWS key you
provide (credentialMode: "static") — unchanged since 1.0.0. Opt into
short-lived, auto-refreshing AWS STS session credentials with one config
field: credentialMode: "sts". That key is then used only as a bootstrap
credential — the SDK mints a 15-minute session credential from the Helix
credential broker and refreshes it automatically before it expires.
Everything else (uploads, downloads, notification polling) works
identically in both modes.
const producer = new HelixProducer({
customerId: process.env.HELIX_CUSTOMER_ID!,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID!,
awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
credentialMode: 'sts', // opt-in; default is 'static'
});See MIGRATION_STS.md for the full guide; nothing changes unless you opt in.
Quickstart — Producer
import { HelixProducer } from '@helix-tools/sdk-typescript';
const producer = new HelixProducer({
customerId: process.env.HELIX_CUSTOMER_ID!,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID!,
awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
});
// Upload a dataset. Encryption and compression are handled automatically
// by default; pass `encrypt: false` / `compress: false` to disable.
const dataset = await producer.uploadDataset('./data/customers.json', {
datasetName: 'customer-records',
description: 'Monthly customer export',
category: 'general', // see DatasetCategory for the full enum
dataFreshness: 'daily', // see DataFreshness for the full enum
});
console.log(`Uploaded ${dataset.name} (${dataset.id})`);
// List everything this producer has uploaded
const myDatasets = await producer.listMyDatasets();
console.log(`${myDatasets.length} dataset(s) on this account`);
// Update metadata without re-uploading the underlying data
await producer.updateDataset(dataset.id, {
description: 'Updated description with more details',
dataFreshness: 'weekly', // camelCase; deprecated `data_freshness` still works
});A newly-created dataset no longer carries a default legacy pricing block —
set a marketplace price with setDatasetMarketplace() (see
Marketplace below) when you're ready to list it for sale.
Quickstart — Consumer
import { HelixConsumer } from '@helix-tools/sdk-typescript';
import * as fs from 'fs';
const consumer = new HelixConsumer({
customerId: process.env.HELIX_CUSTOMER_ID!,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID!,
awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
});
// See what this customer is subscribed to as a consumer
const subscriptions = await consumer.listSubscriptions({ role: 'consumer' });
// Poll the per-consumer notification queue for DATA_PUBLISHED events.
// Messages are auto-acknowledged (deleted) by default once returned.
const notifications = await consumer.pollNotifications({
maxMessages: 10,
waitTimeSeconds: 20,
});
fs.mkdirSync('./downloads', { recursive: true }); // downloadDataset does not create parent dirs
for (const notif of notifications) {
const outputPath = `./downloads/${notif.dataset_id}.json`;
// autoDecrypt / autoDecompress both default to true — set false to get
// the raw bytes as stored.
await consumer.downloadDataset(notif.dataset_id, outputPath, {
autoDecrypt: true,
autoDecompress: true,
});
console.log(`Downloaded ${notif.dataset_name ?? notif.dataset_id} -> ${outputPath}`);
}Field naming: camelCase, with deprecated snake_case aliases
Input objects across the SDK (setDatasetMarketplace,
createSubscriptionCheckout, updateDataset, and more) accept the
TS-idiomatic camelCase spelling of their fields — priceMonthlyCents,
datasetId, requestId, dataFreshness, accessTier, versionNotes, and
so on. The older snake_case spellings (price_monthly_cents, dataset_id,
request_id, data_freshness, access_tier, version_notes) still work
and are not going away, but are marked @deprecated in the type
definitions — prefer camelCase in new code. If a call somehow supplies both
spellings of the same field, the camelCase value wins; the SDK always sends
the correct wire format to the API either way.
Marketplace
The marketplace surface lets consumers browse and pay for listed datasets,
and lets producers price their own datasets and track earnings. Every
marketplace endpoint responds 404 while the server's marketplace_payments
feature flag is off. Listed prices are the producer's own; platform terms
are at https://helix.tools/#pricing.
Browsing and subscribing (consumer)
// GET /v1/datasets/marketplace — search + paginate the public listing
const { datasets, pagination } = await consumer.browseMarketplace({
search: 'phone',
category: 'phone-numbers',
sort: 'price_asc',
page: 1,
});
const first = datasets[0];
if (first) {
// `id` is the modern field; `_id` is the always-present underlying one —
// fall back to it for older API responses that don't set `id`.
const firstId = first.id ?? first._id;
// GET /v1/datasets/:id/details — a composite view: dataset + reviews +
// related datasets + the caller's own subscription info
const details = await consumer.getDatasetDetails(firstId);
// POST /v1/subscriptions/checkout — exactly one of `datasetId` or
// `requestId` (a previously-approved request awaiting payment). Returns
// the Stripe Checkout URL only; the SDK never opens or redirects to it.
// (The deprecated `dataset_id` / `request_id` spellings still work.)
const checkoutUrl = await consumer.createSubscriptionCheckout({
datasetId: firstId,
});
}Pricing and earnings (producer)
const datasetId = dataset.id ?? dataset._id!; // `id` is the modern field; `_id` the legacy one
await producer.setDatasetMarketplace(datasetId, {
priceMonthlyCents: 4900, // $49.00/mo, in USD cents; 0 = free
listed: true,
});
const earnings = await producer.getEarnings(); // optionally getEarnings('2026-07')Approving a subscription request at a price
When a consumer requests access to a dataset, the producer's approval can set what THAT SPECIFIC consumer pays — independent of the dataset's own listed price. This is how a producer comps one named partner while everyone else pays the normal price, or charges a bespoke rate. Platform pricing terms are at https://helix.tools/#pricing.
// Comp this one consumer for free, even if the dataset is a paid listing.
await producer.approveSubscriptionRequest(requestId, { priceMonthlyCents: 0 });
// Charge this consumer a specific price, even if the dataset is currently free.
await producer.approveSubscriptionRequest(requestId, { priceMonthlyCents: 2900 });
// Default: fall back to the dataset's own marketplace price.
await producer.approveSubscriptionRequest(requestId);Partner Invites
A producer can self-serve inviting a consumer partner directly — no
platform-admin step required. Requires the partner_invite feature flag on
the producer's account; without it these calls respond 403.
const invite = await producer.inviteConsumer({
companyName: 'Acme Analytics',
businessEmail: '[email protected]',
datasets: [datasetId], // 1-50 dataset IDs auto-granted at invite time
tier: 'free', // currently the only supported tier
});
console.log(`Invited ${invite.consumer_id} (${invite.status})`);
if (!invite.email_sent) {
// Invite still succeeds even if the welcome email failed to send
console.warn(`Welcome email failed: ${invite.email_error}`);
}
const consumers = await producer.listConsumers();
if (consumers[0]) {
await producer.deactivateConsumer(consumers[0].consumer_id);
}datasets also accepts a per-dataset tier, so one invite can comp some
datasets while charging for others:
await producer.inviteConsumer({
companyName: 'Acme Analytics',
businessEmail: '[email protected]',
datasets: [
{ datasetId: 'dataset-123', tier: 'free' }, // comped for this consumer
{ datasetId: 'dataset-456', tier: 'paid' }, // pays the dataset's listed price
],
});Payouts (Stripe Connect)
Producers accept payouts through a hosted Stripe Connect Express flow. The SDK never opens or redirects to any of the returned URLs itself — send the producer to them.
// One-time: connect a Stripe Express account to receive payouts
const { url } = await producer.connectOnboard();
console.log(`Open this to finish onboarding: ${url}`);
// Check payout account status any time
const status = await producer.getConnectStatus();
if (status.can_price_datasets) {
console.log('Payouts are enabled — datasets can be priced above $0');
}
// Once onboarding is complete, get a one-time link to the Stripe Express
// dashboard (403 until onboarding is complete)
const { url: dashboardUrl } = await producer.createConnectLoginLink();Versioning & Changelog
This SDK follows semantic versioning. See CHANGELOG.md for the full release history.
Support
- Documentation: https://dev.helix.tools (sign in at https://portal.helix.tools and open SDK Docs)
- Issues: https://github.com/helix-tools/sdk-typescript/issues
- Email: [email protected]
License
See LICENSE for details.
