Skip to content

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 users
const users = await truss('/v1/db/users');
// With filters and ordering
const activeUsers = await truss(
'/v1/db/users?active=eq.true&order=created_at.desc&limit=10'
);
// Select specific columns
const names = await truss('/v1/db/users?select=id,name');
// Filter with IN
const specific = await truss('/v1/db/users?id=in.(1,2,3)');

Inserting data

// Single row
const [newUser] = await truss('/v1/db/users', {
method: 'POST',
body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' }),
});
// Multiple rows
const 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 URL
const { 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 S3
await 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.