The Stateset Node.js Library provides convenient access to the Stateset API from applications written in server-side JavaScript.
Install the package with:
npm install stateset-node --saveThe package needs to be configured with your account's secret key, which is available in the Stateset Cloud Platform Dashboard.
- Go to the Stateset Cloud Platform Dashboard.
- Login with your Stateset account.
- Create an API key.
- Try the Node.js quickstart
The SDK exposes helper classes for building intelligent agents. These include:
- Agents for managing agent state and assignments.
- Responses to store generated replies.
- Rules to automate behaviour.
- Attributes describing agent skills or traits.
- Knowledge base entries for retrieval.
- Evals to record evaluation metrics.
- OpenAIIntegration for generating chat completions.
See the Node.js quickstart for complete code.
- Install the SDK package
npm install stateset-node- Initialize the client
import stateset from 'stateset-node';
const client = new stateset({
// apiKey and baseUrl can be omitted if the STATESET_API_KEY and
// STATESET_BASE_URL environment variables are set.
apiKey: process.env.STATESET_API_KEY,
// Optional retry logic for transient failures
retry: 3,
retryDelayMs: 1000,
// Optional request timeout and custom User-Agent
timeout: 60000,
userAgent: 'my-app/1.0',
// Information about your app added to the User-Agent header
appInfo: { name: 'MyApp', version: '1.0', url: 'https://example.com' },
// Additional headers sent with every request
additionalHeaders: { 'X-Customer-ID': 'abc123' },
// Optional HTTP proxy
proxy: 'http://localhost:3128'
});Retry behaviour can also be configured using the STATESET_RETRY and
STATESET_RETRY_DELAY_MS environment variables. Proxy settings can be provided
via the STATESET_PROXY environment variable.
The SDK exposes helper methods to update the API key, base URL and timeout on an existing client instance:
client.setApiKey('new-key');
client.setBaseUrl('https://api.example.com');
client.setTimeout(30000);
client.setRetryOptions(5, 500);
client.setRetryStrategy({ baseDelay: 750, jitter: false });
client.setHeaders({ 'X-Customer-ID': 'abc123' });
client.setProxy('http://localhost:3128');
client.setAppInfo({ name: 'MyApp', version: '1.0', url: 'https://example.com' });- Make an API call
try {
const response = await client.returns.list();
const returns = response.returns;
console.log(returns);
} catch (error) {
console.error('Error fetching returns:', error);
}All failed requests throw subclasses of StatesetError. You can check the
instance type to handle specific cases:
import { StatesetNotFoundError } from 'stateset-node';
try {
await client.orders.get('ord_123');
} catch (err) {
if (err instanceof StatesetNotFoundError) {
console.log('Order not found');
} else {
console.error('API request failed', err);
}
}const ticket = await client.casesTickets.create({
customer_id: 'cust_123',
status: 'OPEN',
priority: 'MEDIUM',
subject: 'Question about my order',
description: 'The package arrived damaged.'
});
await client.casesTickets.assign(ticket.id, 'agent_123');
await client.casesTickets.addNote(ticket.id, 'Customer will provide photos.');
await client.casesTickets.escalate(ticket.id, 'HIGH');
await client.casesTickets.close(ticket.id);
await client.casesTickets.reopen(ticket.id, 'Additional information received.');
const searchResults = await client.casesTickets.search('damaged', {
status: 'OPEN'
});
console.log(searchResults.cases_tickets);
const notes = await client.casesTickets.listNotes(ticket.id);
console.log(notes);import { OpenAIIntegration, OpenAIIntegrationError } from 'stateset-node';
const openai = new OpenAIIntegration(process.env.OPENAI_API_KEY || 'sk-test', {
baseUrl: process.env.OPENAI_BASE_URL,
defaultModel: 'gpt-4o-mini',
});
try {
const completion = await openai.createChatCompletion(
[{ role: 'user', content: 'Where is my order?' }],
{ temperature: 0.4 }
);
console.log(completion.choices[0].message.content);
} catch (error) {
if (error instanceof OpenAIIntegrationError) {
console.error('OpenAI request failed', error.status, error.message);
} else {
throw error;
}
}Fine-tune caching, retries, and safety per request:
const controller = new AbortController();
const inventory = await client.request('GET', '/inventory', null, {
params: { org_id: 'org_123' },
cache: { key: 'inventory:org_123', ttl: 60_000 },
invalidateCachePaths: ['inventory/count'],
idempotencyKey: 'idem-xyz',
signal: controller.signal,
retryOptions: { maxAttempts: 4, baseDelay: 250 },
onRetryAttempt: ({ attempt, delay }) => {
console.log(`retry #${attempt} scheduled in ${delay}ms`);
}
});Disable caching for a single call with cache: false, or turn it off globally with client.setCacheEnabled(false). Mutating requests automatically invalidate related cache keys based on their path plus any invalidateCachePaths you provide.
Override the default retry strategy globally via client.setRetryStrategy() when your deployment requires different backoff semantics, or pass retryOptions/onRetryAttempt per request as shown above for fine-grained control.
const order = await client.orders.create({
customer_id: 'cust_123',
items: [], // order items here
shipping_address: {
first_name: 'John',
last_name: 'Doe',
street_address1: '1 Market St',
city: 'San Francisco',
state: 'CA',
postal_code: '94105',
country: 'US'
},
payment_details: {
payment_method: 'card',
status: 'authorized',
amount_paid: 0,
currency: 'USD'
},
totals: {
subtotal: 0,
shipping_total: 0,
tax_total: 0,
discount_total: 0,
grand_total: 0,
currency: 'USD'
}
});
await client.orders.updateShippingAddress(order.id, {
first_name: 'Jane',
last_name: 'Doe',
street_address1: '2 Market St',
city: 'San Francisco',
state: 'CA',
postal_code: '94105',
country: 'US'
});
await client.orders.updateBillingAddress(order.id, {
first_name: 'Jane',
last_name: 'Doe',
street_address1: '2 Market St',
city: 'San Francisco',
state: 'CA',
postal_code: '94105',
country: 'US'
});
await client.orders.addNote(order.id, 'Customer requested gift wrap');
const orderNotes = await client.orders.listNotes(order.id);
console.log(orderNotes);
// Search orders and delete when necessary
const searchResults = await client.orders.search('Doe', { status: 'CONFIRMED' });
console.log(searchResults.orders);
await client.orders.delete(order.id);// Generate a shipping label for an existing shipment
const label = await client.shipments.generateLabel('ship_123', { format: 'PDF' });
console.log(label.label_url);Keep the repo healthy by running the standard toolchain before opening a pull request:
npm run validate– lint, type-check, and formatting gatenpm test– deterministic Jest run (forced--runInBand)npm run build– emit the ESM/CJS bundles and type declarations
This repository contains sample Node scripts demonstrating how to use the SDK with both live and mocked transports. Highlights:
samples/orders-flow-sample.ts– exercises resource helpers, cache invalidation, and metrics generation using an in-memory mock transport.samples/inventory-cache-sample.ts– shows advanced cache configuration, explicit invalidation, and bypassing cache for live reads.samples/openai-integration-sample.ts– illustrates the OpenAI helper’s happy-path and error handling without calling the real API.- Legacy integration examples (e.g.,
shipStationSample.js) remain available for direct API experimentation.
To run the TypeScript samples locally:
- Install dependencies:
npm install. - Build the SDK:
npm run build(ensures TypeScript paths resolve). - Execute a sample with
npx ts-node, for example:The new samples do not require live API keys because the HTTP layer is mocked. For legacy samples that call real services, export the required credentials (e.g.,npx ts-node samples/orders-flow-sample.ts
STATESET_API_KEY) before running them withnode.
See the Stateset API Documentation for complete documentation.
See CONTRIBUTING.md for more information on contributing to the Stateset Node.js Library.
The contents of this repository are licensed under the Apache License, version 2.0.