Query Language
Instance search uses MongoDB Query Language (MQL) syntax for filters. The $operator convention is familiar, and fields map directly to your process variables. Stateway translates your filter into safe, parameterized PostgreSQL — MongoDB is not involved.
Request body
{
"definitionKey": "loan-application",
"statusScope": "active",
"filter": { "variables.loan_status": "in_review" },
"sort": { "startedAt": -1 },
"page": { "limit": 50, "cursor": null },
"projection": { "variables.loan_status": 1, "variables.amount": 1 }
}
| Field | Required | Description |
|---|---|---|
definitionKey | No | Restrict to one process definition. Absent = all definitions |
definitionVersion | No | latest (default), all, or a specific version number |
statusScope | No | active (default), completed, all, or explicit list. See Status Scope |
filter | No | MQL filter (see below) |
text | No | Text search. See Text Search |
sort | No | { "field": 1 } ascending, { "field": -1 } descending. Default: { "startedAt": -1 } |
page | No | Cursor-based pagination. See Pagination |
projection | No | Which variable fields to include ({ "variables.field": 1 }). Default: all |
Field addressing
| Prefix | What it targets | Examples |
|---|---|---|
variables.<path> | Process variable (dot notation for nested fields) | variables.loan_status, variables.applicant.email |
| Bare name | Instance metadata column | startedAt, endedAt, status, correlationId |
Filter syntax
Equality (implicit)
{ "variables.loan_status": "in_review" }
Root-level fields are implicitly ANDed:
{
"variables.loan_status": "in_review",
"variables.amount": { "$gte": 50000 }
}
Comparison operators
{ "variables.amount": { "$gt": 10000, "$lte": 100000 } }
| Operator | Meaning | Value types |
|---|---|---|
$eq | Equal (explicit form) | any |
$ne | Not equal | any |
$gt | Greater than | number, date (ISO 8601) |
$gte | Greater than or equal | number, date |
$lt | Less than | number, date |
$lte | Less than or equal | number, date |
List operators
{ "variables.applicant.region": { "$in": ["SP", "RJ", "MG"] } }
| Operator | Meaning |
|---|---|
$in | Value is in the list |
$nin | Value is not in the list |
Existence check
{ "variables.flagged": { "$exists": true } }
Returns instances where the variable key exists (true) or does not exist (false).
String matching
{ "variables.applicant.email": { "$regex": "@company\\.com$", "$options": "i" } }
$options: "i" enables case-insensitive matching.
Boolean logic
{
"$or": [
{ "variables.applicant.region": "SP" },
{ "variables.applicant.region": "RJ" }
]
}
| Operator | Meaning |
|---|---|
$and | All conditions must match (also implicit at root level) |
$or | At least one condition must match |
$nor | None of the conditions match |
$not | Negation of a sub-condition |
Operators can be nested up to 10 levels deep:
{
"$and": [
{ "variables.loan_status": "in_review" },
{ "$or": [
{ "variables.amount": { "$gte": 50000 } },
{ "variables.priority": "high" }
]}
]
}
Unsupported operators
The following operators return 400:
| Operator | Reason |
|---|---|
$elemMatch, $all, $size | Array-specific, not applicable to JSONB |
$type, $mod | Not supported |
$where | Never supported — executes arbitrary JavaScript |
Limits
| Limit | Value |
|---|---|
| Filter nesting depth | 10 levels |
| Conditions per query | 50 |
| Page size maximum | 200 |
| Query timeout | 5 seconds |
All limits return 400 with a descriptive message when exceeded.