Skip to main content

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:

StatusMeaning
PENDINGThe task exists and may or may not have an assignee.
IN_PROGRESSThe task has an assignee and is being worked on.
COMPLETEDThe task was resolved with a decision. Terminal.
CANCELLEDThe 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:

SourceMeaning
MANUALCreated explicitly by a user or integration, via CreateManualTask.
AUTO_CONSIDERAuto-spawned when a check's initial recommendation lands as anything other than CLEAR.
AUTO_OM_HITAuto-spawned when an ongoing-monitoring hit drives a fresh CONSIDER re-evaluation on a check that already completed.
AUTO_WAITINGAuto-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 a REVIEW task (source AUTO_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 REVIEW task (source AUTO_OM_HIT), so the new finding gets its own decision rather than silently attaching to the old one.
  • The WAITING placeholder. Every check gets a WAITING-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 reaches INACTIVE.

Invariants

  • One active review per check. A check can have at most one REVIEW task in PENDING or IN_PROGRESS status at a time. CreateManualTask rejects a second request while one is outstanding.
  • The check must be INACTIVE to request a review. Reviews are opened once a check has finished its current processing cycle and produced a recommendation, not while it is still ACTIVE.
  • Optimistic concurrency via etag. CompleteManualTask and CancelManualTask require the task's current etag. A stale value fails with ABORTED, meaning the task changed since you last read it — re-fetch and retry.
  • task_type is 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.

ValueMeaning
SENT_TO_CONSUMERWaiting for the consumer to start their journey. Not currently emitted.
IN_PROGRESSThe check is actively processing.
PROCESSINGThe consumer has finished; backend orchestration is finalising the result. Not currently emitted.
COMPLETEProcessing finished with a CLEAR recommendation and no review task.
READY_FOR_REVIEWProcessing finished with a non-CLEAR recommendation, but no review task has been opened yet.
REVIEW_REQUESTEDA review task is outstanding (PENDING or IN_PROGRESS).
REVIEW_APPROVEDThe latest non-cancelled review task completed with an APPROVED decision.
REVIEW_REJECTEDThe latest non-cancelled review task completed with a REJECTED decision.
CANCELLEDThe 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 User in 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.