> ## Documentation Index
> Fetch the complete documentation index at: https://www.quo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sorting and filtering

> The query parameter conventions list endpoints use for sorting and filtering: syntax, operators, and how parameters combine.

List endpoints share one convention for sorting and filtering. Learn it once and it applies everywhere it's supported. Not every endpoint supports every feature, so check each endpoint's reference page for which fields are sortable or filterable and which operators they accept.

## Sorting

Endpoints that support sorting accept a single `sort` query parameter with one `field:direction` pair.

```plain theme={null}
GET /conversations?sort=createdAt:desc
GET /conversations?sort=updatedAt:asc
```

Direction is `asc` or `desc`. The request is rejected with a [`400`](/docs/2026-03-30/errors#status-codes) if the direction is missing or unrecognized, if the endpoint doesn't support sorting on the field, or if you pass more than one pair (for example, `sort=updatedAt:desc,createdAt:asc`).

Today, [`GET /conversations`](/docs/2026-03-30/conversations/list-conversations) is the only endpoint that accepts `sort`, on `createdAt` or `updatedAt`. Other list endpoints return results in the fixed order described on their reference page.

## Filtering

Endpoints that support filtering expose one query parameter per filterable field. Equality is the implicit default, and every parameter present in the query string combines with logical AND — there's no implicit OR across distinct parameters.

```plain theme={null}
GET /calls?status=missed
GET /calls?status=missed&direction=incoming
GET /contacts?source=openphone-hubspot
```

Parameter names use the singular field name, even for filters that accept multiple values (`participant`, not `participants`).

### Operators

Non-equality operators are appended to the field name in brackets:

| Syntax | Operator |
| - | - |
| `field[in]` | matches any value in a comma-separated set |
| `field[gte]` | greater than or equal (inclusive lower bound) |
| `field[lte]` | less than or equal (inclusive upper bound) |
| `field[gt]` | greater than (exclusive lower bound) |
| `field[lt]` | less than (exclusive upper bound) |
| `field[all]` | matches exactly this comma-separated set, in any order |

Each filter supports only some of these operators. A range filter accepts either the inclusive `[gte]`/`[lte]` pair or the exclusive `[gt]`/`[lt]` pair, never both. An operator the filter doesn't support is rejected with a [`400`](/docs/2026-03-30/errors#status-codes).

```plain theme={null}
GET /calls?status[in]=missed,no-answer&createdAt[gte]=2026-07-01T00:00:00Z
GET /contacts?externalId[in]=ext-1,ext-2
GET /conversations?updatedAt[gte]=2026-07-01T00:00:00Z&updatedAt[lte]=2026-08-01T00:00:00Z
GET /messages?to[all]=%2B15555555555,%2B15555555556
```

Timestamps use ISO 8601 format. URL-encode the `+` in E.164 phone numbers as `%2B`, since a literal `+` in a query string is read as a space.

### OR logic

Values within a single `[in]` parameter OR together — `status[in]=missed,no-answer` matches either status. That's the only place OR applies: parameters across the query string still AND, so `status[in]=missed,no-answer&direction=incoming` requires the incoming direction on top of either status.

Cross-field OR (for example, "status is missed OR direction is outgoing") isn't supported. There's no bracket or suffix in this scheme that expresses OR across distinct fields, so don't try to construct one — build the request as two separate calls instead, or get in touch if this is a hard blocker for your use case.
