Installation
Copy
Ask AI
npm install simplex-ts
Initializing the client
Copy
Ask AI
import Simplex from 'simplex-ts';
const client = new Simplex({
apiKey: process.env.SIMPLEX_API_KEY
});
Configuration options
Copy
Ask AI
const client = new Simplex({
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)
});
Running workflows
Basic workflow execution
Copy
Ask AI
const result = await client.workflows.run('workflow_id', {
variables: {
username: '[email protected]',
search_query: 'order #12345'
}
});
console.log('Session ID:', result.session_id);
With debug webhook callback (useful for local testing)
Copy
Ask AI
const result = await client.workflows.run('workflow_id', {
variables: {
patient_id: 'P-12345'
},
webhook_url: 'https://59d9f4dbc.ngrok-free.app/api/webhook',
metadata: {
internal_id: 'req-789',
source: 'api'
}
});
Handling webhook responses
Next.js App Router
Copy
Ask AI
// 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<string, string> = {};
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
}
Express
Copy
Ask AI
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);
Retrieving session data
Get session replay
Copy
Ask AI
const replay = await client.retrieveSessionReplay('session_id');
// Returns MP4 video recording of the session
console.log('Replay URL:', replay.url);
Get session logs
Copy
Ask AI
const logs = await client.retrieveSessionLogs('session_id');
// Returns JSON session logs
for (const entry of logs.entries) {
console.log(`[${entry.timestamp}] ${entry.level}: ${entry.message}`);
}
Get session store
Copy
Ask AI
const store = await client.getSessionStore('session_id');
// Access metadata about files downloaded during the session
console.log('Stored data:', store.data);
Download session files
Copy
Ask AI
// Download all files as a zip
const allFiles = await client.downloadSessionFiles('session_id');
// Or download a specific file
const specificFile = await client.downloadSessionFiles('session_id', 'report.pdf');
Batch processing
Running multiple workflows
Copy
Ask AI
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 },
webhook_url: 'https://your-domain.com/webhook',
metadata: { patient_id: 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`);
With rate limiting
Copy
Ask AI
async function runWithRateLimit<T>(
items: T[],
fn: (item: T) => Promise<unknown>,
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
);
Searching workflows
Copy
Ask AI
// Search for workflows by name or metadata
const results = await client.workflows.search({
name: 'insurance' // Partial matching supported
});
for (const workflow of results) {
console.log(`${workflow.name}: ${workflow.id}`);
}
Updating workflow metadata
Copy
Ask AI
await client.workflows.updateMetadata('workflow_id', {
category: 'verification',
priority: 'high'
});
Creating workflow sessions
Copy
Ask AI
// Create a new workflow session with a starting URL
const session = await client.workflows.createWorkflowSession(
'My Session',
'https://example.com/portal',
{
variables: { username: '[email protected]' }
}
);
// Run agentic tasks within the session
await client.workflows.agentic(
'Click the login button and enter credentials',
session.id,
{ timeout: 30000 }
);
// Or run a pre-configured agent
await client.workflows.run_agent('login_agent', session.id, {
username: '[email protected]',
password: 'secure_password'
});
Error handling
Copy
Ask AI
import Simplex, {
WorkflowError,
ValidationError,
AuthenticationError,
RateLimitError,
NetworkError
} from 'simplex-ts';
async function runWorkflowSafely(workflowId: string, variables: Record<string, string>) {
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;
}
}
TypeScript types
The SDK exports types for all API responses:Copy
Ask AI
import type {
WebhookPayload,
WorkflowRunResponse,
SessionReplay,
SessionLogs,
SessionStore,
FileMetadata
} from 'simplex-ts';
function handleWebhook(payload: WebhookPayload) {
const {
success,
session_id,
agent_response,
structured_output,
metadata,
file_metadata
} = payload;
// TypeScript knows all the types
}
Environment configuration
Copy
Ask AI
// 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');
}
Next steps
- Webhooks - Set up webhook handlers
- Variables - Use dynamic data in workflows
- Structured Outputs - Extract specific data
- API Reference - Full API documentation
