Skip to content
dhanu docs
Browse pages

SDKs

Node SDK

The official dhanu npm package, install it, generate images and text, and handle errors with DhanuError.

The dhanu package wraps the public API for Node. It has no dependencies and uses the global fetch, so it needs Node 18 or newer.

Install

npm i dhanu

Set up the client

import { Dhanu } from "dhanu";

// Server-side only, never ship your secret key to a browser.
const dhanu = new Dhanu(process.env.DHANU_API_KEY!);

The key is always passed explicitly. There is no baseUrl option: the base URL comes from DHANU_BASE_URL if set, and otherwise defaults to https://api.dhanu.ai. Point DHANU_BASE_URL at http://localhost:3000 for local development.

Generate an image

import { writeFileSync } from "node:fs";

const image = await dhanu.images.generate({
  prompt: "a red bicycle on a white background",
  aspectRatio: "1:1", // "1:1" | "3:4" | "9:16" | "4:3" | "16:9"
});

writeFileSync("out.png", Buffer.from(image.b64, "base64"));

Returns { b64, mimeType, model, usage, cost }. Nothing is stored server-side, see Generate an image.

Generate text

const reply = await dhanu.text.generate({
  prompt: "Write a haiku about Kathmandu",
  system: "You are a concise poet.",
  maxTokens: 200,
});

console.log(reply.text);

Returns { text, model, usage, cost }.

Verify a key

const me = await dhanu.me();

Typed requests and responses

Every request body, query and response is generated from the API contract into ApiTypes, so the wire shape your code compiles against is the one the server validates. The resource methods already return these types, dhanu.tasks.create returns ApiTypes.TasksCreateResponse["task"], and you can name them directly when you keep a value around:

import type { ApiTypes } from "dhanu";

const body: ApiTypes.TasksCreateRequest = { input: "Summarise the week", fileIds };
const task = await dhanu.tasks.create(body);

Retries and timeouts

Every call is retried up to twice on a network error, a timeout, 408, 429 or a 5xx, waiting for Retry-After when the server sends one and backing off exponentially (500 ms, 1 s, 2 s… capped at 8 s) otherwise. JSON POSTs carry a generated Idempotency-Key on every attempt, so a retry can never run the same call twice. Each attempt is aborted after 60 s. Tune or switch it off per client:

const dhanu = new Dhanu(process.env.DHANU_API_KEY!, { maxRetries: 0, timeoutMs: 10_000 });

A request that never reached the server throws DhanuError with status: 0 and code: "network_error" or "timeout".

Handle errors

Every failure throws DhanuError with a machine-readable code, the HTTP status, a message, and the requestId to quote in support reports.

import { DhanuError } from "dhanu";

try {
  await dhanu.images.generate({ prompt: "…" });
} catch (err) {
  if (err instanceof DhanuError) {
    if (err.code === "rate_limited") {
      // back off and retry, see /developer/reference/rate-limits
    }
    console.error(err.code, err.status, err.message, err.requestId);
  }
}

The complete list of codes is on Errors.