Skip to content

TypeScript SDK

The official TypeScript SDK provides typed methods for all Tusky API operations. Zero external dependencies — uses native fetch.

Terminal window
npm install @tuskydp/sdk
import { TuskyClient } from '@tuskydp/sdk';
const tusky = new TuskyClient({
apiKey: 'tdp_your_key',
});

For local development, override the base URL:

const tusky = new TuskyClient({
apiKey: 'tdp_your_key',
baseUrl: 'http://localhost:8000',
});

The SDK is organized into namespaces:

NamespaceDescription
tusky.vaultsCreate, list, update, delete vaults
tusky.filesUpload, download, list, delete files
tusky.webhooksManage webhook endpoints and deliveries
tusky.publicAccess public vaults and files (no auth)
tusky.accountGet account info
tusky.apiKeysCreate, list, revoke API keys
tusky.trashList, restore, delete, empty trash
// Create
const vault = await tusky.vaults.create({
name: 'My Vault',
visibility: 'public',
});
// List all
const vaults = await tusky.vaults.list();
// Update
await tusky.vaults.update(vault.id, { name: 'Renamed' });
// Delete (force moves files to trash first)
await tusky.vaults.delete(vault.id, { force: true });
import { readFile } from 'fs/promises';
const data = await readFile('./photo.jpg');
const file = await tusky.files.upload({
name: 'photo.jpg',
mimeType: 'image/jpeg',
vaultId: vault.id,
data,
});
// 1. Get presigned URL
const { fileId, uploadUrl } = await tusky.files.requestUpload({
name: 'doc.pdf',
mimeType: 'application/pdf',
sizeBytes: buffer.byteLength,
vaultId: vault.id,
});
// 2. PUT to presigned URL
await fetch(uploadUrl, {
method: 'PUT',
body: buffer,
headers: { 'Content-Type': 'application/pdf' },
});
// 3. Confirm
const file = await tusky.files.confirmUpload(fileId);
const { downloadUrl, encryption } = await tusky.files.getDownloadUrl(file.id);
const response = await fetch(downloadUrl);
const bytes = await response.arrayBuffer();
// If encrypted, decrypt client-side using encryption.wrappedKey and encryption.iv

Wait for a file to reach a specific status:

// Promise-based — resolves when status is reached
const synced = await tusky.files.waitForStatus(file.id, ['synced'], {
interval: 3000, // poll every 3s (default: 2s)
timeout: 120000, // give up after 2min (default: 60s)
});

Or use the async iterator for progress updates:

for await (const status of tusky.files.pollStatus(file.id, ['synced'])) {
console.log(`Current status: ${status.status}`);
}
// Create
const webhook = await tusky.webhooks.create({
url: 'https://example.com/webhook',
events: ['file.synced', 'file.error'],
});
console.log(webhook.secret); // Save this — only shown once
// Test
await tusky.webhooks.test(webhook.id);
// List deliveries
const deliveries = await tusky.webhooks.listDeliveries(webhook.id, {
limit: 10,
});

Public methods don’t require authentication:

// Build public URLs (synchronous, no API call)
const fileUrl = tusky.public.getFileUrl(fileId);
const blobUrl = tusky.public.getBlobUrl(walrusBlobId);
// List files in a public vault
const { vault, files } = await tusky.public.listVaultFiles(userId, 'my-vault');
import { TuskyError, TuskyTimeoutError } from '@tuskydp/sdk';
try {
await tusky.vaults.get('non-existent');
} catch (err) {
if (err instanceof TuskyError) {
console.error(err.statusCode, err.message);
}
if (err instanceof TuskyTimeoutError) {
console.error('Polling timed out');
}
}
const tusky = new TuskyClient({
apiKey: 'tdp_...',
baseUrl: 'http://localhost:8000', // Override API URL
headers: { 'X-Custom': 'value' }, // Extra headers on every request
fetch: customFetchFn, // Custom fetch implementation
});