The official Wavix TypeScript SDK provides programmatic access to the Wavix APIs. Use it to add messaging, voice, and account management capabilities to your application.
Use the SDK to:
- Send and receive SMS and MMS messages.
- Place and programmatically control calls.
- Search for, buy, and manage phone numbers.
- Validate phone numbers.
- Manage SIP trunks.
- Retrieve call detail records (CDRs).
- Installation
- Authentication
- Quickstart
- Request and response types
- Error handling
- Pagination
- File uploads
- Binary responses
- Rate limits and retries
- Advanced
- SDK and API compatibility
- Release notes
- Major-version upgrades
- Documentation
- Resources and support
- Contributing
npm i -s wavix-node-sdkRequirements: Node.js 18 or later when you use the SDK with Node.js. See Runtime compatibility for other supported runtimes.
Create an API key in the Wavix portal. Store the key in an environment variable and pass it to the client.
export WAVIX_API_KEY="your-api-key"import { WavixClient } from "wavix-node-sdk";
const client = new WavixClient({ token: process.env.WAVIX_API_KEY });Caution
Don't commit API keys or tokens to source control. In production, store credentials in environment variables or a secrets manager.
Create a client and send an SMS message:
import { WavixClient } from "wavix-node-sdk";
const client = new WavixClient({ token: "YOUR_TOKEN" });
await client.smsAndMms.messages.send({
from: "Wavix",
to: "+447537151866",
message_body: {
text: "Hi there, this is a message from Wavix",
media: null
},
callback_url: "https://you-site.com/webhook",
validity: 3600,
tag: "Fall sale"
});The SDK exports request and response types as TypeScript interfaces. Import
the Wavix namespace to use these types:
import { Wavix } from "wavix-node-sdk";
const request: Wavix.ListApiKeysRequest = {
...
};When the API returns a 4xx or 5xx status code, the SDK throws a subclass
of WavixError. Use the error properties to inspect the status code, message,
response body, and raw response:
import { WavixError } from "wavix-node-sdk";
try {
await client.smsAndMms.messages.send(...);
} catch (err) {
if (err instanceof WavixError) {
console.log(err.statusCode);
console.log(err.message);
console.log(err.body);
console.log(err.rawResponse);
}
}Handle errors that aren't instances of WavixError separately, or rethrow
them so that your application doesn't ignore unexpected failures.
List operations use automatic page-number pagination. The SDK requests additional pages as you iterate through the results.
The Wavix API supports these pagination parameters:
page: Specifies the page to retrieve.per_page: Specifies the number of items per page. The default is25. The minimum is1, and the maximum is100.
Pass a supported file type to an endpoint that accepts file uploads:
import { createReadStream } from "fs";
import * as fs from "fs";
import { WavixClient } from "wavix-node-sdk";
const client = new WavixClient({ token: "YOUR_TOKEN" });
await client.speechAnalytics.create({
file: fs.createReadStream("/path/to/your/file"),
callback_url: "callback_url"
});The client accepts the following file types:
- Streams:
fs.ReadStream,stream.Readable, andReadableStream. - Buffered data:
Buffer,Blob,File,ArrayBuffer,ArrayBufferView, andUint8Array.
Add metadata to an uploaded file:
const file: Uploadable.WithMetadata = {
data: createReadStream("path/to/file"),
filename: "my-file", // optional
contentType: "audio/mpeg", // optional
contentLength: 1949, // optional
};You can also upload a file from a file path:
const file : Uploadable.FromPath = {
path: "path/to/file",
filename: "my-file", // optional
contentType: "audio/mpeg", // optional
contentLength: 1949, // optional
};The SDK uses this metadata to set the Content-Length, Content-Type, and
Content-Disposition headers. If you omit the metadata, the SDK tries to
determine it automatically. For example, the SDK can use the path property
of an fs.ReadStream to retrieve the file size without loading the file into
memory.
Endpoints that return binary data use the BinaryResponse type. Read the
response as a stream, array buffer, blob, or byte array:
const response = await client.billing.invoices.download(...);
const stream: ReadableStream<Uint8Array> = response.stream();
// const arrayBuffer: ArrayBuffer = await response.arrayBuffer();
// const blob: Blob = response.blob();
// const bytes: Uint8Array = response.bytes();
// You can only use the response body once, so you must choose one of the above methods.
// If you want to check if the response body has been used, you can use the following property.
const bodyUsed = response.bodyUsed;Save binary response to a file
Node.js
ReadableStream (most-efficient)
import { createWriteStream } from 'fs'; import { Readable } from 'stream'; import { pipeline } from 'stream/promises'; const response = await client.billing.invoices.download(...); const stream = response.stream(); const nodeStream = Readable.fromWeb(stream); const writeStream = createWriteStream('path/to/file'); await pipeline(nodeStream, writeStream);ArrayBuffer
import { writeFile } from 'fs/promises'; const response = await client.billing.invoices.download(...); const arrayBuffer = await response.arrayBuffer(); await writeFile('path/to/file', Buffer.from(arrayBuffer));Blob
import { writeFile } from 'fs/promises'; const response = await client.billing.invoices.download(...); const blob = await response.blob(); const arrayBuffer = await blob.arrayBuffer(); await writeFile('output.bin', Buffer.from(arrayBuffer));Bytes (UIntArray8)
import { writeFile } from 'fs/promises'; const response = await client.billing.invoices.download(...); const bytes = await response.bytes(); await writeFile('path/to/file', bytes);
Bun
ReadableStream (most-efficient)
const response = await client.billing.invoices.download(...); const stream = response.stream(); await Bun.write('path/to/file', stream);ArrayBuffer
const response = await client.billing.invoices.download(...); const arrayBuffer = await response.arrayBuffer(); await Bun.write('path/to/file', arrayBuffer);Blob
const response = await client.billing.invoices.download(...); const blob = await response.blob(); await Bun.write('path/to/file', blob);Bytes (UIntArray8)
const response = await client.billing.invoices.download(...); const bytes = await response.bytes(); await Bun.write('path/to/file', bytes);
Deno
ReadableStream (most-efficient)
const response = await client.billing.invoices.download(...); const stream = response.stream(); const file = await Deno.open('path/to/file', { write: true, create: true }); await stream.pipeTo(file.writable);ArrayBuffer
const response = await client.billing.invoices.download(...); const arrayBuffer = await response.arrayBuffer(); await Deno.writeFile('path/to/file', new Uint8Array(arrayBuffer));Blob
const response = await client.billing.invoices.download(...); const blob = await response.blob(); const arrayBuffer = await blob.arrayBuffer(); await Deno.writeFile('path/to/file', new Uint8Array(arrayBuffer));Bytes (UIntArray8)
const response = await client.billing.invoices.download(...); const bytes = await response.bytes(); await Deno.writeFile('path/to/file', bytes);
Browser
Blob (most-efficient)
const response = await client.billing.invoices.download(...); const blob = await response.blob(); const url = URL.createObjectURL(blob); // trigger download const a = document.createElement('a'); a.href = url; a.download = 'filename'; a.click(); URL.revokeObjectURL(url);ReadableStream
const response = await client.billing.invoices.download(...); const stream = response.stream(); const reader = stream.getReader(); const chunks = []; while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); } const blob = new Blob(chunks); const url = URL.createObjectURL(blob); // trigger download const a = document.createElement('a'); a.href = url; a.download = 'filename'; a.click(); URL.revokeObjectURL(url);ArrayBuffer
const response = await client.billing.invoices.download(...); const arrayBuffer = await response.arrayBuffer(); const blob = new Blob([arrayBuffer]); const url = URL.createObjectURL(blob); // trigger download const a = document.createElement('a'); a.href = url; a.download = 'filename'; a.click(); URL.revokeObjectURL(url);Bytes (UIntArray8)
const response = await client.billing.invoices.download(...); const bytes = await response.bytes(); const blob = new Blob([bytes]); const url = URL.createObjectURL(blob); // trigger download const a = document.createElement('a'); a.href = url; a.download = 'filename'; a.click(); URL.revokeObjectURL(url);
Convert binary response to text
ReadableStream
const response = await client.billing.invoices.download(...); const stream = response.stream(); const text = await new Response(stream).text();
ArrayBuffer
const response = await client.billing.invoices.download(...); const arrayBuffer = await response.arrayBuffer(); const text = new TextDecoder().decode(arrayBuffer);
Blob
const response = await client.billing.invoices.download(...); const blob = await response.blob(); const text = await blob.text();
Bytes (UIntArray8)
const response = await client.billing.invoices.download(...); const bytes = await response.bytes(); const text = new TextDecoder().decode(bytes);
Rate limits vary by endpoint. When a request exceeds an endpoint's rate
limit, the Wavix API returns an HTTP 429 Too Many Requests response.
The SDK can retry 429 responses as described in Retries.
Configure retries according to your application's traffic patterns and
latency requirements.
The SDK automatically retries eligible requests by using exponential backoff. By default, the SDK makes up to two retry attempts.
The SDK retries requests that return one of these status codes:
These status codes aren't configurable.
Use the maxRetries request option to override the retry limit for an
individual request:
const response = await client.smsAndMms.messages.send(..., {
maxRetries: 0 // override maxRetries at the request level
});Important
A retry can repeat an operation if the server processes the original request but the client doesn't receive the response. Before you retry an operation that sends a message, places a call, or changes a resource, confirm that the operation can be repeated safely.
The Wavix API doesn't support idempotency keys. A repeated request can repeat the operation, including sending a message, placing a call, or changing a resource.
Before you retry a request that changes data or starts an operation, check whether the original request succeeded. When duplicate operations could affect customers or incur charges, track request state in your application and prevent the same operation from being submitted more than once.
Import a subpackage client directly to help JavaScript bundlers remove unused SDK code and reduce the bundle size:
import { ApiKeysClient } from 'wavix-node-sdk/apiKeys';
const client = new ApiKeysClient({...});Use the headers request option to add headers to every request from a client
or to an individual request:
import { WavixClient } from "wavix-node-sdk";
const client = new WavixClient({
...
headers: {
'X-Custom-Header': 'custom value'
}
});
const response = await client.smsAndMms.messages.send(..., {
headers: {
'X-Custom-Header': 'custom value'
}
});Use the queryParams request option to add query parameters to an individual
request:
const response = await client.smsAndMms.messages.send(..., {
queryParams: {
'customQueryParamKey': 'custom query param value'
}
});The default request timeout is 60 seconds. Use the timeoutInSeconds request
option to override the timeout for an individual request:
const response = await client.smsAndMms.messages.send(..., {
timeoutInSeconds: 30 // override timeout to 30s
});Pass an AbortSignal to cancel a request:
const controller = new AbortController();
const response = await client.smsAndMms.messages.send(..., {
abortSignal: controller.signal
});
controller.abort(); // aborts the requestCall abort() while the request is pending. Calling it after the request
settles has no effect.
Call .withRawResponse() to access response headers and other raw response
data. The method returns a promise that resolves to an object with data and
rawResponse properties:
const { data, rawResponse } = await client.smsAndMms.messages.send(...).withRawResponse();
console.log(data);
console.log(rawResponse.headers['X-My-Header']);Pass a logging object to the client options to configure SDK logs:
import { WavixClient, logging } from "wavix-node-sdk";
const client = new WavixClient({
...
logging: {
level: logging.LogLevel.Debug, // defaults to logging.LogLevel.Info
logger: new logging.ConsoleLogger(), // defaults to ConsoleLogger
silent: false, // defaults to true, set to false to enable logging
}
});Caution
Logs can contain request or response data. Review your logging configuration before you enable SDK logs in production, and don't record credentials or sensitive customer data.
The logging object supports these properties:
level: Sets the log level. The default islogging.LogLevel.Info.logger: Sets the logger. The default islogging.ConsoleLogger.silent: Turns logging off when set totrue. The default istrue.
Set level to one of these values:
logging.LogLevel.Debuglogging.LogLevel.Infologging.LogLevel.Warnlogging.LogLevel.Error
To use a custom logger, pass an object that implements the logging.ILogger
interface.
Custom logger examples
The following example uses the winston logging library.
import winston from 'winston';
const winstonLogger = winston.createLogger({...});
const logger: logging.ILogger = {
debug: (msg, ...args) => winstonLogger.debug(msg, ...args),
info: (msg, ...args) => winstonLogger.info(msg, ...args),
warn: (msg, ...args) => winstonLogger.warn(msg, ...args),
error: (msg, ...args) => winstonLogger.error(msg, ...args),
};The following example uses the pino logging library.
import pino from 'pino';
const pinoLogger = pino({...});
const logger: logging.ILogger = {
debug: (msg, ...args) => pinoLogger.debug(args, msg),
info: (msg, ...args) => pinoLogger.info(args, msg),
warn: (msg, ...args) => pinoLogger.warn(args, msg),
error: (msg, ...args) => pinoLogger.error(args, msg),
};Use the low-level fetch method to call an API endpoint that the SDK doesn't
yet support. Requests made with this method use the SDK's authentication,
retry, timeout, and logging configuration:
const response = await client.fetch("/v1/custom/endpoint", {
method: "GET",
}, {
timeoutInSeconds: 30,
maxRetries: 3,
headers: {
"X-Custom-Header": "custom-value",
},
});
const data = await response.json();The SDK supports these runtimes:
- Node.js 18+
- Vercel
- Cloudflare Workers
- Deno v1.25+
- Bun 1.0+
- React Native
Test your application in its target runtime before you deploy it. Runtime implementations can differ in their support for streams, files, and other web APIs.
Each SDK release supports the current version of the Wavix APIs available when that SDK version is released. Update the SDK regularly to access the latest API capabilities and fixes.
Before you update the SDK, review the GitHub releases for changes that might affect your application.
See GitHub releases for new features, fixes, and breaking changes in each SDK release.
The SDK doesn't provide separate migration guides. Breaking changes ship only in major versions, so before you upgrade, review the GitHub releases for breaking changes, then update and test in a development environment before you deploy.
- For API guides and API reference documentation, see the Wavix documentation.
- For SDK methods and types, see the TypeScript SDK reference.
- Versioning: The SDK follows Semantic Versioning. Breaking changes are released in major versions.
- Security: Report vulnerabilities privately by following the instructions in SECURITY.md. Don't report vulnerabilities in public issues.
- Support: For product and API support, contact support@wavix.com.
- Issues: To report an SDK bug or request a feature, open a GitHub issue.
- License: The SDK is available under the MIT License.
The SDK source code is generated. Changes made directly to generated files are overwritten in the next release and can't be merged as submitted. Before you prepare a code change, open an issue to discuss the proposed update.
You can submit README improvements directly in a pull request.