I would tag each inserted row with the current transaction ID (txid_current() or, from v13 on, pg_current_xact_id()).
The “latest safe change” is the right before the xmin of the “current snapshot”, which can be found with txid_snapshot_xmin(txid_current_snapshot()) (or pg_snapshot_xmin(pg_current_snapshot()) from v13 on). That xmin is the transaction ID of ...
The Overlapping Sync solution is a must. It is better to have data you don't need (and not use it), then to not have the data you do need.
The Send me data since... value should be a parameter for the REST API. This will allow the Client to grab changes of data since:
last sync time - 1 (Client keeps track of last sync time)
last 30 days