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 optionallydescription,state,owner,priority,estimate,start_date,due_dateandexternal_id. external_idcomes 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 tooperationto 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.