# Poussez des documents depuis vos propres systèmes
Source: https://nordvec.com/fr/docs/guides/how-to/push-documents

Créez une source de données, poussez des documents dans celle-ci avec une clé d'API d'indexation, choisissez qui peut les lire, et mettez-la en pause ou supprimez-la lorsque la source change.



L'API push indexe des documents provenant de systèmes pour lesquels Nordvec ne dispose pas de connecteur : une export de wiki interne, une archive de tickets, une base de données de notes. Vous envoyez le texte et les personnes autorisées à le lire ; Nordvec le stocke dans l'UE, l'indexe et le rend consultable et citable comme tout autre document. Chaque document poussé atterrit dans une **source de données**, un conteneur nommé dans votre espace de travail qu'un administrateur de l'espace de travail crée en premier. Une poussée qui nomme une source de données inexistante ou en pause est refusée.

## Créer une source de données [#créer-une-source-de-données]

Ouvrez **Paramètres de l'espace de travail > Sources de données** et choisissez **Créer une source de données**. Les administrateurs et les propriétaires de l'espace de travail peuvent le faire ; dans un espace de travail personnel, c'est vous.

| Champ | Notes                                                                                                                                                                               |
| ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Nom   | Ce que les utilisateurs voient dans la liste des paramètres. Jusqu'à 200 caractères.                                                                                                |
| Slug  | Ce que chaque poussée nomme. Lettres minuscules, chiffres, `-` et `_`, commençant par une lettre ou un chiffre, jusqu'à 200 caractères. Il ne peut pas être modifié ultérieurement. |

Le slug `confluence-export` est utilisé dans les exemples ci-dessous.

## Créer une clé API d'indexation [#créer-une-clé-api-dindexation]

Les requêtes de push s'authentifient avec une clé API de la classe **Indexation** qui porte le scope `index:write`. Ajoutez `index:status` pour suivre l'ingestion et `index:delete` pour supprimer des documents ou remplacer une source de données entière. Créez-en une sous **Paramètres de l'espace de travail > Clés API** ; la clé brute commence par `nv_eu_idx_` et n'est affichée qu'une fois. Voir [Authentification](/docs/guides/authentication). Chaque requête nomme également l'identifiant de votre espace de travail sous `tenantId`, l'identifiant présent dans l'adresse de votre espace de travail dans l'application (`/w/<workspace id>/...`), et il doit s'agir de l'espace de travail auquel la clé appartient.

## Pousser un document [#pousser-un-document]

`/documents/push` crée le document, ou le met à jour lorsqu'un document avec le même `id` existe déjà dans la source de données.

```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` est votre identifiant stable pour le document au sein de la source de données. Pousser le même `id` à nouveau le met à jour ; un contenu inchangé est reconnu par son hachage et n'est pas indexé deux fois.
* `body.mimeType` est l'un des types suivants : `text/plain`, `text/markdown`, `text/html`, `application/pdf`, ou les types Word, Excel et PowerPoint (`.docx`, `.xlsx`, `.pptx`). Le contenu binaire est envoyé encodé en base64.
* `sourceUrl` devient le lien « sauter à la source » sur chaque citation du document. Omettez-le lors d'une nouvelle poussée pour conserver celui déjà stocké, ou envoyez `null` pour le supprimer.
* `type` définit le `content_type` du document, sur lequel la recherche et les filtres de liste s'appuient.

Le corps de la requête entier est limité à 1 Mo, donc un fichier volumineux ou un grand lot répond `413` ; divisez-le.

## Choisir qui peut le lire [#choisir-qui-peut-le-lire]

`permissions` est requis à chaque poussée, afin qu'une décision de partage ne soit jamais prise en omettant un champ. Dans une source de données visible par l'espace de travail :

| `permissions`                             | Qui peut lire le document                                                          |
| ----------------------------------------- | ---------------------------------------------------------------------------------- |
| `{}`                                      | Tous les membres de l'espace de travail                                            |
| `{ "allowedUsers": ["ana@example.com"] }` | Uniquement les personnes listées                                                   |
| `{ "allowedGroups": ["GROUP_ID"] }`       | Les membres de ces groupes de l'espace de travail, y compris les groupes imbriqués |
| `{ "allowAllTenantMembers": false }`      | Refusé : un document que personne ne peut lire équivaut à une suppression          |

Pour modifier qui peut lire un document sans renvoyer son contenu, utilisez `POST /documents/push/permissions`. Rendre un document déjà restreint visible par tout l'espace de travail nécessite en plus le scope `index:acl-widen`, afin qu'une synchronisation de routine ne puisse pas annuler discrètement une restriction définie manuellement.

## Pousser par lots [#pousser-par-lots]

`/documents/push/bulk` accepte jusqu'à 100 documents pour une seule source de données par appel. La réponse compte `accepted` et `rejected` et donne un résultat par document, de sorte qu'un document défectueux ne fasse pas échouer le lot. La limite de 1 Mo pour le corps s'applique par appel, divisez donc les gros téléchargements en plusieurs appels sous le même `uploadId`.

```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": {} }
    ]
  }'
```

## Remplacer une source de données entière [#remplacer-une-source-de-données-entière]

Lorsque votre système peut lister tout ce qu'une source de données doit contenir, envoyez la liste complète sous la forme d'une **session de téléchargement**, et les documents qu'elle ne contient plus sont déplacés vers la corbeille lorsque la session se ferme. Les sessions nécessitent une clé API d'indexation portant `index:delete` ainsi que `index:write`, car la fermeture supprime des documents ; la clé qui ouvre une session est la seule qui puisse la poursuivre.

1. Envoyez la première page avec `"isFirstPage": true`. Il s'agit de la page `0`.
2. Envoyez chaque page suivante avec son `pageIndex` (`1`, `2`, ...), dans n'importe quel ordre.
   Une page envoyée deux fois n'est comptée qu'une fois, donc une nouvelle tentative est toujours sûre.
3. Envoyez la dernière page avec `"isLastPage": true` et son `pageIndex`. Une liste
   qui tient en une seule page envoie `isFirstPage` et `isLastPage` ensemble. La
   dernière page peut ne contenir aucun document.

Chaque page utilise le même `uploadId`, et chaque réponse contient la progression de la session sous `upload`. La session ne se ferme que lorsque chaque page de `0` à la dernière est arrivée. La fermer déplace vers la corbeille chaque document de la source de données qui n'a pas été nommé par une page de la session et qui existait avant l'ouverture de celle-ci. Toute autre poussée vers la source de données pendant l'exécution de la session conserve le document qu'elle nomme : une poussée unique, un lot sans champs de session, une mise à jour des permissions, et une nouvelle poussée de contenu inchangé de la même manière. La corbeille conserve ce que la fermeture y a déplacé pendant 30 jours ; pousser à nouveau un document le ramène, tout comme la restauration de la session entière (voir ci-dessous).

Une session qui ne reçoit aucune page pendant 24 heures expire et se termine sans rien supprimer. Une page refusée reçoit une réponse `409 Conflict`, n'écrit rien, et son `data.reason` explique pourquoi :

| `reason`                                               | Que faire                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `upload_incomplete`                                    | Envoyez les pages listées dans `missingPageIndexes`, puis envoyez à nouveau la dernière page                                                                                                                                                                                                                                                                            |
| `deletion_confirmation_required`                       | La fermeture déplacerait vers la corbeille plus de 20 % de la source de données. Si cela est correct, envoyez à nouveau la dernière page avec `"confirmDeletions"` défini à `wouldTombstone`                                                                                                                                                                            |
| `deletion_confirmation_too_large`                      | `confirmDeletions` est supérieur au nombre de documents que la source de données contenait lors de l'ouverture de la session. Envoyez le nombre que vous prévoyez de supprimer                                                                                                                                                                                          |
| `upload_in_progress`                                   | Une session est ouverte sur cette source de données. Si c'est votre clé, terminez-la, attendez son expiration ou recommencez avec `"forceRestartUpload": true` sur votre première page. Si une autre clé l'a ouverte, `forceRestartUpload` ne la remplace qu'une fois qu'elle n'a reçu aucune page pendant une heure, à partir de l'heure indiquée dans `restartableAt` |
| `upload_expired`, `upload_missing`, `upload_restarted` | La session a disparu ; commencez-en une nouvelle avec un nouveau `uploadId`                                                                                                                                                                                                                                                                                             |
| `upload_closed`, `upload_id_reused`                    | Le `uploadId` est épuisé ; utilisez-en un nouveau                                                                                                                                                                                                                                                                                                                       |
| `page_index_required`                                  | Votre clé a une session ouverte sur cette source de données ; envoyez `pageIndex` avec la page                                                                                                                                                                                                                                                                          |

Pour reprendre après un plantage, lisez la session avec `GET /documents/push/upload?tenantId=...&datasource=...&uploadId=...` (portée `index:status`). Son `missingPageIndexes` liste les pages encore à envoyer.

### Annuler la fermeture d'une session [#annuler-la-fermeture-dune-session]

Si une session a supprimé des documents qu'elle n'aurait pas dû, par exemple parce que la liste envoyée était incomplète, restaurez-les en un seul appel :

```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" }'
```

La clé qui a ouvert la session peut la restaurer, et un administrateur d'espace de travail connecté à Nordvec peut le faire pour une session ouverte par n'importe quelle clé. Chaque document que la fermeture a déplacé dans la corbeille revient avec son contenu d'origine, et la réponse en compte le nombre : `restored` sont de nouveau actifs, `purged` avaient déjà été définitivement supprimés par la corbeille, et `skipped` avaient changé depuis la fermeture (repoussés ou supprimés à nouveau) et ont été laissés tels quels. Restaurer une session deux fois répond avec les comptes de la première restauration et `"replayed": true`, et met en file d'attente tout document restauré toujours en attente d'indexation. Répéter une restauration qui n'a pas abouti est donc sans risque. Une session peut être restaurée jusqu'à 35 jours après sa fermeture, et tant que la corbeille contient encore un document qu'elle a supprimé. Une restauration refusée est répondue avec `409 Conflict` et son `data.reason` :

| `reason`                 | Signification                                                                                                                                                                                                                                                |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `upload_not_closed`      | La session ne s'est jamais fermée, donc elle n'a rien supprimé                                                                                                                                                                                               |
| `upload_in_progress`     | Une session est ouverte sur la source de données. Restaurez-la une fois qu'elle est fermée ou expirée                                                                                                                                                        |
| `restore_purged`         | Plus de 30 jours se sont écoulés, et la corbeille a supprimé tous les documents. Repoussez-les                                                                                                                                                               |
| `workspace_not_entitled` | Le forfait actuel de votre espace de travail ne permet pas la restauration depuis la corbeille                                                                                                                                                               |
| `corpus_cap_exceeded`    | Le rétablissement des documents dépasserait la limite de documents de votre espace de travail, donc aucun n'est revenu. `data.wouldRestore` indique combien il en faut et `data.headroom` combien il en reste. Libérez de l'espace, puis restaurez à nouveau |

## Suivre l'ingestion [#suivre-lingestion]

Une poussée répond dès que le document est mis en file d'attente. Demandez sa progression avec `GET /documents/push/status` (scope `index:status`), filtrée par source de données ou identifiant de document. Un document passe de `queued` à `processing`, puis à `completed`, ou à `failed` avec un `error`.

## Lorsqu'une poussée est refusée [#lorsquune-poussée-est-refusée]

Une poussée qui nomme une source de données inconnue ou en pause reçoit une réponse `422 Unprocessable Content`. Le message nomme le slug et contient un lien vers **Paramètres de l'espace de travail > Sources de données** dans votre espace de travail, et le `data` de l'erreur indique pourquoi et ce qu'il faut faire :

```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"
  }
}
```

Ne réessayez pas automatiquement ces poussées : elles ne réussissent qu'après qu'un administrateur a créé ou repris la source de données.

## Supprimer un document [#supprimer-un-document]

`POST /documents/push/delete` (portée `index:delete`) supprime un document poussé
par son `datasource` et son `id`. Les documents que vous cessez de pousser ne sont pas supprimés
automatiquement : supprimez chacun de ceux que vous retirez, ou envoyez la liste complète de la source de données
en tant que session de téléversement, comme décrit ci-dessus.

## Mettre en pause, reprendre et supprimer [#mettre-en-pause-reprendre-et-supprimer]

* **Mettre en pause** refuse toute poussée ultérieure dans la source de données. Ses documents restent consultables. Une poussée déjà en cours d'écriture au moment où vous mettez en pause se termine.
* **Reprendre** accepte à nouveau les poussées.
* **Supprimer** retire la source de données et tous les documents qui y ont été poussés, ainsi que leur index de recherche. Votre propre système conserve sa copie, donc pousser à nouveau après avoir recréé la source de données les restaure. Une suppression ne peut pas être annulée.

Si un autre administrateur a modifié la source de données après le chargement de votre liste, l'action est refusée et la liste se recharge, afin que vous puissiez décider à nouveau en fonction de l'état actuel.
Chaque création, pause, reprise et suppression est enregistrée dans le journal d'audit de l'espace de travail.

<Callout>
  La liste des paramètres indique à qui chaque source de données est visible. Qui peut lire un document poussé est déterminé par le `permissions` envoyé avec celui-ci ; créer, mettre en pause ou supprimer une source de données n'élargit jamais l'accès à quoi que ce soit.
</Callout>

<Callout>
  Les écritures push sont idempotentes : répétez le même `Idempotency-Key` à chaque nouvelle tentative d'une même écriture, et un doublon est répondu à partir de la première tentative au lieu d'être appliqué deux fois. Voir [Erreurs et limites de débit](/docs/guides/errors-and-rate-limits).
</Callout>

## Étapes suivantes [#étapes-suivantes]

<Cards>
  <Card title="Lister et récupérer des documents" href="/docs/guides/how-to/list-documents" />

  <Card title="Filtrer et affiner la recherche" href="/docs/guides/how-to/filter-search" />

  <Card title="Référence de l'API" href="/docs/api" />
</Cards>
