Visena Dokumentasjon
Partner API

Guide

Legitimasjon og tokener

En legitimasjon identifiserer integrasjonen din inne i én kundes Visena-instans; et access token er det kortlevde beviset du sender med hvert kall. Denne siden er mekanikken for begge — opprettet på sekunder, tilbakekalt med ett kall, og hemmeligheten vises nøyaktig én gang.

Begreper forklarer hva en legitimasjon, et token og et scope er, og hvor de hører hjemme. Denne siden går ut fra at du har lest det og vil lage dem. Den dekker tre oppgaver som hører sammen, og er derfor lang med vilje:

Håndtere API-legitimasjon

En legitimasjon er et par: en clientId som navngir den og en clientSecret som beviser den. Alt under skjer inne i én kundes instans, mot instansens egen URL — under /{instanceName}/auth/api/v1/. Legitimasjons-endepunktene bærer et {locale}-segment etter versjonen — /acme/auth/api/v1/en/credentials — mens token-endepunktet ikke gjør det.

i

Legitimasjons-API-et autentiserer med en Visena-brukersesjon (X-ACCESS-TOKEN-informasjonskapselen til en innlogget bruker) — ikke med et bearer-token. Det er et bevisst valg: en maskinlegitimasjon kan ikke opprette flere legitimasjoner.

Hvem oppretter den

Legitimasjon opprettes inne i kundens instans, autentisert med en Visena-brukerinnlogging — så i de fleste integrasjonene er det kundens Visena-administrator som oppretter legitimasjonen og gir deg paret gjennom en sikker kanal. Forespørslene under dokumenterer hva som skjer i det steget, uansett om det er du eller kunden som utfører det.

Opprette en legitimasjon

To felter, begge påkrevde:

FeltVerdi
labelEn etikett som sier hva legitimasjonen er til. Kall den opp etter systemet som skal holde den — det takker du deg selv for når du senere skal rotere eller trekke tilbake.
accessLevelREAD_ONLY eller READ_WRITE — taket på alt legitimasjonen noen gang kan utstede, og det kan ikke endres etterpå. Utelater du feltet, svarer endepunktet 400: nivået er ikke noe plattformen gjetter. To tak, ikke ett forklarer forholdet til scopet du ber om per token.

En legitimasjon opprettet gjennom dette API-et handler alltid som brukeren som oppretter den. Skal den handle som en annen, opprettes den i grensesnittet i stedet — se legitimasjon på vegne av en annen.

Forespørsel
curl -X POST https://api.visena.example/acme/auth/api/v1/en/credentials \
  --cookie "X-ACCESS-TOKEN=<your Visena login session>" \
  -H "Content-Type: application/json" \
  -d '{ "label": "erp-sync-prod", "accessLevel": "READ_WRITE" }'
Svar — 201 Created
{
  "id": "aX8k2m",
  "label": "erp-sync-prod",
  "clientId": "acme-partner-3f9a",
  "accessLevel": "READ_WRITE",
  "clientSecret": "vco_9tK2…",
  "createdAt": "2026-08-21T09:14:03.482+02:00"
}

clientSecret vises nøyaktig én gang — i dette svaret. Visena lagrer bare en enveis hash og kan aldri vise den igjen. Legg den rett i hemmelighetshåndteringen din. Blir den mistet eller lekket, finnes det ingen «vis igjen» og ingen nullstilling: opprett en ny legitimasjon og trekk tilbake den gamle.

Liste legitimasjonene dine

Listingen returnerer bare metadata — aldri en hemmelighet. Bruk den til å se hva som finnes og til å finne den id-en du trenger for å trekke tilbake.

Forespørsel + svar
curl https://api.visena.example/acme/auth/api/v1/en/credentials \
  --cookie "X-ACCESS-TOKEN=<session>"

# 200 OK
[
  { "id": "aX8k2m", "label": "erp-sync-prod", "clientId": "acme-partner-3f9a",
    "accessLevel": "READ_WRITE", "createdAt": "2026-08-21T09:14:03.482+02:00" }
]

Trekke tilbake en legitimasjon

Tilbakekalling er en DELETE på legitimasjonens id (den maskerte id-en fra opprett/list — ikke clientId).

!

Tilbakekalling er umiddelbar og permanent. Legitimasjonen kan ikke lenger utstede tokener, og tokener den allerede har utstedt slutter å virke innen omtrent ett minutt. Det finnes ingen angre og ingen ny utstedelse av samme par: alt som fortsatt bruker den, trenger en ny legitimasjon fra en ny opprettelse. Raden slettes ikke — den blir stående i oversikten med statusen Tilbakekalt, med tidspunktet og hvem som gjorde det.

Forespørsel
curl -X DELETE https://api.visena.example/acme/auth/api/v1/en/credentials/aX8k2m \
  --cookie "X-ACCESS-TOKEN=<session>"

# 204 No Content — done

Rotering, i tre trekk

  1. Opprett erstatningen — samme navnekonvensjon, for eksempel erp-sync-prod-2026q4. Begge legitimasjonene virker gjennom byttet; det finnes ikke noe nedetidsvindu.
  2. Rull ut det nye paret — oppdater hemmelighetslageret, rull ut på tjenestene dine, bekreft at token-utstedelse virker med den nye clientId-en.
  3. Trekk tilbake den gamle legitimasjonenDELETE …/credentials/{id}. Alt som fortsatt bruker den, feiler fort og tydelig, som er nøyaktig det du vil.

Roter etter en plan som passer sikkerhetspolicyen din, og alltid når en person med tilgang til hemmeligheten går ut av prosjektet.

Legitimasjon på vegne av en annen

Når integrasjonen din må handle som en bestemt bruker — for eksempel arkivere dokumenter i en saksbehandlers navn — ber du kundens administrator om en legitimasjon på vegne av den brukeren. Slike utstedes gjennom Visenas administrasjonsverktøy, ikke gjennom selvbetjenings-API-et over. De oppfører seg likt, med to forskjeller:

  • Token-forespørsler må bruke act-as-user:-scopene — act-as-user:read act-as-user:write for en legitimasjon opprettet som Les og skriv, act-as-user:read alene for en opprettet som Bare lesing. Å be om ren read write gir 400 invalid_scope.
  • Hver endring registreres med både brukeren det gjelder og din handlende identitet, og svar på endringer bærer et actedBy-felt som navngir aktøren.

Å håndtere paret. Behandle clientSecret som et produksjonspassord til en database: hemmelighetshåndtering, aldri i git, aldri i en sak eller en chat-melding, én legitimasjon per system og miljø (ikke del et par mellom test og produksjon).

Opprette legitimasjon og token i grensesnittet

Samme vei, gjort klikk for klikk i Visenas webapplikasjon: opprett en legitimasjon, bytt den i et token, hent den første posten — med hver skjerm vist. Dette er veien gjennom brukergrensesnittet, den en kundes administrator vanligvis går.

i

Skjermbildene viser det norske grensesnittet, fordi origos grensesnitt er norsk i alle instanser. Den engelske termen følger hver etikett i teksten, slik at også en engelsk leser finner knappen som faktisk står på skjermen.

  1. Åpne siden for API-tilganger. I Visena følger du Admin → Tilgangskontroll → Administrer API-tilganger. Siden ligger på /admin/access-control/api-credentials og lister hver legitimasjon i instansen.

    Visena-sidemenyen med Admin, Tilgangskontroll og Administrer API-tilganger
    Administrer API-tilganger ligger under Admin → Tilgangskontroll.
  2. Opprett legitimasjonen. Klikk Ny API-tilgang. Dialogen spør om tre ting:

    • Navn — fritekst, slik at du kjenner legitimasjonen igjen senere. Kall den opp etter systemet som skal holde den: erp-sync-prod slår my-token.
    • Gjelder forMeg selv eller På vegne av en annen. Velger du den siste, kommer det fram en personvelger, og den personen blir legitimasjonens aktør: API-klienten utfører alt som vedkommende, med nøyaktig den tilgangen vedkommende har i origo, mens du står som oppretter. Steg 4 under viser hvordan valget ser ut i oversikten.
    • TilgangLes og skriv eller Bare lesing. Dette er taket på alt legitimasjonen noen gang kan utstede, og det kan ikke endres etterpå: velg Bare lesing når integrasjonen aldri skal skrive, så kan den heller ikke få et token som gjør det. To tak, ikke ett forklarer forholdet til scopet du ber om per token.

    Deretter Opprett.

    Dialogen Ny API-tilgang med feltene Navn, Gjelder for og Tilgang, og personvelgeren som følger med På vegne av en annen
    Dialogen Ny API-tilgang. Undertittelen advarer med én gang: «Hemmeligheten vises bare én gang» — og Tilgang er valget som ikke kan endres etterpå. Personnavnet er sladdet her.
  3. Kopier klient-id-en og hemmeligheten. Legitimasjonen er opprettet, og Visena viser de to verdiene OAuth 2.0-flyten trenger:

    • Klient-ID — identifiserer legitimasjonen. Dette er din client_id.
    • Klienthemmelighet — en vco_…-verdi som virker som passordet. Dette er din client_secret.

    Kopier hemmeligheten før du lukker dialogen. Visena lagrer bare en enveis hash, så dette er det ene øyeblikket den finnes i lesbar form. Legg den rett i hemmelighetshåndteringen din. Blir den mistet, finnes det ingen visning og ingen nullstilling: opprett en ny legitimasjon og trekk tilbake denne.

    Dialogen Tilgangen er opprettet med Klient-ID og Klienthemmelighet og kopier-knapper
    Engangsdialogen Tilgangen er opprettet — kopier begge verdiene nå.
  4. Vær klar over hvem tokenet handler som. Hver legitimasjon er knyttet til en brukeridentitet, og kall som gjøres med tokenene den utsteder, handler som den brukeren, med den brukerens rettigheter. Valget Gjelder for fra steg 2 avgjør hvem det er:

    ValgTokenet autentiserer som
    Meg selv
    Myself
    Personen som opprettet legitimasjonen. Aktør og Opprettet av navngir da den samme personen — deg.
    På vegne av en annen
    On behalf of someone else
    Brukeren du valgte. Oversikten viser vedkommende under Aktør og deg under Opprettet av. Tokener for slike legitimasjoner må hentes med act-as-user:…-scopene; se legitimasjon på vegne av en annen.

    Oversikten lister hver legitimasjon med navn, klient-id, Aktør, Tilgang, status, Sist brukt — satt når et token fra legitimasjonen brukes mot API-et, ikke når tokenet ble hentet — samt når den ble opprettet og av hvem:

    Oversikten Administrer API-tilganger med kolonnene Navn, Klient-ID, Aktør, Tilgang, Status, Sist brukt, Opprettet og Opprettet av
    Aktør er identiteten tokenet handler som — kolonnen å sjekke før du tar en legitimasjon i bruk. Klient-id-ene og personnavnene er sladdet her; på skjermen står de i klartekst.
  5. Bytt legitimasjonen i et token. POST paret til gatewayens token-endepunkt med standard OAuth 2.0-grant-typen client_credentials. Skjermbildene under sender legitimasjonen i skjemakroppen, som er det en API-klient gjør som standard; i produksjon er HTTP Basic den anbefalte formen — begge er dekket under token-forespørselen.

    Endepunkt
    POST {baseUrl}/{instanceName}/auth/api/v1/token
    Content-Type: application/x-www-form-urlencoded
    FeltVerdi
    grant_typeclient_credentials
    scopeHva tokenet får gjøre: read, write eller read write. Obligatorisk — det finnes ingen standardverdi.
    client_idKlient-ID fra steg 3
    client_secretKlienthemmelighet fra steg 3
    i

    Skal du bare lese? Be om scope=read. Et slikt token kan aldri endre noe, uansett hva den underliggende brukeren har lov til — Skrivebeskyttet tilgang viser garantien håndhevet, med 403-en som beviser det.

    Forespørsel — curl
    curl -X POST https://api.visena.example/acme/auth/api/v1/token \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=client_credentials" \
      -d "scope=read" \
      -d "client_id=<your Klient-ID>" \
      -d "client_secret=<your Klienthemmelighet>"
    Svar — 200 OK
    {
      "access_token": "dcrEUVpMEpYqbdsDKawBb1yTqIAELMgqIO4KrN…",
      "scope": "read",
      "token_type": "Bearer",
      "expires_in": 86399
    }
    En API-klient som viser token-forespørselen med grant_type, scope, client_id og client_secret, og JSON-svaret med tokenet
    Token-forespørselen i en API-klient — merk scope: read både i forespørselen og i svaret.
    Samme token-forespørsel gjengitt som en generert curl-kommando
    Samme forespørsel som en generert curl-kommando. Dette skjermbildet peker på en lokal utviklings-gateway; din er base-URL-en fra onboardingen.

    Tokenet er opakt, lever i expires_in sekunder, og det finnes ikke noe refresh token: når det utløper, gjentar du forespørselen. Cache tokenet har mønsteret, og feiltabellen hele listen over feil fra token-endepunktet.

  6. Gjør det første kallet. Send tokenet som en Bearer-header til ressursserveren gjennom samme gateway. Stien bærer instansnavnet, API-versjonen og locale-segmentet — her hentes én person:

    Forespørsel — curl
    curl "https://api.visena.example/acme/api/v1/en/person/KDiJs47rD4THRo5uPwlESr0" \
      -H "Authorization: Bearer <access_token>"
    Et GET-kall mot person med en Bearer-autorisasjonsheader og JSON-svaret med personfeltene
    En person hentet gjennom gatewayen — ren JSON, autentisert av Bearer-headeren alene.
    Samme GET-kall mot person gjengitt som en generert curl-kommando med Bearer-headeren
    Samme kall som en generert curl-kommando.

Det er hele runden: legitimasjon → token → kall. Videre herfra dekker Å gjøre kall URL-anatomi, maskerte id-er, locale-segmentet og formene hvert endepunkt returnerer, og Skrivebeskyttet tilgang dekker hva scope=read utelukker.

Hente et access token

Én standard OAuth 2.0-forespørsel gjør legitimasjonen din om til et kortlevd bearer-token, avgrenset til nøyaktig det du ber om.

Token-forespørselen

POST til /{instanceName}/auth/api/v1/token med grant-typen client_credentials. Det er hele stien: instansnavnet, så den faste autentiseringsflaten auth/api/v1, så token — uten locale-segment, og ingenting imellom. Autentiser med HTTP Basic (anbefalt) eller med skjemafeltene client_id/client_secret — begge er standard OAuth 2.0.

Forespørsel — curl
curl -X POST https://api.visena.example/acme/auth/api/v1/token \
  -u "acme-partner-3f9a:$CLIENT_SECRET" \
  -d "grant_type=client_credentials" \
  -d "scope=read write"
Svar — 200 OK
{
  "access_token": "PhVYGf3qK9t2Zx0CmW8rNbL5aTuJdEwSyAoQiHkXgMfDzUcRvBnOl46E…",
  "scope": "read write",
  "token_type": "Bearer",
  "expires_in": 86399
}
  • access_token er opakt — en uleselig streng, ikke en JWT. Prøv aldri å dekode eller inspisere det; bare send det tilbake som en bearer-header.
  • expires_in er sekunder til utløp. Les det fra svaret hver gang — kod aldri inn en levetid.
  • Det finnes ikke noe refresh token. Når tokenet utløper, kjører du samme forespørsel på nytt.

Å sette scopes — reglene

Scope er obligatorisk og eksplisitt. En token-forespørsel uten scope-parameter avvises med 400 invalid_scope — plattformen gjetter aldri hva du mente å be om.

Du kan be om legitimasjonens fulle scope-sett eller et hvilket som helst delsett av det:

Legitimasjonen dinRegistrert forGyldige scope-verdier
Vanlig · Les og skrivread writeread write · read · write
Vanlig · Bare lesingreadread
På vegne av · Les og skrivact-as-user:read act-as-user:writeact-as-user:read act-as-user:write · act-as-user:read · act-as-user:write
På vegne av · Bare lesingact-as-user:readact-as-user:read

Be om read for eksportjobber og dashbord, og om skrivescopet bare i jobbene som faktisk endrer noe.

Å be om et scope legitimasjonen din ikke har — inkludert å be en på-vegne-av-legitimasjon om ren read write — gir 400 invalid_scope. Scopene håndheves deretter per kall: GET-er trenger read-scopet, alle endringer trenger write-scopet. Et token utstedt med bare read får 403 på hver POST/PUT/PATCH/DELETE.

Cache tokenet, ikke hamre på endepunktet

Hent én gang, gjenbruk til kort før utløp, hent så på nytt. En sikkerhetsmargin på 60 sekunder absorberer klokkeavvik og kall som er underveis:

Node.js — minimal token-cache
const baseUrl = "https://api.visena.example";
const instanceName = "acme";

let cachedToken = null;
let cachedTokenExpiresAt = 0;

async function getAccessToken() {
	if (cachedToken && Date.now() < cachedTokenExpiresAt - 60_000) {
		return cachedToken;
	}
	const basicAuth = Buffer
		.from(`${process.env.VISENA_CLIENT_ID}:${process.env.VISENA_CLIENT_SECRET}`)
		.toString("base64");
	const response = await fetch(`${baseUrl}/${instanceName}/auth/api/v1/token`, {
		method: "POST",
		headers: {
			"Authorization": `Basic ${basicAuth}`,
			"Content-Type": "application/x-www-form-urlencoded"
		},
		body: "grant_type=client_credentials&scope=read%20write"
	});
	if (!response.ok) {
		throw new Error(`token request failed: ${response.status}`);
	}
	const token = await response.json();
	cachedToken = token.access_token;
	cachedTokenExpiresAt = Date.now() + token.expires_in * 1000;
	return cachedToken;
}

Når token-endepunktet sier nei

Feil fra token-endepunktet bruker den standard OAuth 2.0-feilkroppen — { "error": "…", "error_description": "…" }:

StatusFeilBetydning · hva du gjør
401invalid_client Feil client_id/client_secret, eller legitimasjonen er trukket tilbake. Sjekk paret; er det rotert, rull ut det nye.
400invalid_scope Scope mangler, eller legitimasjonen har det ikke. Oppgi nøyaktig de scopene du trenger.
400invalid_request / invalid_grant Feilformet skjemakropp eller feil grant_type — den må være client_credentials.
404 Ukjent instansnavn i URL-en. Kontroller det første stisegmentet.
502 / 503 Midlertidig plattformproblem — prøv igjen med eksponentiell backoff.

Den OAuth-feilkroppen er token-endepunktets egen form. Alt bak tokenet — forretnings-API-et du kaller med det — svarer i stedet med RFC 9457-problemdokumenter; se Feil og feilsøking.