Official TypeScript SDK for the Simplex API
npm install simplex-tsOfficial TypeScript SDK for the Simplex API.
This guide provides practical examples for integrating Simplex into your TypeScript applications.
``bash`
npm install simplex-ts
`typescript
import { SimplexClient } from 'simplex-ts';
const client = new SimplexClient({
apiKey: process.env.SIMPLEX_API_KEY
});
`
`typescript`
const client = new SimplexClient({
apiKey: process.env.SIMPLEX_API_KEY,
timeout: 30000, // Request timeout in ms (default: 30000)
maxRetries: 3, // Number of retry attempts (default: 3)
retryDelay: 1000 // Delay between retries in ms (default: 1000)
});
`typescript
const result = await client.workflows.run('workflow_id', {
variables: {
username: 'user@example.com',
search_query: 'order #12345'
}
});
console.log('Session ID:', result.session_id);
`
`typescript`
const result = await client.workflows.run('workflow_id', {
variables: {
patient_id: 'P-12345'
},
webhookUrl: 'https://59d9f4dbc.ngrok-free.app/api/webhook',
metadata: 'req-789'
});
`typescript
// app/api/simplex-webhook/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { verifySimplexWebhook, WebhookPayload } from 'simplex-ts';
export async function POST(request: NextRequest) {
const body = await request.text();
const headers: Record
request.headers.forEach((value, key) => {
headers[key] = value;
});
try {
verifySimplexWebhook(body, headers, process.env.SIMPLEX_WEBHOOK_SECRET!);
const payload: WebhookPayload = JSON.parse(body);
if (payload.success) {
// Process successful workflow
await processResult(payload);
} else {
// Handle failed workflow
await handleFailure(payload);
}
return NextResponse.json({ received: true });
} catch (error) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
}
}
async function processResult(payload: WebhookPayload) {
const { session_id, structured_output, metadata } = payload;
// Your business logic here
console.log('Processing session:', session_id);
if (structured_output) {
// Handle extracted data
await saveToDatabase(structured_output);
}
}
async function handleFailure(payload: WebhookPayload) {
console.error('Workflow failed:', payload.session_id);
// Alert, retry, or log the failure
}
`
`typescript
import express from 'express';
import { verifySimplexWebhook, WebhookPayload } from 'simplex-ts';
const app = express();
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const body = req.body.toString('utf8');
const signature = req.headers['x-simplex-signature'] as string;
try {
verifySimplexWebhook(body, req.headers, process.env.SIMPLEX_WEBHOOK_SECRET!);
const payload: WebhookPayload = JSON.parse(body);
// Process asynchronously
processWebhook(payload).catch(console.error);
res.json({ received: true });
} catch (error) {
res.status(401).json({ error: 'Invalid signature' });
}
});
app.listen(3000);
`
Use polling when you can't receive webhooks or need to check status synchronously:
`typescript
const status = await client.getSessionStatus('session_id');
if (status.in_progress) {
console.log('Session still running...');
} else if (status.success) {
console.log('Session completed successfully');
console.log('Files:', status.file_metadata);
console.log('Scraper outputs:', status.scraper_outputs);
} else {
console.log('Session failed');
}
`
When a flow script calls pause(), you can resume it programmatically:
`typescript
const result = await client.resume('session_id');
if (result.succeeded) {
console.log('Flow resumed successfully');
} else {
console.log('Failed to resume:', result.error);
}
`
`typescript
import fs from 'fs';
const replay = await client.retrieveSessionReplay('session_id');
// Returns a Buffer containing the MP4 video recording
fs.writeFileSync('session-replay.mp4', Buffer.from(replay));
`
`typescript
const logs = await client.retrieveSessionLogs('session_id');
// Returns JSON session logs
console.log('Session logs:', JSON.stringify(logs, null, 2));
`
`typescript`
// Download all files as a zip
const allFiles = await client.downloadSessionFiles('session_id');
`typescript
const patients = ['P-001', 'P-002', 'P-003', 'P-004', 'P-005'];
// Run workflows in parallel with concurrency limit
const results = await Promise.all(
patients.map(async (patientId) => {
try {
return await client.workflows.run('verification_workflow', {
variables: { patient_id: patientId },
webhookUrl: 'https://your-domain.com/webhook',
metadata: patientId
});
} catch (error) {
console.error(Failed to start workflow for ${patientId}:, error);
return null;
}
})
);
const successful = results.filter(Boolean);
console.log(Started ${successful.length}/${patients.length} workflows);`
`typescript
async function runWithRateLimit
items: T[],
fn: (item: T) => Promise
concurrency: number = 5,
delayMs: number = 1000
) {
const results = [];
for (let i = 0; i < items.length; i += concurrency) {
const batch = items.slice(i, i + concurrency);
const batchResults = await Promise.all(batch.map(fn));
results.push(...batchResults);
if (i + concurrency < items.length) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
return results;
}
// Usage
await runWithRateLimit(
patients,
(patientId) => client.workflows.run('workflow_id', {
variables: { patient_id: patientId }
}),
5, // 5 concurrent
1000 // 1 second between batches
);
`
`typescript
// Search for workflows by name or metadata
const results = await client.workflows.search({
workflowName: 'insurance' // Partial matching supported
});
for (const workflow of results.workflows) {
console.log(${workflow.workflow_name}: ${workflow.workflow_id});`
}
`typescript`
await client.workflows.updateMetadata('workflow_id', 'verification-high');
`typescript
import { SimplexClient,
WorkflowError,
ValidationError,
AuthenticationError,
RateLimitError,
NetworkError
} from 'simplex-ts';
async function runWorkflowSafely(workflowId: string, variables: Record
try {
return await client.workflows.run(workflowId, { variables });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key');
throw error;
}
if (error instanceof RateLimitError) {
console.log('Rate limited, retrying after delay...');
await new Promise(resolve => setTimeout(resolve, 5000));
return client.workflows.run(workflowId, { variables });
}
if (error instanceof ValidationError) {
console.error('Invalid parameters:', error.message);
throw error;
}
if (error instanceof WorkflowError) {
console.error('Workflow execution failed:', error.message);
throw error;
}
if (error instanceof NetworkError) {
console.error('Network issue:', error.message);
throw error;
}
throw error;
}
}
`
The SDK exports types for all API responses:
`typescript
import type {
WebhookPayload,
RunWorkflowResponse,
FileMetadata
} from 'simplex-ts';
function handleWebhook(payload: WebhookPayload) {
const {
success,
session_id,
agent_response,
structured_output,
session_metadata,
file_metadata
} = payload;
// TypeScript knows all the types
}
`
`typescript
// config.ts
export const simplexConfig = {
apiKey: process.env.SIMPLEX_API_KEY!,
webhookSecret: process.env.SIMPLEX_WEBHOOK_SECRET!,
webhookUrl: process.env.NODE_ENV === 'production'
? 'https://your-domain.com/api/webhook'
: process.env.NGROK_URL + '/api/webhook'
};
// Validate config on startup
if (!simplexConfig.apiKey) {
throw new Error('SIMPLEX_API_KEY is required');
}
``
MIT