*API REST › Guías*

# Filtrado y orden

> La mayoría de las listas aceptan `sort` y los filtros de tiempo `created*` y `updated*`, muchas aceptan filtros con lista de valores como `statuses`, y algunas aceptan `q` para búsqueda de texto libre. Los ejemplos usan la lista de pedidos.

## Orden

Envía [`sort`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-sort) con hasta tres campos separados por comas; repetir un campo es un 400. Las listas como incidencias, kits, servicios, pagos, pagos de facturas y cuentas de tesorería admiten un solo campo (consulta la descripción del parámetro). Un `-` al principio ordena ese campo de forma descendente: `sort=-startDate,orderNumber`. Cada lista nombra sus campos ordenables en la descripción del parámetro; para los pedidos son `createdAt`, `updatedAt`, `startDate`, `endDate`, `orderNumber`, `grossPrice`, `rentalDays` y `itemsCount`, y el valor por defecto es `-createdAt`.

- Un campo que no está en la lista de campos ordenables se rechaza con 400 [`validation_error`](https://docs.filmo.io/es/rest-api/errors/validation_error), y el error lo nombra.
- Los empates se deshacen por `id`, así que el orden es estable entre páginas.
- Un cursor está ligado al orden con el que se emitió: mantén el mismo `sort` en cada página. Consulta [Paginación](https://docs.filmo.io/es/rest-api/guides/pagination).
- [`GET /api/v1/availability/unavailabilities`](https://docs.filmo.io/es/rest-api/endpoint-reference/availability/list-the-unavailabilities-of-a-resource) no acepta `sort`: sigue el cursor de fecha de su origen. Las listas que no están paginadas (consulta [Paginación](https://docs.filmo.io/es/rest-api/guides/pagination)) tampoco se pueden ordenar.
- Si ordenas por un campo que cambia mientras paginas, como `updatedAt`, un registro puede repetirse u omitirse.

Los campos ordenables de cada lista:

| Operación | Ordenar por |
| --- | --- |
| `GET /api/v1/contacts` | createdAt, updatedAt, name, contactType, role, status, email |
| `GET /api/v1/items` | createdAt, updatedAt, name, sku, salePrice, depositValue, serializedItemsCount, collectionName |
| `GET /api/v1/orders` | createdAt, updatedAt, startDate, endDate, orderNumber, grossPrice, rentalDays, itemsCount |
| `GET /api/v1/orders/{orderId}/lines` | position, itemName, quantity, startDate, endDate, rentalDays, unitPrice, linePrice, status, resourceType, transactionType |
| `GET /api/v1/invoices` | createdAt, updatedAt, invoiceNumber, invoiceDate, dueDate, subTotal, grossPrice |
| `GET /api/v1/quotes` | createdAt, updatedAt, quoteNumber, issueDate, startDate, endDate, subTotal, grossPrice, operativeStatus |
| `GET /api/v1/projects` | createdAt, updatedAt, name, projectNumber, startDate, endDate, status |
| `GET /api/v1/invoices/{invoiceId}/payments` | date, amount, createdAt, updatedAt |
| `GET /api/v1/invoices/{invoiceId}/lines` | position, itemName, quantity, startDate, endDate, rentalDays, unitPrice, linePrice, resourceType, transactionType |
| `GET /api/v1/quotes/{quoteId}/lines` | position, itemName, quantity, startDate, endDate, rentalDays, unitPrice, linePrice, resourceType, transactionType |
| `GET /api/v1/serialized-items` | createdAt, updatedAt, code, serialNumber, status, condition, itemName |
| `GET /api/v1/spaces` | createdAt, updatedAt, name, internalReference, isWarehouse, building, floor |
| `GET /api/v1/repair-tickets` | createdAt, updatedAt, date, status, total |
| `GET /api/v1/vehicles` | createdAt, updatedAt, name, registrationNumber, status, seats, payloadKg |
| `GET /api/v1/staff` | createdAt, updatedAt, fullName, staffType |
| `GET /api/v1/subrents` | createdAt, updatedAt, startDate, endDate, pickupDate, returnDate, status, type, quantity |
| `GET /api/v1/purchase-orders` | createdAt, updatedAt, poNumber, poDate, status, type, grossPrice, netPrice, isDraft |
| `GET /api/v1/contracts` | createdAt, updatedAt, contractNumber, contractDate, startDate, endDate, status, signedAt, grossPrice |
| `GET /api/v1/kits` | name, createdAt, updatedAt |
| `GET /api/v1/collections` | path, name, order, depth, itemCount, createdAt, updatedAt |
| `GET /api/v1/services` | name, serviceType, defaultQty, createdAt, updatedAt |
| `GET /api/v1/internal-services` | startDate, endDate, title, status, createdAt, updatedAt |
| `GET /api/v1/incidents` | createdAt, updatedAt, dueDate, identifier, title, status, priority |
| `GET /api/v1/notes` | createdAt, updatedAt |
| `GET /api/v1/tasks` | createdAt, updatedAt, startDate, endDate, title, isCompleted, type |
| `GET /api/v1/crm/opportunities` | createdAt, updatedAt, name, identifier, status, amount, expectedCloseDate |
| `GET /api/v1/supplier-invoices` | createdAt, updatedAt, invoiceDate, dueDate |
| `GET /api/v1/treasury/accounts` | name, type, status, currency, createdAt, updatedAt |
| `GET /api/v1/treasury/payments` | date, amount, createdAt, updatedAt |
| `GET /api/v1/credit-notes` | createdAt, updatedAt, issueDate, grossPrice |
| `GET /api/v1/proformas` | createdAt, updatedAt, issueDate, proformaNumber |
| `GET /api/v1/workflows` | name, isActive, triggerType, createdAt, updatedAt |
| `GET /api/v1/payment-methods` | name, type, createdAt, updatedAt |
| `GET /api/v1/users` | name, email, status, createdAt, updatedAt |

## Filtros de tiempo

La mayoría de las listas filtran por el momento en que se creó o se actualizó por última vez un registro. Las dos familias comparten cinco sufijos:

| Sufijo | La hora del registro es… | Creado | Actualizado |
| --- | --- | --- | --- |
| En | en esa fecha | `createdOn` | `updatedOn` |
| Después | después de esa fecha | `createdAfter` | `updatedAfter` |
| Antes | antes de esa fecha | `createdBefore` | `updatedBefore` |
| Desde | desde esa fecha, incluida | `createdFrom` | `updatedFrom` |
| Para | hasta esa fecha, incluida | `createdTo` | `updatedTo` |

Cada valor es una fecha sin hora (`YYYY-MM-DD`) o un instante ISO 8601 con desplazamiento. Una fecha sin hora se interpreta en la zona horaria del negocio de la cuenta ([`timezone`](https://docs.filmo.io/es/rest-api/objects/account#response-timezone)): `From` empieza al comienzo de ese día, `To` termina al final de él, `After` significa después del final de ese día, `Before` significa antes de su comienzo y `On` abarca el día entero. Un instante con desplazamiento se aplica tal cual, salvo con `On`, que abarca todo el día de negocio que lo contiene.

Los operadores son estrictos donde lo dicen sus nombres: `After` es `>`, `Before` es `<`, `From` es `>=` y `To` es `<=`, comparados con precisión de milisegundo. Para una fecha sin hora, `From` y `Before` usan las 00:00:00.000 de ese día y `To` y `After` usan las 23:59:59.999, de modo que `updatedAfter=2026-10-09` excluye todo el 9 de octubre. `From` junto con `Before` da una ventana semiabierta, `[from, before)`, cuyos bordes nunca se solapan con la ventana siguiente. Esa es la forma [Sincronizar datos](https://docs.filmo.io/es/rest-api/guides/syncing-data) en el que se basa. No todas las listas tienen estos filtros: [`GET /api/v1/tags`](https://docs.filmo.io/es/rest-api/endpoint-reference/tags/list-tags), [`GET /api/v1/task-types`](https://docs.filmo.io/es/rest-api/endpoint-reference/task-types/list-task-types), [`GET /api/v1/crm/pipelines`](https://docs.filmo.io/es/rest-api/endpoint-reference/crm/list-pipelines), [`GET /api/v1/custom-fields`](https://docs.filmo.io/es/rest-api/endpoint-reference/custom-fields/list-custom-field-definitions) y [`GET /api/v1/project-types`](https://docs.filmo.io/es/rest-api/endpoint-reference/projects/list-project-types) rechazan con 400 cualquier filtro `created*` o `updated*`; [`GET /api/v1/kits`](https://docs.filmo.io/es/rest-api/endpoint-reference/kits/list-kits), [`GET /api/v1/services`](https://docs.filmo.io/es/rest-api/endpoint-reference/services/list-services), [`GET /api/v1/internal-services`](https://docs.filmo.io/es/rest-api/endpoint-reference/internal-services/list-internal-services), [`GET /api/v1/crm/opportunities`](https://docs.filmo.io/es/rest-api/endpoint-reference/crm/list-opportunities), [`GET /api/v1/orders/{orderId}/lines`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-the-lines-of-an-order), [`GET /api/v1/invoices/{invoiceId}/lines`](https://docs.filmo.io/es/rest-api/endpoint-reference/invoices/list-the-lines-of-an-invoice), [`GET /api/v1/quotes/{quoteId}/lines`](https://docs.filmo.io/es/rest-api/endpoint-reference/quotes/list-the-lines-of-a-quote) y [`GET /api/v1/invoices/{invoiceId}/payments`](https://docs.filmo.io/es/rest-api/endpoint-reference/invoices/list-the-payments-of-an-invoice) no tienen filtros `updated*`, y [`GET /api/v1/incidents`](https://docs.filmo.io/es/rest-api/endpoint-reference/incidents/list-incidents) solo tiene `created*`; [`GET /api/v1/payment-methods`](https://docs.filmo.io/es/rest-api/endpoint-reference/treasury/list-payment-methods), [`GET /api/v1/treasury/payments`](https://docs.filmo.io/es/rest-api/endpoint-reference/treasury/list-treasury-payments) y [`GET /api/v1/treasury/accounts`](https://docs.filmo.io/es/rest-api/endpoint-reference/treasury/list-treasury-accounts) se pueden ordenar por `updatedAt` pero no tienen filtros `updated*`. Comprueba los parámetros de la operación. Las listas añaden además sus propios filtros de fecha; los pedidos filtran también por cuándo empiezan y terminan (por ejemplo [`startsFrom`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-startsFrom) y [`endsBefore`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-endsBefore)) y por un periodo de alquiler que se solapa con una ventana ([`overlapsFrom`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-overlapsFrom) y [`overlapsTo`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-overlapsTo)).

## Filtros que admiten varios valores

Algunos filtros tienen un gemelo que admite listas de valores. [`statuses`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-statuses), [`contactIds`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-contactIds) y [`projectIds`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-projectIds) admiten hasta 50 valores y devuelven los registros que coinciden con cualquiera de ellos. Repite el parámetro o separa los valores con comas: `statuses=reserved,prepared` y `statuses=reserved&statuses=prepared` son el mismo filtro.

- El filtro de un solo valor es otro parámetro: [`status`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-status) admite un grupo operativo (`draft`, `reserved`, `prepared`, `in_use`, `returned`, `completed` o `cancelled`), [`contactId`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-contactId) un contacto.
- Más de 50 valores es un 400. Para filtrar por un conjunto mayor, divídelo en lotes de 50 y combina los resultados.

## Búsqueda de texto libre

Cuando una lista ofrece [`q`](https://docs.filmo.io/es/rest-api/endpoint-reference/orders/list-orders#param-q), es una búsqueda de texto libre cuya descripción indica qué compara. En pedidos busca el número de pedido, el nombre o alias del proyecto y la referencia externa, con una longitud de 1 a 200 caracteres.

## Un ejemplo

Pedidos reservados o preparados, actualizados desde el 1 de octubre y antes del 8 de octubre, cuyo texto coincide con `acme`, primero los que empiezan antes y, entre inicios iguales, primero los más grandes:

*Filtrar, buscar y ordenar los pedidos*

**cURL**

```bash
curl -sS --fail-with-body -G "${FILMO_BASE_URL:-https://app.filmo.io}/api/v1/orders" \
  -H "Authorization: Bearer $FILMO_API_KEY" \
  --data-urlencode "statuses=reserved,prepared" \
  --data-urlencode "updatedFrom=2026-10-01" \
  --data-urlencode "updatedBefore=2026-10-08T00:00:00+02:00" \
  --data-urlencode "q=acme" \
  --data-urlencode "sort=startDate,-grossPrice" \
  --data-urlencode "limit=50" |
  jq -r '.data[] | [.orderNumber, .status, .startDate, .grossPrice] | @tsv'
```

**Node**

```javascript
const base = process.env.FILMO_BASE_URL ?? "https://app.filmo.io";
const url = new URL("/api/v1/orders", base);
url.searchParams.set("statuses", "reserved,prepared"); // or repeat: statuses=reserved&statuses=prepared
url.searchParams.set("updatedFrom", "2026-10-01"); // on or after the start of that day (account timezone)
url.searchParams.set("updatedBefore", "2026-10-08T00:00:00+02:00"); // before this instant
url.searchParams.set("q", "acme");
url.searchParams.set("sort", "startDate,-grossPrice"); // soonest start first, then the biggest order
url.searchParams.set("limit", "50");

const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.FILMO_API_KEY}` } });
if (!res.ok) throw new Error(res.status + " " + (await res.text()));
const { data } = await res.json();
for (const order of data) console.log(order.orderNumber, order.status, order.startDate, order.grossPrice);
```

**Python**

```python
import os
import requests

base = os.environ.get("FILMO_BASE_URL", "https://app.filmo.io")
params = {
    "statuses": ["reserved", "prepared"],  # sent as repeated parameters; a comma-separated string works too
    "updatedFrom": "2026-10-01",  # on or after the start of that day (account timezone)
    "updatedBefore": "2026-10-08T00:00:00+02:00",  # before this instant
    "q": "acme",
    "sort": "startDate,-grossPrice",  # soonest start first, then the biggest order
    "limit": 50,
}
res = requests.get(
    base + "/api/v1/orders",
    headers={"Authorization": f"Bearer {os.environ['FILMO_API_KEY']}"},
    params=params,
    timeout=30,
)
res.raise_for_status()
for order in res.json()["data"]:
    print(order["orderNumber"], order["status"], order["startDate"], order["grossPrice"])
```

Combina los filtros con el bucle de [Paginación](https://docs.filmo.io/es/rest-api/guides/pagination): mantén los mismos filtros, `sort` y `limit` en cada página.

---

URL canónica: https://docs.filmo.io/es/rest-api/guides/filtering-and-sorting  
Última actualización: 2026-10-09