Skip to main content

SDKs

Vibedasher ships official, fully-typed SDKs for TypeScript and Python, generated from the API's OpenAPI spec so they stay in lockstep with the platform. They're how your own code reaches the maintained platform: run SQL against your datasets, trigger refreshes, manage connections and access rights, wire a dashboard to live data, or automate anything the MCP tools do from a script instead of an agent.

LanguagePackageDocumented here
TypeScript@vibedasher/client4.1.5
Pythonvibedasher4.3.19

Both SDKs authenticate with an API key in the X-Api-Key header. Mint one in the app under Settings → API keys at cloud.vibedasher.com — see Authentication. (The SDKs are the code path; if your agent is driving Vibedasher over MCP, it signs in with vibedasher login instead and needs no key at all — see Build with your agent.)

Neither client needs to be told which region your account lives in. With no base URL and no region, both resolve to https://api.vibedasher.com/api, which routes each request by the credential it carries — see One host, routed by your credential. Passing region is still supported and pins the client to that region's own hostname, https://api.{region}.vibedasher.com/api; an explicit baseUrl / base_url overrides both. (region became optional in @vibedasher/client 4.1.5 and vibedasher 4.3.19.)

Looking for a specific endpoint? Browse the full API Reference — every operation grouped by resource, with curl / Python / TypeScript request samples generated from the same signatures the SDKs are built from.

The shape of every call​

Both SDKs expose the same resource-grouped fluent client. Construct it once, then call methods grouped by resource. Signatures are flat: path parameters first (in path order), then the request body, then one optional trailing options object holding the query parameters. There are no path / query / body wrapper objects.

Resources are the same 23 in both languages, camelCase in TypeScript and snake_case in Python:

accounts, aiProviders, apiKeys, chats, connections, dashboardSubscriptions, datasets, dbt, embedTokens, folders, groups, images, questions, refreshes, skills, sql, subscriptions, tasks, templates, tools, upload, users, viz.

A non-2xx response raises — VibedasherApiError in both languages. Methods never resolve to an error union, so you do not check a result before using it.

TypeScript​

npm install @vibedasher/client
import { Vibedasher, VibedasherApiError } from '@vibedasher/client';

const client = new Vibedasher({
apiKey: process.env.VIBEDASHER_API_KEY!,
});

// List datasets — query params go in the trailing options object
const page = await client.datasets.list({ limit: 50 });

// Create — the body is positional
const created = await client.datasets.create({ name: 'Sales', type: 'csv' });

// Fetch one by id — path params are positional
const one = await client.datasets.get(created.dataset.id);

// Update — path param, then body
const updated = await client.datasets.update(one.dataset.id, { name: 'Sales 2026' });

Every method is typed end to end: the argument types and the resolved response type come from the spec, and the per-resource interfaces (DatasetsResource, DatasetsListOptions, …) and model types (DatasetResponse, DatasetUpdate, …) are exported from the package root if you want to annotate a variable.

Running SQL​

client.query is the hand-written method the generated surface does not have: one call in, typed columnar results out.

const result = await client.query({
sql: 'SELECT country, SUM(revenue) AS revenue FROM sales GROUP BY 1',
});
console.log(result.columns, result.rows);

datasetIds is optional — omit it and the server resolves the dataset set from the aliases your SQL references, applying exactly the same authorization.

Uploading a CSV​

const uploaded = await client.datasets.upload({
name: 'Sales',
content: 'country,revenue\nFR,10\nDE,12\n',
});
console.log(uploaded.cleanSQLName); // the alias to use in client.query SQL

Escape hatch​

The underlying fetch client is on the instance as client.http if you need interceptors, a custom fetch, or per-call overrides. There is no module-level singleton to configure: each Vibedasher instance owns its own client, so two clients in one process never clobber each other's base URL or key.

Python​

pip install vibedasher
from vibedasher import Vibedasher, VibedasherApiError
from vibedasher.models import DatasetCreate, DatasetUpdate

client = Vibedasher(api_key="<your-api-key>")

# List datasets — query params are keyword-only
page = client.datasets.list(limit=50)

# Create — the body is the first positional argument
created = client.datasets.create(DatasetCreate(name="Sales", type_="csv"))

# Fetch one by id — path params are positional
one = client.datasets.get(created.dataset.id)

# Update — path param, then body
updated = client.datasets.update(one.dataset.id, DatasetUpdate(name="Sales 2026"))

Request and response models live in vibedasher.models. Resource attributes are snake_case (client.datasets, client.api_keys, client.ai_providers, client.embed_tokens, client.viz, …), and so are the methods.

Running SQL​

result = client.query(sql="SELECT country, SUM(revenue) AS revenue FROM sales GROUP BY 1")
print(result.columns, result.rows)

Uploading a CSV​

uploaded = client.datasets.upload(name="Sales", content="country,revenue\nFR,10\nDE,12\n")
print(uploaded["cleanSQLName"]) # the alias to use in client.query SQL

Escape hatch​

The flat operation modules under vibedasher.api.<tag> are still shipped for anything the facade does not cover. Build a raw client with create_client and call .sync(), .sync_detailed(), .asyncio(), or .asyncio_detailed():

from vibedasher import create_client
from vibedasher.api.datasets import read_datasets

raw = create_client(api_key="<your-api-key>")
datasets = read_datasets.sync(client=raw)

Error handling​

Both SDKs raise on a non-2xx response, so the happy path reads straight through and errors are caught where you want to handle them.

TypeScript:

import { Vibedasher, VibedasherApiError } from '@vibedasher/client';

try {
const page = await client.datasets.list({ limit: 50 });
console.log(page.datasets);
} catch (err) {
if (err instanceof VibedasherApiError) {
console.error(`Request failed (${err.status})`, err.detail, err.requestId);
} else {
throw err;
}
}

Python:

from vibedasher import VibedasherApiError

try:
page = client.datasets.list(limit=50)
except VibedasherApiError as err:
print(f"Request failed ({err.status_code})", err.detail, err.request_id)

Common status codes: 401/403 (missing or invalid API key, or a key used on a session-only route), 404 (not found, or a viz that isn't published), 422 (request validation error). Each endpoint's reference page lists the exact responses it can return.

Pagination​

List endpoints return a page of results plus a nextKey cursor. You rarely need to drive that cursor yourself: every listable resource carries iterAll() (TypeScript) / iter_all() (Python), which walks the pages and yields rows.

TypeScript:

for await (const ds of client.datasets.iterAll()) {
handle(ds);
}

Python:

for ds in client.datasets.iter_all():
handle(ds)

Both also expose the page-level form (iterPages() / iter_pages()) when you want the envelope rather than the rows. Driving the cursor by hand still works — pass nextKey back as exclusiveStartKey (exclusive_start_key in Python) and stop when it comes back null/None — but the iterators also detect a cursor that stops advancing and raise rather than looping forever.

The wire name — what the cURL tab and every reference page's parameter table show — is always exclusiveStartKey; the TypeScript SDK keeps that camelCase spelling as its option key, and the Python SDK exposes the same parameter as the exclusive_start_key keyword. It is one cursor, spelled per language — never both on one request.

Response typing caveat​

Some API routes currently return loosely-typed responses (object / Any) because they declare a generic response shape on the backend. Request bodies, query/path params, and an increasing set of responses are fully typed. Response types are being hardened module-by-module — upgrade the SDK to pick up improvements.

note

The SDKs are generated, never hand-edited. If you spot a gap, it's almost always upstream in the API's OpenAPI spec — reach out via the contact page.