TypeScript SDK
TypeScript SDK installation and usage guide
Installation
pnpm add @surflet/sdk
# or
npm install @surflet/sdk
Initialize the Client
import { Surflet } from '@surflet/sdk';
const client = new Surflet({
apiKey: 'sk_live_...',
baseUrl: 'https://api.surflet.app', // optional, defaults to production
timeout: 30000, // optional, timeout in milliseconds
});
Via environment variables:
export SURFLET_API_KEY=sk_live_...
export SURFLET_API_URL=https://api.surflet.app
const client = new Surflet(); // automatically reads environment variables
Quick Publish
const page = await client.publish({
title: 'Daily Briefing',
content: '## Summary\n\nAll systems operational.',
});
console.log(page.pageUrl);
Structured Publish
Use builder functions to create structured content:
import {
Surflet,
keyValue,
callout,
table,
action,
access,
} from '@surflet/sdk';
const client = new Surflet({
apiKey: 'sk_test_surflet123',
baseUrl: 'http://localhost:3001',
});
const page = await client.publish({
pageType: 'approval',
title: 'Server Purchase Request',
blocks: [
keyValue('Details', [
{ key: 'Vendor', value: 'Dell' },
{ key: 'Model', value: 'PowerEdge R760' },
{ key: 'Quantity', value: '5' },
{ key: 'Amount', value: '$15,000' },
]),
callout('Within Q1 budget allocation', 'info'),
table({
title: 'Cost Breakdown',
columns: [
{ key: 'item', label: 'Item' },
{ key: 'qty', label: 'Quantity' },
{ key: 'price', label: 'Unit Price' },
{ key: 'total', label: 'Total' },
],
rows: [
{ item: 'Server', qty: '5', price: '$2,500', total: '$12,500' },
{ item: 'RAM Upgrade', qty: '5', price: '$300', total: '$1,500' },
{ item: 'Setup Fee', qty: '1', price: '$1,000', total: '$1,000' },
],
}),
],
actions: [
action('approve', 'Approve Purchase', { style: 'primary' }),
action('reject', 'Reject', { style: 'danger', requiresComment: true }),
],
access: access.authenticated({ emails: ['[email protected]'] }),
onAction: {
defaultUrl: 'https://your-agent.example.com/webhook/surflet',
},
});
Block Builders
keyValue — Key-Value Pairs
keyValue('User Profile', [
{ key: 'Name', value: 'Alice Wang' },
{ key: 'Email', value: '[email protected]' },
{ key: 'Role', value: 'Engineering Manager' },
]);
text — Markdown Rich Text
import { text } from '@surflet/sdk';
text('## Analysis Report\n\nDetailed findings...', { title: 'Report' });
table — Data Table
table({
title: 'Team Members',
columns: [
{ key: 'name', label: 'Name' },
{ key: 'role', label: 'Role' },
],
rows: [
{ name: 'Alice', role: 'Manager' },
{ name: 'Bob', role: 'Engineer' },
],
});
callout — Callout Box
callout('This is an important notice', 'warning');
// Supported styles: 'info' | 'warning' | 'error' | 'success'
code — Code Block
import { code } from '@surflet/sdk';
code("console.log('hello')", {
language: 'javascript',
title: 'Example',
});
timeline — Timeline
import { timeline } from '@surflet/sdk';
timeline([
{ time: '2026-03-20 10:00', event: 'Created', detail: 'User submitted ticket' },
{ time: '2026-03-20 11:30', event: 'Analyzed', detail: 'AI recommended refund' },
], { title: 'Event History' });
chart — Chart
import { chart } from '@surflet/sdk';
chart({
chartType: 'bar',
data: {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [{ label: 'Revenue', data: [100, 200, 150, 300] }],
},
title: 'Quarterly Revenue',
});
diff — Diff View
import { diff } from '@surflet/sdk';
diff({
oldText: 'old version content',
newText: 'new version content',
language: 'python',
title: 'Config Changes',
});
gallery — Image Gallery
import { gallery } from '@surflet/sdk';
gallery([
{ url: 'https://example.com/img1.png', caption: 'Damage photo' },
{ url: 'https://example.com/img2.png', caption: 'Packaging' },
], { title: 'Evidence' });
form — Interactive Form
import { form } from '@surflet/sdk';
form([
{ fieldId: 'amount', type: 'number', label: 'Refund Amount', required: true },
{ fieldId: 'reason', type: 'textarea', label: 'Reason' },
], { title: 'Refund Details' });
divider — Divider
import { divider } from '@surflet/sdk';
divider();
Action Builder
action('approve', 'Approve', {
style: 'primary', // 'primary' | 'secondary' | 'danger'
requiresComment: false,
confirmMessage: 'Are you sure you want to approve?',
});
Access Builder
// Public access
access.public();
// Specific identities
access.authenticated({ emails: ['[email protected]'] });
// Single-use link
access.oneTime({ burnAfter: 300 });
// Time-limited
access.timeLimited({ expiresAt: '2026-04-01T00:00:00Z' });
// Password protection
access.password({ passwordHash: 'sha256:...' });
Publish from Template
// List available templates
const templates = await client.listTemplates();
templates.templates.forEach((t) => console.log(`${t.name}: ${t.description}`));
// Publish from template
const page = await client.publishTemplate('refund_approval', {
customer: 'Alice Wang',
order_id: '#ORD-7891',
amount: 127.50,
reason: 'Product damaged on arrival',
risk_score: 15,
});
console.log(page.pageUrl);
Append Blocks (Streaming Publish)
import { Surflet, callout, keyValue, chart, text } from '@surflet/sdk';
const client = new Surflet({ apiKey: 'sk_live_...' });
// Create the initial page
const page = await client.publish({
title: 'Analysis Report',
blocks: [callout('Analyzing data...', 'info')],
});
// Append analysis results
await client.appendBlocks(page.pageId, [
keyValue('Key Metrics', [
{ key: 'Total Tickets', value: '156' },
{ key: 'Resolution Rate', value: '94%' },
]),
chart({
chartType: 'line',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
datasets: [{ label: 'Tickets', data: [28, 35, 22, 41, 30] }],
},
title: 'Daily Tickets',
}),
]);
// Continue appending
await client.appendBlocks(page.pageId, [
text('## Summary\n\nTicket resolution improved by 12% this week.', { title: 'Summary' }),
]);
Analytics & Quality Score
// Get page view analytics
const analytics = await client.getAnalytics('pg_xxx');
console.log(`Total views: ${analytics.totalViews}`);
console.log(`Unique viewers: ${analytics.uniqueViewers}`);
// Get agent quality score
const score = await client.getQualityScore();
console.log(`Quality Score: ${score.score}/100`);
console.log(`Acceptance Rate: ${score.acceptanceRate}%`);
Query and Actions
// Get a page
const page = await client.getPage('pg_xxx');
console.log(page.status);
// Revoke a page
await client.revokePage('pg_xxx');
// Inbox
const inbox = await client.getInbox({ status: 'pending' });
for (const item of inbox.items) {
console.log(`${item.title} - ${item.priority}`);
}
// Approval actions
await client.approve('pg_xxx', { comment: 'Looks good' });
await client.reject('pg_xxx', { comment: 'Need more details' });
Type Definitions
The TypeScript SDK provides complete type definitions:
import type {
PublishOptions,
Page,
Block,
Action,
AccessConfig,
ApprovalChain,
OnActionConfig,
InboxResponse,
} from '@surflet/sdk';