Datensätze finden
Zuletzt aktualisiert 17 August 2026

Es gibt zwei Wege, eine Sammlung zu lesen.
| Sie wollen | Senden Sie |
|---|---|
| alles, seitenweise | GET /api/contacts |
| nur die Datensätze, die einer Bedingung entsprechen | POST /api/contacts/search mit einem Regelsatz |
Das Filtern hat seinen eigenen Endpunkt, /search, und er nimmt dieselben Regelsätze an, aus denen die Filter in der Flexie-Oberfläche gebaut sind. Was Sie auf dem Bildschirm abfragen können, können Sie auch hier abfragen.
Das gilt für die Entitäten, die Datensätze enthalten: Kontakte, Leads, Firmen, Deals, Tickets und Ihre eigenen benutzerdefinierten Entitäten. Aufgaben, E-Mails und Berichte listen und lesen auf dieselbe Weise, nehmen aber keine Filter an, und Benutzer sind eine reine Leseliste.
Auflisten
curl -X GET "https://ihre-subdomain.flexie.io/api/contacts?limit=30&start=0" \
-H "apikey: IHR_API_SCHLUESSEL"
| Parameter | Tut | Standard |
|---|---|---|
limit |
wie viele Datensätze zurückkommen | die Seitengröße des Kontos |
start |
wie viele übersprungen werden | 0 |
orderBy |
das Feld, nach dem sortiert wird | date_modified |
orderByDir |
ASC oder DESC |
DESC |
limit ist bei 100 gedeckelt. Fordern Sie 500 an, bekommen Sie 100, mit der echten total in der Antwort, damit Sie wissen, dass es weitergeht.
Der Aufbau eines Filters
curl -X POST "https://ihre-subdomain.flexie.io/api/contacts/search" \
-H "apikey: IHR_API_SCHLUESSEL" \
-H "Content-Type: application/json" \
-d '{
"filters": {
"condition": "AND",
"rules": [
{ "field": "email", "operator": "contains", "value": "acme.com" }
]
},
"orderBy": "date_added",
"orderByDir": "DESC",
"page": 1,
"limit": 50
}'
Eine Regel hat drei Teile:
| Schlüssel | Enthält |
|---|---|
field |
den Alias des Feldes oder ein Objekt für ein Feld an einem verknüpften Datensatz |
operator |
was verglichen wird, aus den Tabellen weiter unten |
value |
womit verglichen wird. Manche Operatoren nehmen keinen Wert |
Und die Antwort sagt Ihnen, wo Sie stehen:
{ "total": "4", "current_page": 1, "total_pages": 1, "contacts": [ … ] }
Welche Felder und welche Operatoren
Raten müssen Sie auch hier nicht. Fragen Sie die Entität, wonach sie gefiltert werden kann, und sie antwortet mit allem: ihren eigenen Feldern, denen, die Flexie pflegt, etwa date_added, den Ids der Datensätze, auf die sie zeigt, und den Feldern jedes Datensatzes, mit dem sie verknüpft ist.
curl "https://ihre-subdomain.flexie.io/api/contacts/list/filters" \
-H "apikey: IHR_API_SCHLUESSEL"
Jeder Eintrag gibt genau an, was als field zu senden ist, welche Operatoren er annimmt und welche Form von Wert jeder davon erwartet, und jeder nennt seine Gruppe, sodass Sie sie so darstellen können wie die Oberfläche.
Nehmen Sie diesen zum Filtern. Es gibt einen zweiten Endpunkt, list/fields, der die Felder zurückgibt, die jemand an der Entität eingerichtet hat, und sonst nichts:
curl "https://ihre-subdomain.flexie.io/api/contacts/list/fields" -H "apikey: IHR_API_SCHLUESSEL"
Beide antworten in derselben Form, ein Leser kommt also mit beiden zurecht. Der Unterschied ist der Umfang: list/fields sind Ihre eigenen Felder, list/filters ist alles, was eine Regel benennen darf, also zusätzlich die Felder, die Flexie pflegt, die Ids verknüpfter Datensätze und die Felder auf der anderen Seite einer Beziehung. Ein Feld, das eingerichtet, aber nicht filterbar ist, kommt mit einer leeren operators-Liste zurück, und eine Regel, die es benennt, wird abgewiesen.
{
"total": 168,
"fields": [
{
"field": "date_added",
"label": "Date Added",
"type": "datetime",
"group": "System Fields",
"related": false,
"operators": [
{ "operator": "is", "value": "period" },
{ "operator": "between", "value": "range" },
{ "operator": "greater", "value": "single" },
{ "operator": "is_empty", "value": "none" }
]
}
]
}
field ist der Name, der in eine Regel gehört. Neben jedem Operator steht die Form des value, den er erwartet, und dieses Wort ist eine Beschreibung, kein Wert: { "operator": "is", "value": "period" } heißt, dass is einen Zeitraum will, nicht, dass Sie das Wort period senden sollen.
| Form | Was zu senden ist |
|---|---|
single |
Ein Wert.{ "field": "email", "operator": "contains", "value": "acme" } |
range |
Zwei Grenzen in einem Array, die untere zuerst.{ "field": "amount", "operator": "between", "value": [1000, 5000] } |
period |
Ein benannter Zeitraum, damit Sie nie selbst ein Datum ausrechnen.{ "field": "date_added", "operator": "is", "value": "this_year" } |
offset |
Ein Vorzeichen, eine Zahl und eine Einheit, als drei Zeichenketten.{ "field": "date_added", "operator": "less_than_now", "value": ["-", "7", "days"] } |
list |
Ein Array von Werten, von denen einer passen muss.{ "field": "owner_id", "operator": "in", "value": [1, 6] } |
polygon |
Die Punkte einer Fläche. Nur an einem Kartenfeld, wo die Fläche gezeichnet statt getippt wird. |
none |
Gar nichts, lassen Sie value weg.{ "field": "phone", "operator": "is_empty" } |
Jeder Zeitraum und jeder Versatz ist weiter unten aufgeführt, unter Benannte Zeitspannen und Relativ zu jetzt.
Lesen Sie die Feldliste einmal zu Beginn einer Integration, und Sie wissen, wie Sie alles an der Entität abfragen, auch Felder, die jemand hinzugefügt hat, nachdem Sie den Code geschrieben hatten.
Die Felder, die Flexie pflegt
Neben Ihren eigenen Feldern trägt jeder Datensatz einen Satz, den Flexie aktuell hält, und der beantwortet die meisten Fragen, die sich zu stellen lohnen. Sie erscheinen in der Filterliste unter System Fields und stehen nicht in list/fields, weil sie niemand eingerichtet hat:
| Feld | Enthält |
|---|---|
date_added, date_modified |
wann der Datensatz entstand und wann er zuletzt geändert wurde |
email_count, last_email_date |
gesendete E-Mails und die letzte davon |
marketing_email_count, last_marketing_email_date |
dasselbe für Marketing-E-Mails |
last_email_click_date |
wann zuletzt auf etwas geklickt wurde |
sms_count, last_sms_date |
gesendete Nachrichten und die letzte davon |
task_count, last_task_date |
erfasste Aufgaben und die letzte davon |
_next_upcoming_task_date |
die nächste fällige Aufgabe, falls es eine gibt |
note_count, last_note_date |
geschriebene Notizen und die letzte davon |
last_hit_date |
der letzte Besuch auf Ihrer Website |
Bei Kontakten kommen deal_count, last_deal_date, deal_ltv und converted_date hinzu.
Die Zähler sind Zahlen und die Datumsangaben sind Zeitstempel, sie nehmen also die Operatoren dieser Typen. „Nie eine E-Mail bekommen" ist last_email_date mit is_empty, und „seit drei Monaten still" ist dasselbe Feld mit is_not und last_90_days.
Alle Operatoren
Welche Operatoren eine Regel verwenden darf, hängt vom Typ des Feldes ab. Das ist der ganze Satz:
| Feldtyp | Operatoren |
|---|---|
| Text, URL | equal, not_equal, contains, not_contains, begins_with, not_begins_with, ends_with, not_ends_with, is_empty, is_not_empty |
| Tags, Mehrfachauswahl | contains, not_contains, begins_with, not_begins_with, ends_with, not_ends_with, is_empty, is_not_empty |
| Zahl | equal, not_equal, greater, greater_or_equal, less, less_or_equal, between, not_between, is_empty, is_not_empty |
| Ja/Nein, Auswahl, Land, Region, Zeitzone, Bundesland | equal, not_equal, is_empty, is_not_empty |
| Auswahl mit mehreren Werten | in, not_in |
| Zeitstempel | is, is_not, equal, not_equal, greater, greater_or_equal, greater_than_now, less, less_or_equal, less_than_now, between, not_between, is_empty, is_not_empty |
| Datum | dieselben, mit greater_than_today und less_than_today anstelle des _now-Paares |
| Uhrzeit | equal, not_equal, greater, greater_or_equal, less, less_or_equal, between, not_between, is_empty, is_not_empty |
| Referenz | equal, not_equal, is_empty, is_not_empty |
| Punkt | in_polygon, is_empty, is_not_empty |
| Zeitraum | includes, excludes, is_empty, is_not_empty |
| Listenzugehörigkeit | in_list, not_in_list |
| Abonnement | is_subscribed, is_not_subscribed, am Feld __unsubscribes |
Ein Operator, den das Feld nicht annimmt, wird mit einem 400 abgewiesen, nicht ignoriert.
Text
Alle bei einer Domain:
{ "field": "email", "operator": "contains", "value": "acme.com" }
Nur Adressen, die darauf enden, was die strengere Frage ist:
{ "field": "email", "operator": "ends_with", "value": "@acme.com" }
Eine Referenz, die mit einem Präfix beginnt:
{ "field": "customer_code", "operator": "begins_with", "value": "AC-2026" }
Eine genaue Übereinstimmung und ihr Gegenteil:
{ "field": "status", "operator": "equal", "value": "Qualified" }
{ "field": "status", "operator": "not_equal", "value": "Qualified" }
Datensätze, denen etwas fehlt, und Datensätze, die es haben:
{ "field": "phone", "operator": "is_empty" }
{ "field": "phone", "operator": "is_not_empty" }
is_empty und is_not_empty nehmen überhaupt keinen value. Beachten Sie, dass not_equal und not_contains nur Datensätze treffen, die einen Wert haben; kombinieren Sie sie also in einer OR-Gruppe mit is_empty, wenn Sie die leeren mitwollen.
Zahlen
{ "field": "deal_count", "operator": "greater", "value": 0 }
{ "field": "annual_revenue", "operator": "greater_or_equal", "value": 50000 }
{ "field": "points", "operator": "between", "value": [100, 500] }
{ "field": "points", "operator": "not_between", "value": [100, 500] }
between und not_between nehmen ihre beiden Grenzen als Array, die untere zuerst.
Datumsangaben
Ein fester Zeitraum, beide Grenzen zusammen:
{ "field": "date_added", "operator": "between",
"value": ["2026-01-01 00:00:00", "2026-06-30 23:59:59"] }
Alles seit einem Zeitpunkt oder alles davor:
{ "field": "date_added", "operator": "greater", "value": "2026-01-01 00:00:00" }
{ "field": "date_added", "operator": "less", "value": "2026-01-01 00:00:00" }
Benannte Zeitspannen, damit Sie nie eine Grenze ausrechnen
is und is_not nehmen statt eines Datums einen Zeitraum, und der wird in dem Moment bestimmt, in dem die Anfrage läuft. Eine gespeicherte Abfrage bleibt richtig, während die Zeit vergeht:
{ "field": "date_added", "operator": "is", "value": "this_month" }
{ "field": "date_added", "operator": "is_not", "value": "this_year" }
Die Zeiträume sind:
| Gruppe | Werte |
|---|---|
| Tage | today, yesterday |
| Kalender | this_week, this_month, this_quarter, this_year |
| der davor | last_week, last_month, last_quarter, last_year |
| der danach | next_week, next_month, next_quarter, next_year, next_day |
| rollierend zurück | last_hour, last_12_hours, last_24_hours, last_7_days, last_14_days, last_30_days, last_60_days, last_90_days |
| rollierend vorwärts | next_hour, next_12_hours, next_24_hours, next_7_days, next_14_days, next_30_days, next_60_days, next_90_days |
| besonders | birthday_today |
Relativ zu jetzt
greater_than_now und less_than_now nehmen einen Versatz, geschrieben als drei Teile: ein Vorzeichen, eine Zahl und eine Einheit.
Alles, was in den nächsten drei Tagen fällig ist:
{ "field": "due_date", "operator": "less_than_now", "value": ["+", "3", "days"] }
Alles, was seit vierzehn Tagen unangetastet ist:
{ "field": "date_modified", "operator": "less_than_now", "value": ["-", "14", "days"] }
An einem date-Feld heißen die beiden greater_than_today und less_than_today und vergleichen ganze Tage.
Ja und Nein
Ein Ja/Nein-Feld wird über die Wörter abgeglichen, nicht über true und false:
{ "field": "is_reseller", "operator": "equal", "value": "yes" }
{ "field": "is_reseller", "operator": "equal", "value": "no" }
Ein Datensatz, bei dem das Häkchen nie angerührt wurde, ist weder das eine noch das andere und antwortet deshalb auf is_empty.
Referenzen
Jeder Datensatz führt die Ids der Datensätze mit, auf die er zeigt, und die kommen zusammen mit allem anderen in der Antwort zurück:
{ "id": "8873", "account_id": "354", "owner_id": "9", "subscriptions_id": null }
Wenn Sie also bereits eine Id haben, filtern Sie direkt darauf. Alles, was zu einer Firma gehört:
{ "field": "account_id", "operator": "equal", "value": 354 }
Alles, was noch an nichts hängt, was der übliche Weg ist, aufzuräumende Waisen zu finden:
{ "field": "account_id", "operator": "is_empty" }
Eine Referenzregel muss in einer AND-Gruppe stehen. Innerhalb eines OR wird sie abgewiesen, statt stillschweigend etwas anderes zu treffen.
In einen verknüpften Datensatz hineingreifen
Sie können auf ein Feld des Datensatzes am anderen Ende einer Beziehung filtern. So fragen Sie nach „Kontakten, deren Firma soundso heißt", ohne vorher die Firmen zu holen:
{ "field": { "entity": "account", "field": "name" }, "operator": "contains", "value": "acme" }
Die Verknüpfung wird für Sie ermittelt.
Welche Beziehungen es gibt, hängt davon ab, wie Ihr Arbeitsbereich eingerichtet ist, deshalb veröffentlicht die Entität sie:
curl "https://ihre-subdomain.flexie.io/api/contacts/list/filters" \
-H "apikey: IHR_API_SCHLUESSEL"
Einträge mit "related": true sitzen am anderen Ende einer Beziehung, auch Ihre eigenen benutzerdefinierten Entitäten. Ihr field ist ein Objekt statt eines Namens:
{
"label": "Subscription / Status",
"related": true,
"field": {
"entity": "subscriptions",
"relation": "manyToOne",
"through": "subscriptions_id",
"field": "status"
}
}
Setzen Sie dieses Objekt unverändert in eine Regel:
{
"field": { "entity": "subscriptions", "field": "status" },
"operator": "equal",
"value": "past_due"
}
entity und field bestimmen es. Ist eine Entität über mehr als einen Weg erreichbar, ergänzen Sie through, um zu sagen, über welchen. Die Verknüpfung wird für Sie ermittelt, und die Regel sieht gleich aus, ob die Beziehung nun eins-zu-viele oder viele-zu-viele ist. Die Beispiele zeigen das in beide Richtungen, auch zwischen zwei benutzerdefinierten Entitäten.
E-Mail-Abonnement
Ob jemand angeschrieben werden darf, ist kein Feld am Datensatz. Es ist die Frage, ob für seine Adresse eine Abmeldung vorliegt, deshalb wird sie über ein eigenes Feld gestellt, __unsubscribes, und sie nimmt keinen Wert:
{ "field": "__unsubscribes", "operator": "is_subscribed" }
{ "field": "__unsubscribes", "operator": "is_not_subscribed" }
Jeder Datensatz ist das eine oder das andere, die beiden ergeben zusammen also die ganze Menge. Abgeglichen wird über die Adresse, das heißt ein Kontakt und ein Lead mit derselben Adresse sind beide abgemeldet, und ein Datensatz ohne Adresse zählt als angemeldet, weil es nichts gibt, wovon er sich hätte abmelden können.
Kombinieren Sie das wie jede andere Regel. Personen, die sich von E-Mails abgemeldet, Ihnen aber eine Telefonnummer hinterlassen haben:
{
"condition": "AND",
"rules": [
{ "field": "__unsubscribes", "operator": "is_not_subscribed" },
{ "field": "phone", "operator": "is_not_empty" }
]
}
Bedingungen kombinieren
Jede Regel kann stattdessen eine Gruppe sein: Geben Sie ihr eine eigene condition und eigene rules, und Gruppen verschachteln sich so tief, wie Sie es brauchen.
Kontakte, die dieses Jahr hinzugekommen sind und entweder bei Ihrer Domain liegen oder gar keine Adresse haben:
{
"condition": "AND",
"rules": [
{ "field": "date_added", "operator": "is", "value": "this_year" },
{
"condition": "OR",
"rules": [
{ "field": "email", "operator": "contains", "value": "acme.com" },
{ "field": "email", "operator": "is_empty" }
]
}
]
}
Ein durchgerechnetes Beispiel, das das meiste zusammenbringt. Kontakte bei einer Firma, mit mindestens einem Deal, im letzten Monat angefasst, neueste zuerst:
curl -X POST "https://ihre-subdomain.flexie.io/api/contacts/search" \
-H "apikey: IHR_API_SCHLUESSEL" \
-H "Content-Type: application/json" \
-d '{
"filters": {
"condition": "AND",
"rules": [
{ "field": "account_id", "operator": "equal", "value": 354 },
{ "field": "deal_count", "operator": "greater", "value": 0 },
{ "field": "date_modified", "operator": "is", "value": "last_30_days" }
]
},
"orderBy": "date_modified",
"orderByDir": "DESC",
"page": 1,
"limit": 100
}'
Seitenweise abrufen
page und limit laufen ein gefiltertes Ergebnis ab, und total zählt die ganze Menge, nicht die Seite:
{ "filters": { … }, "page": 1, "limit": 100 }
{ "filters": { … }, "page": 2, "limit": 100 }
total_pages in der Antwort sagt Ihnen, wann Schluss ist. Senden Sie immer ein orderBy, wenn Sie blättern, denn ohne garantiert nichts dieselbe Reihenfolge zwischen zwei Anfragen, ein Datensatz kann also zweimal auftauchen oder übersprungen werden.
Benutzerdefinierte Datensätze
Eine benutzerdefinierte Entität filtert genau gleich. Der Pfad führt ihren Tabellennamen, genau so, wie er in Flexie gesetzt ist, klein geschrieben mit Unterstrichen:
curl -X POST "https://ihre-subdomain.flexie.io/api/ce/projects/search" \
-H "apikey: IHR_API_SCHLUESSEL" \
-H "Content-Type: application/json" \
-d '{
"filters": {
"condition": "AND",
"rules": [
{ "field": "project_code", "operator": "begins_with", "value": "AC-2026" },
{ "field": "closed_date", "operator": "is_empty" }
]
},
"limit": 30
}'
Wenn ein Filter abgewiesen wird
Eine Regel, die die Entität nicht beantworten kann, wird mit 400 und Invalid filters abgewiesen:
{ "error": { "code": 400, "message": "Invalid filters" } }
Das ist Absicht. Die Alternative wäre, die Regel zu ignorieren und mit einer ungefilterten Liste und einem 200 zu antworten, was genau aussieht wie ein Filter, der auf alles passt. Die Ursachen:
- ein Feld, das nicht zu den filterbaren Feldern der Entität gehört.
idist eines davon, filtern Sie stattdessen auf ein Feld, das den Datensatz kennzeichnet - ein Operator, den der Typ dieses Feldes nicht annimmt
- eine Referenzregel innerhalb einer
OR-Gruppe - ein fehlerhaft aufgebauter Regelsatz, etwa eine Gruppe ohne
rules
Ein 400 heißt, dass der Filter nie gelaufen ist. Es ist kein Teilergebnis.
Das ältere Filterformat
POST /api/contacts, also die Sammlungs-URL selbst, nimmt ein älteres filters-Array an. Es funktioniert weiterhin, und bestehende Integrationen müssen nichts ändern:
{
"filters": [
{
"type": "text",
"alias": "email",
"value": { "operator": "like", "input": "acme.com" },
"strict": false, "starts": false, "ends": false
}
],
"start": 0,
"limit": 30
}
Seine Operatoren sind eq, neq, gt, gte, lt, lte, like, notLike, in, notIn, isNull und isNotNull, und der Textabgleich wird über drei Ja/Nein-Werte gesteuert statt über den Namen des Operators. like allein ist eine genaue Übereinstimmung. strict: false mit starts und ends beide auf false trifft an jeder Stelle des Feldes, starts: true trifft den Anfang und ends: true das Ende. Lassen Sie starts und ends weg, verhalten sie sich wie true, was aus „an jeder Stelle" stillschweigend „beginnt mit" macht.
Es kennt keine Gruppen, keine Zeiträume und keinen Weg, einen verknüpften Datensatz zu erreichen; nehmen Sie für alles Neue also /search.