open → claimed → done | dismissed and back. Every route takes the task id (a UUID) in the path and returns the task in data, in the shape shown on Get Task. The verbs are all POST and answer 200.
Every write needs task-write access in the task’s workspace (an internal member who is not a viewer, or an external editor; internal tasks need internal membership). Every change increments the task’s revision. Every route except touch takes why in its body: one sentence on what the person is trying to accomplish, in their terms (not a description of the edit). An agent call without it is 400 WHY_REQUIRED. See Why on every write.
Auth: Authorization: Bearer tr_...
Every transition is a single conditional update. The guard is in the
WHERE clause and the row count is the verdict, so two harnesses racing for one task resolve at the database. You never have to check, then act: call the verb and branch on the error.PATCH /v0/tasks/{id}
Edit a task’s text, suggested assignee or audience. kind, payload and due are fixed at creation.
Changing the audience drops a suggested assignee who can no longer work the task, and releases a claim whose holder can no longer see it (the task returns to
open).
rip task update <id> --expected-revision 3 --audience shared.
POST /v0/tasks/{id}/claim
Take the task and hold a lease. Re-claiming your own extends it.
Succeeds when the task is
open, when you already hold it, or when someone else’s lease has lapsed (a takeover). The response carries the resolved leaseExpiresAt; advertise that, not the value you asked for.
rip task claim <id> --lease-hours 4.
POST /v0/tasks/{id}/touch
Extend the lease you hold. It can only move the expiry forward, so a deliberately long lease survives a shorter touch.
CLI:
rip task touch <id>.
POST /v0/tasks/{id}/release
Give the claim back. The task returns to open. A workspace admin may release anyone’s claim; everyone else may only release their own.
CLI: rip task release <id>.
POST /v0/tasks/{id}/complete
Close the task and attach what it produced. The task must be claimed by you, with a live lease.
rip task done <id> --result artifact:b7e1c9a2-3f4d-4e5a-8b6c-7d8e9f0a1b2c@2.
The response includes the task’s results.
POST /v0/tasks/{id}/dismiss
Close the task without doing it. Works on an open or claimed task and clears any claim in the same statement.
CLI:
rip task dismiss <id> --reason "Duplicate".
POST /v0/tasks/{id}/reopen
Bring a done or dismissed task back to open. It clears the claim, completion and dismissal fields but keeps the results: status is the truth, not the result set.
CLI: rip task reopen <id>.
Errors on every route
Leases lapse on their own
A sweep runs every minute and returns any task whose lease has expired toopen, attributed to the platform rather than to a person. A lapsed lease is not a failure: it means the work is available again.
Operator mirror
Every route has a mirror under/v0/operator/tasks/{id} with the same body and guards, using an operator session that acts as the bound account. Claims through it record claimedVia: "dashboard" unless the X-Tokenrip-Surface header names the caller.