Guides

Filtering and sorting

Most lists accept sort and the created* and updated* time filters, many accept list-valued filters such as statuses, and some accept q for free-text search. The examples use the orders list.

Send sort with up to three comma-separated fields; repeating a field is a 400. Lists such as incidents, kits, services, payments, invoice payments and treasury accounts take only one field (see the parameter description). A leading - sorts that field in descending order: sort=-startDate,orderNumber. Each list names its sortable fields in the description of the parameter; for orders they are createdAt, updatedAt, startDate, endDate, orderNumber, grossPrice, rentalDays and itemsCount, and the default is -createdAt.

  • A field that is not in the list of sortable fields is rejected with 400 validation_error, and the error names it.
  • Ties are broken by id, so the order is stable across pages.
  • A cursor is bound to the sort it was issued with: keep sort the same on every page. See Pagination.
  • GET /api/v1/availability/unavailabilities does not accept sort: it follows the date cursor of its source. The lists that are not paginated (see Pagination) are not sortable either.
  • If you sort by a field that changes while you page, such as updatedAt, a record can be repeated or skipped.

The sortable fields of every list:

OperationSort by
GET /api/v1/contactscreatedAt, updatedAt, name, contactType, role, status, email
GET /api/v1/itemscreatedAt, updatedAt, name, sku, salePrice, depositValue, serializedItemsCount, collectionName
GET /api/v1/orderscreatedAt, updatedAt, startDate, endDate, orderNumber, grossPrice, rentalDays, itemsCount
GET /api/v1/orders/{orderId}/linesposition, itemName, quantity, startDate, endDate, rentalDays, unitPrice, linePrice, status, resourceType, transactionType
GET /api/v1/invoicescreatedAt, updatedAt, invoiceNumber, invoiceDate, dueDate, subTotal, grossPrice
GET /api/v1/quotescreatedAt, updatedAt, quoteNumber, issueDate, startDate, endDate, subTotal, grossPrice, operativeStatus
GET /api/v1/projectscreatedAt, updatedAt, name, projectNumber, startDate, endDate, status
GET /api/v1/invoices/{invoiceId}/paymentsdate, amount, createdAt, updatedAt
GET /api/v1/invoices/{invoiceId}/linesposition, itemName, quantity, startDate, endDate, rentalDays, unitPrice, linePrice, resourceType, transactionType
GET /api/v1/quotes/{quoteId}/linesposition, itemName, quantity, startDate, endDate, rentalDays, unitPrice, linePrice, resourceType, transactionType
GET /api/v1/serialized-itemscreatedAt, updatedAt, code, serialNumber, status, condition, itemName
GET /api/v1/spacescreatedAt, updatedAt, name, internalReference, isWarehouse, building, floor
GET /api/v1/repair-ticketscreatedAt, updatedAt, date, status, total
GET /api/v1/vehiclescreatedAt, updatedAt, name, registrationNumber, status, seats, payloadKg
GET /api/v1/staffcreatedAt, updatedAt, fullName, staffType
GET /api/v1/subrentscreatedAt, updatedAt, startDate, endDate, pickupDate, returnDate, status, type, quantity
GET /api/v1/purchase-orderscreatedAt, updatedAt, poNumber, poDate, status, type, grossPrice, netPrice, isDraft
GET /api/v1/contractscreatedAt, updatedAt, contractNumber, contractDate, startDate, endDate, status, signedAt, grossPrice
GET /api/v1/kitsname, createdAt, updatedAt
GET /api/v1/collectionspath, name, order, depth, itemCount, createdAt, updatedAt
GET /api/v1/servicesname, serviceType, defaultQty, createdAt, updatedAt
GET /api/v1/internal-servicesstartDate, endDate, title, status, createdAt, updatedAt
GET /api/v1/incidentscreatedAt, updatedAt, dueDate, identifier, title, status, priority
GET /api/v1/notescreatedAt, updatedAt
GET /api/v1/taskscreatedAt, updatedAt, startDate, endDate, title, isCompleted, type
GET /api/v1/crm/opportunitiescreatedAt, updatedAt, name, identifier, status, amount, expectedCloseDate
GET /api/v1/supplier-invoicescreatedAt, updatedAt, invoiceDate, dueDate
GET /api/v1/treasury/accountsname, type, status, currency, createdAt, updatedAt
GET /api/v1/treasury/paymentsdate, amount, createdAt, updatedAt
GET /api/v1/credit-notescreatedAt, updatedAt, issueDate, grossPrice
GET /api/v1/proformascreatedAt, updatedAt, issueDate, proformaNumber
GET /api/v1/workflowsname, isActive, triggerType, createdAt, updatedAt
GET /api/v1/payment-methodsname, type, createdAt, updatedAt
GET /api/v1/usersname, email, status, createdAt, updatedAt

Most lists filter by the time a record was created or last updated. The two families share five suffixes:

SuffixThe record's time is…CreatedUpdated
Onon that datecreatedOnupdatedOn
Afterafter that datecreatedAfterupdatedAfter
Beforebefore that datecreatedBeforeupdatedBefore
Fromon or after that datecreatedFromupdatedFrom
Toon or before that datecreatedToupdatedTo

Each value is a bare day (YYYY-MM-DD) or an ISO 8601 instant with an offset. A bare day is read in the business timezone of the account (timezone): From starts at the beginning of that day, To ends at the end of it, After means after the end of that day, Before means before its start, and On covers the whole day. An instant with an offset is applied as given, except with On, which covers the whole business day that contains it.

The operators are strict where their names say so: After is >, Before is <, From is >= and To is <=, compared with millisecond precision. For a bare day, From and Before use 00:00:00.000 of that day and To and After use 23:59:59.999, so updatedAfter=2026-10-09 excludes the whole of 9 October. From together with Before gives a half-open window, [from, before), whose edges never overlap with the next window. That is the shape Syncing data builds on. Not every list has these filters: GET /api/v1/tags, GET /api/v1/task-types, GET /api/v1/crm/pipelines, GET /api/v1/custom-fields and GET /api/v1/project-types reject any created* or updated* filter with 400; GET /api/v1/kits, GET /api/v1/services, GET /api/v1/internal-services, GET /api/v1/crm/opportunities, GET /api/v1/orders/{orderId}/lines, GET /api/v1/invoices/{invoiceId}/lines, GET /api/v1/quotes/{quoteId}/lines and GET /api/v1/invoices/{invoiceId}/payments have no updated* filters, and GET /api/v1/incidents has only created*; GET /api/v1/payment-methods, GET /api/v1/treasury/payments and GET /api/v1/treasury/accounts can be sorted by updatedAt but have no updated* filters. Check the parameters of the operation. Lists add their own date filters too; orders also filter on when they start and end (for example startsFrom and endsBefore) and on a rental period that overlaps a window (overlapsFrom and overlapsTo).

Some filters have a list-valued twin. statuses, contactIds and projectIds take up to 50 values and return the records that match any of them. Repeat the parameter or separate the values with commas: statuses=reserved,prepared and statuses=reserved&statuses=prepared are the same filter.

  • The single-value filter is a different parameter: status takes one operational bucket (draft, reserved, prepared, in_use, returned, completed or cancelled), contactId one contact.
  • More than 50 values is a 400. To filter by a larger set, split it into batches of 50 and merge the results.

Where a list offers q, it is a free-text search whose description says what it matches. On orders it searches the order number, the project name or alias and the external reference, with 1 to 200 characters.

Orders that are reserved or prepared, updated since 1 October and before 8 October, whose text matches acme, soonest start first and the biggest first among equal starts:

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'

Combine filters with the loop in Pagination: keep the same filters, sort and limit on every page.

  • Guides

    Pagination

    Lists return one page at a time. Ask for a page with limit, and while pagination.hasMore is true call again with the nextCursor you were given.

  • Guides

    Syncing data

    Filmo v1 does not send webhooks, so you keep another system in step by polling: read what changed in half-open time windows, and run a separate sweep to find what was deleted. Do not follow the pagination cursor to decide what changed or what disappeared.

  • Guides

    Data types

    Money is a decimal string, dates are ISO 8601, a property can be present and null, and custom fields are maps. Parse each type once, at the edge of your integration.

Was this page helpful?