Developer Manual

Batches

A batch runs the same agent over up to 500 rows in one call. Creating a batch returns a pending job straight away, and the rows are processed in the background, 10 at a time. Poll the job to watch completed_rows and failed_rows rise toward total_rows, then fetch the batch to read each row's result.

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 the rows, poll until the job is done, and separate the successes from the failures. Each row is its own 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 you create the batch to receive an event per run without polling. See Webhooks.