# Context pack: Fejl og hastighedsgrænser

Source: https://nordvec.com/da/docs/guides/errors-and-rate-limits
Pack: https://nordvec.com/da/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. [Fejl og hastighedsgrænser](https://nordvec.com/da/docs/guides/errors-and-rate-limits) (this guide)
2. [MCP](https://nordvec.com/da/docs/guides/mcp) (linked from this guide)

---

# Fejl og hastighedsgrænser
Source: https://nordvec.com/da/docs/guides/errors-and-rate-limits

Den ene fejlkuvert, som hvert fejlslagent request returnerer, hastighedsgrænse-headers og hvordan du genforsøger en skrivning sikkert.



Hvert endpoint fejler på samme måde, så en klient håndterer fejl, rategrænser og genforsøg én gang og genbruger den kode overalt, herunder over [MCP](/docs/guides/mcp).

## Fejlkapslen [#fejlkapslen]

Ethvert ikke-2xx-svar er ét JSON-objekt:

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

* `code` er fejlen på HTTP-niveau, for eksempel `UNAUTHORIZED`, `FORBIDDEN`,
  `NOT_FOUND`, `BAD_REQUEST` eller `TOO_MANY_REQUESTS`.
* `data.reason`, når den er til stede, er en mere præcis maskinlæsbar årsag som
  `auth.key_not_found` eller `rate_limit.exceeded`. Forgrén på den i stedet for på
  `message`, som er til mennesker og kan ændre sig.
* `defined` er `true`, når operationen oplister den fejl i
  [API-referencen](/docs/api), og `false` for fejl, som enhver anmodning kan møde
  (autentificering, rategrænser, en ukendt rute).
* Et valideringsfejl svarer med `BAD_REQUEST` og problemerne i
  `data.formErrors` og `data.fieldErrors`.

Hvert svar indeholder også et `X-Request-ID`. Citér det, når du kontakter
support, så kan vi finde den præcise anmodning.

## Almindelige statuskoder [#almindelige-statuskoder]

| Status | Kode                    | Hvad du skal gøre                                                 |
| ------ | ----------------------- | ----------------------------------------------------------------- |
| `400`  | `BAD_REQUEST`           | Ret anmodningen; `data.fieldErrors` angiver felterne              |
| `401`  | `UNAUTHORIZED`          | Send en gyldig nøgle eller session                                |
| `403`  | `FORBIDDEN`             | Nøglen mangler det scope eller den rolle, som operationen kræver  |
| `404`  | `NOT_FOUND`             | Ressourcen findes ikke, eller du har ikke adgang til at se den    |
| `409`  | `CONFLICT`              | En duplikat-skrivning er stadig i gang; prøv igen om kort tid     |
| `413`  | `PAYLOAD_TOO_LARGE`     | Anmodningsbrød er over 1 MB; del en bulk-push op i mindre batches |
| `422`  | `UNPROCESSABLE_CONTENT` | Anmodningen er velformet, men kan ikke anvendes                   |
| `429`  | `TOO_MANY_REQUESTS`     | Vent i `Retry-After`, og prøv derefter igen                       |

## Rategrænser [#rategrænser]

Hvert svar angiver den grænse, som det blev talt op imod, i to former:

* `X-RateLimit-*`-headere;
* de IETF-strukturerede felter `RateLimit` (live-tilstand: `r` er de resterende anmodninger,
  `t` er sekunderne, indtil vinduet nulstilles) og `RateLimit-Policy`
  (kvotaen: `q` er grænsen, `w` er vinduet i sekunder).

Et `429` medfører også `Retry-After` i sekunder og `data.retryAfterMs`. Vent mindst så længe,
før du sender den næste anmodning; et tidligere genforsøg tælles med og
afvises igen.

## Sikker genafsendelse af skrivninger [#sikker-genafsendelse-af-skrivninger]

En skrivningsoperation, der oplister en `Idempotency-Key`-header i
[API-referencen](/docs/api), kan genafsendes uden at udføre arbejdet to gange. Send
én nøgle per logisk skrivning, og gentag den samme nøgle ved hvert genforsøg:

* den samme nøgle med det samme brød inden for 24 timer afspiller det gemte svar;
* den samme nøgle med et andet brød afvises med `422`;
* en duplikat, der ankommer, mens den første stadig kører, får `409`.

En operation uden headeren er ikke idempotent, så genafsend den kun, når du
ved, at det første forsøg ikke blev gennemført.


---

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

Tilslut en AI-agent til dit arbejdsområdes vidensbase via Model Context Protocol med en API-nøgle.



Nordvec understøtter [Model Context Protocol](https://modelcontextprotocol.io) (MCP), så en agent eller en assistent, der taler MCP, kan opdage dine arbejdsområdes operationer som værktøjer og kalde dem naturligt uden et OpenAPI-dokument at resonnere over.

Der er to servere:

| Server        | URL                              | Auth      | Hvad den eksponerer                                                                                                        |
| ------------- | -------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
| Dokumentation | `https://nordvec.com/api/mcp`    | ingen     | Disse vejledninger og connectorkataloget, til en agent der integrerer med Nordvec                                          |
| Vidensbase    | `https://nordvec.com/api/v1/mcp` | API-nøgle | Dine arbejdsområdes dokumenter, søgning og indtagelse: de samme operationer som [REST API'et](/docs/guides/authentication) |

Begge kører i EU på den samme infrastruktur som resten af API'et.

## Tilslutning af en klient [#tilslutning-af-en-klient]

Peg en MCP-klient mod vidensbaseserveren med din API-nøgle som bearer-token. De fleste klienter tager en konfigurationsblok 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: hvert meddelelse er én `POST`, der bærer én JSON-RPC-anmodning, og svaret kommer tilbage i response-body. Der er ingen sessioner at holde styr på, og ingen serverinitieret stream, så et `GET` på URL'en svarer `405`, og et `POST` hvis `Content-Type` ikke er `application/json` svarer `415`, før body læses.

<Callout type="warn">
  Kun en API-nøgle kan bruge vidensbaseserveren. En logget ind browsersession afvises, og hvert værktøj kræver den nøglescope, som den tilsvarende REST-operation kræver, så en nøgle oprettet til én opgave kan udføre præcis den opgave via MCP også.
</Callout>

Serveren autentificerer med en statisk bearer-nøgle og tilbyder ikke OAuth-discovery. En klient, der lader dig sætte request-headers (kodningsagenter, IDE-udvidelser, MCP Inspector i header-tilstand), tilsluttes som vist ovenfor. En hosted klient, der kun understøtter OAuth-authorization-flow, kan endnu ikke tilsluttes.

En klient, der sender `MCP-Protocol-Version`-headeren, får svar under den version, når serveren understøtter den (`2025-06-18` og `2024-11-05`), og afvises med `400`, når den ikke gør, så en versionskonflikt rapporteres ved første meddelelse i stedet for som et misdannet svar senere.

## Værktøjer [#værktøjer]

Værktøjerne er afledt af REST API'et, ét værktøj per operation, som en API-nøgle må kalde. Et værktøjs navn er operationens kontraktsti i snake case, hvor et segment, der gentager det foregående, er fjernet. Scope-kolonnen er den API-nøglescope, som værktøjet kræver:

| REST-handling                         | Kontraktsti                          | MCP-værktøj                        | 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 det autoritative katalog: det viser kun en nøgle de værktøjer, som dens scopes tillader, og hvert værktøjs beskrivelse nævner den scope, det kræver. Et værktøjs `inputSchema` er operationens request-schema, og hvor operationen returnerer et objekt, er dens `outputSchema` response-schemaet, og resultaterne bærer `structuredContent` sammen med JSON-teksten.

Et kald til et værktøj, som nøglens scopes ikke tillader, svarer med en værktøjsfejl, der nævner `FORBIDDEN`, den samme afvisning som REST-ruten giver, så en klient, der holder en cachelagret liste fra en anden nøgle, forstår hvorfor i stedet for blot at erfare, at værktøjet mangler.

## Forsøg at skrive igen [#forsøg-at-skrive-igen]

`document_push` og `document_push_bulk` tager et valgfrit `idempotencyKey`-argument, så en agent eller klient, der forsøger at sende en push igen, ikke indekserer dokumenterne to gange. Send én nøgle per logisk skrivning, f.eks. et UUID, og gentag den samme nøgle med de samme argumenter ved hvert forsøg:

* den samme nøgle med de samme argumenter inden for 24 timer returnerer det første kalds resultat uden at køre det igen;
* den samme nøgle med forskellige argumenter afvises: værktøjsresultatet har `isError: true` og nævner `UNPROCESSABLE_CONTENT`;
* et genkald, der ankommer, mens det første kald stadig kører, afvises på samme måde og nævner `CONFLICT`; genkald det efter en kort ventetid.

En nøgle er 1 til 256 læsbare ASCII-tegn og tilhører den API-nøgle, der sendte den: en anden API-nøgle, der bruger samme værdi, kører sin egen skrivning. En nøgle, der bruges med REST-`Idempotency-Key`-headeren, deles ikke med MCP-værktøjet, så et værktøjskald, der genbruger den, afvises med `UNPROCESSABLE_CONTENT`. Et kald uden argumentet kører igen hver gang, hvilket er grunden til, at disse værktøjer ikke deklarerer `idempotentHint`. REST-opførslen er beskrevet under [genafsendelse af skrivninger sikkert](/docs/guides/errors-and-rate-limits).

## Begrænsninger og fejl [#begrænsninger-og-fejl]

Et værktøjskald trækker på den samme rate-limit-bucket som den tilsvarende REST-operation og alle andre meddelelser på endpointens egen bucket. `X-RateLimit-*`-headere, `429`-svaret med dets `Retry-After` og fejlkonvolutten er de samme som på [REST API'et](/docs/guides/errors-and-rate-limits), så en klient, der allerede håndterer dem for REST, håndterer dem her.

Et mislykket værktøjskald returnerer et MCP-værktøjsresultat med `isError: true`, hvis tekst er REST-fejlbody (`code`, `message`, `data`); valideringsfejl bærer den samme `fieldErrors`-form, som REST API'et returnerer. En JSON-RPC-fejl er forbeholdt selve protokollen: en ufortolkelig body, en ukendt metode eller en serverfejl.

Request-bodies er begrænset til 1 MB, den samme grænse som REST-ruterne.

## En første udveksling [#en-første-udveksling]

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

## Dokumentationsserveren [#dokumentationsserveren]

Dokumentationsserveren på `/api/mcp` kræver ingen nøgle. Den tilbyder `list_guides`, `get_guide`, `search_docs` og `list_connectors`, så en agent, der bygger en applikation på API'et, kan læse disse vejledninger direkte. Den er rate-begrænset per IP ligesom de andre offentlige endpoints.
