TypeScript SDK
The get-db9 SDK provides typed TypeScript access to DB9 databases — provisioning, SQL execution, filesystem operations, branching, and token management. This is the server-side SDK for Node.js environments.
Client-side? For browser and edge environments, use the
@db9/browserSDK — it provides a query builder with Row-Level Security enforcement and publishable key authentication.
When to Use the SDK
Section titled “When to Use the SDK”| Scenario | Recommended tool |
|---|---|
| One-liner database provisioning in a script or test | SDK — instantDatabase() |
| Programmatic fleet management (create, branch, delete) | SDK — createDb9Client() |
| File read/write from Node.js (RAG, ingestion) | SDK — client.fs.* |
| Interactive SQL from a terminal | CLI — db9 db sql (CLI Reference) |
| ORM or driver connection to an existing database | Raw pgwire — use the connection string (Connect) |
| Agent onboarding (Codex, Claude Code) | CLI — db9 onboard (Agent Workflows) |
Installation
Section titled “Installation”Runtime requirement: Node.js 18+ (native fetch). TypeScript 5+ for full type exports.
npm install get-db9Also 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.
Quick Start
Section titled “Quick Start”instantDatabase() creates or reuses a database by name. If no name is provided, it defaults to "default".
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);Result shape:
interface InstantDatabaseResult { databaseId: string; connectionString: string; adminUser: string; adminPassword: string; state: string; createdAt: string;}instantDatabase(options?)
Section titled “instantDatabase(options?)”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.
function instantDatabase( options?: InstantDatabaseOptions): Promise<InstantDatabaseResult>;| Option | Type | Description |
|---|---|---|
name | string | Database name. Default: 'default'. |
baseUrl | string | Override API endpoint. Default: https://api.db9.ai or DB9_API_URL env. |
fetch | FetchFn | Custom fetch implementation. |
credentialStore | CredentialStore | Token load/save strategy. |
seed | string | SQL text executed via client.databases.sql() on creation only. |
seedFile | string | SQL file content executed via client.databases.sqlFile() on creation only. |
timeout | number | Request timeout in milliseconds. |
maxRetries | number | Retry count for failed requests (capped at 3). |
retryDelay | number | Delay between retries in milliseconds. |
const db = await instantDatabase({ name: 'analytics', seedFile: ` CREATE TABLE events ( id BIGSERIAL PRIMARY KEY, user_id TEXT NOT NULL, created_at TIMESTAMP DEFAULT NOW() ); `});createDb9Client(options?)
Section titled “createDb9Client(options?)”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.
function createDb9Client(options?: Db9ClientOptions): Db9Client;| Option | Type | Description |
|---|---|---|
baseUrl | string | Default: https://api.db9.ai (or DB9_API_URL env). |
token | string | Bearer token; skips credential store lookup. |
fetch | FetchFn | Custom HTTP implementation. |
credentialStore | CredentialStore | Load/save token state. |
timeout | number | Request timeout in milliseconds. |
maxRetries | number | Retry count for failed requests (capped at 3). |
retryDelay | number | Delay between retries in milliseconds. |
WebSocket | WebSocketConstructor | Override WebSocket for client.fs operations (see Filesystem). |
wsPort | number | Override the fs9 WebSocket port (default: 5480). |
import { createDb9Client, MemoryCredentialStore } from 'get-db9';
const client = createDb9Client({ baseUrl: 'https://api.db9.ai', credentialStore: new MemoryCredentialStore()});Authentication (client.auth)
Section titled “Authentication (client.auth)”me(): Promise<CustomerResponse>— Get current user profile
The SDK itself does not handle login or registration. Use the CLI for auth:
# Zero-setup trial (auto creates anonymous account + token)db9 create --name quickstart
# Upgrade anonymous account to verified SSO identitydb9 claim
# Human operator login (browser-based)db9 login
# API key login (CI/CD, agents)db9 login --api-key <KEY>
# Create an automation tokendb9 token create --name my-agent --expires-in-days 365
# Agent runtimeexport DB9_API_KEY=<token>Once authenticated via CLI, the SDK picks up the stored token automatically.
Token Management (client.tokens)
Section titled “Token Management (client.tokens)”Create, inspect, and revoke API tokens for CI/CD and programmatic access.
create(req: CreateTokenRequest): Promise<CreateTokenResponse>— Create named token with optional expirylist(): Promise<TokenResponse[]>revoke(tokenId: string): Promise<MessageResponse>
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);Database Management (client.databases)
Section titled “Database Management (client.databases)”Core lifecycle APIs: create, list, get, delete, reset password, retrieve credentials, 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 resettingobservability(databaseId: string): Promise<TenantObservabilityResponse>
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);
await client.databases.delete(db.id);For programmatic provisioning patterns, see Provisioning.
SQL Execution
Section titled “SQL Execution”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>
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 Field | Type | Description |
|---|---|---|
columns | ColumnInfo[] | Column metadata for result rows. |
rows | unknown[][] | Result values matrix. |
row_count | number | Rows affected/returned. |
command | string | Executed command label (SELECT, INSERT, etc.). |
error | string | SqlErrorDetail | Structured error with message, code, detail, hint, and position. |
Schema and Dump
Section titled “Schema and Dump”Introspect schema objects or export SQL dump payloads.
schema(databaseId: string): Promise<SchemaResponse>dump(databaseId: string, req?: DumpRequest): Promise<DumpResponse>
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);Migrations
Section titled “Migrations”Apply SQL migrations with checksums and inspect migration history.
applyMigration(databaseId: string, req: MigrationApplyRequest): Promise<MigrationApplyResponse>listMigrations(databaseId: string): Promise<MigrationMetadata[]>
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);}Branching
Section titled “Branching”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>
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.
Database Users (client.databases.users)
Section titled “Database Users (client.databases.users)”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>
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');Filesystem (client.fs)
Section titled “Filesystem (client.fs)”Cloud filesystem operations for reading, writing, and managing files attached to each database. Built for RAG pipelines, document ingestion, and agent workflows.
connect(dbId): Promise<FsClient>— Open a persistent WebSocket connection (caller must callclose())list(dbId, path): Promise<FileInfo[]>— List directory contentsread(dbId, path): Promise<string>— Read file content as textreadBinary(dbId, path): Promise<Uint8Array>— Read file as binarywrite(dbId, path, content): Promise<void>— Write a fileappend(dbId, path, content): Promise<number>— Append to a file, returns bytes writtenstat(dbId, path): Promise<FileInfo>— Get file metadataexists(dbId, path): Promise<boolean>— Check if file existsmkdir(dbId, path): Promise<void>— Create a directory recursivelyremove(dbId, path, opts?): Promise<void>— Delete a file or directoryrename(dbId, oldPath, newPath): Promise<void>— Move or rename a path
import { createDb9Client } from 'get-db9';
const client = createDb9Client();const dbId = 'my-database-id';
// Create directory and write a fileawait client.fs.mkdir(dbId, '/data');await client.fs.write(dbId, '/data/hello.txt', 'Hello from db9!');
// Read file contentconst content = await client.fs.read(dbId, '/data/hello.txt');
// List directoryconst files = await client.fs.list(dbId, '/data/');for (const file of files) { console.log(file.path, file.type, file.size);}
// Stat and check existenceconst 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 renameawait client.fs.append(dbId, '/data/hello.txt', '\nHello again');await client.fs.rename(dbId, '/data/hello.txt', '/data/hello-2.txt');
// Cleanupawait client.fs.remove(dbId, '/data/hello-2.txt');await client.fs.remove(dbId, '/data');FileInfo
Section titled “FileInfo”| Field | Type | Description |
|---|---|---|
path | string | Full file path. |
size | number | File size in bytes. |
type | 'file' | 'dir' | Entry type. |
mode | number | Unix file mode. |
mtime | string | Last modified time as RFC 3339 text. |
FsRemoveOptions
Section titled “FsRemoveOptions”| Option | Type | Description |
|---|---|---|
recursive | boolean | Remove directories recursively (default: false). |
Credential Storage
Section titled “Credential Storage”Credential stores implement a shared async interface used by client auto-auth.
FileCredentialStore(path?)— TOML file store at~/.db9/credentials(shared withdb9CLI)MemoryCredentialStore— Volatile in-memory store for tests and serverlessdefaultCredentialStore()— Factory that returnsnew FileCredentialStore()
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 });Error Handling
Section titled “Error Handling”API failures throw named Db9Error subclasses based on HTTP status code.
Db9Error— Base class withstatusCode,message, and optionalresponseDb9AuthError— Status401Db9NotFoundError— Status404Db9ConflictError— Status409(e.g., duplicate database name)
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; }}TypeScript Types Reference
Section titled “TypeScript Types Reference”The package re-exports all interfaces from ./types in addition to client, credential, and filesystem types.
Already documented inline:
InstantDatabaseResult(see Quick Start),SqlResultandColumnInfo(see SQL Execution),FileInfoandFsRemoveOptions(see Filesystem).
DatabaseResponse
Section titled “DatabaseResponse”Returned by create(), list(), get(), and branch().
interface DatabaseResponse { id: string; name: string; state: string; parent_database_id?: string; region?: string; endpoints?: Endpoint[]; admin_user?: string; admin_password?: string; created_at: string; connection_string?: string;}| Field | Type | Description |
|---|---|---|
id | string | Unique database identifier. |
name | string | Human-readable database name. |
state | string | Lifecycle state: CREATING, ACTIVE, CLONING, DISABLING, DISABLED, CREATE_FAILED. |
parent_database_id | string? | Source database ID for branch databases. |
region | string? | Deployment region (e.g. us-west). |
endpoints | Endpoint[]? | Connection endpoints (host, port, type). |
admin_user | string? | Admin Postgres username. |
admin_password | string? | Admin Postgres password. Only present on create. |
created_at | string | ISO 8601 creation timestamp. |
connection_string | string? | Full postgresql:// connection URI. |
CustomerResponse
Section titled “CustomerResponse”Returned by client.auth.me().
interface CustomerResponse { id: string; email: string; created_at: string; status: string;}| Field | Type | Description |
|---|---|---|
id | string | Customer account identifier. |
email | string | Account email address. Empty for anonymous accounts. |
created_at | string | ISO 8601 account creation timestamp. |
status | string | Account status: active, anonymous. |
TokenResponse
Section titled “TokenResponse”Returned by client.tokens.list(). Metadata only — does not include the token secret.
interface TokenResponse { id: string; name: string; created_at: string; expires_at?: string;}| Field | Type | Description |
|---|---|---|
id | string | Token identifier. Use this to revoke the token. |
name | string | Human-readable token label. |
created_at | string | ISO 8601 creation timestamp. |
expires_at | string? | ISO 8601 expiry timestamp. undefined means never expires. |
CreateTokenResponse
Section titled “CreateTokenResponse”Returned by client.tokens.create(). Includes the token secret — store it immediately.
interface CreateTokenResponse { id: string; name: string; token: string; created_at: string; expires_at?: string;}| Field | Type | Description |
|---|---|---|
id | string | Token identifier. |
name | string | Human-readable token label. |
token | string | The secret token value. Shown only once — store in a secret manager. |
created_at | string | ISO 8601 creation timestamp. |
expires_at | string? | ISO 8601 expiry timestamp. |
SchemaResponse
Section titled “SchemaResponse”Returned by client.databases.schema().
interface SchemaResponse { tables: TableMetadata[]; views: ViewMetadata[];}| Field | Type | Description |
|---|---|---|
tables | TableMetadata[] | All tables in the database. |
views | ViewMetadata[] | All views in the database. |
TableMetadata
Section titled “TableMetadata”interface TableMetadata { name: string; schema: string; columns: ColumnMetadata[];}| Field | Type | Description |
|---|---|---|
name | string | Table name. |
schema | string | Postgres schema name (e.g. public). |
columns | ColumnMetadata[] | Column definitions for this table. |
ColumnMetadata
Section titled “ColumnMetadata”interface ColumnMetadata { name: string; type: string; nullable: boolean; default_value?: string;}| Field | Type | Description |
|---|---|---|
name | string | Column name. |
type | string | Postgres data type (e.g. text, integer, timestamp). |
nullable | boolean | Whether the column accepts NULL. |
default_value | string? | Default expression, if defined. |
ViewMetadata
Section titled “ViewMetadata”interface ViewMetadata { name: string; schema: string;}| Field | Type | Description |
|---|---|---|
name | string | View name. |
schema | string | Postgres schema name. |
DumpResponse
Section titled “DumpResponse”Returned by client.databases.dump().
interface DumpResponse { sql: string; object_count: number;}| Field | Type | Description |
|---|---|---|
sql | string | Full SQL dump text. |
object_count | number | Number of database objects included in the dump. |
TenantObservabilityResponse
Section titled “TenantObservabilityResponse”Returned by client.databases.observability().
interface TenantObservabilityResponse { summary: ObservabilitySummary; samples: QuerySample[];}| Field | Type | Description |
|---|---|---|
summary | ObservabilitySummary | Aggregate metrics for the observation window. |
samples | QuerySample[] | Per-query performance samples. |
ObservabilitySummary
Section titled “ObservabilitySummary”interface ObservabilitySummary { window_seconds: number; statement_count: number; txn_commit_count: number; error_count: number; qps: number; tps: number; latency_avg_ms: number; latency_p99_ms: number; active_connections: number;}| Field | Type | Description |
|---|---|---|
window_seconds | number | Observation window length in seconds. |
statement_count | number | Total statements executed in the window. |
txn_commit_count | number | Total committed transactions. |
error_count | number | Total statement errors. |
qps | number | Average queries per second. |
tps | number | Average transactions per second. |
latency_avg_ms | number | Mean query latency in milliseconds. |
latency_p99_ms | number | 99th-percentile query latency in milliseconds. |
active_connections | number | Current active connection count. |
QuerySample
Section titled “QuerySample”interface QuerySample { query: string; sample_count: number; error_count: number; latency_avg_ms: number; latency_p99_ms: number; latency_max_ms: number; last_seen_ms_ago: number;}| Field | Type | Description |
|---|---|---|
query | string | Normalized query text (literals replaced with $N). |
sample_count | number | Number of times this query pattern was observed. |
error_count | number | Number of times this query pattern produced an error. |
latency_avg_ms | number | Mean execution latency in milliseconds. |
latency_p99_ms | number | 99th-percentile latency in milliseconds. |
latency_max_ms | number | Maximum observed latency in milliseconds. |
last_seen_ms_ago | number | Milliseconds since this query was last observed. |
CustomerPasswordResetResponse
Section titled “CustomerPasswordResetResponse”Returned by client.databases.resetPassword() and client.databases.credentials().
interface CustomerPasswordResetResponse { admin_user: string; admin_password: string; connection_string: string;}| Field | Type | Description |
|---|---|---|
admin_user | string | Admin Postgres username. |
admin_password | string | Admin Postgres password (new password after reset). |
connection_string | string | Full postgresql:// connection URI. |
UserResponse
Section titled “UserResponse”Returned by client.databases.users.list().
interface UserResponse { name: string; is_superuser: boolean; can_login: boolean; can_create_db: boolean; can_create_role: boolean;}| Field | Type | Description |
|---|---|---|
name | string | Postgres username. |
is_superuser | boolean | Whether the user has superuser privileges. |
can_login | boolean | Whether the user can open connections. |
can_create_db | boolean | Whether the user can create databases. |
can_create_role | boolean | Whether the user can create roles. |
MigrationApplyResponse
Section titled “MigrationApplyResponse”Returned by client.databases.applyMigration().
interface MigrationApplyResponse { status: string; name: string;}| Field | Type | Description |
|---|---|---|
status | string | Migration result: applied or skipped (already applied). |
name | string | Migration name as provided in the request. |
MigrationMetadata
Section titled “MigrationMetadata”Returned by client.databases.listMigrations().
interface MigrationMetadata { name: string; checksum: string; applied_at: string; sql_preview: string;}| Field | Type | Description |
|---|---|---|
name | string | Migration name. |
checksum | string | Checksum provided at apply time. |
applied_at | string | ISO 8601 timestamp when the migration was applied. |
sql_preview | string | Truncated SQL for display purposes. |
MessageResponse
Section titled “MessageResponse”Returned by delete and revoke operations.
interface MessageResponse { message: string;}| Field | Type | Description |
|---|---|---|
message | string | Human-readable confirmation message. |
Request Types
Section titled “Request Types”| Type | Key Fields |
|---|---|
CreateDatabaseRequest | name: string, region?: string, admin_password?: string |
CreateTokenRequest | name?: string, expires_in_days?: number |
BranchRequest | name: string |
DumpRequest | ddl_only?: boolean |
CreateUserRequest | username: string, password?: string |
MigrationApplyRequest | name: string, sql: string, checksum: string |
Other Exported Types
Section titled “Other Exported Types”| Type | Description |
|---|---|
TenantState | Union: 'CREATING' | 'ACTIVE' | 'DISABLING' | 'DISABLED' | 'CREATE_FAILED' |
SqlErrorDetail | Structured SQL error: message, code?, position?, hint?, detail? |
Endpoint | Connection endpoint: host, port, type, region?, priority, enabled |
InstantDatabaseOptions | Options for instantDatabase() — see Quick Start |
Db9ClientOptions | Options for createDb9Client() — see createDb9Client |
CredentialStore | Interface for token load/save — see Credential Storage |
FetchFn | Custom fetch implementation type |
FsListOptions, FsConnectOptions | Filesystem operation options |
Next Steps
Section titled “Next Steps”- Browser SDK — Client-side data access with RLS
- CLI Reference — Terminal-based database management
- Connect — Connection strings, TLS, and driver configuration
- Provisioning — Programmatic fleet management patterns
- Agent Workflows — SDK usage in agent pipelines
- Extensions — fs9, HTTP, vector, pg_cron, and more