The Nebius AI SDK for TypeScript is a client library for Nebius AI Cloud services. It uses gRPC. Use the SDK to authenticate, manage resources, and call Nebius APIs from Node.js.
The build generates TypeScript API sources in src/api/ from the protobuf files
in nebius-api/.
Do not edit these generated files.
Install the package from npm:
npm install @nebius/js-sdkTo build this repository, use Node.js 24:
git clone --recurse-submodules git@github.com:nebius/js-sdk.git
cd js-sdk
nvm use
npm install
npm run buildThe package supports Node.js versions 22 through 26. The release build uses Node.js 24.
Use an ECMAScript module import:
import { SDK } from '@nebius/js-sdk';Or use CommonJS:
const { SDK } = require('@nebius/js-sdk');The package provides both formats:
dist/esmcontains the ECMAScript modules.dist/cjscontains the CommonJS modules.
Set
SDKOptions.userAgentPrefix
in each SDK constructor. Use a value that identifies your application and
version. The examples use example-application/1.0.
The following example creates an SDK without credentials:
import { SDK } from '@nebius/js-sdk';
const sdk = new SDK({
userAgentPrefix: 'example-application/1.0',
});Calls that require authentication fail until you set credentials.
Read an IAM token from the NEBIUS_IAM_TOKEN environment variable:
import { SDK } from '@nebius/js-sdk';
import { EnvBearer } from '@nebius/js-sdk/runtime/token/static';
const sdk = new SDK({
credentials: new EnvBearer('NEBIUS_IAM_TOKEN'),
userAgentPrefix: 'example-application/1.0',
});You can also pass a token string or a
StaticBearer:
import { SDK } from '@nebius/js-sdk';
import { StaticBearer } from '@nebius/js-sdk/runtime/token/static';
const token = process.env.NEBIUS_IAM_TOKEN;
if (!token?.trim()) {
throw new Error('NEBIUS_IAM_TOKEN must contain an IAM token');
}
const sdkFromString = new SDK({
credentials: token,
userAgentPrefix: 'example-application/1.0',
});
const sdkFromBearer = new SDK({
credentials: new StaticBearer(token),
userAgentPrefix: 'example-application/1.0',
});Use the Nebius CLI configuration to get credentials, an endpoint, and a default parent ID:
import { SDK } from '@nebius/js-sdk';
import { Config } from '@nebius/js-sdk/runtime/cli_config';
const sdk = new SDK({
configReader: new Config({ clientId: 'example-application' }),
userAgentPrefix: 'example-application/1.0',
});See the Config reference
for profile and environment settings.
To opt in to VM discovery when the CLI file is missing, use the async factory:
const config = await Config.load({ clientId: 'example-application' });
const sdk = new SDK({ configReader: config, userAgentPrefix: 'example-application/1.0' });It probes the VM metadata endpoint, then checks /mnt/cloud-metadata/token.
An existing invalid CLI file still raises an error. new Config() remains synchronous
and requires the CLI file.
Set an HTTP metadata endpoint explicitly, or use token-endpoint in the selected CLI profile:
const sdk = new SDK({
credentials: { tokenEndpoint: 'http://metadata.example/token' },
userAgentPrefix: 'example-application/1.0',
});
const token = await sdk.getToken();The endpoint returns access_token and expires_at. Acquisition starts when a token is needed.
EnvBearer defaults to NEBIUS_IAM_TOKEN. Environment credentials and CLI configuration remain opt-in.
Explicit invalid credentials now fail during SDK construction. Unsupported credential shapes, service-account reader failures, and CLI profile or credential initialization failures throw instead of disabling authorization. Token acquisition from lazy sources still starts on demand.
Use named providers to choose an identity for each request:
import { OneOfProvider } from '@nebius/js-sdk/runtime/authorization/one_of';
import { TokenProvider } from '@nebius/js-sdk/runtime/authorization/token';
import { StaticBearer } from '@nebius/js-sdk/runtime/token/static';
const sdk = new SDK({
credentials: new OneOfProvider({
primary: new TokenProvider(new StaticBearer(primaryToken)),
secondary: new TokenProvider(new StaticBearer(secondaryToken)),
anonymous: null,
}),
userAgentPrefix: 'example-application/1.0',
});
await sdk.whoami(undefined, { authorizationOptions: { selector: 'secondary' } });
await sdk.close();Each request requires a known selector. Each selected provider retains its own renewal and recovery behavior. SDK shutdown closes all providers.
Cached impersonation uses the actor's positive acquisition budget plus five
seconds for token exchange. Interactive federation login no longer has the
fixed five-second impersonation limit. Set refreshRequestTimeoutMs on
CachedImpersonatedBearer for an explicit total cap. On RenewableBearer,
null uses the source's positive budget, or five seconds. The default remains
an explicit five-second budget.
Custom bearers can expose acquisitionBudgetMs. Transparent wrappers must
forward it. Caller deadlines still limit how long each request waits.
If you used EnvBearer() with NEBIUS_TOKEN, rename that variable to NEBIUS_IAM_TOKEN
or pass new EnvBearer('NEBIUS_TOKEN') explicitly. Catch SDK construction errors where
your application loads CLI configuration or service-account credentials. Failed operation
waits now reject with OperationError; its operation property retains the failed state.
The default retry count is now 2 retries after the first attempt, for 3 total attempts.
FederationAccountBearer uses timeoutMs for the browser callback and token HTTP request together.
Pass the service account ID, public key ID, and PEM private key:
import { SDK } from '@nebius/js-sdk';
const sdk = new SDK({
credentials: {
serviceAccountId: 'serviceaccount-xxxxx',
publicKeyId: 'public-key-id',
privateKeyPem: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----',
},
userAgentPrefix: 'example-application/1.0',
});Use
CredentialsFileReader
to read a Nebius service account credentials file:
import { SDK } from '@nebius/js-sdk';
import { CredentialsFileReader } from '@nebius/js-sdk/runtime/service_account/credentials_file';
const sdk = new SDK({
credentials: new CredentialsFileReader('~/.config/nebius/credentials.json'),
userAgentPrefix: 'example-application/1.0',
});You can also use
PkFileReader
with a separate private key file.
SDKOptions.userAgentPrefix
places your application name and version before the SDK user-agent. For
example, the SDK sends a value in this form:
example-application/1.0 nebius-js-sdk/<version> (node/<major>; <platform>/<architecture>; <esm-or-cjs>)
The SDK adds the Node.js major version, operating system, CPU architecture, and
module format to the user-agent. Set userAgentPrefix to identify your
application or framework integration. The SDK does not identify frameworks
automatically.
You can also set grpc.primary_user_agent or grpc.secondary_user_agent in
SDKOptions.clientOptions
and
SDKOptions.perAddress.
The SDK preserves these values and adds its own user-agent.
Call
SDK.whoami()
to test credentials. Close the SDK when your application no longer needs it:
import { SDK } from '@nebius/js-sdk';
import { EnvBearer } from '@nebius/js-sdk/runtime/token/static';
const sdk = new SDK({
credentials: new EnvBearer('NEBIUS_IAM_TOKEN'),
userAgentPrefix: 'example-application/1.0',
});
try {
const profile = await sdk.whoami();
console.log('Signed-in profile:', profile);
} finally {
await sdk.close();
}Generated service clients accept the SDK as their first constructor argument.
Generated message objects provide a
create()
function.
import { SDK } from '@nebius/js-sdk';
import { BucketService, CreateBucketRequest } from '@nebius/js-sdk/api/nebius/storage/v1/index';
import { EnvBearer } from '@nebius/js-sdk/runtime/token/static';
const sdk = new SDK({
credentials: new EnvBearer('NEBIUS_IAM_TOKEN'),
userAgentPrefix: 'example-application/1.0',
});
try {
const buckets = new BucketService(sdk);
const request = CreateBucketRequest.create({/* Set the request fields. */});
const operation = await buckets.create(request).result;
await operation.wait();
console.log('Created resource:', operation.resourceId());
} finally {
await sdk.close();
}Many write methods return an
Operation.
Use
Request.result
to get the operation. Use
Operation.wait()
to wait for completion. Failed operations reject with OperationError.
Inspect error.operation or the original operation for its status and details.
Malformed operation envelopes reject with OperationValidationError, which retains the raw operation.
Some operations report progress.
Operation.progressTracker()
returns undefined when the service does not report progress.
while (!operation.done()) {
await operation.update();
const tracker = operation.progressTracker();
const parts = [`Waiting for operation ${operation.id()}:`];
if (tracker) {
const work = tracker.workFraction();
if (work !== undefined) parts.push(`${Math.round(work * 100)}%`);
const description = tracker.description();
if (description) parts.push(description);
const eta = tracker.estimatedFinishedAt();
if (eta) parts.push(`ETA ${eta.toISOString()}`);
}
process.stdout.write(`${parts.join(' ')}\r`);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
process.stdout.write('\n');
await operation.wait(); // Reject if the completed operation failed.Use
BucketService.getOperationService()
on a generated service client. Do not create a standalone operation service
client for another service address.
import { ListOperationsRequest } from '@nebius/js-sdk/api/nebius/common/v1/index';
const operationService = buckets.getOperationService();
const request = ListOperationsRequest.create({ resourceId: '...' });
const response = await operationService.list(request);Services with paginated list calls provide filter():
import { ListBucketsRequest } from '@nebius/js-sdk/api/nebius/storage/v1/index';
for await (const bucket of buckets.filter(ListBucketsRequest.create({ parentId: 'project-id' }))) {
console.log(bucket.metadata?.id);
}Iteration stops when the page token is empty, or when the caller exits the loop.
Services that return operations also provide listOperations() for their operation service address.
The SDK can fill an empty parent ID from
SDKOptions.parentId
or the CLI configuration.
It fills these request fields:
parentIdforlist,listAggregated, andgetByName.metadata.parentIdfor other methods exceptupdate.
An explicit request value always takes priority. Defaults must match the annotated NID type.
Set tenantId for tenant parents. Set noParentId: true to disable both defaults.
The
Request
object is promise-like. It also exposes response metadata, status, request ID,
and trace ID.
import { GetBucketRequest } from '@nebius/js-sdk/api/nebius/storage/v1/index';
const request = buckets.get(GetBucketRequest.create({ id: 'bucket-id' }));
const bucket = await request;
const status = await request.status;
console.log({ bucket, status });
// Missing headers resolve to an empty string after the final attempt.
void request.requestId.then((requestId) => console.log({ requestId }));
void request.traceId.then((traceId) => console.log({ traceId }));Request.requestId
and
Request.traceId
resolve with an empty string when the final attempt has no corresponding header.
Use Request.result to wait for request completion.
Pass authorization hints in the gRPC call options:
import { Metadata } from '@grpc/grpc-js';
import { UpdateBucketRequest } from '@nebius/js-sdk/api/nebius/storage/v1/index';
const callOptions = {
authorizationOptions: {
renewRequired: true,
renewSynchronous: true,
renewRequestTimeoutMs: 900,
},
};
await sdk.whoami(undefined, callOptions);
const updateRequest = UpdateBucketRequest.create({/* Set the fields to update. */});
const operation = await buckets.update(updateRequest, new Metadata(), callOptions);
await operation.wait();See
AuthorizationOptions
for all fields.
The SDK derives an x-resetmask header for generated update methods. Use
ensureResetMaskInMetadata()
when you must set the header explicitly:
import { UpdateBucketRequest } from '@nebius/js-sdk/api/nebius/storage/v1/index';
import { ensureResetMaskInMetadata } from '@nebius/js-sdk/runtime/resetmask';
const request = UpdateBucketRequest.create({
metadata: bucket.metadata,
spec: {/* Set the fields to update or reset. */},
});
const metadata = ensureResetMaskInMetadata(request);
const operation = await buckets.update(request, metadata).result;
await operation.wait();Read the service documentation before you reset list or map fields.
Set resetMask or selectMask in call options to provide an explicit mask.
runtime/mask_metadata also provides withResetMask() and withSelectMask().
Explicit masks compose with existing mask header values. Supplying resetMask skips automatic discovery.
runtime/protobuf_mask provides descriptor-based known-field masks, modified reset masks, selection, patching, and path traversal.
These helpers use protobuf field names and return message copies for transformations.
Use { includeImmutables: true } to include immutable fields in reset-mask conversion.
runtime/protos/proto_json provides additive canonical protobuf JSON through toProtoJSON() and fromProtoJSON().
Supply the generated protoRegistry to expand registered Any payloads. Standard protobuf wrapper payloads are also supported. Registered extensions use bracketed full names, such as [nebius.nid], and retain explicitly set default values.
Canonical parsing validates field names, oneofs, scalar types, and numeric ranges. Use { ignoreUnknownFields: true } as the fourth fromProtoJSON() argument to skip unknown fields and enum names.
Existing generated toJSON() output remains unchanged.
import { GetBucketRequest } from '@nebius/js-sdk/api/nebius/storage/v1/index';
import { protoRegistry } from '@nebius/js-sdk/api/protobuf';
import { fromProtoJSON, toProtoJSON } from '@nebius/js-sdk/runtime/protos/proto_json';
const request = GetBucketRequest.create({ id: 'bucket-id' });
const json = toProtoJSON(GetBucketRequest, request, protoRegistry);
const restored = fromProtoJSON(GetBucketRequest, json, protoRegistry);Set SDK-wide defaults with SDKOptions.requestOptions. Per-call options override these defaults.
Call construction can throw synchronously for invalid options, serialization failures, or
an unavailable client. Use try/catch around both the call and await request.result.
A failed credential refresh rejects with an AggregateError containing both the refresh error and the original authorization error.
Successful credential recovery starts a fresh request timeout window. The overall deadline still caps all authentication and request cycles.
A unary call has these limits:
deadlinelimits authorization, the request, and all retries. Use aDateor an absolute epoch time in milliseconds. The earlier caller deadline orAuthTimeoutends the logical call.AuthTimeoutlimits the logical call, including all authorization and request cycles. The default is 15 minutes.RetryOptions.RequestTimeoutlimits the request and its retries after authorization. The default is 60 seconds.RetryOptions.PerRetryTimeoutlimits one attempt. The default is 20 seconds.RetryOptions.RetryCountsets the maximum number of retries after the first attempt. The default is 2, for 3 total attempts.
The SDK retries transient transport errors within the request deadline. Explicit service retry hints take priority. Each unary request has one stable idempotency key. Rejected renewable credentials can trigger one retry with a changed token. An explicit authorization header prevents automatic authorization.
import { Metadata } from '@grpc/grpc-js';
import { GetBucketRequest } from '@nebius/js-sdk/api/nebius/storage/v1/index';
const metadata = new Metadata();
const options = {
deadline: new Date(Date.now() + 30_000),
RequestTimeout: 10_000,
PerRetryTimeout: 5_000,
RetryCount: 2,
};
const request = GetBucketRequest.create({ id: 'bucket-id' });
const bucket = await buckets.get(request, metadata, options);TypeDoc writes the API reference to docs. Run:
npm run docsThe reference includes generated service, message, and enum documentation. It also includes runtime classes, interfaces, methods, properties, functions, variables, and type aliases.
See the contributing guidelines.
This project is licensed under the MIT License. See the LICENSE file for details.
Copyright (c) 2025 Nebius B.V.