Skip to content

Using the API with Wallet Authentication ​

When using the Nosana API with wallet authentication instead of an API key, you gain access to additional features like vault management for funding your deployments directly from your Solana wallet.

Overview ​

There are two ways to authenticate with the Nosana API:

  1. API Key Authentication - Simple, uses credits from your account balance
  2. Wallet Authentication - Uses your Solana wallet, enables vault management

Wallet authentication is required for:

  • Creating and managing vaults
  • Topping up vaults with SOL or NOS
  • Withdrawing funds from vaults
  • Getting vault balances

Using with @nosana/kit ​

The easiest way to use wallet authentication is with the @nosana/kit SDK, which automatically handles wallet signing and authentication.

For all the ways to create and configure a wallet (keypair files, base58 keys, browser wallets), see the Wallet Configuration guide.

Installation ​

bash
npm install @nosana/kit

Initialization ​

Create the client without an API key and assign a wallet:

ts
import { 
function createNosanaClient(network: NosanaNetwork | undefined, customConfig: PartialClientConfig & {
    connect: ConnectFactoryConfig & {
        clientSecret: string;
    };
}): NosanaClient & {
    connect: ServerConnect;
} (+3 overloads)
createNosanaClient
,
type NosanaNetwork = "mainnet" | "devnet" | "localnet"
const NosanaNetwork: {
    readonly MAINNET: "mainnet";
    readonly DEVNET: "devnet";
    readonly LOCALNET: "localnet";
}
NosanaNetwork
, function loadWalletFromFile(filePath?: string): Promise<Wallet>
Load a wallet from a Solana CLI keypair JSON file. Reads a JSON file containing a byte array (as used by `solana-keygen`) and creates a wallet from it. Defaults to `~/.config/solana/id.json` if no path is provided.
@paramfilePath - Path to the keypair JSON file (default: `~/.config/solana/id.json`)@returnsA wallet loaded from the file@example```ts import { loadWalletFromFile } from '@nosana/kit'; // Load default Solana CLI keypair const wallet = await loadWalletFromFile(); // Or specify a custom path const wallet = await loadWalletFromFile('/path/to/keypair.json'); console.log(wallet.address); ```@group@nosana/kit
loadWalletFromFile
} from '@nosana/kit';
const const client: NosanaClientclient = function createNosanaClient(network?: NosanaNetwork, customConfig?: PartialClientConfig): NosanaClient (+3 overloads)createNosanaClient(
const NosanaNetwork: {
    readonly MAINNET: "mainnet";
    readonly DEVNET: "devnet";
    readonly LOCALNET: "localnet";
}
NosanaNetwork
.type MAINNET: "mainnet"MAINNET);
// Load a Solana CLI keypair (defaults to ~/.config/solana/id.json) const client: NosanaClientclient.NosanaClient.wallet: Wallet | undefined
The wallet. Must be a Wallet (supports both message and transaction signing). Set this property directly to configure the wallet.
@example```ts import { createNosanaClient, NosanaNetwork } from '@nosana/kit'; const client = createNosanaClient(NosanaNetwork.MAINNET); client.wallet = myWallet; ```
wallet
= await function loadWalletFromFile(filePath?: string): Promise<Wallet>
Load a wallet from a Solana CLI keypair JSON file. Reads a JSON file containing a byte array (as used by `solana-keygen`) and creates a wallet from it. Defaults to `~/.config/solana/id.json` if no path is provided.
@paramfilePath - Path to the keypair JSON file (default: `~/.config/solana/id.json`)@returnsA wallet loaded from the file@example```ts import { loadWalletFromFile } from '@nosana/kit'; // Load default Solana CLI keypair const wallet = await loadWalletFromFile(); // Or specify a custom path const wallet = await loadWalletFromFile('/path/to/keypair.json'); console.log(wallet.address); ```@group@nosana/kit
loadWalletFromFile
();

When you use @nosana/kit with a wallet, it automatically:

  • Creates SignerAuth from your wallet
  • Handles message signing for authentication
  • Provides Solana functions for vault operations

Creating Deployments with Vault ​

With a wallet (and no API key) configured, client.api is the signer variant of the API (NosanaApi), whose deployments include a vault:

ts
const const api: NosanaApiapi = const client: NosanaClientclient.NosanaClient.api: NosanaApiClientapi as NosanaApi; // signer variant: deployments include a vault

const const deployment: Deploymentdeployment = await const api: NosanaApiapi.NosanaApi.deployments: DeploymentsApideployments.DeploymentsApi.create: (deploymentBody: CreateDeployment) => Promise<Deployment>create({
  name: stringname: 'My Deployment',
  market?: string | undefined
@descriptionMarket to post every job in. Omit to post across markets: each job goes to the cheapest PREMIUM market with a node that meets `requirements`.
market
: 'CA5pMpqkYFKtme7K31pNB1s62X2SdhEv1nN9RdxKCpuQ',
replicas: numberreplicas: 1, timeout: number
@descriptionTimeout in minutes, must be at least 1 minute.@descriptionTimeout in minutes, must be at least 60 minute.
timeout
: 60,
strategy: "SIMPLE" | "SIMPLE-EXTEND" | "SCHEDULED" | "INFINITE"
@enum@enum
strategy
: 'SIMPLE',
job_definition: JobDefinitionjob_definition: { version: stringversion: '0.1', type?: string | undefined
@deprecatedThe execution environment is no longer derived from the job definition — it is the node operator's `--vm`/`--cvm` choice. Retained as an optional, unvalidated field so type-less jobs and legacy jobs still carrying `'container' | 'vm' | 'cvm'` continue to validate. Do not read it.
type
: 'container',
meta?: Meta | undefinedmeta: { trigger?: string | undefinedtrigger: 'api' }, ops: Opsops: [ { type: keyof OperationArgsMaptype: 'container/run', id: OperationIdid: 'hello-world', args: ContainerRun | ContainerCreateVolume | VmRunArgsargs: { cmd: stringcmd: 'echo hello world', image: stringimage: 'ubuntu', }, }, ], }, }); // The deployment includes a vault var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
('Vault address:', const deployment: Deploymentdeployment.vault: string & Vaultvault.Vault.address: stringaddress);

For detailed information on managing vaults, see the Vault Management guide.

Using @nosana/api Directly ​

If you're using @nosana/api directly (without @nosana/kit), you need to provide SignerAuth yourself — an identifier (your wallet's public key), a message-signing function, and the Solana functions used for vault operations:

ts
const const signerAuth: SignerAuthsignerAuth: 
type SignerAuth = {
    identifier: string;
    generate: SignedHeaderAuth["generate"];
    solana: ExternalSolanaFunctions;
}
SignerAuth
= {
identifier: stringidentifier:
const wallet: {
    address: string;
    signMessage(message: Uint8Array): Promise<Uint8Array>;
}
wallet
.address: stringaddress, // your wallet's public key
generate: (message: string, options?: Pick<GenerateOptions, "skipCache">) => Promise<string>generate: async (message: stringmessage: string) => { // Sign the message with your wallet and return it base64-encoded const const signature: Uint8Array<ArrayBufferLike>signature = await
const wallet: {
    address: string;
    signMessage(message: Uint8Array): Promise<Uint8Array>;
}
wallet
.function signMessage(message: Uint8Array): Promise<Uint8Array>signMessage(new var TextEncoder: new () => TextEncoder
The **`TextEncoder`** interface takes a stream of code points as input and emits a stream of UTF-8 bytes. [MDN Reference](https://developer.mozilla.org/docs/Web/API/TextEncoder) `TextEncoder` class is a global reference for `import { TextEncoder } from 'node:util'` https://nodejs.org/api/globals.html#textencoder
@sincev11.0.0
TextEncoder
().TextEncoder.encode(input?: string): Uint8Array<ArrayBuffer>
The **`TextEncoder.encode()`** method takes a string as input, and returns a Global_Objects/Uint8Array containing the text given in parameters encoded with the specific method for that TextEncoder object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/TextEncoder/encode)
encode
(message: stringmessage));
return function btoa(data: string): string (+1 overload)
Decodes a string into bytes using Latin-1 (ISO-8859), and encodes those bytes into a string using Base64. The `data` may be any JavaScript-value that can be coerced into a string. **This function is only provided for compatibility with legacy web platform APIs** **and should never be used in new code, because they use strings to represent** **binary data and predate the introduction of typed arrays in JavaScript.** **For code running using Node.js APIs, converting between base64-encoded strings** **and binary data should be performed using `Buffer.from(str, 'base64')` and `buf.toString('base64')`.**
@sincev15.13.0, v14.17.0@legacyUse `buf.toString('base64')` instead.@paramdata An ASCII (Latin1) string.
btoa
(var String: StringConstructor
Allows manipulation and formatting of text strings and determination and location of substrings within strings.
String
.StringConstructor.fromCharCode(...codes: number[]): stringfromCharCode(...const signature: Uint8Array<ArrayBufferLike>signature));
}, solana: ExternalSolanaFunctionssolana: {
getBalance: (address: string) => Promise<{
    SOL: number;
    NOS: number;
}>
Gets the balance of SOL and NOS tokens for a given address
getBalance
: async (address: stringaddress) => {
// Fetch the SOL and NOS balances for the address return { type SOL: numberSOL: 0, type NOS: numberNOS: 0 }; }, transferTokensToRecipient: (recipient: string, tokens: TopupVaultOptions) => Promise<void>
Transfers specified amounts of SOL and NOS to the recipient address
transferTokensToRecipient
: async (recipient: stringrecipient, tokens: TopupVaultOptionstokens) => {
// Transfer the tokens from your wallet to the recipient }, deserializeSignSendAndConfirmTransaction: (transaction: string) => Promise<string>
Deserializes, signs, sends, and confirms a Solana transaction
deserializeSignSendAndConfirmTransaction
: async (transaction: stringtransaction) => {
// Sign, send, and confirm the serialized transaction return 'tx-signature'; }, }, }; const const api: NosanaApiapi = function createNosanaApi(environment: NosanaNetwork, signerAuth: SignerAuth, options?: CreateNosanaApiOptions): NosanaApi (+2 overloads)createNosanaApi(
const NosanaNetwork: {
    readonly MAINNET: "mainnet";
    readonly DEVNET: "devnet";
    readonly LOCALNET: "localnet";
}
NosanaNetwork
.type MAINNET: "mainnet"MAINNET, const signerAuth: SignerAuthsignerAuth);

createNosanaApi and the SignerAuth type are also exported from the standalone @nosana/api package. @nosana/kit implements these functions for you from the configured wallet — that's the recommended path.

HTTP API with Wallet Authentication ​

If you're making direct HTTP requests, you need to:

  1. Sign a message with your wallet
  2. Include the signed message in the Authorization header
  3. Include your public key in the x-user-id header

Authentication Header Format ​

Authorization: NosanaApiAuthentication:<base64-encoded-signature>
x-user-id: <your-wallet-public-key>

Example Request ​

bash
# Sign the message "NosanaApiAuthentication" with your wallet
# Then include it in the Authorization header

curl -X POST https://api.nosana.com/deployments/vaults/create \
  -H "Authorization: NosanaApiAuthentication:<signed-message>" \
  -H "x-user-id: <your-public-key>" \
  -H "Content-Type: application/json"

For vault management endpoints and operations, see the Vault Management guide.

Differences from API Key Authentication ​

FeatureAPI KeyWallet Authentication
AuthenticationBearer <api-key>NosanaApiAuthentication:<signed-message>
FundingUses account creditsUses vault (SOL/NOS)
Vault Management❌ Not available✅ Full vault operations
Setup ComplexitySimpleRequires wallet setup