A task is a background job Filed runs for a workspace: binder ingestion, tax
prep, tax review, tax advisor, or chat. Mutations like
createClient and
addClientDocuments return a
taskId; you use the tasks API to follow that work to completion.
Tasks are reached through the me query as a WorkspaceUser, so
authenticate with a workspaceToken (see
Authentication ). All requests go to:
https://router.apps.filed.com/graphql
The Task type
type Task {
id : ID !
type : TaskType !
status : TaskStatus !
startedAt : String !
completedAt : String
errorMessage : String
attributes : [ TaskAttribute ! ] !
subTasks : [ SubTask ! ] !
result : TaskResult !
client : ClientShortDetails
triggeredBy : UserShortDetails
}
enum TaskType {
BINDER
TAX_PREP
TAX_REVIEW
TAX_ADVISOR
CHAT
}
enum TaskStatus {
RUNNING
COMPLETED
FAILED
}
The task’s unique identifier. This is the value returned as taskId by the
mutations that start work.
What kind of work this is: BINDER, TAX_PREP, TAX_REVIEW, TAX_ADVISOR, or
CHAT.
RUNNING, COMPLETED, or FAILED. Poll this to know when work finishes.
ISO 8601 timestamp of when the task started.
ISO 8601 timestamp of when the task finished. null while RUNNING.
A human-readable error message when status is FAILED. null otherwise.
Arbitrary name/value metadata pairs describing the task.
The individual stages of the task, each with its own status. Use these for
granular progress while a task is RUNNING.
The typed result of the task, resolved by type. See Task
result .
The client this task belongs to (id, name), when applicable.
The user who started the task (id, name, email).
Supporting types
type TaskAttribute {
name : String !
value : String !
}
type SubTask {
id : ID !
type : SubTaskType !
status : TaskStatus !
startedAt : String !
completedAt : String
errorMessage : String
errorCode : DataEntryErrorCode
}
type ClientShortDetails {
id : ID !
name : String !
}
type UserShortDetails {
id : ID !
name : String !
email : String !
emailHash : String
}
The stage, for example CONVERT_DOCUMENTS, CLASSIFY_SUBDOCS,
EXTRACT_SUBDOCS, or EXPORT_AND_INDEX. The full set of stages depends on the
parent task’s type.
A machine-readable code when a data-entry stage fails, for example
INVALID_CREDENTIALS, CLIENT_NOT_FOUND, or TIMEOUT. null otherwise.
List tasks
Read workspace.tasks to list tasks across the whole workspace. Filter, page,
and sort with the arguments below.
query ListTasks ( $filters : TaskFilters , $sortBy : SortBy , $limit : Int , $offset : Int ) {
me {
... on WorkspaceUser {
workspace {
tasks ( filters : $filters , sortBy : $sortBy , limit : $limit , offset : $offset ) {
id
type
status
startedAt
completedAt
client {
id
name
}
triggeredBy {
id
name
}
}
}
}
}
}
Arguments
input TaskFilters {
type : TaskType
status : TaskStatus
triggeredBy : ID
search : String
}
input SortBy {
field : String !
order : SortByOrder ! # ASC | DESC
}
Return only tasks of this type.
Return only tasks in this status (RUNNING, COMPLETED, FAILED).
Return only tasks started by this user.
Free-text search over task metadata.
Sort order, for example { "field": "startedAt", "order": "DESC" }.
Maximum number of tasks to return.
Number of tasks to skip, for pagination.
curl -X POST https://router.apps.filed.com/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_WORKSPACE_TOKEN" \
-d '{
"query": "query ListTasks($filters: TaskFilters, $sortBy: SortBy, $limit: Int) { me { ... on WorkspaceUser { workspace { tasks(filters: $filters, sortBy: $sortBy, limit: $limit) { id type status startedAt completedAt client { id name } triggeredBy { id name } } } } } }",
"variables": {
"filters": { "type": "BINDER", "status": "RUNNING" },
"sortBy": { "field": "startedAt", "order": "DESC" },
"limit": 20
}
}'
{
"data" : {
"me" : {
"workspace" : {
"tasks" : [
{
"id" : "018f9c2b-1a2b-7c3d-8e4f-5a6b7c8d9e0f" ,
"type" : "BINDER" ,
"status" : "RUNNING" ,
"startedAt" : "2026-07-04T09:15:00.000Z" ,
"completedAt" : null ,
"client" : {
"id" : "018f9c2a-3d5f-7a10-b2c4-9e8d7f6a5b4c" ,
"name" : "Jane Taxpayer"
},
"triggeredBy" : {
"id" : "019f0fb6-26e9-74b7-a842-cb43a2a41682" ,
"name" : "Jane Preparer"
}
}
]
}
}
}
}
Check a single task’s status
There is no task(id:) query. To follow one task (for example the taskId
returned by createClient or addClientDocuments), list the tasks for its
client with client.tasks and read the entry whose id matches. Because a
client’s task list is small and typed, this is the reliable way to poll a
specific task.
query ClientTaskStatus ( $clientId : ID ! , $type : TaskType ) {
me {
... on WorkspaceUser {
workspace {
clients ( filters : { ids : [ $clientId ] }) {
tasks ( type : $type ) {
id
status
startedAt
completedAt
errorMessage
subTasks {
type
status
}
}
}
}
}
}
}
Client.tasks accepts these arguments:
tasks ( type : TaskType , status : TaskStatus , triggeredBy : ID , limit : Int ): [ Task !]!
Narrow to one task type, for example BINDER to watch document ingestion.
Cap the number of tasks returned (for example 1 for the most recent).
curl -X POST https://router.apps.filed.com/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_WORKSPACE_TOKEN" \
-d '{
"query": "query ClientTaskStatus($clientId: ID!, $type: TaskType) { me { ... on WorkspaceUser { workspace { clients(filters: { ids: [$clientId] }) { tasks(type: $type) { id status startedAt completedAt errorMessage subTasks { type status } } } } } } }",
"variables": { "clientId": "018f9c2a-3d5f-7a10-b2c4-9e8d7f6a5b4c", "type": "BINDER" }
}'
{
"data" : {
"me" : {
"workspace" : {
"clients" : [
{
"tasks" : [
{
"id" : "018f9c2b-1a2b-7c3d-8e4f-5a6b7c8d9e0f" ,
"status" : "COMPLETED" ,
"startedAt" : "2026-07-04T09:15:00.000Z" ,
"completedAt" : "2026-07-04T09:17:42.000Z" ,
"errorMessage" : null ,
"subTasks" : [
{ "type" : "CONVERT_DOCUMENTS" , "status" : "COMPLETED" },
{ "type" : "CLASSIFY_SUBDOCS" , "status" : "COMPLETED" },
{ "type" : "EXTRACT_SUBDOCS" , "status" : "COMPLETED" },
{ "type" : "EXPORT_AND_INDEX" , "status" : "COMPLETED" }
]
}
]
}
]
}
}
}
}
Poll on an interval (for example every few seconds) until status is no longer
RUNNING. COMPLETED means the work succeeded; FAILED means it did not, and
errorMessage explains why. subTasks show which stage is currently running.
Task result
Every task carries a typed result. TaskResult is a union whose concrete type
is determined by the task’s type. Select fields with an inline fragment on the
member you expect, and read __typename to know which one you got.
union TaskResult =
TaskUnknownResult
| TaskTaxPrepResult
| TaskTaxReviewResult
| TaskTaxAdvisorResult
The fallback result, including for BINDER and CHAT tasks. type TaskUnknownResult {
message : String !
}
A human-readable description of the outcome.
Returned for TAX_PREP tasks: a summary plus document/form counts and the
individual review items. type TaskTaxPrepResult {
taxYear : Int !
returnType : ReturnType !
summary : String !
documentCount : Int !
extractedFormCount : Int !
reviewItemCount : Int !
reviewItems : [ TaxPrepReviewItem ! ] !
}
type TaxPrepReviewItem {
severity : String !
category : String !
description : String !
}
A summary of the tax prep result.
Number of documents processed.
Number of forms extracted.
Number of review items produced.
The review items. Each has severity, category, and description (all String!).
Returned for TAX_REVIEW tasks: a summary plus issue breakdowns by severity and
by form. type TaskTaxReviewResult {
taxYear : Int !
returnType : ReturnType !
summary : String !
issueCountBySeverity : IssueCountBySeverity !
issueCountByForm : [ FormIssueCount ! ] !
}
type IssueCountBySeverity {
critical : Int !
high : Int !
medium : Int !
low : Int !
}
type FormIssueCount {
form : String !
count : Int !
}
A summary of the review result.
Issue counts by severity: critical, high, medium, low (all Int!).
Issue counts per form, each { form: String!, count: Int! }.
Returned for TAX_ADVISOR tasks: a summary plus strategy counts. The by*
fields are JSON maps. type TaskTaxAdvisorResult {
taxYear : Int !
returnType : ReturnType !
summary : String !
strategyTotal : Int !
byDomain : JSON !
bySavingsHorizon : JSON !
estimatedSavingsCentsByHorizon : JSON !
}
A summary of the advisor result.
Total number of strategies.
Strategy counts keyed by domain.
Strategy counts keyed by savings horizon.
estimatedSavingsCentsByHorizon
Estimated savings (in cents) keyed by horizon.
Because the members share taxYear, returnType, and summary, you can select
those on each fragment and branch on __typename:
query TaskResult ( $clientId : ID ! ) {
me {
... on WorkspaceUser {
workspace {
clients ( filters : { ids : [ $clientId ] }) {
tasks ( type : TAX_PREP , limit : 1 ) {
id
status
result {
__typename
... on TaskTaxPrepResult {
summary
documentCount
extractedFormCount
reviewItems {
severity
category
description
}
}
... on TaskTaxReviewResult {
summary
issueCountBySeverity {
critical
high
medium
low
}
issueCountByForm {
form
count
}
}
... on TaskUnknownResult {
message
}
}
}
}
}
}
}
}