Norgesdomene

API-dokumentasjon

Norgesdomene API — versjon 1. Base-URL: https://norgesdomene.no/api/v1

Introduksjon

API-et lar deg lese domenene dine, styre DNS og navnetjenere og følge ordrer programmatisk. Partnere med forhåndssaldo kan i tillegg registrere, flytte og fornye domener. Alle priser er i norske øre (NOK). Alle svar er JSON.

Alle endepunkter har base-URL https://norgesdomene.no/api/v1 og krever autentisering. Foretrekker du å la en AI-assistent gjøre jobben, se MCP for AI-assistenter under — samme nøkkel, samme tilgang.

Autentisering

Alle kunder kan lage API-nøkler under AI-assistenter (MCP) i foretaksmenyen i portalen. Partnere finner også nøklene under Partner-API. Send nøkkelen som et Bearer-token i Authorization-headeren. Alle nøkler starter med ndp_live_.

Authorization: Bearer ndp_live_xxxxxxxxxxxxxxxxxxxx

Nøkler har scopes. Lese-endepunkter krever domains:read eller dns:read, skriveoperasjoner krever domains:write eller dns:write. En nøkkel opprettet som «kun lesetilgang» har bare lese-scopene.

Endepunktene som bestiller mot forhåndssaldo (POST /domains, POST /domains/transfers, POST /domains/:id/renew og GET /account) svarer 403 api_disabled til kontoer uten partneravtale. Alle andre endepunkter er åpne for enhver gyldig nøkkel.

MCP for AI-assistenter

Norgesdomene har en MCP-server (Model Context Protocol) på https://norgesdomene.no/api/mcp. Koble den til Claude Code, Cursor eller en klient med støtte for MCP over HTTP og Bearer-nøkkel, så kan assistenten sjekke domener, lese og endre DNS, bytte navnetjenere og se tjenestene på kontoen. Bestilling og betaling skjer alltid i kassen på norgesdomene.no.

Uten nøkkel finnes bare de offentlige verktøyene. Med en API-nøkkel (samme Authorization: Bearer-header som REST-API-et) kommer kontoverktøyene i tillegg, styrt av nøkkelens scopes.

Claude Code

Oppsett med innlogging i Claude Code:

claude mcp add --scope user --transport http norgesdomene-oauth https://norgesdomene.no/api/mcp/oauth
claude mcp login norgesdomene-oauth

Alternativt med API-nøkkel:

claude mcp add --scope user --transport http norgesdomene https://norgesdomene.no/api/mcp \
  --header "Authorization: Bearer ndp_live_xxxx"

Cursor (~/.cursor/mcp.json)

{
  "mcpServers": {
    "norgesdomene": {
      "url": "https://norgesdomene.no/api/mcp",
      "headers": { "Authorization": "Bearer ndp_live_xxxx" }
    }
  }
}

Du kan også koble til med innlogging på https://norgesdomene.no/api/mcp/oauth. Da velger du kundekonto og godkjenner lesetilgang uten API-nøkkel. OAuth er verifisert med Claude Code. ChatGPT, Claude Desktop og Cursor med OAuth avventer egne klienttester. Lag gjerne en egen nøkkel med kun lesetilgang for hver assistent.

Verktøy

VerktøyKreverGjør
check_domainIngen nøkkelLedighet, pris og bestillingslenke for et domene
get_domain_pricesIngen nøkkelListepriser per toppdomene (inkl. mva)
create_order_linkIngen nøkkelLenke til kassen for registrering eller flytting
get_accountdomains:readHvilken konto nøkkelen tilhører
list_domainsdomains:readKontoens domener med status og utløp
get_domaindomains:readDetaljer om ett domene
list_servicesdomains:readWebhotell, e-post, VPS, Microsoft 365, Deploy
list_dns_recordsdns:readDNS-oppføringer i Norgesdomenes DNS
create_dns_recorddns:writeOpprett DNS-oppføring
update_dns_recorddns:writeEndre DNS-oppføring
delete_dns_recorddns:writeSlett DNS-oppføring
set_nameserversdomains:writeBytt navnetjenere hos registeret

Serveren er stateless (ingen sesjoner) og følger MCP-spesifikasjonen 2026-07-28, med støtte for eldre klienter. Rate limit er den samme som for REST-API-et.

Forhåndssaldo

Bestilling via API er for partnere med avtale: ordrene trekkes fra kontoens forhåndsinnbetalte saldo. Saldoen er i øre. Har du for lav saldo ved bestilling returnerer API-et 402 insufficient_balance. Uten avtale bruker du kassen på norgesdomene.no — MCP-verktøyet create_order_link lager lenken for deg.

Sjekk gjeldende saldo med GET /account.

Idempotens

Alle skrive-operasjoner (POST /domains, POST /domains/:id/renew) krever headeren Idempotency-Key med en unik streng per forsøk. Send samme nøkkel ved retry; du får da samme svar uten at bestillingen dobles.

Idempotency-Key: ordre-klient-ref-abc123

Webhooks

Flytting og registrering er asynkrone — de fullføres hos registeret etter at API-et har svart. I stedet for å spørre om status gjentatte ganger kan du registrere et endepunkt under API i portalen, så sender vi en POST når noe skjer.

Hendelser

domain.transfer.completed — domenet er flyttet og aktivt hos oss

domain.transfer.failed — flyttingen feilet (feil transferkode, avvist av registeret e.l.)

Kropp

{
  "event":     "domain.transfer.completed",
  "createdAt": "2026-08-04T12:00:00.000Z",
  "data": {
    "domainId": "dom_xxxxxxxxxxxx",
    "domain":   "mittdomene.no",
    "orderId":  "ord_xxxxxxxxxxxx"
  }
}

Verifisering

Hver leveranse har headeren X-Norgesdomene-Signature på formen t=<unix>,v1=<hmac>. Signaturen er HMAC-SHA256 over <t>.<rå kropp> med signeringsnøkkelen du fikk da endepunktet ble opprettet. Tidsstemplet er med i signaturen så en avlyttet leveranse ikke kan spilles av på nytt — avvis forespørsler der t er eldre enn fem minutter.

const [t, v1] = header.split(",").map((p) => p.split("=")[1])
const expected = crypto
  .createHmac("sha256", process.env.NORGESDOMENE_WEBHOOK_SECRET)
  .update(`${t}.${rawBody}`)
  .digest("hex")

if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) {
  return res.status(400).end()
}
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) {
  return res.status(400).end()
}

Svar 2xx når du har tatt imot hendelsen. Får vi noe annet, prøver vi på nytt etter 1, 5 og 25 minutter, så 2 og 10 timer, før vi gir opp. Samme hendelse sendes aldri to ganger for samme domene, men bygg mottakeren idempotent likevel.

Endepunktet må bruke https og peke på en offentlig adresse. Interne og private adresser avvises.

Endepunkter

GET/domains/checkdomains:read

Sjekk om et domene er ledig og hent pris.

Query-parameter: domain (f.eks. mittdomene.no)

Svar — ledig

{
  "domain":    "mittdomene.no",
  "available": true,
  "priceOre":  19375,
  "vatOre":    4844,
  "totalOre":  24219,
  "currency":  "NOK"
}

Svar — ikke ledig

{
  "domain":    "opptatt.no",
  "available": false,
  "reason":    "taken"
}

POST/domainsdomains:writeIdempotency-Key

Registrer et nytt domene. Kun .no støttes i denne versjonen — forespørsler på andre toppdomener avvises med 400 invalid_request. Se Registrerings- og deklarasjonsflyt nedenfor.

Forespørselskropp

{
  "domain":   "mittdomene.no",
  "period":   1,                    // valgfri, 1–10 år
  "registrant": {
    "type":        "organisasjon",  // "person" eller "organisasjon"
    "name":        "Mitt Firma AS",
    "orgNumber":   "123456789",     // 9 siffer — kreves for organisasjon
    // "personId": "...",           // kreves for type person
    "email":       "eier@firma.no",
    "phone":       "+4712345678",   // valgfri
    "addressLine1": "Storgata 1",   // valgfri
    "postalCode":  "0001",          // valgfri
    "city":        "Oslo",          // valgfri
    "country":     "NO"             // valgfri, standard NO
  },
  "nameservers": [                  // valgfri
    "ns1.mittfirma.no",
    "ns2.mittfirma.no"
  ]
}

Svar — 202 Accepted

{
  "orderId":        "ord_xxxxxxxxxxxxxxxx",
  "orderNumber":    "10042",
  "domain":         "mittdomene.no",
  "status":         "pendingRegistration",
  "declarationUrl": "https://norgesdomene.no/deklarasjon/a1b2c3d4e5f6"
}

POST/domains/transfersdomains:writeIdempotency-Key

Flytt et domene fra en annen registrar. Kun .no støttes i denne versjonen. Flytting av .no er gratis og beholder utløpsdatoen — domenet forlenges ikke, og du betaler først ved neste fornyelse.

En ren registrarflytting endrer ikke eier, og krever derfor ingen egenerklæring fra innehaveren. Det er forskjellen fra nyregistrering, og det som gjør at en hel portefølje kan flyttes uten at hver sluttkunde må signere noe.

Forespørselskropp

{
  "domain":   "mittdomene.no",
  "authCode": "TransferKode123"    // fra nåværende leverandør
  // "noRegistrar": true           // kun .no som står uten registrar —
                                   // de har aldri hatt en transferkode
}

Navnetjenerne beholdes alltid slik de er, så nettsted og e-post fortsetter uten avbrudd gjennom flyttingen. Vil du over på NorgesDNS, gjør du det i to steg etterpå: opprett oppføringene med POST /domains/{id}/dns, og bytt så navnetjenere med PUT /domains/{id}/nameservers. Rekkefølgen er viktig — bytter du navnetjenere før sonen er fylt, peker domenet mot ingenting.

Svar — 202 Accepted

{
  "orderId":     "ord_xxxxxxxxxxxxxxxx",
  "orderNumber": "10043",
  "domain":      "mittdomene.no",
  "status":      "pendingTransfer",
  "declarationUrl": null
}

Flyttingen kjøres mot registeret etter at svaret er sendt, fordi Norid behandler ett flyttekall om gangen. Poll GET /domains/{id} til status går fra pendingTransfer til active. Feiler den, blir domenet stående i pendingTransfer og forsøkes på nytt automatisk — ingenting går tapt.


GET/domainsdomains:read

Hent liste over alle domener på kontoen (maks 200, sortert på utløpsdato).

Svar — 200 OK

{
  "domains": [
    {
      "id":         "dom_xxxxxxxxxxxxxxxx",
      "name":       "mittdomene.no",
      "status":     "active",
      "expiresAt":  "2026-05-01T00:00:00.000Z",
      "registrar":  "norid"
    }
  ]
}

GET/domains/:iddomains:read

Hent detaljer for ett domene. Bruk status-feltet for å poll-e registreringsstatus.

Svar — 200 OK

{
  "id":         "dom_xxxxxxxxxxxxxxxx",
  "name":       "mittdomene.no",
  "status":     "active",
  "expiresAt":  "2026-05-01T00:00:00.000Z",
  "registrar":  "norid",
  "autoRenew":  false
}

POST/domains/:id/renewdomains:writeIdempotency-Key

Forny et domene med TLD-ens standardperiode (typisk 1 år). Beløpet trekkes fra saldo. Krever ingen forespørselskropp.

Svar — 202 Accepted

{
  "orderId":     "ord_xxxxxxxxxxxxxxxx",
  "orderNumber": "10043",
  "status":      "active"
}

Får ikke registraren svart i tide, kan svaret (eller et replay med samme Idempotency-Key) ha pendingRenewal: utfallet verifiseres mot registraren og ordren fullføres automatisk hvis fornyelsen gikk gjennom. Ikke send en ny forespørsel med en annen nøkkel — et nytt forsøk kan opprette en duplikat fornyelse.


PUT/domains/:id/nameserversdomains:write

Oppdater nameservere for et domene (erstatter eksisterende liste). Minst én, maks 13.

Har domenet DNSSEC på, avvises et bytte bort fra NorgesDNS med 409 conflict. En DS-post uten matchende signering gjør domenet utilgjengelig for validerende resolvere. DNSSEC skrus av i kundeportalen under Navnetjenere — vent noen timer etterpå før du bytter nameservere, så rekker den gamle DS-posten å gå ut av cachene.

Forespørselskropp

{
  "nameservers": [
    "ns1.ditt-hosting.no",
    "ns2.ditt-hosting.no"
  ]
}

Svar — 200 OK

{
  "ok":          true,
  "nameservers": ["ns1.ditt-hosting.no", "ns2.ditt-hosting.no"]
}

GET/domains/:id/dnsdns:read

Hent alle DNS-oppføringer for et domene kontoen eier.

Svar — 200 OK

{
  "records": [
    {
      "id":       "uuid",
      "type":     "A",
      "name":     "@",
      "value":    "203.0.113.10",
      "ttl":      3600,
      "priority": null,
      "weight":   null,
      "flags":    null,
      "tag":      null,
      "port":     null,
      "disabled": false
    }
  ]
}

POST/domains/:id/dnsdns:write

Opprett en ny DNS-oppføring. Se tabellen over støttede typer nedenfor for påkrevde tilleggsfelt per type.

Forespørselskropp

{
  "type":  "A",
  "name":  "@",
  "value": "203.0.113.10",
  "ttl":   3600
}

Svar — 201 Created

{
  "id":       "uuid",
  "type":     "A",
  "name":     "@",
  "value":    "203.0.113.10",
  "ttl":      3600,
  "priority": null,
  "weight":   null,
  "flags":    null,
  "tag":      null,
  "port":     null,
  "disabled": false
}

curl-eksempel

curl -X POST https://norgesdomene.no/api/v1/domains/$DOMAIN_ID/dns \
  -H "Authorization: Bearer $NDP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type":"A","name":"@","value":"203.0.113.10","ttl":3600}'

PUT/domains/:id/dns/:recordIddns:write

Oppdater en eksisterende DNS-oppføring. Samme kropp-format som POST /dns.

Forespørselskropp

{
  "type":  "A",
  "name":  "@",
  "value": "203.0.113.10",
  "ttl":   3600
}

Svar — 200 OK

{
  "id":       "uuid",
  "type":     "A",
  "name":     "@",
  "value":    "203.0.113.10",
  "ttl":      3600,
  "priority": null,
  "weight":   null,
  "flags":    null,
  "tag":      null,
  "port":     null,
  "disabled": false
}

DELETE/domains/:id/dns/:recordIddns:write

Slett en DNS-oppføring. Returnerer tomt svar ved suksess.

Svar — 204 No Content

(tomt svar)


DNS-typer og påkrevde felt

ttl er valgfri (standard 3600, gyldig 60–86400). Tabellen viser hvilke tilleggsfelt som kreves per type.

TypeBeskrivelse og krav
Avalue = IPv4-adresse
AAAAvalue = IPv6-adresse
CNAMEvalue = vertsnavn (kan ikke ligge på rotdomenet/@)
TXTvalue = tekst
MXvalue = mailserver-navn; krever priority
SRVnavn på formen _service._proto; krever priority, weight, port
CAAkrever flags og tag

Navnetjenere og NorgesDNS

DNS-oppføringer trer i kraft når domenet bruker NorgesDNS-navnetjenere (ns1.norgesdns.no / ns2.norgesdns.no). Et domene registrert via API-et får dette automatisk ved første DNS-skriving. Har du satt egne eksterne navnetjenere, lagres oppføringene, men de resolver ikke før domenet peker til NorgesDNS.


Idempotens for DNS-skriving

DNS-skriving krever ikke Idempotency-Key. POST er ikke idempotent — et nytt forsøk kan opprette en duplikat. For å endre en eksisterende oppføring: hent listen (GET) og bruk PUT/DELETE på recordId.


GET/orders/:iddomains:read

Hent status og detaljer for en ordre. Bruk orderId fra POST /domains-svaret for å poll-e.

Svar — 200 OK

{
  "orderId":     "ord_xxxxxxxxxxxxxxxx",
  "orderNumber": "10042",
  "status":      "pendingRegistration",
  "totalOre":    24219,
  "items": [
    {
      "kind":        "domain_registration",
      "description": "mittdomene.no (1 år)",
      "meta":        {}
    }
  ]
}

GET/accountdomains:read

Hent gjeldende saldo på kontoen.

Svar — 200 OK

{
  "balanceOre": 500000,
  "currency":   "NOK"
}

Registrerings- og deklarasjonsflyt (.no)

For .no-domener er registrering en tostegs-prosess. Et 202-svar fra POST /domains betyr at ordren er mottatt og saldo er reservert — ikke at domenet er registrert hos Norid ennå.

Viktig: videresend deklarasjonslenken til din kunde

Svaret inneholder et declarationUrl-felt — en side hos Norgesdomene (norgesdomene.no/deklarasjon/…). Du sender lenken til domenets registrant (din sluttkunde), som fyller ut og signerer Norids egenerklæring der. Vi sender erklæringen til Norid og registrerer domenet først etter at den er levert.

Flyten steg for steg:

  1. Du kaller POST /domains → mottar 202 med status: "pendingRegistration" og declarationUrl.
  2. Du sender declarationUrl til din sluttkunde via e-post eller SMS.
  3. Sluttkunden åpner lenken (hos Norgesdomene), fyller ut og signerer egenerklæringen.
  4. Vi sender erklæringen til Norid og registrerer domenet. Status endres til active.
  5. Poll GET /domains/:id eller GET /orders/:id til status er active.

Håndter at declarationUrl kan være null

I sjeldne tilfeller (f.eks. om lenkegenerering ikke fullførte) er declarationUrl null selv om ordren er opprettet og saldo trukket. Ikke send en tom lenke til kunden — sjekk for null, og kontakt oss (eller prøv igjen) hvis den mangler. Feltet gjelder dessuten kun .no.

Feilkoder

Alle feil returneres med HTTP-statuskoden nedenfor og kroppen:

{ "error": { "code": "invalid_request", "message": "..." } }
KodeHTTPBetydning
unauthorized401Ugyldig eller manglende API-nøkkel.
forbidden_scope403Nøkkelen mangler nødvendig scope.
api_disabled403API-tilgang er ikke aktivert for kontoen.
rate_limited429For mange forespørsler. Vent og prøv igjen.
invalid_request400Manglende eller ugyldig felt i forespørselen.
domain_taken409Domenet er allerede registrert.
invalid_contact422Registrantdata godkjennes ikke (f.eks. manglende orgNumber).
insufficient_balance402Saldo er for lav til å gjennomføre ordren.
provisioning_failed502Ekstern feil ved provisjonering hos register.
not_found404Domene eller ordre finnes ikke.

curl-eksempler

Sjekk om et domene er ledig

curl -s \
  -H "Authorization: Bearer ndp_live_xxxx" \
  "https://norgesdomene.no/api/v1/domains/check?domain=mittdomene.no"

Registrer et .no-domene (organisasjon)

curl -s -X POST \
  -H "Authorization: Bearer ndp_live_xxxx" \
  -H "Idempotency-Key: ordre-ref-001" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "mittdomene.no",
    "period": 1,
    "registrant": {
      "type":      "organisasjon",
      "name":      "Mitt Firma AS",
      "orgNumber": "123456789",
      "email":     "eier@firma.no"
    }
  }' \
  "https://norgesdomene.no/api/v1/domains"