TheDocumentation Index
Fetch the complete documentation index at: https://docs.realie.ai/llms.txt
Use this file to discover all available pages before exploring further.
/property/search endpoint supports two pagination modes: cursor (recommended) and offset (legacy, deprecated). This page explains both, when to use which, and how to handle common workflows.
TL;DR
- For pagination beyond the first page, always use
cursor. - Opt in by passing
cursor=(empty value) on your first request — even with no token. The response will includemetadata.nextCursorfor the next page. - Cursor pagination is constant-time per page regardless of how deep you’ve paginated.
- The
offsetparameter still works for backwards compatibility but does not scale beyond a few thousand records and may time out. - If you’re doing incremental sync (fetching only what’s new since your last run), cursor pagination is the natural fit — save the
nextCursorfrom your last response, and pass it back later to continue from exactly where you stopped.
Cursor mode is opt-in. Without the
cursor query parameter, the response uses the legacy offset shape (metadata.offset: 0, no nextCursor). To enable cursor pagination you must include the cursor parameter — even an empty value (cursor=) is enough. This keeps existing callers’ default responses unchanged.How cursor pagination works
Each response includesmetadata.nextCursor — an opaque string token. Pass that token back as the cursor parameter on the next request to retrieve the next page. When there are no more results, nextCursor is null.
To start a fresh pagination, send an empty cursor (cursor=). To continue a previous one, send the saved token.
Basic example
First page — passcursor= (empty value) to opt into cursor mode:
nextCursor value as cursor:
nextCursor is null.
Last page
When you’ve reached the end of the result set,nextCursor is null:
Saving cursors for later
Cursor tokens are stateless and portable. They aren’t tied to a session, a connection, or a time window. You can:- Save the token to disk, a database, or environment variable
- Send it to a different machine
- Pause for hours, days, or weeks and resume from exactly the same point
Incremental sync example
Suppose you’re keeping a local mirror of all properties in Nevada. You only want to fetch what’s new since your last run. First run (one-time setup): walk to the end of the current dataset and save the final cursor.Performance characteristics
| Scenario | Cursor | Offset (legacy) |
|---|---|---|
| First page | ~200 ms | ~200 ms |
| Page at depth 10,000 | ~200 ms | seconds, may time out |
| Page at depth 50,000 | ~200 ms | will time out |
| Resume from saved position (any depth) | ~200 ms | requires re-walking from page 0 |
| Incremental “what’s new” sync | ~200 ms per new page | impractical — offsets shift as data changes |
Reference: cursor format
The cursor is base64url-encoded JSON of the form{"lastId": "<hex ObjectId>"}. You don’t need to construct or parse it yourself — always treat it as opaque and pass back exactly what the API returned.
Migrating from offset
If your existing code uses?offset=N to paginate, the migration is one query parameter. Replace your first call’s offset with an empty cursor, then use the returned nextCursor for subsequent pages.
metadata.nextCursor. Pass that value back as cursor on the next request and repeat until nextCursor is null. No need to track or increment offsets — the server hands you the next-page token each time.
For codebases with deep pagination (offset > a few thousand), this migration is worth doing soon — offset calls at those depths can time out and return 503.
When to keep using offset
- You’re prototyping and only ever fetch the first page or two
- You have a small result set that fits comfortably under a few hundred records
- You’re working with existing code that already uses offset and shallow depth
offset parameter (with offset > 0) produces a Deprecation: true HTTP header and a metadata.deprecationNotice field in the response body.
Endpoints that support cursor pagination
Other paginated endpoints will adopt the same pattern over time. Until they do,cursor is silently ignored on endpoints that don’t support it.
