Skip to content
view raw .md

Create tasks from a list in one call

Import up to 100 Dailybot tasks per request with the bulk endpoint: Idempotency-Key, a dry run first, per-item results and contiguous task keys.

Beta

Plan is in beta. Everything under /plan in the web app, the CLI and agent skill commands for projects, goals, boards and tasks, and the /v1/plan/ public API may change before general availability. Want to try it with your team? Write to [email protected].

Importing a list (a spreadsheet, a checklist, the output of a planning session) should not be one request per row, and a retry should not create everything twice. POST /v1/plan/tasks/bulk/ creates up to 100 tasks per call, requires an Idempotency-Key, and reports each item separately.

1. Preview with a dry run

?dry_run=true runs the whole call and rolls it back, so you see what would happen without writing anything (no idempotency key needed):

curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/bulk/?dry_run=true" \
  -H "Authorization: Bearer $DAILYBOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "create",
    "board": "00000000-0000-4000-8000-000000000002",
    "items": [
      { "title": "Write the migration guide", "external_id": "row-1" },
      { "title": "Record the demo", "external_id": "row-2", "priority": 2 }
    ]
  }'

The preview answers consequence (a sentence to show a person), items with the changes each item would make, and refused with any item that would fail and why.

2. Create for real

Send the same body without dry_run, with an Idempotency-Key:

curl -sS -X POST "https://api.dailybot.com/v1/plan/tasks/bulk/" \
  -H "Authorization: Bearer $DAILYBOT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: import-2026-09-25-batch-1" \
  -d '{
    "operation": "create",
    "board": "00000000-0000-4000-8000-000000000002",
    "items": [
      { "title": "Write the migration guide", "external_id": "row-1" },
      { "title": "Record the demo", "external_id": "row-2", "priority": 2 }
    ]
  }'
{
  "succeeded": 2,
  "failed": 0,
  "results": [
    { "task": "00000000-0000-4000-8000-000000000105", "key": "ENG-150", "external_id": "row-1", "status": "ok", "version": 1 },
    { "task": "00000000-0000-4000-8000-000000000106", "key": "ENG-151", "external_id": "row-2", "status": "ok", "version": 1 }
  ]
}
  • Items take a title (up to 512 characters) and optionally description, state, owner, priority, estimate, start_date, due_date and external_id.
  • external_id comes back on each result, so you can match results to your rows and reconcile after a retry.
  • Keys are allocated as one contiguous block, in the order you sent the items, so the import reads in order afterwards (ENG-150, ENG-151, …).
  • New tasks land at the bottom of each column by default. Add "position": "start" next to operation to put them at the top instead, in the order of your items.

From the CLI:

dailybot plan task bulk --operation create --board 00000000-0000-4000-8000-000000000002 -f tasks.json --dry-run
dailybot plan task bulk --operation create --board 00000000-0000-4000-8000-000000000002 -f tasks.json

3. Read per-item results

The call answers 200 even when some items fail: the HTTP status says the batch was accepted, not that every item succeeded. Check failed and each result’s status; a failed item carries code, detail and sometimes extra:

{ "task": "ENG-9", "status": "error", "code": "version_conflict", "detail": "This task changed since you loaded it.", "extra": { "current_version": 4 } }

4. Retry safely

If the connection drops, send the same body with the same Idempotency-Key. You get the first response back (with Idempotency-Replayed: true) and nothing is created twice. Keys are remembered for 24 hours. A different body with the same key is 409 idempotency_key_payload_mismatch; use a new key for a new batch.

More than 100 rows

Split the list into batches of up to 100 items, one key per batch (for example import-2026-09-25-batch-1, -batch-2, …). More than 100 items in one call is 400 too_many_items. Bulk calls count against a limit of 30 per minute per actor.

Other bulk operations

The same endpoint applies one operation to up to 100 existing tasks, addressed by uuid or key: move, update, archive, restore and set_labels (which replaces the whole label set). set_owner, set_priority, set_due_date and set_parent are aliases of update, and delete is an alias of archive. A payload that names a task from another organization is refused as a whole, before anything is written.

Reference