Filtering tasks
GET /public/v1/tasks returns every task in the scope (the same set as the project’s table view in the web app) and narrows it down with query-parameter filters. This page shows how the filters combine and gives copy-paste recipes for common queries.
All examples assume:
BASE="https://api.bordio.com/public/v1"AUTH='Authorization: Bearer brd_sk_live_...'PROJECT="proj_6594a1b2c3d4e5f6a7b8c9d1"How filters combine
Section titled “How filters combine”- Different parameters → AND. Every parameter you add narrows the result.
- Multiple values in one parameter → OR. Values are comma-separated:
priority=high,criticalmatches either. - Parameters you omit don’t restrict anything — no filters means all tasks.
| Parameter | Values | Notes |
|---|---|---|
priority |
CSV of lowest, low, medium, high, critical and/or none |
none = tasks with no priority set |
task_status_id |
CSV of task_status_… ids |
Get ids from Definitions |
state |
open | closed |
Groups statuses by their state — no need to enumerate them. With view=by_task it means “is there work to do” |
task_type_id |
CSV of task_type_… ids |
|
assignee_id |
CSV of user_… ids and/or none |
none = tasks with no assignee |
date_from |
YYYY-MM-DD or ISO-8601 datetime |
Inclusive lower bound on the day the task is scheduled for — the date field, not the deadline |
date_to |
YYYY-MM-DD or ISO-8601 datetime |
Inclusive upper bound on the same day. Setting either bound orders the list by date, oldest first |
due_date_from |
YYYY-MM-DD or ISO-8601 datetime |
Inclusive lower bound of the due-date range |
due_date_to |
YYYY-MM-DD or ISO-8601 datetime |
Inclusive upper bound of the due-date range |
due_date |
none |
Only tasks without a due date; incompatible with the range bounds |
tag_id |
CSV of tag_… ids |
Matches tasks that have any of the tags |
view |
by_task | by_date |
Changes what counts as one record — see Repeating tasks in a listing |
closed_since |
YYYY-MM-DD or ISO-8601 datetime |
Only tasks completed at or after this moment, most recently completed first |
Recipes
Section titled “Recipes”Unassigned tasks only
Section titled “Unassigned tasks only”The special value none matches tasks that have no assignee:
curl "$BASE/tasks?project_id=$PROJECT&assignee_id=none" -H "$AUTH"Tasks assigned to a specific person — or to nobody
Section titled “Tasks assigned to a specific person — or to nobody”none can be mixed with user ids in the same CSV; within one parameter the values are OR-ed:
curl "$BASE/tasks?project_id=$PROJECT&assignee_id=user_6594a1b2c3d4e5f6a7b8c9d1,none" -H "$AUTH"Tasks with no priority — or low priority
Section titled “Tasks with no priority — or low priority”Priority is optional, so priority accepts the special value none for tasks where it isn’t set. Like every CSV value it OR-s with the rest — “no priority or low” is one parameter:
curl "$BASE/tasks?project_id=$PROJECT&priority=none,low" -H "$AUTH"Open tasks with high or critical priority
Section titled “Open tasks with high or critical priority”curl "$BASE/tasks?project_id=$PROJECT&state=open&priority=high,critical" -H "$AUTH"state is the easiest way to split open vs closed work. If you need specific statuses (“In progress” but not “New”), use task_status_id with ids from the definitions endpoints.
Tasks due in July
Section titled “Tasks due in July”Both bounds are inclusive; date-only values expand to the start / end of that day (UTC):
curl "$BASE/tasks?project_id=$PROJECT&due_date_from=2026-07-01&due_date_to=2026-07-31" -H "$AUTH"You can also pass just one bound — for example, everything due from today onward (due_date_from alone), or an “overdue” view — open tasks whose deadline has already passed:
curl "$BASE/tasks?project_id=$PROJECT&state=open&due_date_to=2026-07-17" -H "$AUTH"Tasks with no due date
Section titled “Tasks with no due date”A range can never match a task that has no due date, so this is a separate filter:
curl "$BASE/tasks?project_id=$PROJECT&due_date=none" -H "$AUTH"Tasks carrying any of the given tags
Section titled “Tasks carrying any of the given tags”curl "$BASE/tasks?project_id=$PROJECT&tag_id=tag_65dcc9c66f2e4e001ab18859,tag_66446ff2dc01cb59f6cbf7a6" -H "$AUTH"Everything combined
Section titled “Everything combined”Open, high-priority, assigned to nobody, due this month:
curl "$BASE/tasks?project_id=$PROJECT&state=open&priority=high&assignee_id=none&due_date_from=2026-07-01&due_date_to=2026-07-31" -H "$AUTH"Filters compose with pagination as usual — limit and cursor apply to the filtered result (see Conventions).
Repeating tasks in a listing
Section titled “Repeating tasks in a listing”By default a listing returns your one-off tasks plus the individual occurrences of repeating tasks that already exist — the ones somebody edited, completed or rescheduled. One repeating task can therefore appear as several rows, and an occurrence nobody has touched yet does not appear at all.
Pass view=by_task to list tasks instead: a repeating task comes back as a single row carrying its rule and the occurrence to work on next, and its occurrences are not listed separately.
curl "$BASE/tasks?project_id=$PROJECT&view=by_task" -H "$AUTH"The response gains kind, series_id, series_chain_id, recurrence_summary and current_occurrence; see Recurring tasks. Without view the set of records is unchanged, so existing integrations keep working — but new ones should pass it explicitly.
What happens in a period
Section titled “What happens in a period”Pass view=by_date with a date range to list occurrences: every day a repeating task falls on is its own row, next to the one-off tasks scheduled in those days.
curl "$BASE/tasks?project_id=$PROJECT&view=by_date&date_from=2026-09-01&date_to=2026-09-30" -H "$AUTH"The range is required here and cannot exceed 31 days, results run from the start of the range, and closed_since cannot be combined with it (400). Details and the full list of rules: Listing occurrences day by day.
What to work on now
Section titled “What to work on now”curl "$BASE/tasks?project_id=$PROJECT&view=by_task&state=open" -H "$AUTH"In this view state answers “is there work to do”: a one-off task by its own status, a repeating task by its occurrences — open while one is still open, closed once none are left. A repeating task whose occurrences have run out drops out of the list even though the status it starts occurrences in is a perfectly normal “To do”.
What was completed recently
Section titled “What was completed recently”curl "$BASE/tasks?project_id=$PROJECT&closed_since=2026-07-28" -H "$AUTH"Completed work is a different question, so it is a different request. Each completed occurrence is its own record — that is what “we did the standup on Tuesday” means — so this listing is not combined with view=by_task; doing so returns 400 validation_error. Results are ordered by completion time, most recent first, and paginate like any other listing.
closed_since also rejects state=open with 400 for the same reason it rejects view=by_task: the request contradicts itself, and an empty page would read as “nothing was completed” rather than “you asked for something impossible”.
due_date_from / due_date_to / due_date — why three parameters?
Section titled “due_date_from / due_date_to / due_date — why three parameters?”They answer two different questions:
due_date_from/due_date_toselect tasks whose due date falls into a range. Use either bound alone or both together.due_date=noneselects tasks that have no due date at all. No range can express “the field is empty”, which is why it’s a separate parameter rather than a magic range value.
Because “has no due date” and “due date within a range” are mutually exclusive, combining due_date=none with either bound returns 400 validation_error.
What errors to expect
Section titled “What errors to expect”- A malformed value (unknown priority, bad id format, non-date) →
400 validation_error. - A well-formed id that matches nothing (foreign workspace’s tag, deleted status) → not an error: it simply matches no tasks, so you get an empty page.
- The exception is
project_id: a project outside your key’s scope →404 not_found_error.