Bulk Tasks API: creating 100 tasks without breaking rate limits

Bulk Tasks API: creating 100 tasks without breaking rate limits

Sanctum Tasks was built for agents, not humans. That design principle shows most clearly when you need to create tasks in bulk. An agent creating one task at a time is slow, inefficient, and wastes API calls. That's why we built a bulk endpoint — so your automation can create hundreds of tasks in a single request while respecting our rate limits.

When You Need Bulk Creation

Here's the scenario: your agent has analyzed a complex project and identified 73 discrete work items that need to become tasks. Creating those one by one would mean 73 API calls, 73 round trips, and a lot of waiting.

But here's what happens. Rate limits exist for a reason. Our API limits requests per minute to protect the service. If you fire 100 requests in a single second, you'll hit those limits and get 429 errors. Your agent would either fail or need exponential backoff — which could take minutes to recover.

That's where bulk creation helps. Our bulk endpoint accepts up to 100 tasks in a single request, processes them in order, and returns all created task IDs in one response. That's one request, one rate limit consumption, one round trip.

How the Bulk Endpoint Works

The bulk endpoint is straightforward:

 POST /api/tasks/bulk

The request body is an array of task objects:

 {
 "tasks": [
 {
 "title": "Set up database schema",
 "description": "Create initial tables",
 "status": "open"
 },
 {
 "title": "Configure nginx",
 "description": "Set up reverse proxy",
 "status": "open"
 },
 {
 "title": "Install TLS certificates",
 "description": "Configure Let's Encrypt",
 "status": "open"
 }
 ]
 }

The response returns the created tasks:

 {
 "created": [
 {
 "id": "tsk_001",
 "title": "Set up database schema",
 "status": "open"
 },
 {
 "id": "tsk_002",
 "title": "Configure nginx",
 "status": "open"
 },
 {
 "id": "tsk_003",
 "title": "Install TLS certificates",
 "status": "open"
 }
 ],
 "count": 3
 }

That's three tasks created in one request. That's the pattern.

Rate Limit Strategy

Here's what matters: the bulk endpoint itself still respects rate limits. You're not unlimited — you're optimized. Here's how that works:

Each bulk request counts as one request against your rate limit, regardless of how many tasks are inside. That's the efficiency gain. You create 100 tasks with one API call instead of 100 calls.

We cap the bulk endpoint at 100 tasks per request. That's an intentional limit. If you need more than 100 items, batch them:

 POST /api/tasks/bulk (first 100 tasks)
 POST /api/tasks/bulk (next 100 tasks)

That's two requests, two rate limit hits. Still far more efficient than 200 individual calls.

When to Use Bulk vs. Individual

Here's when to use bulk creation:

  • Bulk: When you're creating related tasks from a single analysis, when you're initializing a project, when you're seeding a template
    • Individual: When tasks come in one at a time through async flows, when you need individual task IDs immediately for downstream logic

Here's the practical difference:

 // Bulk — good for startup seeding
 const tasks = analyzeProject(projectSpecs); // returns 85 tasks
 await tasksClient.bulkCreate(tasks);

// Individual — good for async flows
 for (const item of incomingItems) {
 const task = await tasksClient.create(item); // one at a time
 await notifySlack(task); // immediately notify
 }

Both work. The right choice depends on your use case.

Best Practices

Here's what we recommend for bulk operations:

Batch intelligently. Group related tasks together. A project initialization should be one bulk call. A backlog migration should be batches of 100. Don't mix unrelated tasks in one bulk call.

Handle partial failures. Our bulk endpoint is atomic — all tasks succeed or all fail. If one task in the batch has invalid data, the entire batch fails. Validate your data before the bulk call.

Track creation results. The response includes task IDs. Save those — you'll need them for subsequent operations like adding comments or attachments.

Use exponential backoff. Even with bulk, network issues happen. Wrap your bulk calls in retry logic with exponential backoff:

 async function bulkCreateWithRetry(tasks, maxRetries = 3) {
 for (let i = 0; i < maxRetries; i++) {
 try {
 return await tasksClient.bulkCreate(tasks);
 } catch (error) {
 if (error.status === 429 && i < maxRetries - 1) {
 await sleep(Math.pow(2, i) * 1000); // 1s, 2s, 4s
 continue;
 }
 throw error;
 }
 }
 }

That's the exact pattern we use in our own production automation.

What About Updates

We also support bulk updates. Here's the pattern:

 PUT /api/tasks/bulk

The request body:

 {
 "tasks": [
 {
 "id": "tsk_001",
 "status": "completed"
 },
 {
 "id": "tsk_002",
 "status": "in_progress"
 }
 ]
 }

That's two task updates in one request. Same rate limit efficiency as creation.

Bulk delete is:

 DELETE /api/tasks/bulk

With task IDs in the request body. That's how we handle cleanup operations.

Integrator Perspective

Here's what this looks like in practice. Suppose you're building a project kickoff automation:

 async function kickoffProject(projectSpec) {
 // Analyze the spec into tasks
 const taskSpecs = parseSpecs(projectSpec); // returns 127 items

// Create in batches of 100
 const batch1 = taskSpecs.slice(0, 100);
 const batch2 = taskSpecs.slice(100);

const results1 = await tasksClient.bulkCreate(batch1);
 const results2 = await tasksClient.bulkCreate(batch2);

// Results contain task IDs — save for relationship mapping
 return [...results1.created, ...results2.created];
 }

That's creating 127 tasks in two API calls. That's efficient and clean.

What We Don't Support

Bulk operations are powerful but limited. Here's what you can't do:

  • Mixed operations in one call. You can't create some tasks and update others in the same bulk call. Split into separate calls.
    • Individual error handling. If any task in the batch fails, the entire batch rolls back. No partial creation.
    • Unlimited batch sizes. The 100-task cap is firm. More than 100 means multiple batches.

These limits are features, not bugs. They're designed to keep the API predictable and safe.

Close

Bulk operations exist because automation is our primary use case. When agents need to create tasks, they should do it efficiently. That's what the bulk endpoint provides.

If you're building automation around Tasks, use the bulk endpoints. If you'd like to see the full API documentation or discuss integration approaches, reach out. We're always happy to help with automation design.

We run this in production every day. If you want the same capability for your program, or help turning ops data into a clear decision, get in touch.