Pagination, Filtering & Sorting

All list endpoints support pagination, filtering, sorting, and relation inclusion via query parameters.

Pagination

Parameter Type Default Description
page number 1 Current page number (1-indexed)
perPage number 10 Number of items per page

curl:

curl "https://api.incrm.app/api/v1/client?page=2&perPage=25" \
  -H "X-Api-Key: incrm_your-key"

TypeScript SDK:

const { data } = await listClients({ query: { page: 2, perPage: 25 } })

Pagination Metadata

List responses include a meta object:

{
  "success": true,
  "data": [...],
  "meta": {
    "total": 150,
    "lastPage": 6,
    "currentPage": 2,
    "perPage": 25,
    "prev": 1,
    "next": 3
  }
}
Field Type Description
total number Total number of matching records
lastPage number Last available page number
currentPage number Current page number
perPage number Items per page
prev number | null Previous page number, or null if on first page
next number | null Next page number, or null if on last page

Traversing All Pages

To retrieve all records, iterate until meta.next is null:

import { InCRMClient, listClients } from '@incrm-app/sdk'

const incrm = new InCRMClient({
  baseUrl: 'https://api.incrm.app',
  apiKey: 'incrm_your-key',
})

let page = 1
const allClients = []

while (true) {
  const { data: response } = await listClients({ query: { page, perPage: 100 } })
  allClients.push(...response.data)

  if (!response.meta.next) break
  page = response.meta.next
}

console.log(`Fetched ${allClients.length} clients`)

Filtering (where)

The where parameter supports a powerful filter syntax for querying records.

Basic Equality

where=firstName:John

Operators

Use the operator syntax field:operator:value:

Operator Description Example
(none) Equals where=status:ACTIVE
gt Greater than where=amount:gt:int(100)
gte Greater than or equal where=amount:gte:int(50)
lt Less than where=amount:lt:int(1000)
lte Less than or equal where=amount:lte:int(500)
contains String contains where=name:contains:john
startsWith String starts with where=name:startsWith:Jo
endsWith String ends with where=email:endsWith:.com

Type Casting

Wrap values in type functions:

Type Syntax Example
Integer int(value) where=amount:gt:int(100)
Float float(value) where=price:lt:float(99.99)
Boolean bool(value) where=isActive:bool(true)
Date date(value) where=createdAt:gt:date(2025-01-01)

Multiple Conditions (AND)

Separate conditions with commas:

where=status:ACTIVE,firstName:contains:John

OR Conditions

where=OR:[status:ACTIVE,status:PENDING]

NOT Conditions

where=NOT:status:ARCHIVED

Examples

curl — Active clients created after Jan 2025:

curl "https://api.incrm.app/api/v1/client?where=isActive:bool(true),createdAt:gt:date(2025-01-01)" \
  -H "X-Api-Key: incrm_your-key"

curl — Invoices over $1000:

curl "https://api.incrm.app/api/v1/invoice?where=totalAmount:gt:int(1000)" \
  -H "X-Api-Key: incrm_your-key"

Sorting (orderBy)

Sort results using field:direction pairs, separated by commas:

orderBy=lastName:asc,firstName:asc
Direction Description
asc Ascending
desc Descending

curl:

curl "https://api.incrm.app/api/v1/invoice?orderBy=createdAt:desc&perPage=50" \
  -H "X-Api-Key: incrm_your-key"

TypeScript SDK:

const { data } = await listInvoices({
  query: { orderBy: 'createdAt:desc', perPage: 50 },
})

Error on Invalid Sort

{
  "success": false,
  "error": {
    "code": 400011,
    "message": "Invalid sorting order"
  }
}

Relation Inclusion (include)

Expand related entities using the include parameter. Provide a comma-separated list of relation names:

include=invoices,contacts

Prefix with - to exclude a default relation:

include=-contacts

curl:

curl "https://api.incrm.app/api/v1/client/6507a1b2c3d4e5f6a7b8c9d0?include=invoices,contacts" \
  -H "X-Api-Key: incrm_your-key"

Response (with included relations):

{
  "success": true,
  "data": {
    "id": "6507a1b2c3d4e5f6a7b8c9d0",
    "firstName": "John",
    "lastName": "Doe",
    "invoices": [
      { "id": "...", "totalAmount": 500, "status": "PAID" }
    ],
    "contacts": [
      { "id": "...", "type": "EMAIL", "value": "john@example.com" }
    ]
  }
}

Available relations depend on the entity. Refer to the OpenAPI spec at GET /api/v1/openapi.json for the complete list of relations per resource.

Error on Invalid Include

{
  "success": false,
  "error": {
    "code": 400019,
    "message": "Invalid query format"
  }
}