Developer Manual

Batches

A batch runs the same agent over many rows in a single call. Creating a batch returns immediately with a pending job; processing happens asynchronously. Poll the job to watch completed_rows and failed_rows climb toward total_rows, and fetch a single batch to read per-row results.

Create a batch

POST /v1/batches — scope batch:run. Body: agent_type (required), rows[] (required, each { task, data? }), optional name and webhook_url. Returns 201 with the created { job } in pending state; processing starts in the background.

bash
curl -X POST https://api.eclips.tech/v1/batches \
  -H "Authorization: Bearer $ECLIPS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_type": "ap_specialist",
    "name": "June invoices",
    "rows": [
      { "task": "Process invoice INV-1001" },
      { "task": "Process invoice INV-1002", "data": { "amount": 12000 } }
    ]
  }'
json
{
  "job": {
    "id": "b1a2t3c4-0000-4000-8000-000000000000",
    "name": "June invoices",
    "agent_type": "ap_specialist",
    "status": "pending",
    "total_rows": 2,
    "completed_rows": 0,
    "failed_rows": 0,
    "created_at": "2026-06-06T09:00:00.000Z"
  }
}
Important:A batch may contain at most 500 rows. More than 500 returns 400 Maximum 500 rows per batch. An empty or missing rows[], or a missing agent_type, also returns 400.

Get & list

GET /v1/batches/:id — scope batch:read. Returns { job, rows } with per-row status, result, and error_message, ordered by row_index.

json
{
  "job": { "id": "b1a2t3c4-...", "status": "running", "total_rows": 2, "completed_rows": 1, "failed_rows": 0 },
  "rows": [
    { "row_index": 0, "task": "Process invoice INV-1001", "status": "completed", "result": { "approved": true }, "error_message": null },
    { "row_index": 1, "task": "Process invoice INV-1002", "status": "running", "result": null, "error_message": null }
  ]
}

GET /v1/batches — scope batch:read. Lists jobs newest-first (query: status, limit, offset); returns { jobs }.

Cancel

POST /v1/batches/:id/cancel — scope batch:run. Cancels a job in pending or running state and returns { cancelled: true }. Cancelling a job in any other state returns 400.

From the SDK

createBatch(agentType, rows, options?), getBatch(id), listBatches(options?), and cancelBatch(id) mirror the endpoints above.

typescript
const batch = await client.createBatch("ap_specialist", [
  { task: "Process invoice INV-1001" },
  { task: "Process invoice INV-1002", data: { amount: 12000 } },
], { name: "June invoices" });

// Poll for progress.
const status = await client.getBatch(batch.id);
console.log(status.completed_rows, "/", status.total_rows);

const jobs = await client.listBatches({ status: "running" });
await client.cancelBatch(batch.id);

Worked example

Example · Process a month of invoices

Submit hundreds of rows, poll to completion, and split successes from failures. Each row is a separate agent run billed in credits.

typescript
import { EClipsClient } from "@eclips/sdk";

const client = new EClipsClient({ apiKey: process.env.ECLIPS_API_KEY! });

// 1. Submit up to 500 rows in one call.
const rows = invoices.map((inv) => ({
  task: `Process invoice ${inv.number}`,
  data: { amount: inv.amount },
}));
const { id } = await client.createBatch("ap_specialist", rows, { name: "June invoices" });

// 2. Poll until every row reaches a terminal state.
let job = await client.getBatch(id);
while (job.status === "pending" || job.status === "running") {
  await new Promise((r) => setTimeout(r, 3000));
  job = await client.getBatch(id);
  console.log(`${job.completed_rows + job.failed_rows} / ${job.total_rows}`);
}

// 3. Inspect per-row results (failed_rows tells you how many to retry).
console.log("done:", job.completed_rows, "failed:", job.failed_rows);
Tip:Pass a webhook_url when creating the batch to receive per-run events instead of polling — see Webhooks.