# Consume sync records Read changes after your saved cursor. Apply the changes and save the new cursor in the same database transaction. ![Atlas travel desk showing bookings synchronized into the application database.](/docs/consumer.png) ## Fetch a page ```sh curl -G "$BROWSERLAYER_API_URL/connections/$CONNECTION_ID/syncs/bookings/records" \ -H "Authorization: Bearer $BROWSERLAYER_API_KEY" \ --data-urlencode "cursor=$SAVED_CURSOR" \ --data-urlencode 'limit=100' ``` Omit `cursor` on the first request. ```json { "changes": [ { "id": "booking-1", "deleted": false, "record": { "id": "booking-1", "status": "confirmed" }, "cursor": "opaque-cursor" }, { "id": "booking-2", "deleted": true, "record": null, "cursor": "opaque-cursor" } ], "cursor": "next-page-cursor", "hasMore": false } ``` Records contain the fields declared by your sync model; this response is shortened to show the change envelope. ## Apply changes ```text Receive sync.updated, or catch up when your app starts → load this connection + sync's saved cursor → fetch changes → in one transaction: upsert records where deleted=false delete records where deleted=true save response.cursor → repeat while hasMore=true ``` The route returns a change feed, not just the latest snapshot. Retrying from an old cursor must be safe. Never advance the cursor before applying its records. Use a separate cursor for each environment, connection and sync. Serialize consumers for the same stream, or use a conditional transaction to prevent a stale page from overwriting progress. **Next:** [Receive webhooks](/docs/webhooks).