Daten lesen: filtern, sortieren, blättern, suchen
Lesen ist der häufigste Fall, und er ist einfach. Diese Seite zeigt alles, was du dafür brauchst.
1. Die Antwort hat immer dieselbe Form
Egal welchen Bereich du abfragst — die Hülle ist gleich. Bei Erfolg:
{
"data": [ ... ],
"meta": { "page": 1, "per_page": 50, "count": 50, "total": 1234, "pages": 25 }
}
Bei einem Fehler:
{
"error": {
"status": 422,
"code": "validation_failed",
"message": "Die übergebenen Daten sind ungültig.",
"details": [
{ "field": "email",
"message": "Keine gültige E-Mail-Adresse." }
]
}
}
Dein Programm kann also immer gleich prüfen: Steht data drin, hat es geklappt. Steht error drin, nicht.
2. Eine Liste holen
GET /api/v1/contacts
Das liefert die ersten 50 Kontakte. Mehr auf einmal geht mit per_page, höchstens 500:
GET /api/v1/contacts?per_page=200&page=2
In meta.pages steht, wie viele Seiten es insgesamt gibt. Zusätzlich trägt die Antwort die Kopfzeilen X-Total-Count und Link mit den Adressen der ersten, vorherigen, nächsten und letzten Seite.
3. Nur die Felder holen, die du brauchst
Ein Kontakt hat über 140 Felder. Wenn du nur Namen und E-Mail brauchst, sag es:
GET /api/v1/contacts?fields=id,lastname,firstname,email
Das macht die Antwort um ein Vielfaches kleiner und schneller. Bei großen Beständen lohnt es sich immer.
4. Sortieren
GET /api/v1/contacts?sort=lastname
GET /api/v1/contacts?sort=-created (Minus = absteigend)
GET /api/v1/contacts?sort=lastname,-created (mehrere Felder)
Wonach du sortieren kannst, sagt dir /api/v1/contacts/_schema unter sortable.
5. Filtern
Der einfachste Filter ist ein genauer Vergleich:
GET /api/v1/contacts?city=Berlin
Für alles andere schreibst du den Vergleich in eckige Klammern:
| Was du willst | So schreibst du es |
| enthält | ?lastname[like]=Mül |
| beginnt mit | ?lastname[start]=Sch |
| endet auf | ?email[end]=@example.de |
| größer/gleich | ?created[gte]=2026-01-01 |
| kleiner/gleich | ?created[lte]=2026-12-31 |
| größer | ?id[gt]=100 |
| kleiner | ?id[lt]=100 |
| ungleich | ?city[ne]=Berlin |
| einer von mehreren | ?id[in]=1,2,3 |
| keiner von mehreren | ?id[nin]=4,5 |
| zwischen zwei Werten | ?id[between]=10,20 |
| ist leer | ?email[null]=1 |
| ist gefüllt | ?email[notnull]=1 |
Mehrere Filter werden mit UND verknüpft. Zwei Vergleiche am selben Feld sind erlaubt — so baust du einen Zeitraum:
GET /api/v1/coachingappointments
?appointment_date[gte]=2026-09-01
&appointment_date[lte]=2026-09-30
Wichtig bei curl: Der Schalter -g muss dazu. Ohne ihn hält curl die eckigen Klammern für eine Bereichsangabe und bricht ab:
curl -g -H "Authorization: Bearer <Schlüssel>" \
"https://deine-adresse.de/api/v1/contacts?lastname[like]=Mül"
6. Suchen
Wenn du nicht weißt, in welchem Feld etwas steht:
GET /api/v1/contacts?q=Müller
Das durchsucht die dafür vorgesehenen Felder des Bereichs. Bei Kontakten sind das Nachname, Vorname, Firma, E-Mail, Kundennummer und Ort. Welche Felder ein Bereich durchsucht, steht in /_schema unter searchable.
7. Verknüpftes gleich mitholen
Statt erst den Kontakt und dann seine Tiere zu holen, geht beides in einem Aufruf:
GET /api/v1/contacts/42?include=pets,invoices
Oder als eigene, blätterbare Liste:
GET /api/v1/contacts/42/pets
Welche Verknüpfungen es bei einem Bereich gibt, sagt /_schema unter relations.
8. Gelöschte Datensätze
Was in PetWorkers gelöscht wird, landet im Papierkorb, nicht im Nichts. Die Schnittstelle blendet den Papierkorb standardmäßig aus:
?deleted=exclude | Papierkorb ausblenden (Vorgabe) |
?deleted=include | Papierkorb mit anzeigen |
?deleted=only | nur den Papierkorb |
Für einen Abgleich mit einem Fremdsystem ist ?deleted=only nützlich: So erfährst du, was seit dem letzten Lauf gelöscht wurde.
9. Alles durchlaufen
Bei großen Beständen holst du nicht alles auf einmal, sondern blätterst. Das Muster ist immer gleich:
Seite = 1
Wiederhole:
Antwort = GET /api/v1/contacts?page=<Seite>&per_page=200
verarbeite Antwort.data
Wenn Seite >= Antwort.meta.pages: fertig
Seite = Seite + 1
Alle Beispielskripte enthalten diese Schleife fertig gebaut.
10. Nur das Neue holen
Für einen laufenden Abgleich brauchst du nicht jedes Mal alles. Jeder Datensatz trägt created und modified, und danach kannst du filtern:
GET /api/v1/contacts?modified[gte]=2026-08-17 04:00:00&sort=modified&per_page=200
Merke dir nach jedem Lauf den Zeitpunkt und setze ihn beim nächsten Mal als untere Grenze. So überträgst du nur, was sich wirklich geändert hat.