# Context pack: Feil og ratelimiter

Source: https://nordvec.com/no/docs/guides/errors-and-rate-limits
Pack: https://nordvec.com/no/docs/packs/errors-and-rate-limits

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. [Feil og ratelimiter](https://nordvec.com/no/docs/guides/errors-and-rate-limits) (this guide)
2. [MCP](https://nordvec.com/no/docs/guides/mcp) (linked from this guide)

---

# Feil og ratelimiter
Source: https://nordvec.com/no/docs/guides/errors-and-rate-limits

Den ene feilenveloppen som hvert mislykkede forespørsel returnerer, ratelimit-hodene, og hvordan du kan prøve en skriving på nytt på en trygg måte.



Hvert endepunkt feiler på samme måte, så en klient håndterer feil, ratelimiter og
omforsøk én gang og gjenbruker den koden overalt, inkludert over
[MCP](/docs/guides/mcp).

## Feilkonvolutten [#feilkonvolutten]

Hvert ikke-2xx-svar er ett JSON-objekt:

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

* `code` er HTTP-nivåfeilen, for eksempel `UNAUTHORIZED`, `FORBIDDEN`,
  `NOT_FOUND`, `BAD_REQUEST` eller `TOO_MANY_REQUESTS`.
* `data.reason`, når til stede, er en mer presis maskinlesbar årsak som
  `auth.key_not_found` eller `rate_limit.exceeded`. Forgrening baseres på denne i stedet for på
  `message`, som er for mennesker og kan endre seg.
* `defined` er `true` når operasjonen lister den feilen i
  [API-referansen](/docs/api), og `false` for feil enhver forespørsel kan møte
  (autentisering, ratelimiter, en ukjent rute).
* Et valideringsproblem svarer med `BAD_REQUEST` med problemene i
  `data.formErrors` og `data.fieldErrors`.

Hvert svar inneholder også en `X-Request-ID`. Oppgi den når du kontakter
support, så kan vi finne akkurat den forespørselen.

## Vanlige statuskoder [#vanlige-statuskoder]

| Status | Kode                    | Hva du skal gjøre                                                         |
| ------ | ----------------------- | ------------------------------------------------------------------------- |
| `400`  | `BAD_REQUEST`           | Rett forespørselen; `data.fieldErrors` navngir feltene                    |
| `401`  | `UNAUTHORIZED`          | Send en gyldig nøkkel eller sesjon                                        |
| `403`  | `FORBIDDEN`             | Nøkkelen mangler scopet eller rollen operasjonen trenger                  |
| `404`  | `NOT_FOUND`             | Ressursen finnes ikke, eller du har ikke tilgang til å se den             |
| `409`  | `CONFLICT`              | En duplikat skriving er fortsatt under behandling; prøv igjen om kort tid |
| `413`  | `PAYLOAD_TOO_LARGE`     | Forespørselsteksten er over 1 MB; del en bulk-push i mindre batcher       |
| `422`  | `UNPROCESSABLE_CONTENT` | Forespørselen er velformet, men kan ikke utføres                          |
| `429`  | `TOO_MANY_REQUESTS`     | Vent i `Retry-After`, så prøv igjen                                       |

## Ratelimiter [#ratelimiter]

Hvert svar oppgir grensen det ble telt mot, i to former:

* `X-RateLimit-*`-headerne;
* de IETF-strukturerte feltene `RateLimit` (live-tilstand: `r` er gjenværende forespørsler,
  `t` sekunder til vinduet nullstilles) og `RateLimit-Policy`
  (kvoten: `q` er grensen, `w` vinduet i sekunder).

Et `429` inneholder også `Retry-After` i sekunder og `data.retryAfterMs`. Vent minst så lenge
før neste forespørsel; å prøve igjen tidligere telles og avslås på nytt.

## Sikker omprøving av skriveoperasjoner [#sikker-omprøving-av-skriveoperasjoner]

En skriveoperasjon som lister en `Idempotency-Key`-header i
[API-referansen](/docs/api) kan prøves på nytt uten å utføre arbeidet to ganger. Send
én nøkkel per logisk skriving og gjenta samme nøkkel ved hvert omforsøk:

* samme nøkkel med samme kropp innen 24 timer spiller av det lagrede svaret;
* samme nøkkel med ulik kropp avslås med `422`;
* et duplikat som ankommer mens den første fortsatt kjører får `409`.

En operasjon uten headeren er ikke idempotent, så prøv den bare på nytt når du
vet at det første forsøket ikke ble gjennomført.


---

# MCP
Source: https://nordvec.com/no/docs/guides/mcp

Koble en KI-agent til kunnskapsbasen din i arbeidsområdet over Model Context Protocol med en API-nøkkel.



Nordvec støtter [Model Context Protocol](https://modelcontextprotocol.io) (MCP), slik at en agent eller assistent som snakker MCP kan oppdage operasjonene i arbeidsområdet ditt som verktøy og kalle dem direkte, uten et OpenAPI-dokument å resonnere over.

Det finnes to servere:

| Server        | URL                              | Autentisering | Hva den eksponerer                                                                                                         |
| ------------- | -------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------- |
| Dokumentasjon | `https://nordvec.com/api/mcp`    | ingen         | Disse guidene og koblingkatalogen, for en agent som integrerer med Nordvec                                                 |
| Kunnskapsbase | `https://nordvec.com/api/v1/mcp` | API-nøkkel    | Dokumentene, søket og inntaket i arbeidsområdet ditt: de samme operasjonene som [REST API-et](/docs/guides/authentication) |

Begge kjører i EU, på samme infrastruktur som resten av API-et.

## Koble til en klient [#koble-til-en-klient]

Pek en MCP-klient mot kunnskapsbaseserveren med API-nøkkelen din som bearer-token. De fleste klienter tar en konfigurasjonsblokk som denne:

```json
{
  "mcpServers": {
    "nordvec": {
      "url": "https://nordvec.com/api/v1/mcp",
      "headers": {
        "Authorization": "Bearer nv_eu_live_your_api_key"
      }
    }
  }
}
```

Serveren er stateless Streamable HTTP: hver melding er én `POST` som bærer én JSON-RPC-forespørsel, og svaret kommer tilbake i responsens body. Det finnes ingen sesjoner å opprettholde og ingen serverinitierte strømmer, så en `GET` på URL-en svarer med `405`, og en `POST` hvis `Content-Type` ikke er `application/json` svarer med `415` før bodyen leses.

<Callout type="warn">
  Bare en API-nøkkel kan bruke kunnskapsbaseserveren. En pålogget nettlesersesjon avvises, og hvert verktøy trenger nøkkelomfanget som den tilsvarende REST-operasjonen krever, så en nøkkel opprettet for én jobb kan gjøre akkurat den jobben via MCP også.
</Callout>

Serveren autentiserer med en statisk bearer-nøkkel og tilbyr ikke OAuth-discovery. En klient som lar deg sette forespørselshoder (kodeagenter, IDE-utvidelser, MCP Inspector i hode-modus) kobler til som vist over. En hostet klient som kun støtter OAuth-autentiseringsflyten kan ikke koble til ennå.

En klient som sender `MCP-Protocol-Version`-hodet blir besvart under den versjonen når serveren støtter den (`2025-06-18` og `2024-11-05`), og avvist med `400` når den ikke gjør det. Dermed rapporteres en versjonskonflikt ved første melding, i stedet for som et feilformet svar senere.

## Verktøy [#verktøy]

Verktøyene er avledet fra REST API-et, ett verktøy per operasjon en API-nøkkel kan kalle. Et verktøys navn er operasjonens kontraktbane i snake case, der et segment som gjentar det forrige droppes. Omfangskolonnen er API-nøkkelomfanget verktøyet trenger:

| REST-operasjon                        | Kontraktbane                         | MCP-verktøy                        | Omfang         |
| ------------------------------------- | ------------------------------------ | ---------------------------------- | -------------- |
| `POST /documents/search`              | `documents.search`                   | `documents_search`                 | `search:read`  |
| `GET /documents/{id}`                 | `documents.get`                      | `documents_get`                    | `search:read`  |
| `POST /documents/batch`               | `documents.batchGet`                 | `documents_batch_get`              | `search:read`  |
| `GET /documents/list`                 | `documents.list`                     | `documents_list`                   | `search:read`  |
| `POST /documents/push`                | `documentPush.push`                  | `document_push`                    | `index:write`  |
| `POST /documents/push/bulk`           | `documentPush.pushBulk`              | `document_push_bulk`               | `index:write`  |
| `POST /documents/push/permissions`    | `documentPush.pushUpdatePermissions` | `document_push_update_permissions` | `index:write`  |
| `POST /documents/push/delete`         | `documentPush.pushDelete`            | `document_push_delete`             | `index:delete` |
| `GET /documents/push/status`          | `documentPush.pushStatus`            | `document_push_status`             | `index:status` |
| `GET /documents/push/upload`          | `documentPush.pushUploadStatus`      | `document_push_upload_status`      | `index:status` |
| `POST /documents/push/upload/restore` | `documentPush.pushUploadRestore`     | `document_push_upload_restore`     | `index:write`  |
| `GET /analytics/ingestion`            | `analytics.ingestion`                | `analytics_ingestion`              | `index:status` |
| `GET /quota/embedding`                | `quota.embedding`                    | `quota_embedding`                  | `quota:read`   |
| `GET /analytics/usage`                | `analytics.usage`                    | `analytics_usage`                  | `quota:read`   |
| `POST /tenant/audit-log/search`       | `auditLog.list`                      | `audit_log_list`                   | `audit:read`   |
| `GET /tenant/audit-log/catalog`       | `auditLog.catalog`                   | `audit_log_catalog`                | `audit:read`   |

`tools/list` er den autoritative katalogen: den viser bare nøklene verktøyene dens omfang tillater, og hvert verktøys beskrivelse navngir omfanget det krever. Et verktøys `inputSchema` er operasjonens forespørselsskjema, og der operasjonen returnerer et objekt, er `outputSchema` svarsskjemaet, og resultater bærer `structuredContent` sammen med JSON-teksten.

Å kalle et verktøy som nøkkelens omfang ikke tillater, svarer med en verktøyfeil som navngir `FORBIDDEN`, samme avslag som REST-ruten gir. Dermed får en klient som holder en mellomlagret liste fra en annen nøkkel vite hvorfor, i stedet for bare at verktøyet mangler.

## Prøv på nytt et skriving [#prøv-på-nytt-et-skriving]

`document_push` og `document_push_bulk` tar et valgfritt `idempotencyKey`-argument, slik at en agent eller klient som prøver på nytt et push, ikke indekserer dokumentene to ganger. Send én nøkkel per logisk skriving, for eksempel en UUID, og gjenta samme nøkkel med de samme argumentene ved hvert forsøk:

* samme nøkkel med de samme argumentene innen 24 timer returnerer det første kallets resultat uten å kjøre det på nytt;
* samme nøkkel med forskjellige argumenter avvises: verktøyresultatet har `isError: true` og navngir `UNPROCESSABLE_CONTENT`;
* et nytt forsøk som kommer mens det første kallet fortsatt kjører, avvises på samme måte, og navngir `CONFLICT`; prøv igjen etter en kort pause.

En nøkkel er 1 til 256 utskrivbare ASCII-tegn og tilhører API-nøkkelen som sendte den: en annen API-nøkkel som bruker samme verdi, kjører sin egen skriving. En nøkkel brukt med REST-overskriften `Idempotency-Key` deles ikke med MCP-verktøyet, så et verktøykall som gjenbruker den, avvises med `UNPROCESSABLE_CONTENT`. Et kall uten argumentet kjører på nytt hver gang, og det er derfor disse verktøyene ikke deklarerer `idempotentHint`. REST-atferden er beskrevet under [sikker gjenopptakelse av skrivinger](/docs/guides/errors-and-rate-limits).

## Begrensninger og feil [#begrensninger-og-feil]

Et verktøykall trekker på samme ratelimit-bøtte som REST-operasjonen det tilsvarer, og alle andre meldinger på endepunktet har sin egen bøtte. `X-RateLimit-*`-hodene, `429`-svaret med sin `Retry-After`, og feilkonvolutten er de samme som på [REST API-et](/docs/guides/errors-and-rate-limits), så en klient som allerede håndterer dem for REST, håndterer dem her også.

Et mislykket verktøykall returnerer et MCP-verktøyresultat med `isError: true` hvis tekst er REST-feilens body (`code`, `message`, `data`). Valideringsfeil har samme `fieldErrors`-form som REST API-et returnerer. En JSON-RPC-feil er reservert for selve protokollen: en uleselig body, en ukjent metode eller en serverfeil.

Forespørselsbodyer er begrenset til 1 MB, samme grense som REST-rutene.

## Et første utveksling [#et-første-utveksling]

```bash
# Discover the tools your key can call
curl https://nordvec.com/api/v1/mcp \
  -H "Authorization: Bearer $NORDVEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# Search the workspace
curl https://nordvec.com/api/v1/mcp \
  -H "Authorization: Bearer $NORDVEC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"documents_search","arguments":{"query":"data retention policy"}}}'
```

## Dokumentasjonsserveren [#dokumentasjonsserveren]

Dokumentasjonsserveren på `/api/mcp` trenger ingen nøkkel. Den tilbyr `list_guides`, `get_guide`, `search_docs` og `list_connectors`, slik at en agent som bygger en applikasjon på API-et kan lese disse guidene direkte. Den er ratelimitert per IP, på samme måte som de andre offentlige endepunktene.
