# Listings, search and the change feed

A list_folder cursor is a change feed: it pages a folder, then returns each later change once, and a long poll wakes on a write; search matches names and pages by cursor.

A `list_folder` cursor pages a folder and then reports what changed in it since, which is how a sync client stays current. Boot the simulator as in the Quickstart, take a cursor at the folder's current state, change the folder and read what the cursor reports:

```bash
H='Authorization: Bearer sl.placeholder'
J='Content-Type: application/json'
O='Content-Type: application/octet-stream'
C=$(curl -s "$RYSTIC_URL/2/files/list_folder/get_latest_cursor" -H "$H" -H "$J" -d '{"path":"/Documents"}' | jq -r .cursor)
curl -s "$RYSTIC_URL/2/files/upload" -H "$H" -H "$O" -H 'Dropbox-API-Arg: {"path":"/Documents/new.txt"}' --data-binary 'x' | jq -c '{name}'
# -> {"name":"new.txt"}
curl -s "$RYSTIC_URL/2/files/delete_v2" -H "$H" -H "$J" -d '{"path":"/Documents/receipts.csv"}' | jq -c '.metadata.name'
# -> "receipts.csv"
curl -s "$RYSTIC_URL/2/files/list_folder/continue" -H "$H" -H "$J" -d "{\"cursor\":\"$C\"}" | jq -c '{has_more, entries: [.entries[] | {tag: .[".tag"], name}]}'
# -> {"has_more":false,"entries":[{"tag":"deleted","name":"receipts.csv"},{"tag":"file","name":"new.txt"}]}
curl -s "$RYSTIC_URL/2/files/list_folder/longpoll" -H "$J" -d "{\"cursor\":\"$C\",\"timeout\":30}"
# -> {"changes":true}
```

### Paging and the change feed

`files/list_folder` pages through the folder by `limit`: a full page returns `has_more: true` with a cursor, and `list_folder/continue` walks the rest of that listing. Once the listing is done, the same cursor returns the folder's changes. A cursor from `get_latest_cursor` returns them from the moment it is minted.

Each path written since appears once, in its final state: `deleted` for a deleted or moved-away path, and the entry for a created, copied, moved-in or overwritten one. A page lists its deleted and folder entries first, then its files, each in the order they happened. A cursor is never used up: continuing it again returns the same page. A cursor the simulator never handed out returns 400.

### Long poll

`files/list_folder/longpoll` holds the request open until a write lands or the timeout passes. It takes no `Authorization` header and refuses one with 400.

| When | The long poll returns |
|---|---|
| the cursor already has a change waiting | `{"changes": true}` at once |
| a write lands in the namespace of the cursor's folder | `{"changes": true}` as soon as it lands |
| `timeout` seconds (30 to 480) pass with no change | `{"changes": false}` |

**Differs from Dropbox:** `{"changes": false}` comes after `timeout` seconds, with none of the random jitter Dropbox adds.

### Search

`files/search_v2` matches the words of a name, case-insensitively, scoped by `options.path`, and pages through `search/continue_v2` when `options.max_results` is smaller than the matches. Search matches names only: a word that appears only in a file's content finds nothing.

---

Source: https://www.rystic.ai/docs/simulators/dropbox/features/change-feed · Markdown: https://www.rystic.ai/docs/simulators/dropbox/features/change-feed.md
