> ## Documentation Index
> Fetch the complete documentation index at: https://developers.jobhandy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination, Filterung und Sortierung

> Erstellen Sie präzise Collection-Abfragen mit Seitenverarbeitung, Einzelfeldsortierung, UTC-Zeitfenstern und der Filterausdruckssprache.

Collection-Endpoints verwenden dasselbe Abfragemodell. Jede Operation listet die exakten öffentlichen skalaren Felder auf, die für Filterung und Sortierung zur Verfügung stehen.

## Pagination

| Parameter  | Standard | Einschränkung              |
| ---------- | -------: | -------------------------- |
| `page`     |      `1` | Einsbasierter Integer      |
| `pageSize` |    `100` | Integer von `1` bis `1000` |

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --get 'https://api.jobhandy.io/v1/employees' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --data-urlencode 'page=1' \
  --data-urlencode 'pageSize=250'
```

### Zuverlässige Seitenverarbeitung

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart TD
    A[Tenant und Filterfenster festlegen] --> B[Seite 1 anfordern]
    B --> C[Elemente verarbeiten]
    C --> D[Checkpoint speichern]
    D --> E{Letzte Seite?}
    E -- Nein --> F[Nächste Seite anfordern]
    F --> C
    E -- Ja --> G[Lauf abschließen]
```

Offset-basierte Pagination ist kein Snapshot. Parallele Erstellungen oder Aktualisierungen können spätere Seiten beeinflussen. Verwenden Sie für wiederholbare inkrementelle Verarbeitung einen stabilen fachlichen Checkpoint und ein explizites Zeitfenster, statt davon auszugehen, dass Seiten unverändert bleiben.

### Seitenmetadaten und Randfälle

Collection-Responses enthalten `page`, `pageSize`, `totalPages`, `totalElements` und `items`. Der öffentliche Vertrag definiert kein separates Sonderverhalten für Seiten außerhalb des gültigen Bereichs und keinen exakten `totalPages`-Wert bei null Treffern. Verwenden Sie die Werte aus der Response, statt Annahmen fest zu codieren.

## Sortierung

Verwenden Sie genau ein vom Endpoint unterstütztes skalares Feld. Stellen Sie `-` voran, um absteigend zu sortieren.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
sort=createdAt
sort=-updatedAt
```

Mehrere Felder und Leerzeichen werden abgelehnt. Null-Werte stehen bei aufsteigender Sortierung am Anfang und bei absteigender Sortierung am Ende.

<Warning>
  Ein einzelnes Sortierfeld ist weder ein Idempotenz- noch ein Snapshot-Mechanismus. Speichern Sie verarbeitete Ressourcen-IDs oder Quell-Checkpoints, wenn Duplikate schädlich wären.
</Warning>

## Created-at-Zeitfenster

Wo dokumentiert, sind `createdAtFrom` und `createdAtTo` inklusive ISO-8601-UTC-Zeitstempel mit abschließendem `Z`.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
createdAtFrom=2026-08-01T00:00:00.000Z
createdAtTo=2026-08-31T23:59:59.999Z
```

## Filteroperatoren

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
=  !=  >  >=  <  <=
IN (...)
CONTAINS
STARTS_WITH
ENDS_WITH
IS NULL
IS NOT NULL
```

`AND` bindet stärker als `OR`. Verwenden Sie Klammern, wenn die gewünschte Gruppierung ausdrücklich erkennbar sein soll.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
blocked=false AND (countryCode="DE" OR countryCode="AT")
```

## String-Werte und Anführungszeichen

String-Vergleiche sind case-insensitive. Folgende Formen werden unterstützt:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
lastName=Example
lastName="Example"
lastName='Example'
```

Werte mit Leerzeichen müssen in Anführungszeichen gesetzt werden:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
lastName='van Example'
lastName="van Example"
```

Escapen Sie ein Apostroph mit einem Backslash:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
lastName='O\'Example'
lastName="O\'Example"
```

Die Beispiele zeigen decodierte Filterausdrücke. URL-encodieren Sie den vollständigen Query-Wert. `curl --data-urlencode` wird empfohlen.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --get 'https://api.jobhandy.io/v1/employees' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --data-urlencode 'filter=lastName="van Example"'
```

## `IN`, null und Textoperatoren

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
countryCode IN ("DE","AT","CH")
divisionId IS NULL
privateEmail IS NOT NULL
lastName STARTS_WITH "M"
additionalInfo CONTAINS "Building B"
```

## Formales Ausdrucksmodell

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
expression  = term, { "OR", term };
term        = factor, { "AND", factor };
factor      = comparison | "(", expression, ")";
comparison  = field, operator, value;
```

Der Endpoint bestimmt, welche Felder und Operatoren gültig sind. Ein syntaktisch gültiger Filter kann weiterhin mit `UNSUPPORTED_FILTER_FIELD` oder `UNSUPPORTED_FILTER_OPERATOR` fehlschlagen.

## Grenzen der Query-Größe

Der öffentliche Vertrag nennt keine separate maximale Länge für Filterausdrücke. Halten Sie Ausdrücke begrenzt, bevorzugen Sie mehrere gezielte Anfragen statt eines übermäßig komplexen Ausdrucks und behandeln Sie reguläre Request-Validierungs- oder Größenlimitantworten.

## Filterfehler

| Fehlercode                    | Ursache                                      | Maßnahme                                           |
| ----------------------------- | -------------------------------------------- | -------------------------------------------------- |
| `INVALID_FILTER_SYNTAX`       | Ausdruck kann nicht geparst werden           | Quoting, Escaping, Klammern und `IN`-Syntax prüfen |
| `UNSUPPORTED_FILTER_FIELD`    | Feld ist auf diesem Endpoint nicht filterbar | Ein von der Operation aufgeführtes Feld verwenden  |
| `UNSUPPORTED_FILTER_OPERATOR` | Operator ist für das Feld nicht erlaubt      | Kompatiblen Operator verwenden                     |
| `UNSUPPORTED_SORT_FIELD`      | Sortierfeld ist nicht erlaubt                | Ein dokumentiertes skalares Feld verwenden         |
| `UNKNOWN_QUERY_PARAMETER`     | Query-Name wird nicht unterstützt            | Unbekannten Parameter entfernen                    |
