API
Create and update tasks from your own tools, from an AI agent reading a Slack thread, or while moving off another tracker. Plain REST over HTTPS - no SDK, nothing to install.
curl -s https://app.taskbite.rocks/api/v1/me \
-H "Authorization: Bearer $TASKBITE_TOKEN" \
-H "Accept: application/json"
Authentication
A bearer token, created in Settings → API tokens inside your workspace. It is shown once; only a hash is stored, so a leaked token can be revoked but never recovered.
Authorization: Bearer 7|xxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/json
What a token can do
A token belongs to a person, not to the workspace, and carries exactly that person's permissions. There is no master key with rights of its own:
- it only ever sees its own workspace;
- a token made by a Member reaches only the projects that Member was added to;
- creating a client is owner-only through the API, the same as in the app;
- your plan's client limit still applies.
To give an integration narrower access, add a Member, put them on just the projects it should touch, and make the token as them.
Endpoints
Base URL: https://app.taskbite.rocks/api/v1
| Endpoint | What it does |
|---|---|
| GET /me | The token's user, workspace, and the exact status and priority strings this workspace uses |
| GET /clients | q, with_projects, per_page |
| POST /clients | Owner only |
| GET /projects | client_id, status, q |
| POST /projects | |
| GET /tasks | project_id, status, assignee_id, q, updated_since |
| POST /tasks | |
| GET /tasks/{id} | |
| PATCH /tasks/{id} | Send only the fields that changed |
| POST /tasks/{id}/comments | Internal by default - see below |
Lists are paginated (per_page, max 100) and return data, links, meta.
Statuses and priorities
Read these from /me rather than hard-coding them.
Statuses are todo, doing,
qa, review,
bug, done - note that
"in progress" is spelled doing and "completed" is
done. Priorities are low,
normal, high,
urgent.
Creating a task
curl -s -X POST https://app.taskbite.rocks/api/v1/tasks \
-H "Authorization: Bearer $TASKBITE_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"project_id": 31,
"title": "Fix the double-charge on annual upgrade",
"description": "<p>From #support, 12 Mar.</p>",
"status": "todo",
"priority": "high",
"assignee_email": "sam@studio.com",
"due_date": "2026-03-20",
"estimate_minutes": 120
}'
Only project_id and title are
required. An assignee_email matching nobody leaves the
task unassigned rather than failing - an import shouldn't stop because one
person left the company.
Two field names differ from the app on purpose.
estimate_minutes is minutes, because the form takes
hours and a field called "estimate" would get sent 2
when it meant 120. And visible_to_client defaults to
false - a task filed by a machine is yours until you
say otherwise.
Comments are internal by default
The opposite of the app's composer, and deliberate: an agent summarising a
thread must not email your client because nobody thought about the default.
Pass "internal": false to deliver it normally.
curl -s -X POST https://app.taskbite.rocks/api/v1/tasks/99/comments \
-H "Authorization: Bearer $TASKBITE_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"body": "<p>Agreed to ship behind a flag first.</p>"}'
Moving off another tracker
For a one-off migration you do not need this API at all - there is a visual importer in Settings → Import. Upload a CSV export, point each column at a field, preview exactly what it would create, then run it. It reads ClickUp, ActiveCollab, Trello and Asana exports without being told which is which.
Through the API, send external_source and that
system's own id as external_ref. TaskBite matches on
the pair, so running the same import twice updates instead of
duplicating - a half-finished migration is safe to simply run again.
# The client, then its project, then the tasks - each referring
# to the one above by the OTHER system's id, so you never have to
# hold a map of TaskBite ids while importing.
POST /clients {"name":"Northwind","external_source":"clickup",
"external_ref":"space_9001"}
POST /projects {"name":"Rebuild","client_external_ref":"space_9001",
"external_source":"clickup","external_ref":"list_4410"}
POST /tasks {"title":"Migrate the blog","project_external_ref":"list_4410",
"external_source":"clickup","external_ref":"task_77123"}
Every write returns meta.created:
true for a new record, false
when an existing one was matched and updated.
Errors
Always JSON.
| Code | Meaning |
|---|---|
| 401 | Token missing, malformed, or revoked |
| 403 | The token's owner lacks the role - a Member creating a client, say |
| 404 | Not in this workspace, or in a project this person can't see |
| 422 | Validation. The body names the field |
404 not distinguishing "doesn't exist" from "not yours" is deliberate - telling them apart would confirm that some other workspace holds that id.
{
"message": "No project of yours matches that.",
"errors": { "project_id": ["No project of yours matches that."] }
}
Get a token
Start free, then open Settings → API tokens. Free workspaces get the API too.