Datensätze finden

Zuletzt aktualisiert 17 August 2026

Ein Regelsatz, an den Such-Endpunkt gesendet, daneben die Anzahl und die Seite, die zurückkommen

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. id ist 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.