Skip to content
Discord Get Started

TypeScript SDK

The get-db9 SDK provides typed TypeScript access to DB9 databases — provisioning, SQL execution, filesystem operations, branching, and token management.

ScenarioRecommended tool
One-liner database provisioning in a script or testSDKinstantDatabase()
Programmatic fleet management (create, branch, delete)SDKcreateDb9Client()
File read/write from Node.js (RAG, ingestion)SDKclient.fs.*
Interactive SQL from a terminalCLIdb9 db sql (CLI Reference)
ORM or driver connection to an existing databaseRaw pgwire — use the connection string (Connect)
Agent onboarding (Codex, Claude Code)CLIdb9 onboard (Agent Workflows)

Runtime requirement: Node.js 18+ (native fetch). TypeScript 5+ for full type exports.

Terminal
npm install get-db9

Also available via yarn add get-db9, pnpm add get-db9, or bun add get-db9.

The SDK shares the credential store (~/.db9/credentials) with the db9 CLI. If you have logged in via the CLI, the SDK picks up the token automatically.

instantDatabase() creates or reuses a database by name. If no name is provided, it defaults to "default".

TypeScript
import { instantDatabase } from 'get-db9';
const db = await instantDatabase({
name: 'myapp',
seed: 'CREATE TABLE users (id SERIAL PRIMARY KEY, email TEXT)'
});
console.log(db.databaseId);
console.log(db.connectionString);
console.log(db.adminUser, db.adminPassword);
console.log(db.state, db.createdAt);

Prerequisite: The SDK requires a valid token in ~/.db9/credentials or passed via Db9ClientOptions.token. If no token is available, the client throws an error. Run db9 login or db9 create (which auto-registers an anonymous account) before using the SDK, or pass a token explicitly.

Result shape:

TypeScript
interface InstantDatabaseResult {
databaseId: string;
connectionString: string;
adminUser: string;
adminPassword: string;
state: string;
createdAt: string;
}

High-level API that wraps createDb9Client(), checks for an existing database by name, creates one if missing, and optionally executes seed SQL. Seed SQL runs only on initial creation — if the database already exists, seed is skipped.

TypeScript
function instantDatabase(
options?: InstantDatabaseOptions
): Promise<InstantDatabaseResult>;
OptionTypeDescription
namestringDatabase name. Default: 'default'.
baseUrlstringOverride API endpoint. Default: https://api.db9.ai or DB9_API_URL env.
fetchFetchFnCustom fetch implementation.
credentialStoreCredentialStoreToken load/save strategy.
seedstringSQL text executed via client.databases.sql() on creation only.
seedFilestringSQL file content executed via client.databases.sqlFile() on creation only.
timeoutnumberRequest timeout in milliseconds.
maxRetriesnumberRetry count for failed requests (capped at 3).
retryDelaynumberDelay between retries in milliseconds.
TypeScript
const db = await instantDatabase({
name: 'analytics',
seedFile: `
CREATE TABLE events (
id BIGSERIAL PRIMARY KEY,
user_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
`
});

Low-level typed client exposing grouped APIs: auth, tokens, databases, and fs.

The client lazy-loads the token from the credential store on the first protected call. If no token is found, it throws Db9Error (status 401). Use db9 login or pass a token via options.token before calling protected methods.

TypeScript
function createDb9Client(options?: Db9ClientOptions): Db9Client;
OptionTypeDescription
baseUrlstringDefault: https://api.db9.ai (or DB9_API_URL env).
tokenstringBearer token; skips credential store lookup.
fetchFetchFnCustom HTTP implementation.
credentialStoreCredentialStoreLoad/save token state.
timeoutnumberRequest timeout in milliseconds.
maxRetriesnumberRetry count for failed requests (capped at 3).
retryDelaynumberDelay between retries in milliseconds.
WebSocketWebSocketConstructorOverride WebSocket for client.fs operations (see Filesystem).
wsPortnumberOverride the fs9 WebSocket port (default: 5480).
TypeScript
import { createDb9Client, MemoryCredentialStore } from 'get-db9';
const client = createDb9Client({
baseUrl: 'https://api.db9.ai',
credentialStore: new MemoryCredentialStore()
});
  • me(): Promise<CustomerResponse> — Get current user profile

The SDK itself does not handle login or registration. Use the CLI for auth:

Terminal
# Zero-setup trial (auto creates anonymous account + token)
db9 create --name quickstart
# Upgrade anonymous account to verified SSO identity
db9 claim
# Human operator login (browser-based)
db9 login
# API key login (CI/CD, agents)
db9 login --api-key <KEY>
# Create an automation token
db9 token create --name my-agent --expires-in-days 365
# Agent runtime
export DB9_API_KEY=<token>

Once authenticated via CLI, the SDK picks up the stored token automatically.

Create, inspect, and revoke API tokens for CI/CD and programmatic access.

  • create(req: CreateTokenRequest): Promise<CreateTokenResponse> — Create named token with optional expiry
  • list(): Promise<TokenResponse[]>
  • revoke(tokenId: string): Promise<MessageResponse>
TypeScript
const newToken = await client.tokens.create({
name: 'ci-deploy',
expires_in_days: 90
});
console.log(newToken.token); // Store in secret manager
const tokens = await client.tokens.list();
for (const token of tokens) {
console.log(token.id, token.name, token.created_at, token.expires_at);
}
await client.tokens.revoke(tokens[0].id);

Core lifecycle APIs: create, list, get, delete, reset password, retrieve credentials, create connect tokens, and read observability metrics.

  • create(req: CreateDatabaseRequest): Promise<DatabaseResponse>
  • list(): Promise<DatabaseResponse[]>
  • get(databaseId: string): Promise<DatabaseResponse>
  • delete(databaseId: string): Promise<MessageResponse>
  • resetPassword(databaseId: string): Promise<CustomerPasswordResetResponse>
  • credentials(databaseId: string): Promise<CustomerPasswordResetResponse> — Get stored admin credentials without resetting
  • connectToken(databaseId: string, role?: string): Promise<CreateConnectTokenResponse> — Create a short-lived connect token (10-min TTL)
  • observability(databaseId: string): Promise<TenantObservabilityResponse>
TypeScript
const db = await client.databases.create({
name: 'billing',
region: 'us-west',
admin_password: 'StrongAdminPass1'
});
const all = await client.databases.list();
const current = await client.databases.get(db.id);
const rotated = await client.databases.resetPassword(db.id);
const creds = await client.databases.credentials(db.id);
const metrics = await client.databases.observability(db.id);
// Short-lived connect token for psql/ORM usage
const connectToken = await client.databases.connectToken(db.id);
console.log(connectToken.host, connectToken.user, connectToken.token);
await client.databases.delete(db.id);

For programmatic provisioning patterns, see Provisioning.

Execute SQL strings or SQL file content through the customer API. Both methods return SqlResult.

  • sql(databaseId: string, query: string): Promise<SqlResult>
  • sqlFile(databaseId: string, fileContent: string): Promise<SqlResult>
TypeScript
const result = await client.databases.sql(
databaseId,
'SELECT id, email FROM users ORDER BY id LIMIT 10'
);
console.log(result.columns);
console.log(result.rows);
console.log(result.row_count, result.command, result.error);
const fromFile = await client.databases.sqlFile(databaseId, `
CREATE TABLE audit_log (id BIGSERIAL PRIMARY KEY, event TEXT);
INSERT INTO audit_log(event) VALUES ('created');
`);
SqlResult FieldTypeDescription
columnsColumnInfo[]Column metadata for result rows.
rowsunknown[][]Result values matrix.
row_countnumberRows affected/returned.
commandstringExecuted command label (SELECT, INSERT, etc.).
errorstring | SqlErrorDetailStructured error with message, code, detail, hint, and position.

Introspect schema objects or export SQL dump payloads.

  • schema(databaseId: string): Promise<SchemaResponse>
  • dump(databaseId: string, req?: DumpRequest): Promise<DumpResponse>
TypeScript
const schema = await client.databases.schema(databaseId);
for (const table of schema.tables) {
console.log(table.schema, table.name);
}
const ddlOnly = await client.databases.dump(databaseId, { ddl_only: true });
console.log(ddlOnly.object_count);
console.log(ddlOnly.sql);

Apply SQL migrations with checksums and inspect migration history.

  • applyMigration(databaseId: string, req: MigrationApplyRequest): Promise<MigrationApplyResponse>
  • listMigrations(databaseId: string): Promise<MigrationMetadata[]>
TypeScript
await client.databases.applyMigration(databaseId, {
name: '20260218_add_users',
sql: 'CREATE TABLE users (id SERIAL PRIMARY KEY, email TEXT NOT NULL);',
checksum: 'f0b9c43b'
});
const applied = await client.databases.listMigrations(databaseId);
for (const migration of applied) {
console.log(migration.name, migration.applied_at, migration.checksum);
}

Create a database branch from an existing database. Branch creation starts in CLONING state — poll with get() until it reaches ACTIVE or CREATE_FAILED.

  • branch(databaseId: string, req: BranchRequest): Promise<DatabaseResponse>
TypeScript
const featureDb = await client.databases.branch(databaseId, {
name: 'feature-auth'
});
let current = featureDb;
while (current.state === 'CLONING') {
await new Promise((resolve) => setTimeout(resolve, 1000));
current = await client.databases.get(featureDb.id);
}
if (current.state === 'CREATE_FAILED') {
throw new Error('Branch clone failed');
}
console.log('Branch ready:', current.id, current.name);

For branch workflow patterns, see Multi-Tenant Patterns.

Manage Postgres users inside a database.

  • list(databaseId: string): Promise<UserResponse[]>
  • create(databaseId: string, req: CreateUserRequest): Promise<MessageResponse>
  • delete(databaseId: string, username: string): Promise<MessageResponse>
TypeScript
await client.databases.users.create(databaseId, {
username: 'app_user',
password: 'AppUserPass!'
});
const users = await client.databases.users.list(databaseId);
users.forEach((u) => {
console.log(u.name, u.can_login, u.can_create_db, u.is_superuser);
});
await client.databases.users.delete(databaseId, 'app_user');

Cloud filesystem operations for reading, writing, and managing files attached to each database. Built for RAG pipelines, document ingestion, and agent workflows.

WebSocket requirement: Filesystem operations use WebSocket connections. Node.js 21+ and browsers have native WebSocket support. On Node.js 18–20, install the ws package or pass a WebSocket constructor via Db9ClientOptions.WebSocket.

  • connect(dbId): Promise<FsClient> — Open a persistent WebSocket connection (caller must call close())
  • list(dbId, path): Promise<FileInfo[]> — List directory contents
  • read(dbId, path): Promise<string> — Read file content as text
  • readBinary(dbId, path): Promise<Uint8Array> — Read file as binary
  • write(dbId, path, content): Promise<void> — Write a file
  • append(dbId, path, content): Promise<number> — Append to a file, returns bytes written
  • stat(dbId, path): Promise<FileInfo> — Get file metadata
  • exists(dbId, path): Promise<boolean> — Check if file exists
  • mkdir(dbId, path): Promise<void> — Create a directory recursively
  • remove(dbId, path, opts?): Promise<void> — Delete a file or directory
  • rename(dbId, oldPath, newPath): Promise<void> — Move or rename a path
TypeScript
import { createDb9Client } from 'get-db9';
const client = createDb9Client();
const dbId = 'my-database-id';
// Create directory and write a file
await client.fs.mkdir(dbId, '/data');
await client.fs.write(dbId, '/data/hello.txt', 'Hello from db9!');
// Read file content
const content = await client.fs.read(dbId, '/data/hello.txt');
// List directory
const files = await client.fs.list(dbId, '/data/');
for (const file of files) {
console.log(file.path, file.type, file.size);
}
// Stat and check existence
const info = await client.fs.stat(dbId, '/data/hello.txt');
console.log(info.type, info.size, info.mtime);
const exists = await client.fs.exists(dbId, '/data/hello.txt');
console.log('File exists:', exists);
// Append and rename
await client.fs.append(dbId, '/data/hello.txt', '\nHello again');
await client.fs.rename(dbId, '/data/hello.txt', '/data/hello-2.txt');
// Cleanup
await client.fs.remove(dbId, '/data/hello-2.txt');
await client.fs.remove(dbId, '/data');
FieldTypeDescription
pathstringFull file path.
sizenumberFile size in bytes.
type'file' | 'dir'Entry type.
modenumberUnix file mode.
mtimestringLast modified time as RFC 3339 text.
OptionTypeDescription
recursivebooleanRemove directories recursively (default: false).

Performance note: Convenience methods like read(), write(), and list() each open and close a WebSocket connection per call. For batch operations, use client.fs.connect(dbId) to open a persistent connection.

Credential stores implement a shared async interface used by client auto-auth.

  • FileCredentialStore(path?) — TOML file store at ~/.db9/credentials (shared with db9 CLI)
  • MemoryCredentialStore — Volatile in-memory store for tests and serverless
  • defaultCredentialStore() — Factory that returns new FileCredentialStore()
TypeScript
import {
createDb9Client,
FileCredentialStore,
MemoryCredentialStore,
defaultCredentialStore
} from 'get-db9';
const fileStore = new FileCredentialStore();
const customStore = new FileCredentialStore('/tmp/db9-credentials.toml');
const memStore = new MemoryCredentialStore();
const client = createDb9Client({ credentialStore: fileStore });

API failures throw named Db9Error subclasses based on HTTP status code.

  • Db9Error — Base class with statusCode, message, and optional response
  • Db9AuthError — Status 401
  • Db9NotFoundError — Status 404
  • Db9ConflictError — Status 409 (e.g., duplicate database name)
TypeScript
import {
createDb9Client,
Db9Error,
Db9AuthError,
Db9NotFoundError,
Db9ConflictError
} from 'get-db9';
const client = createDb9Client();
try {
await client.databases.get('missing-id');
} catch (error) {
if (error instanceof Db9NotFoundError) {
console.error('Database not found');
} else if (error instanceof Db9AuthError) {
console.error('Authentication required — run `db9 login` first');
} else if (error instanceof Db9ConflictError) {
console.error('Conflict (e.g., duplicate name)');
} else if (error instanceof Db9Error) {
console.error(`db9 API error ${error.statusCode}: ${error.message}`);
} else {
throw error;
}
}

The package re-exports all interfaces from ./types in addition to client, credential, and filesystem types.

MessageResponse, ColumnInfo, SqlResult, SqlErrorDetail, TenantState

CreateDatabaseRequest, SqlExecuteRequest, DumpRequest, MigrationApplyRequest, BranchRequest, CreateUserRequest, CreateTokenRequest

CustomerResponse, DatabaseResponse, CustomerPasswordResetResponse, CreateConnectTokenResponse, TokenResponse, CreateTokenResponse, DumpResponse, SchemaResponse, TableMetadata, ColumnMetadata, ViewMetadata, MigrationApplyResponse, MigrationMetadata, UserResponse, TenantObservabilityResponse, ObservabilitySummary, QuerySample

FileInfo, FsListOptions, FsRemoveOptions, FsConnectOptions, FsAuthInfo, FsWsRequest, FsWsResponse, FsWsError, StreamWriteReady

Credentials, CredentialStore, FetchFn, HttpClient, HttpClientOptions, InstantDatabaseOptions, InstantDatabaseResult, Db9ClientOptions, Db9Client