Errors and limits
Error responses
All errors have the same shape, with a requestId you can give if you contact us. It is
also in the X-Request-ID header on every response.
{"error": {"status": 401, "message": "…", "requestId": "9c38fd23f4c14471b86c023902341627"}}
| Status | Means | Do this |
|---|---|---|
400 |
Invalid request | Read message |
401 |
Key is missing, invalid, expired or revoked | Send the key in X-API-Key. The response has registerUrl |
403 |
The request requires a higher level | Semantic search requires ext. See Access levels |
404 |
The work does not exist, or is not published | Check nmId |
422 |
Error in parameters or body | details says which field |
429 |
Too many requests | Wait as many seconds as Retry-After says |
5xx |
Error on our side | Try again a little later. If it persists, contact us with the requestId |
One exception: when the key is missing, message is an object with links to the terms and
the registration page (registerUrl, termsUrl). Programs that display message must handle both forms.
Without a key:
Without a key: 401 with a link to the registration page
curl -s -w "\nHTTP %{http_code}\n" "https://api.nasjonalmuseet.no/api/v1/objects/NG.M.00939"
Rate budget
| Requests | Limit per key |
|---|---|
| Works, browse, text search, IIIF | 120 per minute |
Images (/multimedia) |
60 per minute |
Search (/search/*) |
30 per minute |
Linked Art (/api/linkedart/*) |
120 per minute per IP address |
When the limit is exceeded, the API answers 429 with Retry-After (seconds),
X-RateLimit-Remaining and X-RateLimit-Reset. Wait and try again:
import os import time import requests
API = "https://api.nasjonalmuseet.no/api/v1" headers = {"X-API-Key": os.environ["NM_API_KEY"]}
def fetch(url, **kw): """GET that respects the rate limit: on 429 we wait Retry-After seconds.""" for _ in range(5): r = requests.get(url, headers=headers, timeout=30, **kw) if r.status_code != 429: r.raise_for_status() return r.json() time.sleep(int(r.headers.get("Retry-After", "5"))) raise RuntimeError("Gave up after five attempts")
print(fetch(f"{API}/objects/NG.M.00939", params={"lang": "en"})["mainTitle"])
If a public service needs more, the key can get its own limit. Contact us.
The key
- It lasts 180 days. Renew it on the registration page before it expires.
- Do not share it. Each person or service creates their own.
- Do not put it in the URL (
?api_key=). It does not work there, and it ends up in logs.