Concepts and the task model
Task management is in preview and available in the v1alpha2 API. Requests, responses, and activity-log payloads described in this guide may change without notice.
Task management exposes the same review-task capability that Thirdfort portal users have today: a queue of work items attached to checks, and the ability to request, reassign, cancel, and resolve a review. This page defines the resource model, the automations that create and retire tasks, and the delegation model that lets an integration act for a named user.
The ManualTask resource
A ManualTask is a discrete unit of work attached to a check. Most task types are created and completed internally by Thirdfort's own workflows (document review, income verification, Onfido report validation, and so on). This guide, and the API surface it documents, concerns the one task type integrators can create and resolve directly: REVIEW.
A review task represents a human decision on a check: approve or reject, based on the findings the check has produced. Everything else in this guide — the queue, the workflow, the notifications — is built around that one task type.
task_type is a plain string field, not a proto enum. Thirdfort may introduce new internal task types without a schema change. Treat unrecognised values as opaque and continue processing rather than rejecting them; if you only want reviews, filter on task_type = "REVIEW" (see Building a task queue).
Status lifecycle
A ManualTask moves through a fixed sequence of statuses:
| Status | Meaning |
|---|---|
PENDING | The task exists and may or may not have an assignee. |
IN_PROGRESS | The task has an assignee and is being worked on. |
COMPLETED | The task was resolved with a decision. Terminal. |
CANCELLED | The task is no longer required. Terminal. |
For review tasks specifically, the transition from PENDING to IN_PROGRESS happens automatically the first time an assignee is set — the server advances the status; callers do not send it (see The review workflow). From IN_PROGRESS, a review task ends in COMPLETED (a decision was recorded) or CANCELLED (the review is no longer needed).
How review tasks come into being
The source field records how a task was created and never changes thereafter:
| Source | Meaning |
|---|---|
MANUAL | Created explicitly by a user or integration, via CreateManualTask. |
AUTO_CONSIDER | Auto-spawned when a check's initial recommendation lands as anything other than CLEAR. |
AUTO_OM_HIT | Auto-spawned when an ongoing-monitoring hit drives a fresh CONSIDER re-evaluation on a check that already completed. |
AUTO_WAITING | Auto-spawned at check creation as an "in progress" placeholder while the check awaits consumer action. Paired with task_type = "WAITING". |
Three automations follow from this:
- Auto-review on non-clear completion. When a check's initial recommendation is not
CLEAR, the server opens aREVIEWtask (sourceAUTO_CONSIDER) so a human decides whether to approve or reject. Source of Funds checks always receive a review task on completion, regardless of recommendation, given the judgement Source of Funds decisions require. - Ongoing-monitoring hit: cancel and respawn. If ongoing monitoring produces a new hit on a check that already has a resolved review, the server cancels the settled state and opens a fresh
REVIEWtask (sourceAUTO_OM_HIT), so the new finding gets its own decision rather than silently attaching to the old one. - The
WAITINGplaceholder. Every check gets aWAITING-type task at creation, assigned to the check's creator, so it appears on that user's "in progress" view while the consumer completes their side of the check. The server cancels it automatically once the check reachesINACTIVE.
Invariants
- One active review per check. A check can have at most one
REVIEWtask inPENDINGorIN_PROGRESSstatus at a time.CreateManualTaskrejects a second request while one is outstanding. - The check must be
INACTIVEto request a review. Reviews are opened once a check has finished its current processing cycle and produced a recommendation, not while it is stillACTIVE. - Optimistic concurrency via
etag.CompleteManualTaskandCancelManualTaskrequire the task's currentetag. A stale value fails withABORTED, meaning the task changed since you last read it — re-fetch and retry. task_typeis a string, not an enum. See above — tolerate values you do not recognise.
Entitlement
Review tasks are gated behind the Task Management feature set (REVIEW_TASKS feature). This is arranged with Thirdfort as part of your account setup, not something you enable yourself. If your organisation or team does not have it, task-management calls fail — contact api-support@thirdfort.com to have it configured.
Check status and review progress
Check.composite_status folds the check's state, its recommendation, and any outstanding review into a single at-a-glance status. Callers should prefer it to the raw state field when rendering check status, and can filter ListChecks on it.
| Value | Meaning |
|---|---|
SENT_TO_CONSUMER | Waiting for the consumer to start their journey. Not currently emitted. |
IN_PROGRESS | The check is actively processing. |
PROCESSING | The consumer has finished; backend orchestration is finalising the result. Not currently emitted. |
COMPLETE | Processing finished with a CLEAR recommendation and no review task. |
READY_FOR_REVIEW | Processing finished with a non-CLEAR recommendation, but no review task has been opened yet. |
REVIEW_REQUESTED | A review task is outstanding (PENDING or IN_PROGRESS). |
REVIEW_APPROVED | The latest non-cancelled review task completed with an APPROVED decision. |
REVIEW_REJECTED | The latest non-cancelled review task completed with a REJECTED decision. |
CANCELLED | The check has been cancelled. |
REVIEW_REQUESTED wins over the underlying recommendation: a pending review takes precedence over a CLEAR recommendation, because the reviewer may still be looking at supplementary context.
The delegation model
Everything above describes review tasks as portal users see them. Integrations interact with the same tasks, but as a distinct actor: the integration is always the caller that authenticates and makes the request, and an on_behalf_of field on the write RPCs (CreateManualTask, UpdateManualTask, CompleteManualTask, CancelManualTask) names the human the request is made for.
The named user is recorded exactly where a direct action by that user would have been recorded: a delegated creation records them as the task's creator_name, a delegated assignment records them as the task's requester_name, and a delegated completion is attributed to them as the completer (completed_by, always the assignee). The task read out of the API is therefore indistinguishable from one produced by the same user acting in the portal. The integration itself appears as the actor on the corresponding activity-log events, so the audit trail preserves both who acted and who decided.
What Thirdfort validates about the named user:
- They are a real, non-deleted
Userin the same organisation as the check. - They are active.
- They are reviewer-eligible — they hold the permission to complete review tasks on the team.
- For completion specifically, they are the task's current assignee — delegated completion cannot resolve a task assigned to someone else.
What Thirdfort does not validate, and what you are asserting by setting on_behalf_of: that the named person actually made the decision. Thirdfort has no independent way to confirm that a human in your system approved or rejected the check — it trusts the integration's attestation. Treat on_behalf_of as a compliance-significant field: set it only when you can stand behind the claim that the named user made the call.
See The review workflow for the exact request shape and error behaviour, and Observing outcomes for how delegated actions appear in reads, notifications, and the activity log.