For asynchronous executions, use the runs resource to check status and retrieve results.
Execution Status
Executions progress through these statuses:
| Status | Description |
|---|
queued | Waiting to be processed |
running | Currently processing |
success | Completed successfully |
failed | Completed with error |
cancelled | Cancelled by user |
queued → running → success
→ failed
→ cancelled
Check Status
Use runs.get() to check the current status:
const execution = await client.runs.get('exec_abc123');
console.log('Status:', execution.status);
console.log('Created:', execution.createdAt);
if (execution.status === 'success') {
console.log('Output:', execution.output);
console.log('Duration:', execution.duration, 'ms');
} else if (execution.status === 'failed') {
console.error('Error:', execution.error?.message);
}
Wait for Completion
Use runs.waitForCompletion() to poll until the execution finishes:
// Start async execution
const execution = await client.flows.run('flow_abc123', {
input: {
document: { base64, filename, mimeType: 'application/pdf' }
}
});
// Poll until complete
const result = await client.runs.waitForCompletion(execution.id, {
interval: 2000, // Poll every 2 seconds
timeout: 300000 // Wait up to 5 minutes
});
console.log('Final status:', result.status);
console.log('Output:', result.output);
Options
| Option | Type | Default | Description |
|---|
interval | number | 1000 | Time between polls (ms) |
timeout | number | 300000 | Maximum wait time (ms) |
If the execution doesn’t complete within the timeout, a TimeoutError is thrown. The execution continues running—you can call waitForCompletion() again with a new timeout.
Manual Polling
For more control, implement your own polling loop:
async function pollExecution(executionId: string) {
const maxAttempts = 60;
const interval = 2000;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const execution = await client.runs.get(executionId);
switch (execution.status) {
case 'success':
return { success: true, output: execution.output };
case 'failed':
return { success: false, error: execution.error };
case 'cancelled':
return { success: false, error: { message: 'Cancelled' } };
case 'queued':
case 'running':
// Still processing, wait and retry
await new Promise(r => setTimeout(r, interval));
break;
}
}
throw new Error('Polling timeout');
}
Execution Result
Completed executions include:
interface Execution<T> {
id: string;
flowId: string;
status: ExecutionStatus;
createdAt: string;
completedAt?: string; // When finished
duration?: number; // Duration in ms
output?: T; // Extracted data
metrics?: {
tokensUsed: number;
cost: number;
stepsRun: number;
stepsTotal: number;
};
traceId?: string;
metadata?: Record<string, unknown>;
error?: {
code: string;
message: string;
details?: Record<string, unknown>;
};
}
Type-Safe Results
Use generics for typed output:
interface InvoiceData {
invoiceNumber: string;
vendor: { name: string; address: string };
totalAmount: number;
lineItems: Array<{
description: string;
amount: number;
}>;
}
const result = await client.runs.get<InvoiceData>('exec_abc123');
if (result.status === 'success' && result.output) {
// result.output is typed as InvoiceData
console.log('Invoice:', result.output.invoiceNumber);
console.log('Total:', result.output.totalAmount);
}
Cancel Execution
Cancel a running execution:
await client.runs.cancel('exec_abc123');
After cancellation, the execution status becomes cancelled. Partial results may be available.
Batch Processing
Process multiple documents and poll all results:
// Start all executions
const executions = await Promise.all(
documents.map(doc =>
client.flows.run('flow_abc123', {
input: { document: doc }
})
)
);
// Wait for all to complete
const results = await Promise.all(
executions.map(exec =>
client.runs.waitForCompletion(exec.id, { timeout: 120000 })
)
);
// Process results
for (const result of results) {
if (result.status === 'success') {
console.log('Output:', result.output);
} else {
console.error('Failed:', result.error?.message);
}
}
Next Steps