Appearance
GraphQL API Definition
The following document outlines the AireFlow GraphQL API, available at /api/graphql/v2.
Tasks
The tasks query can be used to read all instantiated tasks. There are currently no mutations available via GraphQL and any changes will need to be made via the REST API.
Query Structure
The following properties can be retrieved via the GraphQL API
query {
tasks {
nodes {
id
taskKey
name
description
taskType
subjectId
correlationId
assigneeId
assigneeType
canSetAssignee
owner
ownerType
workflowDefinitionVersion
workflowDefinitionId
workflowDefinitionKey
filters
context
created
updated
lastRun
activityContext {
status
...on ManualActivityContext {
due
}
...on EmailActivityContext {
to
subject
body
retryCount
}
...on HttpActivityContext {
url
body
contentType
headers
retryCount
}
...on AireFrameCreateFormActivityContext {
key
version
subjectId
userId
retryCount
}
...on PublishEventActivityContext {
eventKey
retryCount
}
...on FormActivityContext {
key
version
instanceId
due
}
}
state {
key
value
}
transitions {
from
to
description
}
}
# pageCount and itemCount count every matching task, which can be slow on large
# result sets. Only select them when absolutely necessary. Not available with cursorPaging.
pageCount
itemCount
# Only available when using cursor paging
pageInfo {
hasNextPage
endCursor
}
}
}Filtering
The filter parameter is used as follows. Each item in the filter array must be true for a task to be included in the result:
query {
tasks (
filter:[{
property: "activityContext.status"
condition: EQ
value: ["New", "InProgress"]
},
{
property: "assigneeId"
condition: EQ
value: "1"
},
{
property: "assigneeType"
condition: EQ
value: "Subject"
},
{
property: "state[comments]"
condition: INCLUDES
value: "Some Comment"
}
]) {
...
}
}Where property is the name of the property to filter, condition defines what type of filter is applied and value is the value the condition is checked against. The value can be a string or an array of strings (in some cases). In the above example, the status must be either new or in progress, the assigneeId must be 1 and there is a state item called "comments" who's value includes the substring "Some Comment".
In order to access a nested property, separate them using a '.' as above.
For dictionaries, use {property}.key to filter on the keys, use {property}[{key name}] to filter on the value of a specific key.
Types of Filter
Each property type has a subset of valid conditions listed here.
| Property Type | Valid Conditions | Accepts Array Value | True When |
|---|---|---|---|
| string | EQ | True | Property value equals one of the input values (Case-Sensitive) |
| NOT | True | Property value does not equal one of the input values (Case-Sensitive) | |
| INCLUDES | True | One of the input values is a substring of the property value (Case-Sensitive) | |
| DateTime | LT | False | Property value is before than the input value |
| GT | False | Property value is after the input value | |
| Int | EQ | False | Property value is equal to the input value |
| GT | False | Property value is greater than the input value | |
| LT | False | Property value is less than the input value | |
| List | AnyEq | False | Property list contains the input value |
| NoneEq | False | Property list does not contain the input value | |
| Enum | EQ | True | Property value equals one of the input values |
| NOT | True | Property value does not equal one of the input values | |
| INCLUDES | True | One of the input values is a substring of the property value | |
| Dictionary Key | AnyEq | True | Input value is a key in the dictionary |
| NoneEq | True | Input value is not a key in the dictionary | |
| Dictionary Value | EQ | True | Property value equals one of the input values (Case-Sensitive) |
| NOT | True | Property value does not equal one of the input values (Case-Sensitive) | |
| INCLUDES | True | One of the input values is a substring of the property value (Case-Sensitive) |
Sorting
The sorting parameter is used as follows. The direction is either ASCENDING or DESCENDING.
query {
tasks (
sort: {
property: "activityContext.due"
direction: ASCENDING
}
) {
...
}
}Paging
Two types of paging are supported: cursor paging and offset paging. Cursor paging is recommended where possible. Only one of cursorPaging and paging may be supplied in a query.
Cursor Paging
Cursor (keyset) paging returns results that stay consistent while tasks are being created or updated, and it performs better on large result sets than offset paging. Use the cursorPaging parameter as follows:
query {
tasks (
sort: {
property: "updated"
direction: DESCENDING
}
cursorPaging: {
first: 50
}
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
...
}
}
}Where first is the number of tasks to return (between 1 and 1000) and after is an optional cursor to start from. To get the next page, pass the endCursor from the previous response as after, with the same filter and sort:
query {
tasks (
sort: {
property: "updated"
direction: DESCENDING
}
cursorPaging: {
first: 50
after: "<endCursor from the previous page>"
}
) {
...
}
}Continue until hasNextPage is false. If a page contains no tasks, endCursor is null.
Cursor paging has the following restrictions:
- The sort property must be
createdorupdated. If no sort is supplied, tasks are sorted bycreated, descending. pageCountanditemCountcannot be selected, because cursor paging never counts the full result set. Use offset paging if you absolutely must have a total (but be aware that performance will be poor for large data sets).- A cursor only works with the filter and sort it was returned for. If you change the filter or sort, start again from the first page without an
aftervalue. - Treat cursors as opaque strings. Don't construct or modify them.
Offset Paging
Offset paging is still supported for backwards compatibility. Use the paging parameter as follows:
query {
tasks (
paging: {
pageNumber: 1,
pageSize: 50
}
) {
...
}
}pageCount and itemCount are only available with offset paging. pageInfo is only populated when cursorPaging is used.
Selecting pageCount or itemCount makes AireFlow count every task that matches the filter, which can be slow when there are a lot of tasks. The count only runs if one of these fields is selected, so leave them out unless you need a total.