Skip to main content
The Batch API allows you to process multiple DeepResearch tasks in parallel with shared configuration and progress monitoring.
For conceptual overview, batch lifecycle, and best practices, see the Batch Processing Guide. This page focuses on TypeScript SDK method reference.

Quick Start

import { Valyu } from "valyu-js";

const client = new Valyu();

// Create batch, add tasks, wait for completion
const batch = await client.batch.create({ name: "Research Batch", mode: "standard" });
await client.batch.addTasks(batch.batch_id, {
  tasks: [
    { query: "Research AI trends" },
    { query: "Analyze market data" }
  ]
});
const result = await client.batch.waitForCompletion(batch.batch_id);
console.log(`Completed: ${result.counts.completed} tasks`);

Methods

batch.create(options?)

Creates a new batch container. Returns a batch ID that you’ll use for subsequent operations. Parameters:
interface CreateBatchOptions {
  name?: string;                                    // Optional batch name
  mode?: "fast" | "standard" | "heavy" | "max";      // Research mode: "standard" (default), "heavy" (comprehensive), or "fast" (faster completion)
  outputFormats?: ("markdown" | "pdf" | "toon" | Record<string, any>)[];  // Output formats: ["markdown"], ["pdf"], ["toon"], or JSON schema. Cannot mix JSON schema with "markdown"/"pdf". "toon" requires JSON schema.
  search?: {                                        // Search configuration (type, sources, dates, category). See Search Configuration section for details.
    searchType?: "all" | "web" | "proprietary";     // Default: "all"
    includedSources?: string[];                     // e.g., ["web", "academic", "finance", "patent", "transportation", "politics", "legal"]
    excludedSources?: string[];                     // Array of source types to exclude
    startDate?: string;                             // YYYY-MM-DD format
    endDate?: string;                               // YYYY-MM-DD format
    category?: string;                              // Category filter (source-dependent)
  };
  webhookUrl?: string;                              // HTTPS URL for completion notification
  metadata?: Record<string, string | number | boolean>; // Custom metadata
}
Response:
interface CreateBatchResponse {
  success: boolean;
  batch_id?: string;                                // Use this for subsequent operations
  name?: string;                                     // Batch name
  status?: BatchStatus;
  mode?: "fast" | "standard" | "heavy";             // Research mode
  output_formats?: ("markdown" | "pdf" | "toon" | Record<string, any>)[];
  search_params?: {
    search_type?: "all" | "web" | "proprietary";
    included_sources?: string[];
  };
  counts?: BatchCounts;                              // Task counts
  cost?: number;                                     // Total cost in dollars
  created_at?: string;                               // ISO 8601 timestamp string
  completed_at?: string;                              // ISO 8601 timestamp string (if completed)
  webhook_secret?: string;                           // Secret for webhook verification (only on creation)
  error?: string;
}
Example:
const batch = await client.batch.create({
  name: "Q4 Research Batch",
  mode: "fast",
  outputFormats: ["markdown"],
  metadata: {
    project: "Q4-Research",
    user: "analyst-1"
  }
});

if (batch.success) {
  console.log(`Created batch: ${batch.batch_id}`);
}

batch.addTasks(batchId, options)

Adds one or more tasks to an existing batch. You can call this multiple times to add tasks incrementally. Constraints:
  • Maximum tasks per request: 100
  • Minimum tasks per request: 1
  • Batch must be in "open" or "processing" status
Parameters:
interface AddBatchTasksOptions {
  tasks: BatchTaskInput[]; // Array of 1-100 tasks
}

interface BatchTaskInput {
  id?: string;                                      // Optional custom task identifier (for tracking)
  query: string;                                    // Research query or task description (required)
  strategy?: string;                                // Custom research strategy instructions
  urls?: string[];                                  // Array of URLs to extract content from
  metadata?: Record<string, string | number | boolean>; // Custom metadata
}
Tasks inherit mode, outputFormats, and search from the batch and cannot override them. Response:
interface AddBatchTasksResponse {
  success: boolean;
  batch_id?: string;                                // Batch ID
  added?: number;                                    // Number of tasks successfully added
  tasks?: BatchTaskCreated[];                       // Array of created task objects
  counts?: BatchCounts;                             // Updated task counts for the batch
  error?: string;
}

interface BatchTaskCreated {
  task_id?: string;                                 // User-provided task identifier (if specified)
  deepresearch_id: string;                          // DeepResearch task ID
  status: string;                                    // Task status
}
Example:
    const addResult = await client.batch.addTasks(batchId, {
      tasks: [
        {
          query: "What are the latest developments in quantum computing?"
        },
        {
          query: "Analyze the impact of AI on healthcare in 2024"
        },
        {
          query: "Compare renewable energy trends across Europe",
          urls: ["https://example.com/report.pdf"]
        }
      ]
    });

    if (addResult.success) {
      console.log(`Added ${addResult.added} tasks`);
    }

batch.status(batchId)

Gets the current status of a batch, including task counts and cost information. Response:
interface BatchStatusResponse {
  success: boolean;
  batch?: DeepResearchBatch;
  error?: string;
}

interface DeepResearchBatch {
  batch_id: string;
  organisation_id?: string;
  api_key_id?: string;
  credit_id?: string;
  name?: string;
  status: BatchStatus;                              // "open" | "processing" | "completed" | "completed_with_errors" | "cancelled"
  mode: "fast" | "standard" | "heavy";             // Research mode
  output_formats?: ("markdown" | "pdf" | "toon" | Record<string, any>)[];
  search_params?: {
    search_type?: "all" | "web" | "proprietary";
    included_sources?: string[];
  };
  counts: BatchCounts;
  cost: number;                                     // Total cost in dollars (replaces 'usage' object)
  webhook_url?: string;
  webhook_secret?: string;                         // Only returned on batch creation
  created_at: string;                               // ISO 8601 timestamp string
  completed_at?: string;                            // ISO 8601 timestamp string (only present when batch is completed)
  metadata?: Record<string, string | number | boolean>;
}

interface BatchCounts {
  total: number;                                    // Total tasks in batch
  queued: number;                                    // Tasks waiting to start
  running: number;                                  // Tasks currently running
  completed: number;                                // Successfully completed tasks
  failed: number;                                   // Failed tasks
  cancelled: number;                                // Cancelled tasks
}
Example:
const status = await client.batch.status(batchId);

if (status.success && status.batch) {
  console.log(`Status: ${status.batch.status}`);
  console.log(
    `Progress: ${status.batch.counts.completed}/${status.batch.counts.total}`
  );
  console.log(`Cost: $${status.batch.cost}`);
}

batch.listTasks(batchId, options?)

Lists all tasks in a batch with their individual statuses. Pass includeOutput: true to get full output, sources, images, and cost for each task. Parameters:
interface ListBatchTasksOptions {
  status?: string;          // Filter: "completed", "failed", "cancelled", "running", "queued"
  limit?: number;           // Results per page (default: 25, max: 50)
  lastKey?: string;         // Pagination cursor from previous response
  includeOutput?: boolean;  // Include full output, sources, images, and cost (default: false)
}
Response:
interface ListBatchTasksResponse {
  success: boolean;
  batch_id?: string;                                // Batch ID
  tasks?: BatchTaskListItem[];
  pagination?: BatchPagination;                     // Pagination information
  error?: string;
}

interface BatchPagination {
  count: number;                                    // Number of tasks returned in this response
  last_key?: string;                                // Pagination key for fetching next page (if has_more is true)
  has_more: boolean;                                // Whether there are more tasks to fetch
}

interface BatchTaskListItem {
  task_id?: string;                                 // User-provided task identifier
  deepresearch_id: string;                          // Task ID (use with deepresearch.status())
  query: string;                                    // The research query
  status: DeepResearchStatus;                       // Task status
  created_at: string;                               // ISO 8601 timestamp string
  completed_at?: string;                            // ISO 8601 timestamp string
  // Additional fields when includeOutput is true:
  output_type?: string;                             // "markdown", "pdf", "toon", "structured"
  output?: string;                                  // Full research output
  sources?: Source[];                               // Cited sources
  images?: string[];                                // Image URLs
  pdf_url?: string;                                 // PDF download URL
  deliverables?: any;                               // Deliverable outputs
  error?: string;                                   // Error message (failed tasks)
  cost?: number;                                    // Task cost in dollars
}
Example:
// Lightweight listing (status only)
const tasksList = await client.batch.listTasks(batchId);

if (tasksList.success && tasksList.tasks) {
  tasksList.tasks.forEach((task, i) => {
    console.log(`${i + 1}. ${task.status}: ${task.query.substring(0, 50)}...`);
  });
}

// Get full output for completed tasks
const results = await client.batch.listTasks(batchId, {
  status: "completed",
  includeOutput: true,
});

for (const task of results.tasks) {
  console.log(`Task: ${task.task_id || task.deepresearch_id}`);
  console.log(`Query: ${task.query}`);
  console.log(`Output: ${task.output?.substring(0, 200)}...`);
  console.log(`Sources: ${task.sources?.length} cited`);
  console.log(`Cost: $${task.cost}`);
}

// Paginate through all results
let lastKey = results.pagination.last_key;
while (lastKey) {
  const nextPage = await client.batch.listTasks(batchId, {
    status: "completed",
    includeOutput: true,
    lastKey,
  });
  for (const task of nextPage.tasks) {
    console.log(`Task: ${task.deepresearch_id} - ${task.query}`);
  }
  lastKey = nextPage.pagination.last_key;
}
By default, includeOutput is false, returning a lightweight listing with task status only. Set includeOutput: true when you need the full output, sources, images, and cost for each task.

batch.waitForCompletion(batchId, options?)

Waits for a batch to complete by polling its status at regular intervals. This is useful for long-running batches where you want to be notified when all tasks finish. Parameters:
interface BatchWaitOptions {
  pollInterval?: number;                            // Polling interval in ms (default: 10000)
  maxWaitTime?: number;                             // Maximum wait time in ms (default: 7200000 = 2 hours)
  onProgress?: (batch: DeepResearchBatch) => void; // Progress callback
}
Response: Returns the final DeepResearchBatch object when the batch reaches a terminal state (completed, completed_with_errors, or cancelled). Example:
try {
  const finalBatch = await client.batch.waitForCompletion(batchId, {
    pollInterval: 10000,                            // Check every 10 seconds
    maxWaitTime: 600000,                            // Wait up to 10 minutes
    onProgress: (batch) => {
      console.log(
        `Progress: ${batch.counts.completed}/${batch.counts.total} completed`
      );
      console.log(
        `Running: ${batch.counts.running}, Queued: ${batch.counts.queued}`
      );
    }
  });

  console.log("Batch completed!");
  console.log(`Final status: ${finalBatch.status}`);
} catch (error) {
  console.error(`Wait interrupted: ${error.message}`);
}

batch.cancel(batchId)

Cancels a batch and all its pending tasks. Tasks that are already running will continue, but queued tasks will be cancelled. Response:
interface CancelBatchResponse {
  success: boolean;
  message?: string;
  batch_id?: string;
  error?: string;
}
Example:
const result = await client.batch.cancel(batchId);

if (result.success) {
  console.log(`Batch ${batchId} cancelled successfully`);
} else {
  console.log(`Failed to cancel: ${result.error}`);
}

batch.list()

Lists all batches associated with your API key. Response:
interface ListBatchesResponse {
  success: boolean;
  batches?: DeepResearchBatch[];                    // Array of batches (direct array, no wrapper)
  error?: string;
}
Example:
const result = await client.batch.list();

if (result.success && result.batches) {
  console.log(`Found ${result.batches.length} batches:`);

  result.batches.forEach((batch, i) => {
    console.log(`${i + 1}. ${batch.batch_id}`);
    console.log(`   Name: ${batch.name || "Unnamed"}`);
    console.log(`   Status: ${batch.status}`);
    console.log(`   Tasks: ${batch.counts.total}`);
  });
}

Complete Example

Here’s a complete example that demonstrates the full batch workflow:
const { Valyu } = require('valyu-js');

const client = new Valyu(process.env.VALYU_API_KEY);

async function runBatchExample() {
  try {
    // 1. Create a batch
    console.log('Creating batch...');
    const batch = await client.batch.create({
      name: 'Research Questions Batch',
      mode: 'fast',
      outputFormats: ['markdown'],
      search: {
        searchType: 'all',
        includedSources: ['valyu/valyu-arxiv']
      },
      metadata: {
        project: 'Q4-Research',
        user: 'analyst-1'
      }
    });

    if (!batch.success) {
      throw new Error(`Failed to create batch: ${batch.error}`);
    }

    const batchId = batch.batch_id;
    console.log(`✓ Created batch: ${batchId}\n`);

    // 2. Add tasks to the batch
    console.log('Adding tasks...');
    const addResult = await client.batch.addTasks(batchId, {
      tasks: [
        {
          query: 'What are the latest developments in quantum computing?'
        },
        {
          query: 'Analyze the impact of AI on healthcare in 2024'
        },
        {
          query: 'Compare renewable energy trends across Europe'
        }
      ]
    });

    if (!addResult.success) {
      throw new Error(`Failed to add tasks: ${addResult.error}`);
    }
    console.log(`✓ Added ${addResult.added} tasks\n`);

    // 3. Monitor progress
    console.log('Waiting for completion...');
    const finalBatch = await client.batch.waitForCompletion(batchId, {
      pollInterval: 10000,
      maxWaitTime: 600000,
      onProgress: (batch) => {
        console.log(
          `  Progress: ${batch.counts.completed}/${batch.counts.total} completed ` +
            `(${batch.counts.running} running, ${batch.counts.queued} queued)`
        );
      }
    });

    console.log('\n✓ Batch completed!');
    console.log(`Final status: ${finalBatch.status}`);
    console.log(`Completed: ${finalBatch.counts.completed}`);
    console.log(`Failed: ${finalBatch.counts.failed}`);

    // 4. Get all results with full output
    console.log('\nFetching task results...');
    const results = await client.batch.listTasks(batchId, {
      status: 'completed',
      includeOutput: true,
    });

    for (const task of results.tasks) {
      console.log(`\nTask: ${task.query.substring(0, 50)}...`);
      console.log(`Output length: ${task.output?.length || 0} characters`);
      console.log(`Sources: ${task.sources?.length || 0} cited`);
      console.log(`Cost: $${task.cost}`);
    }

  } catch (error) {
    console.error('Error:', error.message);
  }
}

runBatchExample();

Search Configuration

The search parameter controls which data sources are queried. See the Batch Processing Guide for complete documentation of all search options.
const batch = await client.batch.create({
  name: "Academic Research",
  mode: "standard",
  search: {
    searchType: "proprietary",
    includedSources: ["academic", "finance"],
    startDate: "2024-01-01",
    endDate: "2024-12-31"
  }
});
Batch-level search parameters are inherited by all tasks and cannot be overridden per-task.

Integration with DeepResearch API

Individual tasks in a batch are DeepResearch tasks. You can use the standard DeepResearch methods:
// Get detailed task result
const result = await client.deepresearch.status(task.deepresearch_id);

// Update a running task
await client.deepresearch.update(task.deepresearch_id, "Focus on recent data");

// Cancel an individual task
await client.deepresearch.cancel(task.deepresearch_id);

Limitations

Batch tasks do not support: files, deliverables, mcpServers, or previousReports. Use client.deepresearch.create() for these features.
ConstraintValue
Maximum tasks per request100
Minimum tasks per request1
Batch status to add tasksopen or processing
Inherited settings (cannot override per-task): mode, outputFormats, search Per-task overrides allowed: strategy, urls, metadata See the Batch Processing Guide for complete details.

See Also