Skip to content
Klozzo API
OpenAPI Postman

Lists, paging and filters

Every endpoint that returns more than one record follows the same contract, so you write the paging code once.

Two kinds of paging, and they are not interchangeable

Page numbers Cursor
You send ?page=2&per_page=50 ?cursor=<the last one you got>
You get back links and meta next_cursor and prev_cursor
Used by Most listings: contacts, tags, deals, quotes, imports… Feeds that keep growing: a contact's activity, a conversation's messages
Total known Yes, in meta.total No, on purpose

Page numbers are the default. Cursors are used exactly where a page number would lie: a timeline grows while you read it, so page 2 half an hour later is not the page 2 you would have got. Follow next_cursor until it comes back null; never build ?page=2 by hand on those endpoints.

The page-number envelope

{
  "data": [ … ],
  "links": { "first": "…?page=1", "last": "…?page=4", "prev": null, "next": "…?page=2" },
  "meta": { "current_page": 1, "from": 1, "to": 25, "per_page": 25, "last_page": 4, "total": 87 }
}

Walk it with links.next rather than by incrementing current_page: when links.next is null you are done, and that stays true if the shape ever gains a filter you did not send.

The cursor envelope

{
  "data": [ … ],
  "next_cursor": "eyJpZCI6ODgxfQ",
  "prev_cursor": null
}

per_page

Optional everywhere. Every endpoint caps it, because an integration asking for per_page=100000 is not malicious — it is just written in a hurry — and the honest answer to that is a ceiling rather than a timeout.

Endpoints Default Maximum
Most listings 20–25 100
Commercial API (/api/v1/*) 50 100
Audit log · conversation messages 50 200

Above the ceiling you are silently given the ceiling — meta.per_page tells you how many you really got. The audit log is the exception and answers 422: there, quietly returning fewer rows than were asked for would read as "nothing else happened".

Filters

Filters are query parameters, they are additive (every one you send narrows the result further), and each endpoint documents its own. There is no shared filter language: ?status=open on deals and ?unread=true on notifications are each defined where they are used.

Two rules hold everywhere:

  • An unknown filter is ignored, not rejected. A typo silently widens your result instead of failing, so check that what you sent is in the endpoint's parameter list.
  • Filters never cross the location. They narrow what your token can already see; there is no parameter that widens it.

Sorting

Listings come back in the order that makes sense for what they are — newest first for anything with a timeline, alphabetical for catalogues like tags — and each endpoint says so. Where sorting is configurable, the endpoint documents its own parameter; there is no global sort= and adding one is not planned.