Skip to content

Time blocks

Time blocks are the stretches of scheduled time in your plan. The Planner creates them when it schedules tasks, and you can move, lock and reorder them by hand. Every endpoint acts only on your own blocks and needs an API key or a signed-in session — see API keys. Requests without one get 401 Unauthorized; error responses carry an error message.

Lists the blocks starting inside a time range, in start-time order. Cancelled blocks are left out.

GET /api/time-blocks

Both query parameters are optional; the default range is the next 24 hours.

Name Type Required Description
from string No ISO 8601 timestamp the range starts at; defaults to now
to string No ISO 8601 timestamp the range ends at; defaults to 24 hours after from

200 OK with a JSON array of time blocks.

[
{
"id": "5e8b2d17-4c9a-4f6b-8d3e-1a7c0b9f2d45",
"userId": "b1d4e7a0-2c5f-4b8e-9a1d-6c3f0e2b5a78",
"taskId": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64",
"title": "Write project brief",
"type": "task",
"startAt": "2026-10-01T09:00:00.000Z",
"endAt": "2026-10-01T10:30:00.000Z",
"locked": false,
"defended": false,
"source": "auto",
"sortOrder": 0,
"status": "scheduled",
"explanation": null,
"createdAt": "2026-09-30T22:05:11.342Z",
"updatedAt": "2026-09-30T22:05:11.342Z",
"task": { "id": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64", "title": "Write project brief", "priority": "high", "status": "todo" }
}
]

A block appears when its startAt falls inside the range and its status is not cancelled; the task summary carries id, title, priority and status, and is null for blocks with no task.

  • 400 Bad Request — from or to is not a usable timestamp; the error message is from and to must be ISO dates.
  • 400 Bad Request — to is not after from, or the range is longer than 62 days.
  • 401 Unauthorized — no valid API key or session.

Places a block by hand, for example dropping a task onto the Today grid. Hand-placed blocks are never touched by the planner.

POST /api/time-blocks
Name Type Required Description
taskId string Yes Id of one of your tasks
startAt string Yes ISO 8601 timestamp the block starts at
endAt string Yes ISO 8601 timestamp the block ends at; after startAt, at most 24 hours later

201 Created with the new block, including its task summary.

{
"id": "5e8b2d17-4c9a-4f6b-8d3e-1a7c0b9f2d45",
"userId": "b1d4e7a0-2c5f-4b8e-9a1d-6c3f0e2b5a78",
"taskId": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64",
"title": "Write project brief",
"type": "task",
"startAt": "2026-10-01T09:00:00.000Z",
"endAt": "2026-10-01T10:00:00.000Z",
"locked": false,
"defended": false,
"source": "manual",
"sortOrder": 0,
"status": "scheduled",
"explanation": null,
"createdAt": "2026-09-30T22:05:11.342Z",
"updatedAt": "2026-09-30T22:05:11.342Z",
"task": { "id": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64", "title": "Write project brief", "priority": "high", "status": "todo" }
}
  • 400 Bad Request — the body failed validation (Validation failed), endAt is not after startAt, or the block would span more than 24 hours.
  • 404 Not Found — no task with that id belongs to you (Task not found).
  • 401 Unauthorized — no valid API key or session.

Returns one time block.

GET /api/time-blocks/{id}

{id} is the time block’s id.

200 OK with the time block.

{
"id": "5e8b2d17-4c9a-4f6b-8d3e-1a7c0b9f2d45",
"userId": "b1d4e7a0-2c5f-4b8e-9a1d-6c3f0e2b5a78",
"taskId": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64",
"title": "Write project brief",
"type": "task",
"startAt": "2026-10-01T09:00:00.000Z",
"endAt": "2026-10-01T10:30:00.000Z",
"locked": true,
"defended": false,
"source": "auto",
"sortOrder": 0,
"status": "scheduled",
"explanation": null,
"createdAt": "2026-09-30T22:05:11.342Z",
"updatedAt": "2026-09-30T23:12:04.887Z",
"task": { "id": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64", "title": "Write project brief", "priority": "high" }
}

The task summary on this response carries id, title and priority; the List time blocks response also carries the task’s status.

  • 404 Not Found — no time block of that id belongs to you.
  • 401 Unauthorized — no valid API key or session.

Changes a time block’s times, lock state or status.

PATCH /api/time-blocks/{id}

Every body field is optional; fields you leave out keep their values.

Name Type Required Description
startAt string No ISO 8601 timestamp the block starts at
endAt string No ISO 8601 timestamp the block ends at
locked boolean No Lock the block so the planner keeps it
sortOrder integer No Position in manual sorts; 0 or greater
status string No scheduled, in_progress, completed or cancelled

200 OK with the updated time block.

{
"id": "5e8b2d17-4c9a-4f6b-8d3e-1a7c0b9f2d45",
"userId": "b1d4e7a0-2c5f-4b8e-9a1d-6c3f0e2b5a78",
"taskId": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64",
"title": "Write project brief",
"type": "task",
"startAt": "2026-10-01T09:30:00.000Z",
"endAt": "2026-10-01T11:00:00.000Z",
"locked": true,
"defended": false,
"source": "auto",
"sortOrder": 0,
"status": "scheduled",
"explanation": null,
"createdAt": "2026-09-30T22:05:11.342Z",
"updatedAt": "2026-09-30T23:20:36.129Z",
"task": { "id": "c9f2a5d8-3e6b-4a1c-9d7f-2b5e8a0c3f64", "title": "Write project brief", "priority": "high" }
}

The planner replaces unlocked task blocks on its next run, so set locked to true to protect a hand-placed block.

  • 400 Bad Request — a field failed validation; details names the fields.
  • 404 Not Found — no time block of that id belongs to you.
  • 401 Unauthorized — no valid API key or session.

Deletes a time block for good.

DELETE /api/time-blocks/{id}

It takes no body.

200 OK once the block is gone.

{ "success": true }

Deleting a block never deletes its task.

  • 404 Not Found — no time block of that id belongs to you.
  • 401 Unauthorized — no valid API key or session.

Saves a drag-and-drop ordering by setting each block’s sortOrder to its position in the list.

PATCH /api/time-blocks/reorder

This route takes PATCH only. The body lists the blocks in their new order.

Name Type Required Description
orderedIds array of string Yes Time block ids in their new order; at least one, and every id must be one of yours

200 OK once the new order is saved.

{ "success": true }

All the sortOrder values update in one transaction, so a failure leaves the old order in place.

  • 400 Bad Request — orderedIds is missing or empty, or an entry is not a UUID; details names the fields.
  • 404 Not Found — one of the ids is not a time block of yours; the error message is One or more time blocks not found or access denied.
  • 401 Unauthorized — no valid API key or session.

Push a block half an hour later.

Terminal window
curl -X PATCH https://tasks.example.com/api/time-blocks/5e8b2d17-4c9a-4f6b-8d3e-1a7c0b9f2d45 \
-H "Authorization: Bearer dp_change-me" \
-H "Content-Type: application/json" \
-d '{"startAt":"2026-10-01T09:30:00.000Z","endAt":"2026-10-01T11:00:00.000Z"}'

The response is 200 OK with the moved block; send locked in the same body to stop the planner moving it again.