# Dokumente aus deinen eigenen Systemen pushen
Source: https://nordvec.com/de/docs/guides/how-to/push-documents

Erstelle eine Datenquelle, pushe Dokumente mit einem Indexing-API-Key hinein, wähle aus, wer sie lesen darf, und pausiere oder lösche sie, wenn sich die Quelle ändert.



Die Push-API indexiert Dokumente aus Systemen, für die Nordvec keinen Connector hat: einen internen Wiki-Export, ein Ticket-Archiv, eine Notizdatenbank. Du sendest den Text und legst fest, wer ihn lesen darf; Nordvec speichert ihn in der EU, indexiert ihn und macht ihn durchsuchbar und zitierbar wie jedes andere Dokument. Jedes gepushte Dokument landet in einer **Datenquelle**, einem benannten Container in deinem Arbeitsbereich, den ein Arbeitsbereich-Admin zuerst erstellt. Ein Push, der eine nicht existierende oder pausierte Datenquelle benennt, wird abgelehnt.

## Datenquelle erstellen [#datenquelle-erstellen]

Öffne **Arbeitsbereich-Einstellungen > Datenquellen** und wähle **Datenquelle erstellen**. Arbeitsbereich-Admins und Eigentümer können das tun; in einem persönlichen Arbeitsbereich bist das du.

| Feld | Hinweise                                                                                                                                                                   |
| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Name | Was Nutzer in der Einstellungsliste sehen. Bis zu 200 Zeichen.                                                                                                             |
| Slug | Was jeder Push benennt. Kleinbuchstaben, Ziffern, `-` und `_`, beginnt mit einem Buchstaben oder einer Ziffer, bis zu 200 Zeichen. Kann später nicht mehr geändert werden. |

Der Slug `confluence-export` wird in den folgenden Beispielen verwendet.

## Indexing-API-Schlüssel erstellen [#indexing-api-schlüssel-erstellen]

Pushes authentifizieren sich mit einem API-Schlüssel der Klasse **Indexing**, der den `index:write`-Scope trägt. Füge `index:status` hinzu, um die Aufnahme zu verfolgen, und `index:delete`, um Dokumente zu entfernen oder eine gesamte Datenquelle zu ersetzen. Erstelle einen unter **Arbeitsbereich-Einstellungen > API-Schlüssel**. Der Rohschlüssel beginnt mit `nv_eu_idx_` und wird nur einmal angezeigt. Siehe [Authentication](/docs/guides/authentication). Jede Anfrage enthält außerdem deine Arbeitsbereich-ID als `tenantId`, die ID in der Adresse deines Arbeitsbereichs in der App (`/w/<workspace id>/...`), und sie muss der Arbeitsbereich sein, zu dem der Schlüssel gehört.

## Ein Dokument pushen [#ein-dokument-pushen]

`/documents/push` erstellt das Dokument oder aktualisiert es, wenn ein Dokument mit demselben `id` bereits in der Datenquelle existiert.

```bash
curl https://nordvec.com/api/v1/documents/push \
  -H "Authorization: Bearer $NORDVEC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: page-4711-2026-09-28" \
  -d '{
    "tenantId": "YOUR_WORKSPACE_ID",
    "document": {
      "id": "page-4711",
      "title": "Travel expense policy",
      "datasource": "confluence-export",
      "body": { "mimeType": "text/markdown", "content": "# Travel expenses\n..." },
      "permissions": {},
      "sourceUrl": "https://wiki.example.com/pages/4711",
      "type": "policy"
    }
  }'
```

```json
{ "documentId": "page-4711", "status": "queued", "updated": false }
```

* `id` ist deine stabile ID für das Dokument innerhalb der Datenquelle. Wenn du denselben `id` erneut übermittelst, wird das Dokument aktualisiert. Unveränderter Inhalt wird anhand seines Hash-Werts erkannt und nicht zweimal indexiert.
* `body.mimeType` ist einer der Typen `text/plain`, `text/markdown`, `text/html`,
  `application/pdf` oder die Word-, Excel- und PowerPoint-Typen (`.docx`, `.xlsx`,
  `.pptx`). Binärinhalte werden base64-kodiert gesendet.
* `sourceUrl` wird zum "Zur Quelle springen"-Link bei jeder Zitierung des Dokuments. Lasse das Feld bei einer erneuten Übermittlung weg, um den gespeicherten Link beizubehalten, oder sende `null`, um ihn zu löschen.
* `type` legt den `content_type` des Dokuments fest, nach dem in der Suche und Filterliste gefiltert wird.

Der gesamte Anfragebody ist auf 1 MB begrenzt, sodass eine große Datei oder ein großer Batch mit `413` antwortet; teile sie auf.

## Entscheide, wer es lesen darf [#entscheide-wer-es-lesen-darf]

`permissions` ist bei jedem Push erforderlich, sodass eine Freigabeentscheidung nie durch Weglassen eines Feldes getroffen wird. In einer für den Arbeitsbereich sichtbaren Datenquelle:

| `permissions`                             | Wer das Dokument lesen darf                                                      |
| ----------------------------------------- | -------------------------------------------------------------------------------- |
| `{}`                                      | Jedes Mitglied des Arbeitsbereichs                                               |
| `{ "allowedUsers": ["ana@example.com"] }` | Nur die aufgelisteten Personen                                                   |
| `{ "allowedGroups": ["GROUP_ID"] }`       | Mitglieder dieser Arbeitsbereich-Gruppen, einschließlich verschachtelter Gruppen |
| `{ "allowAllTenantMembers": false }`      | Abgelehnt: Ein Dokument, das niemand lesen kann, ist ein Löschvorgang            |

Um zu ändern, wer ein Dokument lesen darf, ohne dessen Inhalt erneut zu senden, verwende `POST /documents/push/permissions`. Damit ein bereits eingeschränktes Dokument für den gesamten Arbeitsbereich sichtbar wird, ist zusätzlich der `index:acl-widen`-Scope erforderlich. So kann eine routinemäßige Synchronisierung eine manuell gesetzte Einschränkung nicht unbemerkt aufheben.

## In Batches pushen [#in-batches-pushen]

`/documents/push/bulk` nimmt bis zu 100 Dokumente für eine Datenquelle pro Aufruf entgegen. Die Antwort zählt `accepted` und `rejected` und gibt ein Ergebnis pro Dokument zurück, sodass ein fehlerhaftes Dokument nicht den gesamten Batch fehlschlagen lässt. Die 1-MB-Grenze für den Body gilt pro Aufruf, daher teile große Uploads in mehrere Aufrufe unter derselben `uploadId` auf.

```bash
curl https://nordvec.com/api/v1/documents/push/bulk \
  -H "Authorization: Bearer $NORDVEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tenantId": "YOUR_WORKSPACE_ID",
    "uploadId": "nightly-2026-09-28",
    "datasource": "confluence-export",
    "documents": [
      { "id": "page-4711", "title": "Travel expense policy", "datasource": "confluence-export",
        "body": { "mimeType": "text/plain", "content": "..." }, "permissions": {} }
    ]
  }'
```

## Gesamte Datenquelle ersetzen [#gesamte-datenquelle-ersetzen]

Wenn dein System alles auflisten kann, was eine Datenquelle enthalten soll, sende die vollständige Liste als eine **Upload-Session**, und die Dokumente, die sie nicht mehr enthält, werden in den Papierkorb verschoben, sobald die Session abgeschlossen ist. Sessions benötigen einen Indexing-API-Schlüssel, der sowohl `index:delete` als auch `index:write` enthält, da das Abschließen Dokumente entfernt; der Schlüssel, der eine Session eröffnet, ist der einzige, der sie fortsetzen kann.

1. Sende die erste Seite mit `"isFirstPage": true`. Das ist Seite `0`.
2. Sende jede weitere Seite mit ihrem `pageIndex` (`1`, `2`, ...), in beliebiger Reihenfolge.
   Eine Seite, die zweimal gesendet wird, zählt einmal, daher ist ein erneuter Versuch immer sicher.
3. Sende die letzte Seite mit `"isLastPage": true` und ihrem `pageIndex`. Eine Auflistung,
   die auf eine Seite passt, sendet `isFirstPage` und `isLastPage` zusammen. Die
   letzte Seite darf keine Dokumente enthalten.

Jede Seite verwendet denselben `uploadId`, und jede Antwort enthält den Fortschritt der Session unter `upload`. Die Session schließt erst, wenn jede Seite von `0` bis zur letzten eingetroffen ist. Durch das Schließen werden alle Dokumente in der Datenquelle, die keine Seite der Session benannt hat und die vor dem Öffnen der Session existierten, in den Papierkorb verschoben. Jeder andere Push in die Datenquelle während der Session läuft, behält das Dokument, das er benennt: ein einzelner Push, ein Batch ohne Session-Felder, eine Aktualisierung der Berechtigungen und ein erneutes Pushen unveränderten Inhalts gleichermaßen. Der Papierkorb behält, was das Schließen dorthin verschoben hat, für 30 Tage; ein erneutes Pushen eines Dokuments holt es zurück, und das Gleiche gilt für das Wiederherstellen der gesamten Session (siehe unten).

Eine Sitzung, die 24 Stunden lang keine Seite erhält, läuft ab und schließt ohne Entfernungen. Eine abgelehnte Seite wird mit `409 Conflict` beantwortet, schreibt nichts und ihr `data.reason` erklärt den Grund:

| `reason`                                               | Was zu tun ist                                                                                                                                                                                                                                                                                                                                                                |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `upload_incomplete`                                    | Sende die in `missingPageIndexes` aufgelisteten Seiten, dann die letzte Seite erneut                                                                                                                                                                                                                                                                                          |
| `deletion_confirmation_required`                       | Das Schließen würde mehr als 20 % der Datenquelle in den Papierkorb verschieben. Wenn das korrekt ist, sende die letzte Seite erneut mit `"confirmDeletions"` auf `wouldTombstone` gesetzt                                                                                                                                                                                    |
| `deletion_confirmation_too_large`                      | `confirmDeletions` ist größer als die Anzahl der Dokumente, die die Datenquelle hielt, als die Session geöffnet wurde. Sende die Anzahl, die du entfernen möchtest                                                                                                                                                                                                            |
| `upload_in_progress`                                   | Eine Session ist für diese Datenquelle geöffnet. Wenn es dein Schlüssel ist, beende sie, warte, bis sie abläuft, oder beginne von vorne mit `"forceRestartUpload": true` auf deiner ersten Seite. Wenn ein anderer Schlüssel sie geöffnet hat, ersetzt `forceRestartUpload` sie erst, wenn sie eine Stunde lang keine Seite erhalten hat, ab dem Zeitpunkt in `restartableAt` |
| `upload_expired`, `upload_missing`, `upload_restarted` | Die Session ist verschwunden; starte eine neue mit einem neuen `uploadId`                                                                                                                                                                                                                                                                                                     |
| `upload_closed`, `upload_id_reused`                    | Der `uploadId` ist aufgebraucht; verwende einen neuen                                                                                                                                                                                                                                                                                                                         |
| `page_index_required`                                  | Dein Schlüssel hat eine Session für diese Datenquelle geöffnet; sende `pageIndex` mit der Seite                                                                                                                                                                                                                                                                               |

Um nach einem Absturz fortzufahren, lies die Sitzung mit `GET /documents/push/upload?tenantId=...&datasource=...&uploadId=...` (Bereich `index:status`) aus. Ihr `missingPageIndexes` listet die noch zu sendenden Seiten auf.

### Eine Session-Schließung rückgängig machen [#eine-session-schließung-rückgängig-machen]

Wenn eine Session Dokumente entfernt hat, die nicht entfernt werden sollten, zum Beispiel weil die gesendete Liste unvollständig war, kannst du sie mit einem Aufruf wiederherstellen:

```bash
curl https://nordvec.com/api/v1/documents/push/upload/restore \
  -H "Authorization: Bearer $NORDVEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tenantId": "YOUR_WORKSPACE_ID", "datasource": "confluence-export", "uploadId": "nightly-2026-09-28" }'
```

Der Schlüssel, der die Sitzung geöffnet hat, kann sie wiederherstellen, und das gilt auch für einen Arbeitsbereich-Admin, der bei Nordvec angemeldet ist, für eine von jedem Schlüssel geöffnete Sitzung. Jedes Dokument, das das Schließen in den Papierkorb verschoben hat, kommt mit dem Inhalt zurück, den es hatte, und die Antwort zählt sie: `restored` sind wieder live, `purged` waren bereits endgültig vom Papierkorb gelöscht, und `skipped` hatten sich seit dem Schließen geändert (erneut gepusht oder erneut entfernt) und blieben unverändert. Das Wiederherstellen einer Sitzung zweimal antwortet mit den Zählungen der ersten Wiederherstellung und `"replayed": true` und stellt jedes wiederhergestellte Dokument, das noch auf die Indexierung wartet, in die Warteschlange, sodass das Wiederholen einer fehlgeschlagenen Wiederherstellung sicher ist. Eine Sitzung kann bis zu 35 Tage nach ihrem Schließen wiederhergestellt werden, und so lange, wie der Papierkorb noch ein Dokument enthält, das sie entfernt hat. Eine abgelehnte Wiederherstellung wird mit `409 Conflict` und ihrem `data.reason` beantwortet:

| `reason`                 | Bedeutung                                                                                                                                                                                                                                                         |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `upload_not_closed`      | Die Sitzung wurde nie abgeschlossen, daher hat sie keine Dokumente entfernt                                                                                                                                                                                       |
| `upload_in_progress`     | Eine Sitzung ist für die Datenquelle geöffnet. Stelle sie wieder her, sobald sie abgeschlossen oder abgelaufen ist                                                                                                                                                |
| `restore_purged`         | Es sind mehr als 30 Tage vergangen, und der Papierkorb hat jedes der Dokumente gelöscht. Pushe sie erneut                                                                                                                                                         |
| `workspace_not_entitled` | Der Plan des Arbeitsbereichs erlaubt derzeit keine Wiederherstellung aus dem Papierkorb                                                                                                                                                                           |
| `corpus_cap_exceeded`    | Das Zurückbringen der Dokumente würde das Dokumentenlimit des Arbeitsbereichs überschreiten, daher kam keines zurück. `data.wouldRestore` ist, wie viele benötigt werden, und `data.headroom`, wie viele passen. Schaffe Platz, dann stelle sie erneut wieder her |

## Aufnahme verfolgen [#aufnahme-verfolgen]

Ein Push antwortet, sobald das Dokument in die Warteschlange gestellt wurde. Frage den Fortschritt mit `GET /documents/push/status` (Scope `index:status`) ab, gefiltert nach Datenquelle oder Dokument-ID. Ein Dokument durchläuft die Stati von `queued` über `processing` zu `completed` oder zu `failed` mit einem `error`.

## Wenn ein Push abgelehnt wird [#wenn-ein-push-abgelehnt-wird]

Ein Push, der eine unbekannte oder pausierte Datenquelle benennt, wird mit `422 Unprocessable Content` beantwortet. Die Nachricht enthält den Slug und verlinkt auf **Arbeitsbereich-Einstellungen > Datenquellen** in deinem Arbeitsbereich, und das `data` des Fehlers erklärt, warum und was zu tun ist:

```json
{
  "defined": true,
  "code": "UNPROCESSABLE_CONTENT",
  "status": 422,
  "message": "Datasource \"confluence-export\" is paused and accepts no documents. A workspace admin resumes it under Workspace settings > Datasources: https://nordvec.com/w/YOUR_WORKSPACE_ID/workspace/settings?tab=datasources",
  "data": {
    "why": "The datasource \"confluence-export\" is paused",
    "fix": "Resume it at https://nordvec.com/w/YOUR_WORKSPACE_ID/workspace/settings?tab=datasources, then retry the push",
    "link": "https://nordvec.com/docs/guides/how-to/push-documents"
  }
}
```

Wiederhole diese Anfragen nicht automatisch: Sie sind nur erfolgreich, nachdem ein Admin die Datenquelle erstellt oder fortgesetzt hat.

## Dokument entfernen [#dokument-entfernen]

`POST /documents/push/delete` (Scope `index:delete`) entfernt ein hochgeladenes Dokument anhand seiner `datasource` und `id`. Dokumente, die du nicht mehr hochlädst, werden nicht automatisch gelöscht: Lösche jedes Dokument, das du nicht mehr benötigst, oder sende die vollständige Auflistung der Datenquelle als Upload-Session, wie oben beschrieben.

## Pausieren, fortsetzen und löschen [#pausieren-fortsetzen-und-löschen]

* **Pausieren** lehnt jeden weiteren Push in die Datenquelle ab. Ihre Dokumente bleiben durchsuchbar. Ein Push, der bereits geschrieben wird, wenn du pausierst, wird abgeschlossen.
* **Fortsetzen** akzeptiert Pushes wieder.
* **Löschen** entfernt die Datenquelle und jedes in sie gepushte Dokument, einschließlich ihres Suchindex. Dein eigenes System behält seine Kopie, sodass ein erneutes Pushen nach dem Neuerstellen der Datenquelle sie wiederherstellt. Ein Löschen kann nicht rückgängig gemacht werden.

Wenn ein anderer Admin die Datenquelle geändert hat, nachdem deine Liste geladen wurde, wird die Aktion abgelehnt und die Liste neu geladen, sodass du erneut gegen den aktuellen Stand entscheidest. Jedes Erstellen, Pausieren, Fortsetzen und Löschen wird im Arbeitsbereich-Audit-Log protokolliert.

<Callout>
  Die Einstellungsliste zeigt, für wen jede Datenquelle sichtbar ist. Wer ein gepushtes Dokument lesen darf, wird durch den `permissions` entschieden, der mit ihm gesendet wird; das Erstellen, Pausieren oder Löschen einer Datenquelle erweitert niemals den Zugriff auf etwas.
</Callout>

<Callout>
  Push-Schreibvorgänge sind idempotent: Wiederhole denselben `Idempotency-Key` bei jedem erneuten Versuch eines Schreibvorgangs, und eine Dublette wird aus dem ersten Versuch beantwortet, anstatt zweimal angewendet zu werden. Siehe [Fehler und Ratenlimits](/docs/guides/errors-and-rate-limits).
</Callout>

## Nächste Schritte [#nächste-schritte]

<Cards>
  <Card title="Dokumente auflisten und abrufen" href="/docs/guides/how-to/list-documents" />

  <Card title="Suche filtern und verfeinern" href="/docs/guides/how-to/filter-search" />

  <Card title="API-Referenz" href="/docs/api" />
</Cards>
