@zuora/zuora-sdk-ts
v0.0.1-alpha.4
Published
Zuora TypeScript SDK
Readme
Zuora TypeScript SDK
This cookbook-style guide shows the recommended way to use @zuora/zuora-sdk-ts in
application code. The SDK is generated from Zuora OpenAPI specs and provides a
ZuoraClient wrapper for authentication, environment selection, default headers,
timeouts, authentication retries, normalized errors, and optional request/response
logging.
Installation
npm install @zuora/zuora-sdk-tsFor TypeScript projects, no separate @types package is required.
Runtime and Module Support
The SDK officially supports Node.js 20 or newer:
{
"engines": {
"node": ">=20"
}
}Package entry points:
| Use case | Entry | Notes |
| --- | --- | --- |
| CommonJS | main: ./dist/index.js | Use from Node.js with require. |
| TypeScript and bundlers | module: ./dist/esm/index.js | Use with import in TypeScript, Webpack, Rollup, Vite, and similar bundlers. |
| Types | types: ./dist/index.d.ts | No separate @types package is required. |
CommonJS:
const { ZuoraClient, ZuoraEnvironments } = require("@zuora/zuora-sdk-ts");
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
});TypeScript or bundler ESM:
import { ZuoraClient, ZuoraEnvironments } from "@zuora/zuora-sdk-ts";
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
});Native Node.js ESM is not the primary published format yet because the package
does not publish a Node exports map. For Node.js applications, CommonJS is the
most predictable runtime path today. Bundler ESM is supported through the
module entry.
Build-time dependencies:
- Runtime HTTP client:
axios - TypeScript compiler:
typescript5.x - SDK build Node typings:
@types/node20.x
Basic Client Setup
import { ZuoraClient, ZuoraEnvironments } from "@zuora/zuora-sdk-ts";
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId: process.env.ZUORA_CLIENT_ID!,
clientSecret: process.env.ZUORA_CLIENT_SECRET!,
});
await client.initialize();Call initialize() before the first API call. The client fetches and caches an
OAuth token, then refreshes it when it is expired or close to expiring.
Do not hard-code credentials in source code. Load clientId and clientSecret
from your application configuration or secret manager.
Environments
Use env with exported environment constants for standard Zuora environments:
const client = new ZuoraClient({
env: ZuoraEnvironments.PROD,
clientId,
clientSecret,
});Supported environment constants:
ZuoraEnvironments.SBX
ZuoraEnvironments.SBX_NA
ZuoraEnvironments.SBX_EU
ZuoraEnvironments.CSBX
ZuoraEnvironments.CSBX_EU
ZuoraEnvironments.CSBX_AP
ZuoraEnvironments.PROD
ZuoraEnvironments.PROD_NA
ZuoraEnvironments.PROD_EU
ZuoraEnvironments.PROD_APUse baseUrl only when you need a custom endpoint:
const client = new ZuoraClient({
clientId,
clientSecret,
baseUrl: "https://rest.apisandbox.zuora.com",
});Configuration Options
import { ZuoraEnvironments } from "@zuora/zuora-sdk-ts";
import type { ZuoraClientOptions } from "@zuora/zuora-sdk-ts";
const options: ZuoraClientOptions = {
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
requestTimeout: 60_000,
maxRetries: 3,
retryBaseDelay: 1_000,
zuoraVersion: "2025-08-12",
zuoraEntityIds: "entity-id",
zuoraOrgIds: "org-id",
zuoraTrackId: "trace-id",
headers: {
"X-Custom-Header": "custom-value",
},
};
const client = new ZuoraClient(options);Header Configuration
Prefer typed Zuora header fields so callers do not need to remember exact HTTP header names:
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
zuoraVersion: "2025-08-12",
zuoraEntityIds: "entity-id",
zuoraOrgIds: "org-id",
zuoraTrackId: "trace-id",
});The SDK maps these fields to HTTP headers:
| Option | HTTP header |
| --- | --- |
| zuoraVersion | Zuora-Version |
| zuoraEntityIds | Zuora-Entity-Ids |
| zuoraOrgIds | Zuora-Org-Ids |
| zuoraTrackId | Zuora-Track-Id |
Use headers for custom headers or advanced cases:
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
headers: {
"X-Custom-Header": "custom-value",
},
});Header precedence is:
- Typed Zuora fields such as
zuoraTrackId headersdefaultHeaderscompatibility alias- SDK defaults
For per-call overrides, pass the generated request field when available:
await client.productsApi.createProduct({
createRequest,
idempotencyKey: "product-create-123",
zuoraTrackId: "request-specific-trace-id",
});API Return Shape
API methods return business data directly:
const product = await client.productsApi.getProduct({
productKey: productId,
});
console.log(product.name);When you need HTTP metadata such as status, headers, or request ID, use the
matching WithResponse method:
const response = await client.productsApi.getProductWithResponse({
productKey: productId,
});
console.log(response.data.name);
console.log(response.status);
console.log(response.requestId);The SDK exposes a Zuora-owned ZuoraResponse<T> wrapper for metadata instead of
exposing Axios response types as the public API shape.
Additional Fields
Generated models include additionalFields for forward-compatible fields and
tenant-specific top-level fields. Use normal typed properties first, and use
additionalFields only for fields that are not in the current SDK model.
await client.ordersApi.createOrder({
body: {
orderDate: "2026-06-28",
existingAccountNumber: "A00000001",
additionalFields: {
FutureField__c: null,
},
},
});Request additionalFields are flattened into the outgoing JSON body. Response
fields that are not known to the generated model are collected into
additionalFields:
const order = await client.ordersApi.createOrder({ body: orderRequest });
console.log(order.orderNumber);
console.log(order.additionalFields?.FutureServerField__c);Values must be JSON-serializable. null is supported. undefined is rejected so
payloads are explicit.
Timeout and Retry Settings
requestTimeout sets the Axios request timeout in milliseconds:
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
requestTimeout: 120_000,
});You can update it after construction:
client.requestTimeout(120_000);maxRetries and retryBaseDelay configure OAuth authentication retry behavior:
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
maxRetries: 4,
retryBaseDelay: 2_000,
});
client.setRetryConfig(4, 2_000);Axios uses a single request timeout. Unlike the Java SDK's OkHttp client, this SDK does not expose separate connect, read, and write timeouts.
Logging
The SDK does not write to console directly. To enable request/response debug
logs, inject a logger:
import { ZuoraEnvironments } from "@zuora/zuora-sdk-ts";
import type { ZuoraLogger } from "@zuora/zuora-sdk-ts";
const applicationLogger = {
debug: (..._args: unknown[]) => {
// Forward to your application logger.
},
};
const logger: ZuoraLogger = {
debug: (...args) => applicationLogger.debug(...args),
};
const client = new ZuoraClient({
env: ZuoraEnvironments.SBX,
clientId,
clientSecret,
logger,
});Sensitive values are redacted before logging, including:
Authorizationclient_idclient_secret- access tokens
- refresh tokens
- password and secret fields
Request and response bodies can still contain business data, so enable logging only where that data is safe to capture.
Product CRUD Example
const suffix = Date.now().toString();
const createResponse = await client.productsApi.createProduct({
createRequest: {
Name: `SDK TS Product ${suffix}`,
Description: "created by @zuora/zuora-sdk-ts",
EffectiveStartDate: "2024-01-01",
EffectiveEndDate: "2034-01-01",
},
idempotencyKey: `product-${suffix}`,
});
const productId = createResponse.Id!;
const product = await client.productsApi.getProduct({
productKey: productId,
});
console.log(product.name);
await client.productsApi.updateProduct({
id: productId,
modifyRequest: {
Description: "updated by @zuora/zuora-sdk-ts",
},
});
await client.productsApi.deleteProduct({
id: productId,
});Error Handling
Generated API methods reject with ZuoraApiError for API, network, and timeout
failures. Use isZuoraApiError instead of reading Axios internals:
import { isZuoraApiError } from "@zuora/zuora-sdk-ts";
try {
await client.productsApi.getProduct({
productKey: "missing-product",
});
} catch (error) {
if (isZuoraApiError(error)) {
const errorSummary = {
status: error.status,
statusText: error.statusText,
code: error.code,
traceId: error.traceId,
requestId: error.requestId,
data: error.data,
};
// Send errorSummary to your application logger or error handler.
return;
}
throw error;
}error.cause preserves the original Axios error for advanced diagnostics, but
application code should prefer the normalized fields above. Request metadata and
headers exposed by ZuoraApiError are redacted for sensitive keys such as
Authorization, client_id, client_secret, and token fields.
Example negative response:
{
name: "ZuoraApiError",
message: "Cannot find entity by key: 'missing-product'.",
status: 404,
statusText: "",
code: "50000040",
traceId: "trace-id",
requestId: "...",
data: {
success: false,
processId: "...",
reasons: [
{
code: 50000040,
message: "Cannot find entity by key: 'missing-product'."
}
],
requestId: "..."
}
}API Reference
Generated endpoint and model reference files are published in the package under
docs/. Use this cookbook for recommended client setup, authentication,
headers, logging, and error handling. Use the generated reference when you need
the exact request and response shape for a specific API method.
Each generated API method uses a single request object. For example:
await client.productsApi.getProduct({
productKey: productId,
});This object-shaped style is preferred over positional arguments because it is clearer, safer to extend, and easier to read in application code.
Security Notes
- Do not commit client IDs, client secrets, OAuth tokens, entity IDs, org IDs, or request traces to source control.
- Store credentials in your platform's secret manager or runtime configuration.
- Treat request and response bodies as application data. They can contain customer or business information.
- Enable request/response logging only in environments where the log destination is approved for that data.
- Prefer typed header options such as
zuoraEntityIds,zuoraOrgIds, andzuoraTrackIdinstead of raw header strings.
Recommended Practices
- Use
ZuoraClientas the main entry point instead of instantiating generated API classes directly. - Prefer typed Zuora header fields over raw header strings.
- Use
headersonly for custom headers or advanced cases. - Set
zuoraTrackIdfor workflows where request tracing matters. - Keep
requestTimeoutexplicit for long-running operations. - Use idempotency keys for create/update workflows that may be retried.
- Keep debug logging disabled in production unless log data is approved for the destination.
