# Context pack: Documenten pushen vanuit jouw eigen systemen

Source: https://nordvec.com/nl/docs/guides/how-to/push-documents
Pack: https://nordvec.com/nl/docs/packs/how-to/push-documents

This pack bundles one Nordvec guide with the guides it builds on and the guides it links to, in reading order, so an assistant reading it meets no reference it cannot follow.

## Contents

1. [Verificatie](https://nordvec.com/nl/docs/guides/authentication) (builds on)
2. [Fouten en snelheidslimieten](https://nordvec.com/nl/docs/guides/errors-and-rate-limits) (builds on)
3. [Documenten pushen vanuit jouw eigen systemen](https://nordvec.com/nl/docs/guides/how-to/push-documents) (this guide)
4. [Zoekopdracht filteren en verfijnen](https://nordvec.com/nl/docs/guides/how-to/filter-search) (linked from this guide)
5. [Documenten bekijken en ophalen](https://nordvec.com/nl/docs/guides/how-to/list-documents) (linked from this guide)

---

# Verificatie
Source: https://nordvec.com/nl/docs/guides/authentication

Verifieer API-verzoeken met een werkruimte-API-sleutel die als bearer token wordt verzonden, en kies de sleutelklasse en scopes die een taak nodig heeft.



Een programma roept de Nordvec API aan met een **API-sleutel**, die als bearer token in de `Authorization` header wordt verzonden.

```bash
curl https://nordvec.com/api/v1/documents/list \
  -H "Authorization: Bearer $NORDVEC_API_KEY"
```

Niet elke endpoint vereist een sleutel. Gesprekken, webhooks en sleutelbeheer horen bij een ingelogde persoon en reageren alleen op een sessie; de [API-referentie](/docs/api) geeft bij elke bewerking aan welke credentials worden geaccepteerd.

## Sleutelklassen [#sleutelklassen]

Een sleutel behoort tot één van twee klassen, en het voorvoegsel geeft aan welke:

| Klasse   | Voorvoegsel   | Voor                                                                             |
| -------- | ------------- | -------------------------------------------------------------------------------- |
| Client   | `nv_eu_live_` | Lezen: zoeken, documenten oplijsten en ophalen, quotum, audit trail              |
| Indexing | `nv_eu_idx_`  | Schrijven: documenten pushen, verwijderen en hertoestemmen, ingestie controleren |

## Scopes [#scopes]

Een sleutel bevat één of meer scopes, en een bewerking reageert `403` op een sleutel zonder de vereiste scope. Een sleutel kan alleen scopes van zijn eigen klasse bevatten.

| Scope             | Klasse   | Staat toe                                                                                                                  |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
| `search:read`     | Client   | Documenten zoeken, oplijsten, ophalen en batch-ophalen                                                                     |
| `quota:read`      | Client   | Embedding-quotum en gebruiksanalyses                                                                                       |
| `audit:read`      | Client   | De audit trail van de werkruimte doorzoeken en de evenementencatalogus lezen                                               |
| `index:write`     | Indexing | Documenten en bulk-documenten pushen, hun machtigingen bijwerken                                                           |
| `index:delete`    | Indexing | Gepushte documenten verwijderen                                                                                            |
| `index:status`    | Indexing | Pushstatus en ingestiegezondheid                                                                                           |
| `index:acl-widen` | Indexing | Een reeds-beperkt document zichtbaar maken voor de hele werkruimte. Een sleutel met deze scope moet een vervaldatum hebben |

Geef elke sleutel zo min mogelijk scopes die zijn taak nodig heeft, zodat een gelekte sleutel zo weinig mogelijk kan doen.

## Een sleutel aanmaken [#een-sleutel-aanmaken]

Maak een sleutel aan onder **Instellingen > API-sleutels**. Om er een aan te maken, heb je de rol **eigenaar** of **beheerder** van de werkruimte nodig; in een persoonlijke werkruimte ben jij dat. De **ruwe sleutel wordt exact één keer geretourneerd** en is daarna nooit meer opvraagbaar, dus kopieer hem direct naar jouw geheimenopslag.

Een sleutel behoort tot de werkruimte, niet tot de persoon die hem heeft aangemaakt. Hij leest wat de werkruimte deelt: documenten die een persoon heeft verbonden maar niet gedeeld heeft, blijven alleen zichtbaar voor die persoon, en geen enkele sleutel kan ze zien.

Een sleutel kan ook een vervaldatum (1 tot 3650 dagen) en een IP-toegestaanlijst van maximaal 50 adressen of CIDR-bereiken bevatten.

## Roteren en intrekken [#roteren-en-intrekken]

<Callout type="warn">
  Behandel een API-sleutel als een wachtwoord. Als er één uitlekt, roteer of trek hem dan onmiddellijk in.
</Callout>

* **Roteer** vervangt de credentials van een sleutel op zijn plaats. De vorige credential blijft werken gedurende een respijtperiode die jij kiest: geen, 15 minuten, 1 uur, 6 uur of 24 uur (de standaard), zodat je de nieuwe credential kunt uitrollen naar jouw services zonder downtime.
* **Intrekken** schakelt een sleutel onmiddellijk uit; hij kan niet langer authenticeren.

Beide acties vereisen een ingelogde sessie (ze zijn zelf geen API-sleutelbewerkingen), dus een gelekte sleutel kan niet worden gebruikt om zichzelf te roteren.

## Goede praktijken [#goede-praktijken]

* Bewaar sleutels in een geheimenbeheerder of omgevingsvariabele, nooit in broncode.
* Gebruik een aparte sleutel per service of omgeving, zodat je nauwkeurig kunt intrekken.
* Stel een vervaldatum in voor sleutels voor CI en scripts.


---

# Fouten en snelheidslimieten
Source: https://nordvec.com/nl/docs/guides/errors-and-rate-limits

De foutenvelop die elke mislukte aanvraag retourneert, de snelheidslimiet-headers en hoe je een schrijfopdracht veilig opnieuw kunt proberen.



Elke endpoint faalt op dezelfde manier, dus een client handelt fouten, snelheidslimieten en pogingen opnieuw af door die code één keer te schrijven en overal te hergebruiken, ook via [MCP](/docs/guides/mcp).

## De foutenvelop [#de-foutenvelop]

Elke niet-2xx-respons is één JSON-object:

```json
{
  "defined": false,
  "code": "TOO_MANY_REQUESTS",
  "message": "Too many requests",
  "data": { "reason": "rate_limit.exceeded", "retryAfterMs": 12000 }
}
```

* `code` is de fout op HTTP-niveau, bijvoorbeeld `UNAUTHORIZED`, `FORBIDDEN`,
  `NOT_FOUND`, `BAD_REQUEST` of `TOO_MANY_REQUESTS`.
* `data.reason`, indien aanwezig, is een preciezere machineleesbare reden zoals
  `auth.key_not_found` of `rate_limit.exceeded`. Baseer je hierop in plaats van op
  `message`, dat voor mensen is en kan veranderen.
* `defined` is `true` wanneer de bewerking die fout vermeldt in de
  [API-referentie](/docs/api), en `false` voor fouten die elke aanvraag kan tegenkomen
  (authenticatie, snelheidslimieten, een onbekende route).
* Een validatiefout antwoordt met `BAD_REQUEST` en de problemen in
  `data.formErrors` en `data.fieldErrors`.

Elke respons bevat ook een `X-Request-ID`. Vermeld deze wanneer je contact opneemt met support, zodat we die exacte aanvraag kunnen terugvinden.

## Gangbare statussen [#gangbare-statussen]

| Status | Code                    | Wat te doen                                                                    |
| ------ | ----------------------- | ------------------------------------------------------------------------------ |
| `400`  | `BAD_REQUEST`           | Corrigeer de aanvraag; `data.fieldErrors` benoemt de velden                    |
| `401`  | `UNAUTHORIZED`          | Verstuur een geldige sleutel of sessie                                         |
| `403`  | `FORBIDDEN`             | De sleutel heeft niet de vereiste scope of rol voor de bewerking               |
| `404`  | `NOT_FOUND`             | De resource bestaat niet, of je hebt geen toestemming om deze te zien          |
| `409`  | `CONFLICT`              | Een dubbele schrijfbewerking is nog bezig; probeer het kort daarna opnieuw     |
| `413`  | `PAYLOAD_TOO_LARGE`     | De aanvraagbody is groter dan 1 MB; splits een bulkpush op in kleinere batches |
| `422`  | `UNPROCESSABLE_CONTENT` | De aanvraag is correct gevormd maar kan niet worden toegepast                  |
| `429`  | `TOO_MANY_REQUESTS`     | Wacht `Retry-After`, probeer het dan opnieuw                                   |

## Snelheidslimieten [#snelheidslimieten]

Elke respons geeft de limiet aan waartegen deze is geteld, in twee vormen:

* de `X-RateLimit-*` headers;
* de IETF gestructureerde velden `RateLimit` (live status: `r` is het aantal resterende aanvragen, `t` de seconden tot het venster reset) en `RateLimit-Policy` (de quota: `q` is de limiet, `w` het venster in seconden).

Een `429` bevat ook `Retry-After` in seconden en `data.retryAfterMs`. Wacht minstens zo lang voordat je de volgende aanvraag doet; eerder opnieuw proberen wordt geteld en opnieuw geweigerd.

## Schrijfbewerkingen veilig opnieuw proberen [#schrijfbewerkingen-veilig-opnieuw-proberen]

Een schrijfbewerking die een `Idempotency-Key` header vermeldt in de
[API-referentie](/docs/api), kan opnieuw worden geprobeerd zonder het werk dubbel uit te voeren. Verstuur één sleutel per logische schrijfbewerking en herhaal dezelfde sleutel bij elke poging opnieuw:

* dezelfde sleutel met dezelfde body binnen 24 uur speelt de opgeslagen respons opnieuw af;
* dezelfde sleutel met een andere body wordt geweigerd met `422`;
* een duplicaat dat aankomt terwijl de eerste nog loopt, krijgt `409`.

Een bewerking zonder de header is niet idempotent, dus probeer deze alleen opnieuw als je zeker weet dat de eerste poging niet is geland.


---

# Documenten pushen vanuit jouw eigen systemen
Source: https://nordvec.com/nl/docs/guides/how-to/push-documents

Maak een gegevensbron aan, push documenten erin met een indexing API-sleutel, kies wie ze mag lezen, en pauzeer of verwijder deze wanneer de bron verandert.



De push-API indexeert documenten uit systemen waar Nordvec geen connector voor heeft: een export van een interne wiki, een ticketarchief, een database met notities. Jij stuurt de tekst en bepaalt wie deze mag lezen; Nordvec slaat het op in de EU, indexeert het en maakt het doorzoekbaar en citeerbaar zoals elk ander document. Elk gepusht document komt terecht in een **gegevensbron**, een benoemde container in jouw werkruimte die eerst door een beheerder van de werkruimte wordt aangemaakt. Een push die een niet-bestaande of gepauzeerde gegevensbron noemt, wordt geweigerd.

## Maak een gegevensbron aan [#maak-een-gegevensbron-aan]

Open **Instellingen werkruimte > Gegevensbronnen** en kies **Maak gegevensbron aan**. Beheerders en eigenaren van de werkruimte kunnen dit doen; in een persoonlijke werkruimte ben jij dat.

| Veld | Opmerkingen                                                                                                                                                   |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Naam | Wat mensen zien in de instellingenlijst. Maximaal 200 tekens.                                                                                                 |
| Slug | Wat elke push noemt. Kleine letters, cijfers, `-` en `_`, beginnend met een letter of cijfer, maximaal 200 tekens. Deze kan later niet meer gewijzigd worden. |

De slug `confluence-export` wordt gebruikt in de onderstaande voorbeelden.

## Maak een indexerings-API-sleutel aan [#maak-een-indexerings-api-sleutel-aan]

Pushes authenticeren met een API-sleutel van de **Indexing**-klasse die de `index:write`-scope bevat; voeg `index:status` toe om de opname te volgen en `index:delete` om documenten te verwijderen of een hele gegevensbron te vervangen. Maak er een aan onder **Instellingen werkruimte > API-sleutels**; de onbewerkte sleutel begint met `nv_eu_idx_` en wordt één keer getoond. Zie [Authentication](/docs/guides/authentication). Elk verzoek vermeldt ook jouw werkruimte-id als `tenantId`, de id in het adres van jouw werkruimte in de app (`/w/<workspace id>/...`), en het moet de werkruimte zijn waartoe de sleutel behoort.

## Push één document [#push-één-document]

`/documents/push` maakt het document aan, of werkt het bij wanneer een document met dezelfde `id` al bestaat in de gegevensbron.

```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` is jouw stabiele id voor het document binnen de gegevensbron. Het opnieuw pushen van dezelfde `id` werkt het bij; ongewijzigde inhoud wordt herkend aan de hash en niet twee keer geïndexeerd.
* `body.mimeType` is een van `text/plain`, `text/markdown`, `text/html`, `application/pdf`, of de Word-, Excel- en PowerPoint-typen (`.docx`, `.xlsx`, `.pptx`). Binaire inhoud wordt base64-gecodeerd verzonden.
* `sourceUrl` wordt de "spring naar bron"-link bij elke citering van het document. Laat het weg bij een her-push om de opgeslagen link te behouden, of stuur `null` om deze te wissen.
* `type` stelt het `content_type` van het document in, waarop zoeken en lijsten filteren.

Het hele requestbody is begrensd tot 1 MB, dus een groot bestand of een grote batch antwoordt met `413`; splits het.

## Kies wie het mag lezen [#kies-wie-het-mag-lezen]

`permissions` is vereist bij elke push, zodat er nooit een deelbeslissing wordt genomen door een veld weg te laten. In een gegevensbron die zichtbaar is voor de werkruimte:

| `permissions`                             | Wie het document mag lezen                                         |
| ----------------------------------------- | ------------------------------------------------------------------ |
| `{}`                                      | Elk lid van de werkruimte                                          |
| `{ "allowedUsers": ["ana@example.com"] }` | Alleen de genoemde personen                                        |
| `{ "allowedGroups": ["GROUP_ID"] }`       | Leden van die groepen in de werkruimte, inclusief geneste groepen  |
| `{ "allowAllTenantMembers": false }`      | Geweigerd: een document dat niemand kan lezen, is een verwijdering |

Om te wijzigen wie een document mag lezen zonder de inhoud opnieuw te verzenden, gebruik je `POST /documents/push/permissions`. Het zichtbaar maken van een reeds beperkt document voor de hele werkruimte vereist bovendien de `index:acl-widen`-scope, zodat een routinematige synchronisatie een handmatig ingestelde beperking niet stilletjes kan ongedaan maken.

## Push in batches [#push-in-batches]

`/documents/push/bulk` accepteert tot 100 documenten voor één gegevensbron per oproep. Het antwoord telt `accepted` en `rejected` en geeft een resultaat per document, zodat één slecht document de batch niet laat mislukken. De limiet van 1 MB voor de body geldt per oproep, dus splits grote uploads in meerdere oproepen onder dezelfde `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": {} }
    ]
  }'
```

## Vervang een volledige gegevensbron [#vervang-een-volledige-gegevensbron]

Als jouw systeem alles kan opsommen wat een gegevensbron moet bevatten, stuur dan de volledige lijst als één **uploadsessie**, en de documenten die er niet meer in staan, worden naar de prullenbak verplaatst wanneer de sessie sluit. Sessies hebben een indexing API-sleutel nodig die zowel `index:delete` als `index:write` bevat, omdat het sluiten documenten verwijdert; de sleutel die een sessie opent, is de enige die deze kan voortzetten.

1. Stuur de eerste pagina met `"isFirstPage": true`. Dit is pagina `0`.
2. Stuur elke volgende pagina met zijn `pageIndex` (`1`, `2`, ...), in willekeurige volgorde.
   Een pagina die twee keer wordt verstuurd, telt één keer, dus een herhaling is altijd veilig.
3. Stuur de laatste pagina met `"isLastPage": true` en zijn `pageIndex`. Een lijst die in één pagina past, verstuurt `isFirstPage` en `isLastPage` samen. De laatste pagina mag geen documenten bevatten.

Elke pagina gebruikt dezelfde `uploadId`, en elk antwoord bevat de voortgang van de sessie onder `upload`. De sessie sluit pas wanneer elke pagina van `0` tot de laatste is aangekomen. Het sluiten verplaatst elk document in de gegevensbron dat geen enkele pagina van de sessie heeft genoemd en dat bestond voordat de sessie werd geopend, naar de prullenbak. Elke andere push naar de gegevensbron terwijl de sessie loopt, behoudt het document dat het noemt: een enkele push, een batch zonder sessievelden, een machtigingenupdate en een her-push van ongewijzigde inhoud. De prullenbak bewaart wat het sluiten ernaartoe heeft verplaatst voor 30 dagen; het opnieuw pushen van een document haalt het terug, net als het herstellen van de hele sessie (zie hieronder).

Een sessie die 24 uur lang geen pagina ontvangt, verloopt en wordt afgesloten zonder iets te verwijderen. Een geweigerde pagina krijgt een antwoord met `409 Conflict`, schrijft niets weg, en de `data.reason` geeft aan waarom:

| `reason`                                               | Wat te doen                                                                                                                                                                                                                                                                                                                                                    |
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `upload_incomplete`                                    | Stuur de pagina's vermeld in `missingPageIndexes`, en daarna de laatste pagina opnieuw                                                                                                                                                                                                                                                                         |
| `deletion_confirmation_required`                       | Het sluiten zou meer dan 20% van de gegevensbron naar de prullenbak verplaatsen. Als dat juist is, stuur de laatste pagina opnieuw met `"confirmDeletions"` ingesteld op `wouldTombstone`                                                                                                                                                                      |
| `deletion_confirmation_too_large`                      | `confirmDeletions` is groter dan het aantal documenten dat de gegevensbron bevatte toen de sessie werd geopend. Stuur het aantal dat je verwacht te verwijderen                                                                                                                                                                                                |
| `upload_in_progress`                                   | Er is een sessie actief op deze gegevensbron. Als het jouw sleutel is, voltooi deze, wacht tot deze verloopt, of begin opnieuw met `"forceRestartUpload": true` op jouw eerste pagina. Als een andere sleutel deze heeft geopend, vervangt `forceRestartUpload` deze pas nadat er een uur lang geen pagina is ontvangen, vanaf het tijdstip in `restartableAt` |
| `upload_expired`, `upload_missing`, `upload_restarted` | De sessie is verdwenen; start een nieuwe met een nieuwe `uploadId`                                                                                                                                                                                                                                                                                             |
| `upload_closed`, `upload_id_reused`                    | De `uploadId` is verbruikt; gebruik een nieuwe                                                                                                                                                                                                                                                                                                                 |
| `page_index_required`                                  | Jouw sleutel heeft een sessie actief op deze gegevensbron; stuur `pageIndex` met de pagina                                                                                                                                                                                                                                                                     |

Om na een crash verder te gaan, lees de sessie uit met `GET /documents/push/upload?tenantId=...&datasource=...&uploadId=...` (scope `index:status`). De `missingPageIndexes` vermeldt de pagina's die nog moeten worden verstuurd.

### Ongedaan maken van het sluiten van een sessie [#ongedaan-maken-van-het-sluiten-van-een-sessie]

Als een sessie documenten heeft verwijderd die niet verwijderd hadden mogen worden, bijvoorbeeld omdat de lijst die het heeft verzonden onvolledig was, herstel ze dan in één aanroep:

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

De sleutel die de sessie heeft geopend, kan deze herstellen, en dat geldt ook voor een beheerder van de werkruimte die is ingelogd op Nordvec, voor een sessie die is geopend door elke sleutel. Elk document dat het sluiten naar de prullenbak heeft verplaatst, komt terug met de inhoud die het had, en het antwoord telt ze: `restored` zijn weer live, `purged` waren al definitief verwijderd door de prullenbak, en `skipped` zijn veranderd sinds het sluiten (opnieuw gepusht, of opnieuw verwijderd) en zijn ongewijzigd gelaten. Het tweemaal herstellen van een sessie antwoordt met de aantallen van de eerste herstelactie en `"replayed": true`, en zet elk hersteld document dat nog wacht om geïndexeerd te worden in de wachtrij, dus het herhalen van een herstelactie die niet heeft geantwoord, is veilig. Een sessie kan tot 35 dagen na het sluiten worden hersteld, en zolang de prullenbak nog een document bevat dat deze heeft verwijderd. Een geweigerd herstel wordt beantwoord met `409 Conflict` en de `data.reason`:

| `reason`                 | Wat het betekent                                                                                                                                                                                                                                 |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `upload_not_closed`      | De sessie is nooit gesloten, dus er is niets verwijderd                                                                                                                                                                                          |
| `upload_in_progress`     | Er is een sessie actief op de gegevensbron. Herstel deze nadat deze is gesloten of verlopen                                                                                                                                                      |
| `restore_purged`         | Er zijn meer dan 30 dagen verstreken en de prullenbak heeft elk document verwijderd. Push ze opnieuw                                                                                                                                             |
| `workspace_not_entitled` | Het abonnement van de werkruimte staat momenteel niet toe om uit de prullenbak te herstellen                                                                                                                                                     |
| `corpus_cap_exceeded`    | Het terugbrengen van de documenten zou de documentlimiet van de werkruimte overschrijden, dus er is er geen teruggekomen. `data.wouldRestore` is hoeveel er nodig zijn en `data.headroom` hoeveel er passen. Maak ruimte vrij en herstel opnieuw |

## Volg de opname [#volg-de-opname]

Een push antwoordt zodra het document in de wachtrij staat. Vraag de voortgang op met `GET /documents/push/status` (scope `index:status`), gefilterd op gegevensbron of document-id. Een document gaat van `queued` via `processing` naar `completed`, of naar `failed` met een `error`.

## Wanneer een push wordt geweigerd [#wanneer-een-push-wordt-geweigerd]

Een push die een onbekende of gepauzeerde gegevensbron noemt, wordt beantwoord met `422 Unprocessable Content`. Het bericht vermeldt de slug en linkt naar **Instellingen werkruimte > Gegevensbronnen** in jouw werkruimte, en de foutmelding `data` zegt waarom en wat te doen:

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

Probeer deze niet automatisch opnieuw: ze slagen alleen nadat een beheerder de gegevensbron heeft aangemaakt of hervat.

## Verwijder een document [#verwijder-een-document]

`POST /documents/push/delete` (scope `index:delete`) verwijdert een gepusht document op basis van zijn `datasource` en `id`. Documenten die je niet meer pusht, worden niet vanzelf verwijderd: verwijder elk document dat je niet meer gebruikt, of stuur de volledige lijst van de gegevensbron als een uploadsessie, zoals hierboven beschreven.

## Pauzeren, hervatten en verwijderen [#pauzeren-hervatten-en-verwijderen]

* **Pauzeren** weigert elke verdere push naar de gegevensbron. De documenten blijven doorzoekbaar. Een push die al bezig was met schrijven wanneer je pauzeert, wordt voltooid.
* **Hervatten** accepteert pushes opnieuw.
* **Verwijderen** verwijdert de gegevensbron en elk document dat ernaar is gepusht, inclusief hun zoekindex. Jouw eigen systeem behoudt zijn kopie, dus het opnieuw pushen nadat je de gegevensbron opnieuw hebt aangemaakt, herstelt ze. Een verwijdering kan niet ongedaan worden gemaakt.

Als een andere beheerder de gegevensbron heeft gewijzigd nadat jouw lijst is geladen, wordt de actie geweigerd en laadt de lijst opnieuw, zodat je opnieuw beslist op basis van wat er nu staat. Elke aanmaak, pauze, hervatting en verwijdering wordt vastgelegd in het auditlogboek van de werkruimte.

<Callout>
  De instellingenlijst toont aan wie elke gegevensbron zichtbaar is. Wie een gepusht document mag lezen, wordt bepaald door de `permissions` die ermee is meegestuurd; het aanmaken, pauzeren of verwijderen van een gegevensbron breidt nooit de toegang tot iets uit.
</Callout>

<Callout>
  Push-schrijfacties zijn idempotent: herhaal dezelfde `Idempotency-Key` bij elke herhaling van één schrijfactie, en een duplicaat wordt beantwoord vanuit de eerste poging in plaats van twee keer te worden toegepast. Zie [Fouten en ratelimieten](/docs/guides/errors-and-rate-limits).
</Callout>

## Volgende stappen [#volgende-stappen]

<Cards>
  <Card title="Documenten opsommen en ophalen" href="/docs/guides/how-to/list-documents" />

  <Card title="Zoeken filteren en verfijnen" href="/docs/guides/how-to/filter-search" />

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


---

# Zoekopdracht filteren en verfijnen
Source: https://nordvec.com/nl/docs/guides/how-to/filter-search

Beperk je zoekopdracht naar documenten met filters voor gegevensbron, aanbieder, type en datum, en lees de gerangschikte resultaten.



`/documents/search` voert een full-text zoekopdracht uit over de titel en de volledige tekst van
jouw documenten en retourneert de beste overeenkomsten, elk met een relevantiescore en het
brondocument waar het vandaan kwam. Deze handleiding laat zien hoe de zoekopdracht overeenkomt, hoe je de resultaten kunt verfijnen met filters en hoe je het antwoord kunt lezen.

## Het verzoek [#het-verzoek]

Alleen `query` is vereist. Al het andere beperkt of bepaalt de grenzen van de resultaten.

```bash
curl https://nordvec.com/api/v1/documents/search \
  -H "Authorization: Bearer $NORDVEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "renewal terms",
    "limit": 20,
    "datasource": "contracts",
    "sourceProvider": "google",
    "createdAfter": "2026-01-01T00:00:00Z",
    "createdBefore": "2026-07-01T00:00:00Z"
  }'
```

| Veld             | Type    | Opmerkingen                                                                                                                                       |
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`          | string  | Vereist. 1 tot 500 tekens. Gequoteerde zinsdelen, `or` en een voorafgaande `-` om een woord uit te sluiten worden begrepen.                       |
| `limit`          | integer | Optioneel. 1 tot 50, standaard 20. Aantal resultaten dat wordt teruggegeven.                                                                      |
| `datasource`     | string  | Optioneel. Beperk tot één gegevensbron via de slug (maximaal 200 tekens).                                                                         |
| `sourceProvider` | string  | Optioneel. Beperk tot één connectorprovider, bijvoorbeeld `google`, `sharepoint` of `slack`.                                                      |
| `createdAfter`   | string  | Optioneel. ISO 8601-tijdstempel met offset; alleen documenten die op of na dit tijdstip zijn aangemaakt.                                          |
| `createdBefore`  | string  | Optioneel. ISO 8601-tijdstempel met offset; alleen documenten die op of vóór dit tijdstip zijn aangemaakt.                                        |
| `contentType`    | string  | Optioneel. Beperk tot één kennistype, het `type` dat een gepushte gegevensbron of een kennisbestand opgeeft (bijvoorbeeld `policy` of `runbook`). |

<Callout>
  Elk filter wordt gecombineerd met AND: een document moet overeenkomen met de zoekopdracht **en** elk filter dat je opgeeft. Laat een filter weg om de zoekopdracht te verbreden.
</Callout>

## Hoe de zoekopdracht overeenkomt [#hoe-de-zoekopdracht-overeenkomt]

* **Het hele document wordt doorzocht.** De titel en elke passage van de tekst
  tellen mee, hoe lang het document ook is.
* **Woorden komen overeen in de vorm waarin je ze schrijft, in elke taal.** Er is geen
  stamreductie: `invoice` komt niet overeen met `invoices`, en `tilbagebetaling` komt niet
  overeen met `tilbagebetalingen`. Om meerdere vormen te vangen, voeg je ze samen met `or`.
* **Accenten worden aan beide kanten genegeerd.** `cafe` vindt `café`, en `børnehave`
  en `bornehave` vinden elkaar. Hoofdletters worden ook genegeerd.
* **Operatoren.** Zet woorden tussen dubbele aanhalingstekens om ze als een zin te matchen, schrijf
  `or` tussen woorden om een van beide te matchen, en zet `-` voor een woord om
  documenten die het bevatten uit te sluiten.

## Probeer het uit [#probeer-het-uit]

Als je bent ingelogd, kun je een zoekopdracht uitvoeren over je eigen documenten vanaf deze pagina. Verander de zoekopdracht in de API-referentie om je eigen voorbeelden te proberen.

Try it in the API reference: [`POST /api/v1/documents/search`](https://nordvec.com/docs/api#tag/documents/POST/documents/search) (Search documents).

## Het antwoord [#het-antwoord]

```json
{
  "results": [
    {
      "id": "0198f2a4-6c1e-7d30-b6a1-2f9d54c08a11",
      "title": "Acme Corp Master Services Agreement",
      "snippet": "Automatic **renewal**: the agreement continues for successive twelve month **terms** unless…",
      "score": 0.82,
      "datasource": "contracts",
      "source_provider": "google",
      "source_type": null,
      "mime_type": "application/pdf",
      "content_type": null,
      "status": "indexed",
      "created_at": "2026-02-14T09:00:00Z",
      "updated_at": "2026-02-14T09:00:00Z"
    }
  ],
  "totalCount": 7
}
```

Elk resultaat is één document. De `snippet` is geknipt uit de passage die het best overeenkwam,
ongeacht waar die passage in de tekst staat, met de overeenkomende woorden verpakt in
`**`; een woord dat je zonder accenten hebt getypt, wordt gevonden en gerangschikt, maar kan
onopvallend in de snippet verschijnen. De `score` loopt van 0 tot, maar nooit inclusief, 1
(hoger is relevanter), en de metadata van het brondocument laat je het resultaat terugvolgen.
`totalCount` is het totale aantal documenten dat overeenkwam, wat groter kan zijn dan het aantal
`results` dat je hebt opgevraagd met `limit`.

## De resultaten lezen [#de-resultaten-lezen]

* **Resultaten worden gerangschikt op relevantie**, meest relevant eerst. Een document rangschikt op
  zijn best overeenkomende passage. Gebruik `score` om zwakke overeenkomsten binnen één set resultaten te verwijderen;
  scores van verschillende zoekopdrachten zijn niet op dezelfde schaal.
* **`totalCount` vs `results.length`**: `results` bevat maximaal `limit` items;
  `totalCount` is het volledige aantal overeenkomsten. Als `totalCount` veel groter is dan jouw
  `limit`, maak de `query` dan specifieker of voeg een filter toe; er is geen tweede pagina met zoekresultaten.
* **`status` laat zien waar het document zich in de verwerking bevindt.** Een document wordt
  gematcht op de opgeslagen tekst, dus een document dat nog `processing` kan verschijnen; `indexed`
  betekent dat elke stap is voltooid. Zie
  [Documenten & zoeken](/docs/guides/concepts/documents) voor de levenscyclus.

<Callout>
  Zoeken retourneert alleen documenten die jij mag zien. Toegang wordt afgedwongen in de database,
  niet in de applicatiecode, dus een filter kan nooit uitbreiden wat jij ziet. Voor een API-sleutel is dat wat de werkruimte deelt; zie
  [Wie een document ziet](/docs/guides/concepts/documents#who-sees-a-document).
</Callout>

## Volgende stappen [#volgende-stappen]

<Cards>
  <Card title="Documenten & zoeken" href="/docs/guides/concepts/documents" />

  <Card title="Documenten opsommen en ophalen" href="/docs/guides/how-to/list-documents" />

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


---

# Documenten bekijken en ophalen
Source: https://nordvec.com/nl/docs/guides/how-to/list-documents

Blader door jouw documenten met cursor-paginering, filter en sorteer ze, en haal er één of meerdere op met id.



Waar [zoeken](/docs/guides/how-to/filter-search) documenten rangschikt op relevantie voor
een query, doorloopt listing je hele corpus in volgorde. Gebruik het om te synchroniseren, te controleren of
je eigen index op te bouwen over wat Nordvec bevat. Listing retourneert alleen metadata, geen
documentinhoud.

## Doorlopen met cursor-paginering [#doorlopen-met-cursor-paginering]

`/documents/list` retourneert een pagina met documenten plus een ondoorzichtige `nextCursor`. Geef
die cursor terug om de volgende pagina te krijgen, en stop wanneer `hasMore` `false` is.

```bash
curl "https://nordvec.com/api/v1/documents/list?limit=50" \
  -H "Authorization: Bearer $NORDVEC_API_KEY"
```

```json
{
  "items": [
    { "id": "…", "title": "Q3 Financial Report", "status": "indexed", "datasource": "finance", "created_at": "2026-04-01T10:00:00Z" }
  ],
  "nextCursor": "eyJrIjoi…",
  "hasMore": true
}
```

Als je bent ingelogd, kun je de eerste pagina van je eigen documenten hiervandaan doorlopen:

Try it in the API reference: [`GET /api/v1/documents/list`](https://nordvec.com/docs/api#tag/documents/GET/documents/list) (List documents).

Om elke pagina te doorlopen, herhaal je de aanvraag totdat `hasMore` `false` is, waarbij je elke keer de `nextCursor`
van het vorige antwoord doorgeeft, met dezelfde `sort` en `direction`:

```bash
curl "https://nordvec.com/api/v1/documents/list?limit=50&cursor=eyJrIjoi…" \
  -H "Authorization: Bearer $NORDVEC_API_KEY"
```

<Callout>
  De cursor is ondoorzichtig; parseer of construeer hem niet. Geef exact terug wat het
  vorige antwoord heeft geretourneerd. Een ongeldige cursor, of een cursor uit een andere sortering,
  wordt afgewezen.
</Callout>

## Filteren en sorteren [#filteren-en-sorteren]

Alle filters zijn optioneel en worden gecombineerd met AND. Sorteren gebeurt standaard op nieuwste eerst.

| Veld                             | Type    | Opmerkingen                                                         |
| -------------------------------- | ------- | ------------------------------------------------------------------- |
| `limit`                          | integer | 1 tot 200 (standaard 50).                                           |
| `cursor`                         | string  | Ondoorzichtige cursor van de vorige pagina.                         |
| `datasource`                     | string  | Beperk tot één gegevensbron via de slug (maximaal 200 tekens).      |
| `status`                         | enum    | `indexed`, `processing` of `failed`.                                |
| `sourceProvider`                 | string  | Beperk tot één connectorprovider, bijvoorbeeld `google` of `slack`. |
| `contentType`                    | string  | Beperk tot één kennistype, bijvoorbeeld `policy` of `runbook`.      |
| `createdAfter` / `createdBefore` | string  | ISO 8601-tijdstempels met een offset, beide inclusief.              |
| `sort`                           | enum    | `createdAt` (standaard), `updatedAt` of `title`.                    |
| `direction`                      | enum    | `desc` (standaard) of `asc`.                                        |

```bash
curl "https://nordvec.com/api/v1/documents/list?status=indexed&datasource=finance&sort=updatedAt&direction=desc&limit=100" \
  -H "Authorization: Bearer $NORDVEC_API_KEY"
```

### Welke sortering je moet gebruiken voor doorlopen [#welke-sortering-je-moet-gebruiken-voor-doorlopen]

* **Een volledige, eenmalige opsomming**: `sort=createdAt`. De aanmaaktijd
  verandert nooit, dus elk document verschijnt precies één keer.
* **Incrementele bijwerking vanaf een watermerk**: `sort=updatedAt&direction=asc`. Een
  document dat wordt bijgewerkt terwijl je doorloopt, kan twee keer verschijnen, dus voeg het toe of werk het bij op basis van `id`.
* **Weergavevolgorde**: `updatedAt` of `title` aflopend. Een document dat wordt bijgewerkt
  tussen twee pagina's kan voorbij de cursor bewegen en overgeslagen worden, dus gebruik dit niet
  om te doorlopen.

## Een enkel document ophalen [#een-enkel-document-ophalen]

`/documents/{id}` retourneert de metadata, verwerkingsstatus en tekst van één document.
Een lange tekst kan in vensters worden gelezen: `contentOffset` en `contentMaxChars`
(geteld in UTF-16-code-eenheden) selecteren één venster, en `content_range` rapporteert
het venster en de volledige lengte, dus blijf lezen totdat `offset + length`
`total` bereikt.

```bash
curl "https://nordvec.com/api/v1/documents/DOCUMENT_ID?contentMaxChars=100000" \
  -H "Authorization: Bearer $NORDVEC_API_KEY"
```

## Meerdere tegelijk ophalen [#meerdere-tegelijk-ophalen]

Om tot 200 id's in één aanroep op te lossen, stuur je ze met POST naar `/documents/batch` in plaats van
voor elke id één aanvraag te doen. De batch retourneert metadata en verwerkingsstatus;
`content` is altijd `null`, dus lees de tekst met de aanroep voor één document.

```bash
curl https://nordvec.com/api/v1/documents/batch \
  -H "Authorization: Bearer $NORDVEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["DOCUMENT_ID_1", "DOCUMENT_ID_2"] }'
```

<Callout>
  Listing retourneert, net als zoeken, alleen documenten die de aanroeper mag zien.
  `status` vertelt je waar een document zich in de verwerking bevindt: `processing` terwijl het
  nog wordt geïndexeerd, `failed` wanneer het niet kon worden verwerkt. Zie
  [Documenten & zoeken](/docs/guides/concepts/documents) voor de levenscyclus.
</Callout>

## Volgende stappen [#volgende-stappen]

<Cards>
  <Card title="Zoeken filteren en verfijnen" href="/docs/guides/how-to/filter-search" />

  <Card title="Documenten & zoeken" href="/docs/guides/concepts/documents" />

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