Skip to main content

Node.js SDK

The official Devotel Node.js SDK provides a fully typed client for the Devotel API. Built with TypeScript, it supports all Devotel services — messaging, voice, agents, flows, numbers, and verify.

Installation

Or with other package managers:

Quickstart: send your first SMS

A runnable end-to-end in five lines — the key comes from your environment, never from source. Copy it into a file and run it with node first-send.mjs:
Set ORBIT_API_KEY to a sandbox key prefixed dv_test_sk_ first — sandbox sends are simulated, free, and never reach a carrier. Swap in your live key (dv_live_sk_...) when you’re ready to send for real; the code does not change. The per-channel helpers (sendWhatsApp, sendEmail, …) are covered under Messaging below, and the full request/response contract — including language tabs with this exact call — lives on the Messages API reference. For a complete runnable project, the two SMS starter repos on Starter examples build on this exact flow.

Messaging

Voice

The Voice resource exposes call control, recordings, transcripts, conferences, IVR, dialer campaigns, SIP trunks, and analytics. See Voice operations below for the full surface.
AI-agent / IVR routing and webhooks are not per-call options. Configure them once on the Application / IVR Flow that owns the number — the call then follows that routing. See Voice operations below.

Voice operations

A complete tour of the live call-control surface. Every snippet matches the actual SDK API in packages/sdk-node/src/resources/voice.ts.

Make a call

The AI voice agent is bindable per call via agent_id. When set, the call is dispatched to that named, tenant-scoped voice agent — the server validates it exists and is not archived (the same first-class field shown in the Quickstart). voice.calls.create() accepts to, from, record, amd, campaignId, orgTimezone, agent_id, and metadata; any other field is silently stripped by the server. IVR flows and webhooks remain Application / IVR-Flow level configuration, not per create() overrides. Attach the destination number to an Application (or IVR Flow) and the call inherits its IVR routing and webhook configuration.

Get call details

You can also list with pagination + filters:

Hang up a call

Transfer a call

Both cold (blind) and warm (consult-first) transfers are supported on the same transfer() method:
warmTransfer() forwards its params to the server verbatim, so the field names below are camelCase exactly as shown — the route validates them under those keys:
  • destination — E.164 number to consult-then-bridge to (required).
  • from — optional caller ID presented on the consultation leg.
  • contextWhisper — when true, a short summary is spoken to the receiving agent on answer, before the bridge. Defaults to false.
  • context — optional custom whisper text (max 220 characters). When omitted while contextWhisper is true, a generic summary is spoken.

Conference call

Conference participant controls

Once a conference is live, the moderator can mute, hold, kick, lock, and record from orbit.voice.conferences.*. The participantId is the Jambonz call_sid of the leg (the leg_call_sid field on each row of the conference detail / listParticipants response):

IVR flows

Trigger a published IVR flow as an outbound session, or browse the flow catalog:

Conversational IVR intents

Per-tenant NLU buckets the LLM classifier uses to route free-speech caller utterances to an ACD queue or a direct agent:

Outbound dialer campaigns

Manage power/predictive dialer campaigns. Status changes flow through the server’s campaign state machine — start() and pause() are ergonomic wrappers over the status transition:

SIP trunks

Voice clones & VAQI analytics

Record a call

Recording is started by passing record: true at call creation; pause/resume happens via call-control endpoints. After the call ends, fetch the recording metadata and a signed download URL:

Listen to a recording

Live transcript stream (Node-only)

Voice webhook handling

Verify the signature with the shared SDK helper, then dispatch on event.type: The signing secret is the dashboard-issued whsec_... value from your endpoint’s settings (see Webhook Security) — a customer-side secret you store in your own environment, not an Orbit env.ts variable. Name the env var whatever you like; ORBIT_WEBHOOK_SECRET is used here.

Verify

The fastest first integration on the platform: send a one-time passcode, then check the code your user types in. Three lines:
Check the code after the user enters it — on a wrongly-typed or expired code result.data.valid is false; it never throws for a bad guess (only for transport/auth failures). The full contract is on the Verify API reference, and the OTP sign-in starter repo shows the same flow as a complete, runnable Next.js app.

Paginate a list

List endpoints are cursor-paginated — each response carries meta.pagination.cursor and meta.pagination.has_more, and you pass the cursor back until has_more is false. Page through SMS messages:
For the common “iterate everything” case the SDK ships an auto-paginating async iterator — no cursor bookkeeping at all:
The full pagination model (cursor vs. offset endpoints, page-size caps, and why cursors are not bookmarkable) is in the Pagination guide.

Webhooks

Error Handling

Every non-2xx response is thrown as an OrbitApiError, but the SDK constructs a status-specific subclass so you can branch on the failure mode. Narrow on the subclass first, then fall back to the OrbitApiError base. All of these names are importable from @devotel-orbit/node: OrbitApiError (base), OrbitAuthError (401/403), OrbitNotFoundError (404), OrbitRateLimitError (429), OrbitValidationError (400/422), OrbitServerError (5xx), and OrbitWebhookSignatureError (webhook verification — extends Error, not OrbitApiError).
See the SDK overview for the full error tree shared across every Orbit SDK.

Runnable examples

The package’s examples/ directory holds self-contained, runnable end-to-end files (each takes ORBIT_API_KEY / ORBIT_WEBHOOK_SECRET from the environment): cursor pagination over orbit.messages.iter(...), the OTP send+check round trip, a programmable outbound call with an answer_url callback, webhook signature verification against a signed test payload, a bulk contacts CSV import, and a phone-number identity-risk score. Run any of them with node examples/<name>.js. The API recipes cookbook walks the same flows task by task.

Configuration

Requirements

  • Node.js 18 or later
  • TypeScript 5.0+ (recommended but not required)