Node.js SDK
The official @rymi/node package provides convenient, strongly-typed access to the Rymi REST API from any server-side JavaScript or TypeScript application.
Installation
Install the package using your preferred package manager:
npm install @rymi/node
# or
yarn add @rymi/node
# or
pnpm add @rymi/nodeInitialization
Import the Rymi class and initialize it with your API key. If you omit the apiKey configuration, the SDK will automatically look for a RYMI_API_KEY environment variable.
import { Rymi } from '@rymi/node';
// Initialize with an explicit API Key:
const rymi = new Rymi({ apiKey: 'rymi_your_secret_key' });
// OR rely on process.env.RYMI_API_KEY:
const rymiEnv = new Rymi();Agents
Create, list, and manage your AI voice personas.
// Create a new conversational Agent
const agent = await rymi.agents.create({
name: 'Customer Support',
system_prompt: 'You are a helpful customer support assistant for Acme Corp.',
voice: 'Aoede',
language: 'en-US'
});
console.log(agent.id);
// List all configured agents
const { agents } = await rymi.agents.list();Clone an agent
const clone = await rymi.agents.clone(agent.id);
console.log(clone.id); // new agent ID, name gets " (Copy)" appendedList calls for an agent
const { calls, total } = await rymi.agents.listCalls(agent.id, { limit: 20 });Validate before publishing
Check whether an agent's config is ready to go live. Returns a validation report without changing anything.
const report = await rymi.agents.validatePublish({ agent_id: agent.id });
if (!report.valid) {
console.error(report.errors);
}Apply a structured change-set
Validate and resolve a flat key/value diff against the field registry. Does not persist — follow up with update().
const result = await rymi.agents.applyChanges({
currentConfig: { name: 'Support', voice: 'Aoede' },
changes: [{ key: 'voice', value: 'Charon' }],
mode: 'edit',
});
// result.config has the merged config; result.applied lists what changed
await rymi.agents.update(agent.id, result.config);Enrich company from website
Generate a company description for the agent's persona using AI + Google Search grounding.
const info = await rymi.agents.enrichCompany({
companyName: 'Acme Corp',
websiteUrl: 'https://acme.example.com',
});
if (info.enriched) {
console.log(info.companyDescription);
}Calls
Create voice call sessions with one or more participants. Each call maps to a single room that can include WebRTC (browser) and PSTN (phone) participants.
// Start an outbound PSTN call
const call = await rymi.calls.create({
agent_id: agent.id,
participants: [
{
transport: 'pstn',
identity: '+15551234567',
from_number: '+15559876543'
}
],
metadata: {
customer_name: 'Alice',
order_status: 'shipped'
}
});
console.log(`Call queued with ID: ${call.id}`);
console.log(`Room: ${call.room_name}`);
// Start a WebRTC call (returns a LiveKit token)
const webCall = await rymi.calls.create({
agent_id: agent.id,
participants: [
{ transport: 'webrtc', identity: 'browser-user-1' }
]
});
// Access the participant's LiveKit credentials
const participant = webCall.participants[0];
console.log(`LiveKit URL: ${participant.access?.url}`);
console.log(`Token: ${participant.access?.token}`);
// Retrieve transcript and metadata after the call ends
const details = await rymi.calls.retrieve(call.id);
const transcript = await rymi.calls.transcript(call.id);Batch Calls
Queue up to 500 outbound PSTN recipients in one request.
const batch = await rymi.calls.batch({
agent_id: agent.id,
to: ['+15551234567', '+15557654321'],
from_number: '+15559876543',
variables: { batch_label: 'renewal-q2' }
});
console.log(batch.batch_id, batch.queued);Phone Numbers
Register carrier-owned BYOC numbers, list registered numbers, and attach them to agents. Rymi does not purchase phone numbers; provision numbers in your carrier account first.
await rymi.numbers.register('+15559876543');
const { numbers } = await rymi.numbers.list();
await rymi.numbers.attach(numbers[0].number, agent.id);Verifying Webhooks
When your application receives asynchronous events (like call.intelligence.ready), you must cryptographically verify the webhook signature to protect against replay attacks and spoofing.
The Node SDK includes a built-in helper to securely validate the Rymi-Signature HMAC.
import express from 'express';
import { Rymi } from '@rymi/node';
const app = express();
const rymi = new Rymi();
// Ensure you parse the body as raw TEXT or BUFFER for accurate HMAC verification
app.post('/webhook', express.text({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-rymi-signature'] as string;
const timestamp = req.headers['x-rymi-timestamp'] as string;
const payload = req.body; // Raw JSON string
try {
rymi.webhooks.verifySignature(
payload,
signature,
timestamp,
process.env.RYMI_WEBHOOK_SECRET!
);
console.log('Webhook authenticated successfully!');
// Process webhook event safely...
const event = JSON.parse(payload);
if (event.type === 'call.intelligence.ready') {
console.log('Call intelligence:', event.data.call_id, event.data.summary);
}
res.status(200).send('OK');
} catch (error) {
console.error('Invalid webhook signature!', error);
res.status(401).send('Unauthorized');
}
});
