@rechannel/sdk
v0.1.0
Published
Node.js SDK for the reChannel API
Maintainers
Readme
@rechannel/sdk
Node.js SDK for the reChannel API. Zero dependencies, uses native fetch (Node 18+), full TypeScript types.
Installation
npm install @rechannel/sdkQuick Start
import { ReChannel } from '@rechannel/sdk';
// Authenticate with token or API key
const rc = new ReChannel({
token: 'your-jwt-token', // or apiKey: 'your-api-key'
tenantId: 'your-tenant-id',
});
// Or login to get an authenticated client
const { client, auth } = await ReChannel.login({
email: '[email protected]',
password: 'password',
});
// Register a new developer account
const { client: newClient, auth: newAuth } = await ReChannel.register({
email: '[email protected]',
password: 'password',
companyName: 'Acme Inc',
});Configuration
| Option | Type | Required | Default |
| ---------- | -------- | -------- | ---------------------------------- |
| token | string | * | - |
| apiKey | string | * | - |
| tenantId | string | yes | - |
| baseUrl | string | no | https://rc-api.rift.wyrld.com |
* Either token or apiKey must be provided.
You can update credentials at runtime:
rc.setToken('new-token');
rc.setTenantId('new-tenant-id');Resources
Users
CRUD user profiles, manage device tokens, and list user events.
// Create or update a user
const user = await rc.users.upsert({
externalId: 'user-123',
email: '[email protected]',
firstName: 'Alice',
customAttributes: { plan: 'pro' },
});
// Bulk upsert (up to 100)
const users = await rc.users.bulkUpsert([
{ externalId: 'user-1', email: '[email protected]' },
{ externalId: 'user-2', email: '[email protected]' },
]);
// Get, update, delete
const user = await rc.users.get('user-123');
await rc.users.update('user-123', { firstName: 'Bob' });
await rc.users.delete('user-123');
// List with cursor pagination
const page = await rc.users.list({ limit: 50 });
// => { data: UserProfile[], nextCursor?, hasMore, total? }
// Async iteration over all users
for await (const user of rc.users.listAll()) {
console.log(user.externalId);
}
// Device tokens
await rc.users.registerDeviceToken('user-123', {
token: 'fcm-token',
platform: 'fcm',
});
await rc.users.removeDeviceToken('user-123', 'fcm-token');
// User events
const events = await rc.users.listEvents('user-123');Events
Track user events individually or in batches.
// Track a single event
const event = await rc.events.track({
externalUserId: 'user-123',
eventName: 'purchase_completed',
properties: { amount: 49.99, currency: 'USD' },
});
// Batch track (max 500 per call)
await rc.events.trackBatch([
{ externalUserId: 'user-1', eventName: 'page_view', properties: { page: '/home' } },
{ externalUserId: 'user-2', eventName: 'page_view', properties: { page: '/pricing' } },
]);Segments
Create audience segments using DSL queries, manage membership manually or dynamically.
// Create a segment with a DSL query
const segment = await rc.segments.create({
name: 'Pro Users',
description: 'Users on the pro plan',
query: '{"customAttributes.plan": "pro"}',
});
// CRUD
const segments = await rc.segments.list();
const seg = await rc.segments.get(segment._id);
await rc.segments.update(segment._id, { name: 'Premium Users' });
await rc.segments.delete(segment._id);
// Preview a query without saving
const matchingUsers = await rc.segments.preview('{"locale": "en-US"}');
// Evaluate and count
const evaluated = await rc.segments.evaluate(segment._id);
const { count } = await rc.segments.count(segment._id);
// Manual membership
await rc.segments.addMember(segment._id, 'user-123');
await rc.segments.removeMember(segment._id, 'user-123');
const members = await rc.segments.listMembers(segment._id);Campaigns
Create and manage messaging campaigns. Types: one-shot, scheduled, recurring, event-triggered.
// Create a scheduled push campaign
const campaign = await rc.campaigns.create({
name: 'Welcome Push',
type: 'scheduled',
segmentId: 'seg-id',
channels: ['push'],
pushMessage: {
title: 'Welcome!',
body: 'Thanks for signing up.',
},
scheduledAt: '2026-05-01T12:00:00Z',
});
// Create an event-triggered email campaign
const triggered = await rc.campaigns.create({
name: 'Cart Abandonment',
type: 'event-triggered',
segmentId: 'seg-id',
channels: ['email'],
triggerEventName: 'cart_abandoned',
triggerDelayMs: 3600000, // 1 hour
emailMessage: {
from: '[email protected]',
subject: 'You left something behind',
html: '<h1>Come back!</h1>',
},
});
// Lifecycle
await rc.campaigns.activate(campaign._id);
await rc.campaigns.pause(campaign._id);
await rc.campaigns.archive(campaign._id);
// List with filters
const active = await rc.campaigns.list({ status: 'active', type: 'recurring' });
// Async iteration
for await (const c of rc.campaigns.listAll()) {
console.log(c.name, c.status);
}
// Execution history
const executions = await rc.campaigns.listExecutions(campaign._id);Journeys
Build multi-step user journeys with delays, conditions, and messages.
// Create a journey
const journey = await rc.journeys.create({
name: 'Onboarding Flow',
entryType: 'event',
triggerEventName: 'user_signed_up',
nodes: [
{ nodeId: 'delay-1', type: 'delay', config: { delayMs: 86400000 } },
{ nodeId: 'push-1', type: 'push', config: { title: 'Day 1 tip' }, nextNodeId: 'delay-1' },
],
});
// Lifecycle
await rc.journeys.activate(journey._id);
await rc.journeys.pause(journey._id);
await rc.journeys.archive(journey._id);
// List and iterate
const journeys = await rc.journeys.list({ status: 'active' });
for await (const j of rc.journeys.listAll()) {
console.log(j.name);
}
// Enroll a user manually (for entryType: 'api')
const enrollment = await rc.journeys.enroll(journey._id, 'user-123');
// Enrollment management
const enrollments = await rc.journeys.listEnrollments(journey._id);
const single = await rc.journeys.getEnrollment(journey._id, enrollment._id);Push
Send push notifications, configure FCM, and manage delivery settings.
// Send to a user by externalId
const notification = await rc.push.send({
externalId: 'user-123',
title: 'New message',
body: 'You have a new message.',
data: { deepLink: '/messages/456' },
});
// Send to a specific device token
await rc.push.sendRaw({
deviceToken: 'fcm-device-token',
platform: 'fcm',
title: 'Hello',
});
// Get and list notifications
const notif = await rc.push.get(notification._id);
const list = await rc.push.list({ externalUserId: 'user-123' });
// FCM configuration
await rc.push.setConfig({
projectId: 'my-project',
clientEmail: '[email protected]',
privateKey: '-----BEGIN PRIVATE KEY-----\n...',
});
const config = await rc.push.getConfig();
await rc.push.deleteConfig();
// Frequency cap (rate limiting)
await rc.push.setFrequencyCap({
maxMessages: 5,
windowSeconds: 86400,
channels: ['push'],
});
const cap = await rc.push.getFrequencyCap();
// Quiet hours (suppress notifications during certain times)
await rc.push.setQuietHours({
enabled: true,
startTime: '22:00',
endTime: '08:00',
defaultTimezone: 'America/New_York',
});
const quiet = await rc.push.getQuietHours();Social
Connect social accounts via OAuth, manage integrations, create and publish posts, and fetch insights.
// List available providers
const providers = await rc.social.listProviders();
// Start OAuth flow
const session = await rc.social.createAuthSession({
provider: 'instagram',
mode: 'connect',
redirectUri: 'https://app.example.com/callback',
});
// Redirect user to session.authorizationUrl
// Poll for session completion
const completed = await rc.social.getAuthSession(session._id);
// Select accounts (multi-account OAuth flows)
await rc.social.selectAccounts(session._id, {
providerAccountIds: ['acct-1', 'acct-2'],
});
// Manage integrations
const integrations = await rc.social.listIntegrations({ provider: 'instagram' });
const integration = await rc.social.getIntegration('integration-id');
await rc.social.updateIntegration('integration-id', { displayName: 'My Brand' });
await rc.social.refreshIntegration('integration-id');
await rc.social.disconnectIntegration('integration-id');
// Fetch provider-specific resources
const pages = await rc.social.getResource('integration-id', 'pages');
// Posts
const post = await rc.social.createPost({
integrationId: 'integration-id',
text: 'Hello world!',
scheduledAt: '2026-05-01T12:00:00Z',
});
const posts = await rc.social.listPosts({ integrationId: 'integration-id' });
const fetched = await rc.social.getPost(post._id);
await rc.social.publishPost(post._id);
// Insights
const accountInsights = await rc.social.getAccountInsights('integration-id', {
since: '2026-01-01',
until: '2026-04-01',
});
const postInsights = await rc.social.getPostInsights(post._id);Connect email domains, verify DNS, and send transactional emails.
// Connect a domain
const email = await rc.email.connect({ domain: 'mail.example.com' });
// Get DNS records and verify
const records = await rc.email.getDnsRecords(email._id);
// Add records to your DNS provider, then verify:
const verified = await rc.email.verify(email._id);
// Send an email
const message = await rc.email.send(email._id, {
from: '[email protected]',
to: ['[email protected]'],
subject: 'Welcome',
html: '<h1>Welcome!</h1>',
});
// List integrations and messages
const integrations = await rc.email.list();
const messages = await rc.email.listMessages(email._id);
// Delete an integration
await rc.email.delete(email._id);Analytics
Retrieve delivery and engagement metrics for campaigns, journeys, and users.
// Campaign analytics
const stats = await rc.analytics.campaign('campaign-id');
// => { campaignId, totals: { sent, delivered, opened, ... }, byChannel: { push: {...}, email: {...} } }
// Journey analytics
const journeyStats = await rc.analytics.journey('journey-id');
// Per-node analytics
const nodeStats = await rc.analytics.journeyNodes('journey-id');
// => [{ nodeId, metrics: { entered, exited, ... } }, ...]
// User message history
const userStats = await rc.analytics.user('user-123');
// => { data: [{ type, channel, sourceId, sourceType, status, timestamp }, ...] }Pagination
All list endpoints return a PaginatedResponse<T>:
interface PaginatedResponse<T> {
data: T[];
nextCursor?: string;
hasMore: boolean;
total?: number;
}Fetch the next page by passing the cursor:
const page1 = await rc.users.list({ limit: 50 });
if (page1.hasMore) {
const page2 = await rc.users.list({ limit: 50, cursor: page1.nextCursor });
}For automatic pagination, use listAll (available on users, campaigns, and journeys):
for await (const user of rc.users.listAll({ limit: 100 })) {
// processes all users across all pages
}Error Handling
All errors extend ReChannelError. Specific subclasses map to HTTP status codes:
| Class | Status | Properties |
| --------------------- | ------ | ----------------------- |
| ApiError | any | status, details |
| AuthenticationError | 401 | - |
| NotFoundError | 404 | - |
| ValidationError | 400 | details |
| RateLimitError | 429 | retryAfter (seconds) |
import { ApiError, NotFoundError, RateLimitError } from '@rechannel/sdk';
try {
await rc.users.get('nonexistent');
} catch (err) {
if (err instanceof NotFoundError) {
console.log('User not found');
} else if (err instanceof RateLimitError) {
console.log(`Retry after ${err.retryAfter}s`);
} else if (err instanceof ApiError) {
console.log(`API error ${err.status}: ${err.message}`);
}
}Requirements
- Node.js >= 18.0.0 (uses native
fetch) - TypeScript >= 5.0 (recommended)
