Shape your requests
Pagination, filtering, sorting, and field selection on MindCloud API list endpoints.
Every list endpoint shares one query grammar: workflows, workflow runs, run operations, connections, members, roles, companies, environments, API keys, child organizations, Universal API app and action discovery, and Embedded end-user connections. Learn it once and it applies to all of them.
Some endpoints add parameters of their own, and their pages say so:
- Universal API app discovery also takes
qandactionQ; action discovery takesversion,q,verbosity, andincludeArguments. - Universal API lookups page the provider's choices with
limit1 to 200 (default 50) andoffset. - Workflow versions, run steps, and the usage endpoints return their full result without pagination.
Pagination
Use limit and offset. limit defaults to 100 and accepts 1 to 1000; offset starts at 0. A value outside those ranges returns 400. The response meta.pagination describes where you are:
{
"meta": {
"pagination": { "totalCount": 312, "totalCountExact": true, "hasNextPage": true, "hasPreviousPage": true }
}
}Page with hasNextPage. totalCount is for display: counting stops at 10,000 rows, and past that totalCount reads 10000 with totalCountExact set to false.
curl "https://connect.mindcloud.co/v2/workflows/Wq3kZ8pLx2Nb/runs?limit=50&offset=100" \
-H "Authorization: Bearer $MINDCLOUD_API_KEY"Lists have a stable default order, with the resource id breaking ties, so pages stay consistent without passing sort.
Sorting
Pass sort with one or more comma-separated fields. Prefix a field with - for descending:
curl "https://connect.mindcloud.co/v2/workflows/Wq3kZ8pLx2Nb/runs?sort=-startedOn" \
-H "Authorization: Bearer $MINDCLOUD_API_KEY"Field selection
Pass fields to receive only the columns you need. id is always included:
curl "https://connect.mindcloud.co/v2/workflows?fields=id,name,isActive" \
-H "Authorization: Bearer $MINDCLOUD_API_KEY"Filtering
Any exposed field filters with plain equality or a bracket operator:
# Equality
curl "https://connect.mindcloud.co/v2/workflows/Wq3kZ8pLx2Nb/runs?status=failed" \
-H "Authorization: Bearer $MINDCLOUD_API_KEY"
# Operators
curl "https://connect.mindcloud.co/v2/workflows/Wq3kZ8pLx2Nb/runs?startedOn[gte]=2026-07-01&status[in]=failed,interrupted" \
-H "Authorization: Bearer $MINDCLOUD_API_KEY"| Operator | Meaning |
|---|---|
eq | Equals (same as no operator) |
ne | Not equal |
gt, gte | Greater than, greater or equal |
lt, lte | Less than, less or equal |
contains | Substring match |
starts, ends | Prefix or suffix match |
in, nin | In or not in a comma-separated list |
contains, starts, ends, and =like= are case-insensitive and treat % and _ as plain characters; * is the one wildcard (name[contains]=sync*v2). They apply to text fields only.
Date fields take a date (2026-10-01 or 10/01/2026) or a timestamp (2026-10-01T12:00:00Z), in UTC.
Use only the field names listed on each endpoint's page. A filter, sort, fields entry, or where comparison on a name the endpoint does not expose returns 400 naming the accepted names, and so does a value the field cannot hold, like a date that does not exist. For GET /v2/connections?stauts=valid:
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "Cannot filter on \"stauts\". Filterable fields: id, appId, status, isCompany, endUserId, installationId, userId, testedOn, expiresOn, authenticatedOn, createdOn, createdBy, updatedOn.",
"details": {
"reason": "UNKNOWN_FILTER_FIELD",
"field": "stauts",
"accepted": ["id", "appId", "status", "isCompany", "endUserId", "installationId", "userId", "testedOn", "expiresOn", "authenticatedOn", "createdOn", "createdBy", "updatedOn"]
}
}
}Unknown query parameters and unknown JSON body fields are refused the same way on every endpoint. A few long-standing read endpoints still accept them for now; see Errors.
Advanced filters
For OR conditions and grouping, pass an RSQL expression in where:
curl "https://connect.mindcloud.co/v2/workflows/Wq3kZ8pLx2Nb/runs" \
--data-urlencode "where=(status==failed,status==interrupted);startedOn>=2026-07-01" -G \
-H "Authorization: Bearer $MINDCLOUD_API_KEY"| Syntax | Meaning |
|---|---|
==, != | Equals, not equal |
>, >=, <, <= | Comparisons |
=in=(a,b), =out=(a,b) | In or not in a list |
=like= | Case-insensitive match; * is the wildcard |
; | AND |
, | OR |
( ) | Grouping |
AND binds tighter than OR, as in the RSQL specification: status==failed,status==interrupted;version==draft means failed runs, or interrupted draft runs. Group with parentheses to say otherwise. where expressions are limited to 2,048 characters and combine with bracket filters using AND.
Rate limits
Each API key gets 240 read requests (GET) and 60 write requests (POST, PUT, DELETE) per minute, in separate budgets. Every response reports where you stand:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute for this budget |
X-RateLimit-Remaining | Requests left in the current window |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets |
Past the limit, requests return 429 with code RATE_LIMITED and a Retry-After header with the seconds to wait. Back off until then; the budget refills at the reset time.
Errors
Every error uses one envelope. code is one of a small fixed set, decided by the HTTP status; details.reason names the specific cause when there is more to say, and details carries any evidence, such as the accepted values or the workflows that block a delete:
{
"success": false,
"error": {
"code": "CONFLICT",
"message": "This connection is used by 2 active workflows.",
"details": { "reason": "CONNECTION_IN_USE", "workflows": [{ "id": "Wq3kZ8pLx2Nb", "name": "Order Sync", "usageCount": 3 }] }
}
}| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | A parameter, field, body key, or value the endpoint does not accept |
| 401 | UNAUTHORIZED | Missing, invalid, or revoked API key |
| 403 | FORBIDDEN | The key cannot do this, for example API_KEY_ACCESS_DENIED or COMPANY_SCOPE_MISMATCH |
| 404 | NOT_FOUND | The resource does not exist in your company |
| 409 | CONFLICT | The resource's state prevents it, for example WORKFLOW_NOT_PUBLISHED or CONNECTION_IN_USE |
| 410 | GONE | The operation is no longer available |
| 413 | PAYLOAD_TOO_LARGE | The result is too large to serve, for example RUN_OUTPUT_TOO_LARGE |
| 429 | RATE_LIMITED | Rate limit reached; wait for Retry-After |
| 500 | INTERNAL_ERROR | Something failed on our side |
| 502 | PROVIDER_ERROR | The connected app itself refused or failed; details.provider.status is its HTTP status |
| 503 | UNAVAILABLE | A dependency is temporarily unavailable; retry |
Branch on code for the kind of failure and on details.reason for the cause. A provider's own status never becomes the response status: a Universal action whose provider answers 404 returns 502 PROVIDER_ERROR with details.provider.status 404. PROVIDER_ERROR only means the app answered; when MindCloud refuses a run before calling the app (a connection for another app, an operation the action does not support), the code is the matching one above with the cause in details.reason.
Run step reads can also return 409 with reason RUN_OUTPUT_UNAVAILABLE when the final log upload is still pending or failed. A finished execution does not guarantee that its final step output is available.
Long-standing read endpoints
These endpoints serve live integrations and keep their earlier behavior until it can change without breaking them: GET /v2/workflows, /v2/workflows/{workflowId}, /v2/workflows/{workflowId}/runs, /v2/workflows/{workflowId}/versions, /v2/runs/{runId}, /v2/runs/{runId}/steps, /v2/usage, /v2/usage/daily, /v2/usage/workflows, and /v2/me. On them:
- Unknown parameters and names are ignored, an out-of-range
limitfalls back to100, and%and_incontains,starts, andendsact as wildcards. - The specific cause is the
codeitself, with nodetails:INVALID_QUERYfor every400,NOT_FOUND,RUN_OUTPUT_UNAVAILABLE,USAGE_UNAVAILABLE.
The 401 envelope and the AND-before-OR rule above apply to them too. Send only the names their pages list, and they keep working when they adopt the rest.