> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.jarvi.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Suche

> Profile, Unternehmen und Projekte über indizierte Felder mit dem Operator _search filtern

## Warum `_search`

Jarvi betreibt eine Volltextsuchmaschine über deine Daten. Namen, E-Mail-Adressen, Telefonnummern, Jobtitel, Kompetenzen und Werte eigener Felder sind indiziert, und `_search` fragt diese Indizes ab.

Mit `_ilike "%Begriff%"` zu filtern macht etwas völlig anderes: PostgreSQL geht jeden Datensatz deines Arbeitsbereichs durch und vergleicht ihn mit dem Muster. Auf einer Produktivdatenbank wurde ein einzelnes `_ilike` auf einen Nachnamen mit 2,4 Sekunden gemessen; dieselbe Suche über den Index antwortet in einigen zehn Millisekunden.

<Warning>
  `_ilike`, `_like`, `_nilike` und `_nlike` werden am **31. Juli 2027** aus der öffentlichen API
  entfernt.

  Bei den REST-Endpunkten musst du nichts tun — `_ilike`-Filter werden bereits für dich in eine
  indizierte Suche übersetzt, und die Antwort nennt den Filter, der deinen ersetzt hat. Über den
  Endpunkt `/graphql` gehört die Abfrage dir: sie kann jede Tabelle ansprechen, also änderst du sie
  selbst.
</Warning>

## Den Operator verwenden

Ein Filter besteht aus dem Namen eines Suchziels und einem Begriff:

```json theme={null}
{ "quickSearch": { "_search": "Dupont" } }
```

Kombiniere mehrere mit `_and`, `_or` und `_not`, wie bei jedem anderen Filter:

```json theme={null}
{
  "_and": [
    { "globalSearch": { "_search": "javascript" } },
    { "isTalent": true },
    { "addedAt": { "_gte": "2026-01-01" } }
  ]
}
```

### Abfragesyntax

Der Begriff ist selbst eine Abfrage, keine einfache Zeichenkette:

| Syntax                           | Trifft auf                                                       |
| -------------------------------- | ---------------------------------------------------------------- |
| `developer designer`             | eines der beiden Wörter                                          |
| `developer AND designer`         | beide Wörter                                                     |
| `developer AND (java OR kotlin)` | beide, mit einer der beiden Technologien                         |
| `NOT intern`                     | Datensätze ohne dieses Wort                                      |
| `"project manager"`              | genau diese Wortfolge, in dieser Reihenfolge                     |
| `java^10 python`                 | beide Wörter, wobei java in der Rangfolge zehnmal schwerer wiegt |

### Ganze Wörter, keine Fragmente

Namen werden Wort für Wort vom Anfang her indiziert: `Dupo` findet *Dupont*, `upont` nicht. Dasselbe gilt für Unternehmens- und Projektnamen.

E-Mail-Adressen und Telefonnummern sind anders indiziert und treffen ein Fragment an beliebiger Stelle: eine Nummer findest du über ihre letzten Ziffern, eine E-Mail über ihre Domain.

## Die Filter, Ressource für Ressource

Alle folgenden Filter stützen sich auf einen Index. Andere Hasura-Spalten und -Beziehungen werden weiterhin akzeptiert, sind aber weder optimiert noch garantiert.

### Profiles

| Filter                                 | Operators                         | What it matches                                                                                                                                                                                                                          |
| -------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quickSearch`                          | `_search`                         | Searches name, email, phone and short id — the target for simple person or name lookups.                                                                                                                                                 |
| `globalSearch`                         | `_search`                         | Searches name, headline, summary, position titles, company names, skills, educations and custom field values — the target for skill, role or technology searches.                                                                        |
| `emailPhoneAndNameSearch`              | `_search`                         | Searches name, email, phone and short id — the target for simple person or name lookups.                                                                                                                                                 |
| `fullPositionTitleSkillsAndTagsSearch` | `_search`                         | Searches name, headline, summary, position titles, company names, skills, educations and custom field values — the target for skill, role or technology searches.                                                                        |
| `headline`                             | `_search`                         | Headline of the profile: the tagline shown under the name on LinkedIn, or the summary line extracted from the CV for profiles that have no LinkedIn page. Editable by hand only when the profile has no LinkedIn identifier.             |
| `currentPositions.global`              | `_search`                         | Full-text over title, description                                                                                                                                                                                                        |
| `currentPositions.global.title`        | `_search`                         | Job title held at this position, coming from LinkedIn, from a parsed CV or entered by hand. This is the main field behind job title search.                                                                                              |
| `currentPositions.global.description`  | `_search`                         | What the person wrote about this role on their profile or CV. Often empty on imported records.                                                                                                                                           |
| `emails`                               | `_search`                         | Email address of the profile or the company it belongs to. Normalized on save: lowercased, and when the input is not a clean address the first valid one found inside it is kept, the row being dropped if there is none.                |
| `phones`                               | `_search`                         | Phone number search. Only the digits are compared, so a number matches whatever spacing, separators or country prefix it was typed with, and a suffix matches too.                                                                       |
| `profiles.shortId`                     | `_search`                         | Short readable reference for the profile — what users type in quick search and what appears on generated documents. Assigned once at creation and never changes.                                                                         |
| `historyEntries`                       | `_search`                         | Full-text over subject, message                                                                                                                                                                                                          |
| `historyEntries.subject`               | `_search`                         | Subject of the interaction: the email subject, the meeting title, or the job offer title. Empty for channels that carry no subject, such as LinkedIn messages, WhatsApp and SMS.                                                         |
| `historyEntries.message`               | `_search`                         | Content of the interaction: the email body, the text of the LinkedIn, WhatsApp, SMS or Telegram message, or what the recruiter typed for a manual note.                                                                                  |
| `historyEntries.type`                  | `_eq`, `_in`, `_is_null`          | What kind of interaction this entry records: emails, LinkedIn messages and InMails, connection invitations, SMS, WhatsApp, Telegram, phone calls, scheduled meetings, job applications, or a free note.                                  |
| `historyEntries.subTypeId`             | `_eq`, `_in`, `_is_null`          | Optional sub-category of the interaction, defined by the group itself — naming its own kinds of notes or calls, for instance. Each sub-category belongs to a single parent type.                                                         |
| `historyEntries.occurredAt`            | `_eq`, `_gte`, `_lte`, `_is_null` | Single date used to place the interaction on the timeline: the meeting start for a scheduled event, the creation date otherwise. Maintained by a trigger.                                                                                |
| `historyEntries.userId`                | `_eq`, `_in`, `_is_null`          | Jarvi user this entry belongs to. Determines the group the entry is attached to, and is used as its sender by default.                                                                                                                   |
| `historyEntries.hasFiles`              | `true`, `false`                   | The profile has at least one interaction carrying an attached file.                                                                                                                                                                      |
| `historyEntries.hasRecording`          | `true`, `false`                   | The profile has at least one interaction with a meeting recording.                                                                                                                                                                       |
| `customField`                          | `_search`                         | Value of a custom field. Target one field by suffixing its id, as in "customField.\<fieldId>".                                                                                                                                           |
| `location`                             | `_near`                           | Geographic search. Use range 0 for an exact city or region match, or a radius in meters.                                                                                                                                                 |
| `hasEmail`                             | `true`, `false`                   | The profile has at least one email address.                                                                                                                                                                                              |
| `hasEmailType`                         | `_eq`, `_in`, `_is_null`          | The profile has an email address of this type. Takes the same values as the type of an email address.                                                                                                                                    |
| `hasPhone`                             | `true`, `false`                   | The profile has at least one phone number.                                                                                                                                                                                               |
| `hasValidPhone`                        | `true`, `false`                   | The profile has at least one phone number not marked as invalid.                                                                                                                                                                         |
| `hasLocation`                          | `true`, `false`                   | The profile has at least one location.                                                                                                                                                                                                   |
| `hasPhoneType`                         | `_eq`, `_in`, `_is_null`          | The profile has a phone number of this type. Takes the same values as the type of a phone number.                                                                                                                                        |
| `hasWhatsApp`                          | `true`, `false`                   | The profile has a phone number reachable on WhatsApp.                                                                                                                                                                                    |
| `isTalent`                             | `true`, `false`                   | The profile is a talent — someone you recruit, followed in the ATS. A profile can be a talent and a contact at once.                                                                                                                     |
| `isContact`                            | `true`, `false`                   | The profile is a contact — a client or a hiring manager, followed in the CRM. A profile can be a contact and a talent at once.                                                                                                           |
| `hasLinkedin`                          | `true`, `false`                   | The profile is matched to a LinkedIn account.                                                                                                                                                                                            |
| `hasResume`                            | `true`, `false`                   | The profile has at least one CV attached.                                                                                                                                                                                                |
| `isConnectedOnLinkedinWithMe`          | `true`, `false`                   | The calling user is connected with this profile on LinkedIn, as recorded in the profile's history.                                                                                                                                       |
| `hasReplied`                           | `true`, `false`                   | The profile has answered at least once, on any channel.                                                                                                                                                                                  |
| `hasScheduledMessage`                  | `true`, `false`                   | A message or a connection invitation is still waiting to be sent to this profile.                                                                                                                                                        |
| `hasUnreadMessagesNotifications`       | `true`, `false`                   | The profile has an unread message notification.                                                                                                                                                                                          |
| `firstPositionStartDate`               | `_eq`, `_gte`, `_lte`, `_is_null` | Start date of the earliest position on the profile — the usual way to reason about years of experience.                                                                                                                                  |
| `lastPositionStartDate`                | `_eq`, `_gte`, `_lte`, `_is_null` | Start date of the current position, that is the one with no end date.                                                                                                                                                                    |
| `currentPositions.companyId`           | `_eq`, `_in`, `_is_null`          | The profile currently works at this company. Takes the identifier of the LinkedIn company page, not a Jarvi company id.                                                                                                                  |
| `projectId`                            | `_eq`, `_in`, `_is_null`          | The profile is associated with this project.                                                                                                                                                                                             |
| `statusId`                             | `_eq`, `_in`, `_is_null`          | Status of the profile. A parent status also matches profiles carrying any of its children, and the search is narrowed by the project or entity given in the context. Pass "other" for profiles whose status has no parent.               |
| `hasProject`                           | `true`, `false`                   | The profile is associated with at least one project.                                                                                                                                                                                     |
| `projectCount`                         | `_eq`, `_gte`, `_lte`, `_is_null` | How many distinct projects the profile is associated with.                                                                                                                                                                               |
| `emptyCustomFields`                    | `_all`, `_in`                     | Custom field UUIDs. \_all requires every field, \_in requires any of them.                                                                                                                                                               |
| `filledCustomFields`                   | `_all`, `_in`                     | Custom field UUIDs. \_all requires every field, \_in requires any of them.                                                                                                                                                               |
| `isInCrm`                              | `true`, `false`                   | The profile is followed in the CRM, meaning it is a contact. Same as isContact.                                                                                                                                                          |
| `isInAts`                              | `true`, `false`                   | The profile is followed in the ATS, meaning it is a talent. Same as isTalent.                                                                                                                                                            |
| `hasAttachedFiles`                     | `true`, `false`                   | The profile has at least one attached file.                                                                                                                                                                                              |
| `isOpenToNewOpportunities`             | `true`, `false`                   | The profile is flagged as open to new opportunities.                                                                                                                                                                                     |
| `isHiring`                             | `true`, `false`                   | The profile is flagged as hiring.                                                                                                                                                                                                        |
| `id`                                   | `_eq`, `_in`, `_is_null`          | Jarvi identifier of the profile, used in the public API and in app URLs.                                                                                                                                                                 |
| `createdAt`                            | `_eq`, `_gte`, `_lte`, `_is_null` | Technical timestamp of the row creation. For the date the profile entered the base, use addedAt (added\_at) instead.                                                                                                                     |
| `addedAt`                              | `_eq`, `_gte`, `_lte`, `_is_null` | Date the profile entered the group's base — what recruiters read as "added on". Set automatically when the profile is created or restored, unless the caller provides its own value, which is what imports do to keep the original date. |
| `externalId`                           | `_eq`, `_in`                      | Identifier of the profile in the client's own system — their ATS, their CRM, or whatever calls the public API. Never a Jarvi identifier. Unique per group, and used to recognise a profile that is sent again.                           |
| `publicIdentifier`                     | `_eq`, `_in`                      | LinkedIn public slug, the part after linkedin.com/in/. Unique per group. The person can change it on LinkedIn, which makes it the least reliable of the LinkedIn identifiers.                                                            |
| `linkedinId`                           | `_eq`, `_in`                      | Numeric LinkedIn identifier of the person. Unique per group. Not to be confused with memberId (member\_id), which holds the obfuscated "ACoAA…" identifier, nor with publicIdentifier (public\_identifier), which holds the URL slug.    |
| `primaryLocale`                        | `_eq`, `_in`, `_is_null`          | Main language of the profile itself — the language its LinkedIn page or CV is written in. Different from the profiles\_locales table, which lists the languages the person speaks and how well.                                          |
| `auditLogs.createdAt`                  | `_eq`, `_gte`, `_lte`, `_is_null` | When the tracked change happened. This is the reference date for incremental synchronisation: fetching everything modified since a given date goes through this column.                                                                  |

### Companies

| Filter                 | Operators                         | What it matches                                                                                                                                                         |
| ---------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `companySearch`        | `_search`                         | Searches company name and description, LinkedIn tagline and description, legal activity and NAF code, and custom fields — the target for keyword or industry searches.  |
| `companyQuickSearch`   | `_search`                         | Searches company name, email and phone — for name lookups only.                                                                                                         |
| `companies.global`     | `_search`                         | Company name and description.                                                                                                                                           |
| `location`             | `_near`                           | Geographic search. Use range 0 for an exact city or region match, or a radius in meters.                                                                                |
| `customField`          | `_search`                         | Value of a custom field. Target one field by suffixing its id, as in "customField.\<fieldId>".                                                                          |
| `hasLinkedinCompanyId` | `true`, `false`                   | The company is matched to a LinkedIn company page.                                                                                                                      |
| `hasContacts`          | `true`, `false`                   | The company has at least one profile associated as a contact.                                                                                                           |
| `hasProject`           | `true`, `false`                   | The company has at least one project.                                                                                                                                   |
| `isParentCompany`      | `true`, `false`                   | The company has at least one subsidiary.                                                                                                                                |
| `isSubsidiary`         | `true`, `false`                   | The company has a parent company.                                                                                                                                       |
| `isProtected`          | `true`, `false`                   | The company is under protection, meaning its protection date is still in the future.                                                                                    |
| `statusId`             | `_eq`, `_in`, `_is_null`          | Status of the company. A parent status also matches companies carrying any of its children.                                                                             |
| `filledCustomFields`   | `_all`, `_in`                     | Custom field UUIDs. \_all requires every field, \_in requires any of them.                                                                                              |
| `emptyCustomFields`    | `_all`, `_in`                     | Custom field UUIDs. \_all requires every field, \_in requires any of them.                                                                                              |
| `id`                   | `_eq`, `_in`, `_is_null`          | Jarvi identifier of the company, used in the public API and in app URLs.                                                                                                |
| `createdAt`            | `_eq`, `_gte`, `_lte`, `_is_null` | Date the company record was created. Data imports replace it with the creation date coming from the source ATS or CRM.                                                  |
| `externalId`           | `_eq`, `_in`                      | Identifier of the company in the client's own system. Unique per group, and used as the matching key by imports and by the public API.                                  |
| `linkedinCompanyId`    | `_eq`, `_in`                      | Link to the LinkedIn page data of this company. That data is shared across all groups, and a given LinkedIn page can be attached to at most one company per group.      |
| `parentId`             | `_eq`, `_in`, `_is_null`          | Parent company when this record is a subsidiary. Used as a single level: searching on a parent can include its direct subsidiaries, but not their own.                  |
| `auditLogs.createdAt`  | `_eq`, `_gte`, `_lte`, `_is_null` | When the tracked change happened. This is the reference date for incremental synchronisation: fetching everything modified since a given date goes through this column. |

### Projects

| Filter                | Operators                         | What it matches                                                                                                                                                         |
| --------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `projectNameSearch`   | `_search`                         | Searches project name, its company name and its reference id — the target for project lookups.                                                                          |
| `customField`         | `_search`                         | Value of a custom field. Target one field by suffixing its id, as in "customField.\<fieldId>".                                                                          |
| `hasJobBoardEnabled`  | `true`, `false`                   | The project is published on at least one job board.                                                                                                                     |
| `hasLinkedinId`       | `true`, `false`                   | The project is matched to a LinkedIn job posting.                                                                                                                       |
| `filledCustomFields`  | `_all`, `_in`                     | Custom field UUIDs. \_all requires every field, \_in requires any of them.                                                                                              |
| `emptyCustomFields`   | `_all`, `_in`                     | Custom field UUIDs. \_all requires every field, \_in requires any of them.                                                                                              |
| `statusId`            | `_eq`, `_in`, `_is_null`          | Status of the project. A parent status also matches projects carrying any of its children.                                                                              |
| `id`                  | `_eq`, `_in`, `_is_null`          | Jarvi identifier of the project, used in the public API and in app URLs.                                                                                                |
| `createdAt`           | `_eq`, `_gte`, `_lte`, `_is_null` | Date the project was created. Data imports replace it with the creation date coming from the source ATS or CRM.                                                         |
| `externalId`          | `_eq`, `_in`                      | Identifier of the project in the client's own system. Unique per group, and used as the matching key by imports and by the public API.                                  |
| `referenceId`         | `_eq`, `_in`                      | The project reference id is used to map external job applications on website or jobboard to the project.                                                                |
| `companyId`           | `_eq`, `_in`, `_is_null`          | Client company the project is for. Optional — a project can exist without a company, and deleting the company clears the link rather than the project.                  |
| `auditLogs.createdAt` | `_eq`, `_gte`, `_lte`, `_is_null` | When the tracked change happened. This is the reference date for incremental synchronisation: fetching everything modified since a given date goes through this column. |

<Info>
  Diese Listen werden von der Suchmaschine selbst erzeugt und entsprechen damit immer dem, was die
  API akzeptiert. Dieselben Definitionen werden als JSON Schema von [GET
  /openapi](https://functions.prod.jarvi.tech/v1/public-api/openapi) ausgeliefert, unter
  `ProfilesFilters`, `CompaniesFilters` und `ProjectsFilters`.
</Info>

## Sortieren

Der Parameter `orderBy` jedes REST-Endpunkts verbindet ein Feld mit einer Richtung:

```
?orderBy={"addedAt":"desc"}
```

Welche Felder eine Ressource akzeptiert, steht in der Dokumentation des Parameters selbst, auf der Seite des Endpunkts. Nach etwas anderem zu sortieren fällt auf die Standardreihenfolge zurück, statt zu scheitern.

## Über GraphQL suchen

Die Query `search` liefert Bezeichner und eine Gesamtzahl, die du anschließend mit einem zweiten Aufruf lädst. Diese Aufteilung in zwei Schritte hält eine Suche schnell, unabhängig von der Größe der Datensätze:

```graphql theme={null}
query FindDevelopers {
  search(
    resource: "profiles"
    filters: { globalSearch: { _search: "javascript AND react" }, isTalent: true }
    sort: { field: "addedAt", order: "DESC" }
    limit: 50
  ) {
    ids
    total
  }
}
```

```graphql theme={null}
query LoadThem($ids: [uuid!]!) {
  profiles(where: { id: { _in: $ids } }) {
    id
    firstName
    lastName
  }
}
```

`resource` ist `profiles`, `companies` oder `projects`. `filters` nimmt dasselbe Objekt wie der REST-Parameter `where`.

## Weg von `_ilike`

| Statt                                                     | Schreibe                                      |
| --------------------------------------------------------- | --------------------------------------------- |
| `{"lastName": {"_ilike": "%Dupont%"}}`                    | `{"quickSearch": {"_search": "Dupont"}}`      |
| `{"emailAddresses": {"email": {"_ilike": "%@acme.com"}}}` | `{"emails": {"_search": "acme.com"}}`         |
| `{"headline": {"_ilike": "%developer%"}}`                 | `{"globalSearch": {"_search": "developer"}}`  |
| `{"name": {"_ilike": "%Acme%"}}` (Unternehmen)            | `{"companyQuickSearch": {"_search": "Acme"}}` |
| `{"externalId": {"_ilike": "ABC-123"}}`                   | `{"externalId": {"_eq": "ABC-123"}}`          |

Ein Bezeichner oder eine URL ist nie eine Suche: nimm `_eq`, das über seinen eigenen Index läuft.

<Note>
  Fehlt dir etwas, oder findest du einen erwarteten Filter nicht? Schreib uns — die Liste oben wird
  von der Suchmaschine gesteuert, einen Filter hinzuzufügen ist eine kleine Änderung.
</Note>
