Answer the decision request named by the `requestId` query parameter
PATCH/api/projects/:id/tasks/:taskId/decision-request
Answer the decision request named by the requestId query parameter. Exactly one of chosenOptionIndex (an in-range index into the request's own options) or a non-empty free-text answer must be given — the effective answer is the chosen option's label, or the free text. Addressing by explicit id (not "the task's latest request") keeps a stale retry idempotent: it resolves the exact request it named and can never hit a newer one that opened since. Open-guarded: answering an already-terminal request is a no-op that returns the existing (resolved) row rather than erroring. Requires tasks.update.any. Records one auditCritical entry (metadata only — never the answer body) on the transition that actually resolves it.
Request
Responses
- 200
- 400
- 401
- 403
- 404
Successful response
Bad Request — a missing/malformed requestId, a malformed body, chosenOptionIndex is out of range for this request's options, or the task has since become complete — answering is then REFUSED and the request is left as it is. Closing it as cancelled is the completion path's job, not this endpoint's, and on the three best-effort paths that close post-commit it may not have run at all, so the row can still read open here.
Unauthorized — no authenticated user.
Forbidden — the caller cannot read this project, lacks 'tasks.update.any', or the tenant wrapper rejected the request (an x-act-as-org override the caller is not an active member of, or no valid tenant context).
Task not found in this project, or no decision request with that requestId exists for this task.