Skip to main contentSkip to main content
PropRadar Data API

Mirror and sync Australian property data

The recently-modified feed lets you incrementally synchronise a local copy of Australian listings and sold records without scraping, polling individual property IDs, or doing full-table dumps.

How the feed works

1

Pass a since= timestamp

Any ISO timestamp up to 30 days ago. On the first run, use 7 days ago. On subsequent runs, use the timestamp returned by your last call.

2

Page through events

Each response includes up to 20 events and a next_cursor. Follow the cursor until it's null - that's the end of the change window.

3

Store the high-water mark

Save the most recent event_date from the page. Use it as since= on your next sync run. No full dumps, no missed updates.

4

Apply events in order

Three types come back: listing_update, sold, and withdrawn. Apply them in event_date order and let the latest win. withdrawn is reversible, so a relisted property arrives later as a listing_update.

Complete Python example

A runnable sync script. Run it daily via cron or a scheduled job to keep your local copy current. The endpoint requires the Starter plan or higher; if you are syncing for a business, commercial use starts at Pro.

import requests
from datetime import datetime, timezone, timedelta

API_KEY = "pr_live_..."
BASE    = "https://api.propradar.com.au/v1"

def sync_changes(since_iso: str) -> str:
    """
    Pull all property changes since `since_iso`, upsert them locally,
    and return the new high-water mark to store for the next run.
    """
    cursor = None
    latest_ts = since_iso

    while True:
        params = {
            "since":      since_iso,
            "event_type": "all",   # "listing_update" | "sold" | "withdrawn" | "all"
            "limit":      20,
        }
        if cursor:
            params["cursor"] = cursor

        r = requests.get(
            f"{BASE}/properties/recently-modified",
            params=params,
            headers={"X-API-Key": API_KEY},
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()

        for event in data["events"]:
            upsert_locally(event)           # your DB logic here
            if event["event_date"] > latest_ts:
                latest_ts = event["event_date"]

        cursor = data["pagination"].get("next_cursor")
        if not cursor:
            break   # all pages consumed

    return latest_ts   # save this as the new since= for next run


def upsert_locally(event: dict) -> None:
    pid        = event["property_id"]
    event_type = event["event_type"]   # "listing_update" | "sold" | "withdrawn"
    summary    = event["summary"]

    # Example: insert/update a local `properties` table
    print(f"[{event_type}] {pid} - {summary.get('suburb')} {summary.get('postcode')}")
    # db.execute("INSERT INTO properties ... ON CONFLICT (property_id) DO UPDATE ...")


if __name__ == "__main__":
    # First run: look back 7 days
    since = (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
    # Subsequent runs: load from your state store, e.g. a file or DB row
    # since = load_last_run_timestamp()

    new_since = sync_changes(since)
    print(f"Sync complete. Next run: since={new_since}")
    # save_last_run_timestamp(new_since)

Event types

event_typeMeaningKey summary fields
listing_updateAn active listing was added or its price changedasking_price_low, asking_price_high, suburb, postcode
soldA property sold and was recorded in the datasetsold_price, sold_date, suburb, postcode

Key endpoint reference

/v1/properties/recently-modified

Listing updates, sold events and withdrawals since an ISO timestamp. Cursor-paginated, max 30-day lookback.

/v1/properties/{property_id}

Fetch full detail for any property_id returned in the feed.

/v1/health

Verify your key and check remaining quota before a long sync run.

The recently-modified feed requires the Starter plan or higher, and commercial use requires Pro or higher. The 30-day lookback window means you can catch up after a weekend without gaps.

Upgrade to Pro