Zum Inhalt springen

Eine Kopie aktuell halten

Der Change-Feed listet jedes neue Item, jede Änderung und jede Entfernung der Reihe nach. Mit einem Cursor gelesen, bekommen Sie jede Änderung genau einmal.

Der Change-Feed (/changes) ist der Weg, Ihre eigene Kopie eines Datasets aktuell zu halten: Statt alles neu zu lesen, lesen Sie, was seit dem letzten Mal passiert ist. Er ist in den bezahlten Plänen enthalten; in Free antwortet er mit 402.

So funktioniert es

Jede Änderung hat eine id, und ids werden nur größer. Sie fragen nach den Änderungen nach der letzten id, die Sie haben; die Antwort liefert die nächsten, die ältesten zuerst, und den Cursor, mit dem es weitergeht:

Shell
curl -H "Authorization: Bearer $PRICANA_KEY" "https://pricana.io/api/v1/changes?after=0&limit=1000"
JSON
{
  "changes": [
    {
      "id": 812,
      "kind": "CHANGED",
      "observedAt": "2026-10-06T21:03:00Z",
      "price": 1399.0,
      "previousPrice": 1499.0,
      "changes": { "price": [1499.0, 1399.0] },
      "item": { "id": 77, "title": "Lenovo ThinkPad X1 Carbon Gen 12", "url": "https://…", "currency": "EUR" }
    }
  ],
  "nextCursor": 812,
  "hasMore": true
}
  1. Beginnen Sie mit after=0 (dem Anfang der Historie Ihres Plans) oder mit einem gespeicherten Cursor.
  2. Verarbeiten Sie die Änderungen. Übergeben Sie dann nextCursor als after in der nächsten Anfrage.
  3. Solange hasMore true ist, fragen Sie sofort wieder. Ist es false, sind Sie auf dem neuesten Stand: Speichern Sie den Cursor und fragen Sie später wieder (alle paar Minuten genügt).

So gelesen, bekommen Sie jede Änderung genau einmal, in der richtigen Reihenfolge, auch nach einer Pause: Der Feed reicht so weit zurück wie die Historie Ihres Plans (bei Pro zum Beispiel 365 Tage). Änderungen erscheinen etwa 30 Sekunden, nachdem sie passiert sind, im Feed.

Eine vollständige Sync-Schleife

Python
import os, time, requests

KEY = os.environ["PRICANA_KEY"]
BASE = "https://pricana.io/api/v1"


def load_cursor() -> int:
    try:
        return int(open("pricana.cursor").read())
    except FileNotFoundError:
        return 0


def save_cursor(cursor: int) -> None:
    with open("pricana.cursor", "w") as f:
        f.write(str(cursor))


cursor = load_cursor()
while True:
    r = requests.get(f"{BASE}/changes", params={"after": cursor, "limit": 1000},
                     headers={"Authorization": f"Bearer {KEY}"}, timeout=60)
    if r.status_code == 429:
        time.sleep(int(r.headers.get("Retry-After", "5")))
        continue
    r.raise_for_status()
    page = r.json()
    for change in page["changes"]:
        apply(change)          # your code: insert, update or mark removed
    cursor = page["nextCursor"]
    save_cursor(cursor)        # after applying: a crash repeats changes, never skips them
    if not page["hasMore"]:
        time.sleep(300)

Speichern Sie den Cursor erst, nachdem Sie die Änderungen angewendet haben, wenn möglich in derselben Transaktion. Dann wiederholt ein Absturz schlimmstenfalls einige Änderungen, und eine Änderung zweimal anzuwenden schadet nicht, wenn die id des Items der Schlüssel Ihrer Zeilen ist.

Änderungen anwenden

kindin Ihrer Kopie
NEWdas Item einfügen (mit /items/{id} lesen, wenn Sie alle Felder brauchen)
CHANGEDes aktualisieren: changes enthält [alt, neu] für jedes geänderte Feld; price ist der neue Preis
REMOVEDals nicht mehr gelistet markieren
RELISTEDals wieder gelistet markieren

Änderungen enthalten id, Titel, Link und Site des Items. Das vollständige Item lesen Sie mit /items/{id}, viele auf einmal mit /items?changedSince= (unten).

Die erste Kopie

Der Feed beginnt am Anfang der Historie Ihres Plans, und die kann lang sein. So beginnen Sie stattdessen frisch:

  1. Lesen Sie /changes/recent?limit=1 und merken Sie sich die id der Änderung darin (gibt es keine, nehmen Sie 0). Eine Änderung erscheint dort, wenn sie im Feed erscheint; nichts danach geht verloren.
  2. Lesen Sie dann alle Items mit einem Export (oder mit /items Seite für Seite).
  3. Lesen Sie den Feed ab after=<diese id>. Änderungen während des Exports kommen noch einmal; eine Änderung zweimal anzuwenden schadet nicht.

Einfacher und oft ausreichend: /items?changedSince=<Zeitpunkt der letzten Synchronisation>&status=all liefert jedes Item, das sich seitdem geändert hat, in seinem aktuellen Stand. Entfernte Items sind mit gesetztem removedAt dabei: Löschen Sie sie aus Ihrer Kopie. (Ohne status=all kommen nur gelistete Items, und eine so gepflegte Kopie erfährt nie von Entfernungen.)

Nur ein Dataset

dataset=<id> grenzt den Feed auf eines Ihrer Datasets ein. Führen Sie für jeden Feed, den Sie lesen, einen eigenen Cursor.

Geschickt statt abgefragt

Webhooks schicken dieselben Änderungen an Ihren Server, sobald sie passieren, in derselben Reihenfolge und mit denselben Objekten. Nutzen Sie sie, wenn Ihnen Änderungen binnen einer Minute geschickt werden sollen, und den Feed, wenn Sie lieber selbst abfragen.