Client SDK
Truss doesn’t ship a dedicated SDK package yet, but the REST API is simple enough to use with fetch. Here are ready-to-use patterns for common operations.
Base setup
const TRUSS_URL = 'http://localhost:8787';const TRUSS_KEY = 'truss_pk_your_anon_key'; // or truss_sk_ for service_role
async function truss(path: string, options: RequestInit = {}) { const res = await fetch(`${TRUSS_URL}${path}`, { ...options, headers: { 'apikey': TRUSS_KEY, 'Content-Type': 'application/json', ...options.headers, }, }); if (!res.ok) { const err = await res.json().catch(() => ({ error: res.statusText })); throw new Error(err.error || res.statusText); } return res.json();}Querying data
// Select all usersconst users = await truss('/v1/db/users');
// With filters and orderingconst activeUsers = await truss( '/v1/db/users?active=eq.true&order=created_at.desc&limit=10');
// Select specific columnsconst names = await truss('/v1/db/users?select=id,name');
// Filter with INconst specific = await truss('/v1/db/users?id=in.(1,2,3)');Inserting data
// Single rowconst [newUser] = await truss('/v1/db/users', { method: 'POST', body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' }),});
// Multiple rowsconst newUsers = await truss('/v1/db/users', { method: 'POST', body: JSON.stringify([ { name: 'Alice', email: 'alice@example.com' }, { name: 'Bob', email: 'bob@example.com' }, ]),});Updating data
// Update matching rows (filter required)const updated = await truss('/v1/db/users?id=eq.42', { method: 'PATCH', body: JSON.stringify({ name: 'Updated Name' }),});Deleting data
// Delete matching rows (filter required)const deleted = await truss('/v1/db/users?id=eq.42', { method: 'DELETE',});Calling functions
const result = await truss('/v1/db/rpc/calculate_total', { method: 'POST', body: JSON.stringify({ order_id: 42 }),});Running raw SQL
Requires a service_role key:
const SERVICE_KEY = 'truss_sk_your_service_key';
const result = await fetch(`${TRUSS_URL}/v1/sql`, { method: 'POST', headers: { 'apikey': SERVICE_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ sql: 'SELECT * FROM users WHERE email ILIKE $1', params: ['%@example.com'], }),});
const { rows, columns, rowCount } = await result.json();Transactions
const { results } = await fetch(`${TRUSS_URL}/v1/sql/transaction`, { method: 'POST', headers: { 'apikey': SERVICE_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ statements: [ { sql: 'INSERT INTO orders (total) VALUES ($1) RETURNING id', params: [99.99] }, { sql: 'INSERT INTO order_items (order_id, product_id) VALUES ($1, $2)', params: [null, 5] }, ], }),}).then(r => r.json());File uploads
// 1. Get a presigned upload URLconst { url, headers } = await fetch(`${TRUSS_URL}/api/storage/buckets/my-bucket/objects/presign-upload`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key: 'photos/avatar.jpg', contentType: 'image/jpeg' }),}).then(r => r.json());
// 2. Upload directly to S3await fetch(url, { method: 'PUT', headers, body: file, // File object from <input type="file">});Realtime (WebSocket)
function connectRealtime(url = 'ws://localhost:8787/realtime') { const ws = new WebSocket(url);
ws.onmessage = (event) => { const data = JSON.parse(event.data); console.log(`${data.operation} on ${data.table}:`, data.row); };
ws.onclose = () => { // Auto-reconnect after 2 seconds setTimeout(() => connectRealtime(url), 2000); };
return ws;}
const ws = connectRealtime();Platform status
const status = await fetch(`${TRUSS_URL}/v1/status`, { headers: { 'apikey': SERVICE_KEY },}).then(r => r.json());
console.log(`Database: ${status.database.size_gb} GB`);console.log(`Tables: ${status.database.table_count}`);console.log(`Auth MAU: ${status.auth.mau}`);console.log(`Storage: ${status.storage.size_gb} GB`);Error handling
try { const users = await truss('/v1/db/nonexistent_table');} catch (err) { // Error messages come from the API: // "relation \"nonexistent_table\" does not exist" console.error(err.message);}The API returns structured errors with error, code (Postgres error code), detail, and hint fields when available.