Visena Dokumentasjon
Partner API

Referanse

API-referanse

Kontrakten for Partner API, endepunkt for endepunkt: hver rute, parameter, forespørselskropp, svarstruktur og statuskode, med et kopiklart eksempel på hvert endepunkt. Denne siden bærer det de alle deler.

Endepunktreferansen står på engelsk i begge språktrærne. Den gjengir API-kontrakten ordrett, og det finnes ingen generator å bygge den på nytt fra, så en oversatt kopi ville drevet fra API-et første gang et endepunkt endres.

Base-URL-en

Eksemplene bruker plassholderen https://api.visena.example som base-URL og instansnavnet acme; bytt ut begge med verdiene du fikk under onboarding. Alle forretningsstier starter med instansnavnet, så API-versjonen, så en locale, så ressursen:

https://api.visena.example/acme/api/v1/en/person/xK9mQ2
/acmeinstansnavn /enlocale (en · no) /personressurs

Ressursnavnene er i entall, og stien har ikke noe partner/-segment: den er /{instanceName}/api/v1/{locale}/person, aldri /partner/api/v1/en/persons. Hvert endepunkt i referansen er skrevet ut med de to første stiparameterne på plass.

Token-endepunktet er det ene unntaket, fordi det ikke er et forretningsendepunkt: det ligger på /{instanceName}/auth/api/v1/token — instansnavnet, så den faste autentiseringsflaten, og ingen locale.

Ressurser

Ni ressurser utgjør flaten i dag. Hver av dem har sin egen side med en endepunktliste, den fulle kontrakten for hvert endepunkt, og objektstrukturene endepunktene utveksler.

Å lese denne referansen

Alle ressurssidene er bygget likt, så den andre du leser trenger ingen orientering:

  • En endepunktliste øverst — metode, sti og sammendrag, hver med lenke ned til endepunktet.
  • Én seksjon per endepunkt: metoden og den fulle stien, hva det gjør, parameterne, forespørselskroppen, en tabell over svarene det kan gi, og et curl-eksempel.
  • Objektstrukturer nederst: hver forespørsels- og svarkropp siden viser til, felt for felt.

Ankrene til endepunktene er stabile. Id-en til en seksjon er operasjons-id-en fra kontrakten — #createPerson, #listPersonsByCursor — og den er den samme i begge språktrærne, så en dyplenke du limer inn i en sak fortsetter å virke.

Det ressurssidene med vilje utelater: de to første stiparameterne, som står på denne siden, og de fire fellesfeilene, som står under Feil og feilsøking. For gjennomgåtte eksempler, integrasjonsmønstre og den veiledede introduksjonen leser du guiden først — Kom i gang er den korte veien fra en legitimasjon til det første svaret.

Den samme flaten finnes som et OpenAPI 3.0-dokument for import i Postman, Insomnia eller en kodegenerator — spør Visena-kontakten din om partner-openapi.json.

Autentisering

Én standard OAuth 2.0-forespørsel gjør clientId og clientSecret om til et kortlevd bearer-token, avgrenset til nøyaktig det du ber om. Alle andre endepunkter i denne referansen krever det tokenet. Hvordan du oppretter legitimasjonen i grensesnittet, og en token-cache verdt å kopiere, står under Legitimasjon og tokener.

Scopes

Skjemafeltet scope er obligatorisk — en token-forespørsel uten det avvises med 400 invalid_scope. Du kan be om hele scope-settet legitimasjonen din har, eller en delmengde av det:

Scope Tillater
read All safe methods — GET reads, lists, downloads and change feeds.
write All mutations — POST, PUT, PATCH, DELETE.
act-as-user:read Safe methods with an on-behalf credential (one issued to act for a specific named user).
act-as-user:write Mutations with an on-behalf credential. Mutation responses carrying an entity body echo the acting user's masked id in actedBy.

De to familiene blandes aldri: en vanlig legitimasjon hører til read/write-familien, en på-vegne-av-legitimasjon til act-as-user:*-familien — og innenfor familien har en legitimasjon opprettet som Bare lesing bare lese-scopet. Ber du om et scope legitimasjonen ikke har, får du 400 invalid_scope. Be bare om det jobben trenger — en eksportjobb har ingenting å gjøre med write.

Tokenets livsløp

  • Tokener er ugjennomsiktige. Dekod eller inspiser aldri et access_token; behandle det som tilfeldig tekst.
  • expires_in er autoritativ. Les levetiden fra hvert svar; ikke hardkod den.
  • Det finnes ikke noe refresh token. Når et token utløper, kjører du samme forespørsel på nytt — utvekslingen er billig.
  • Cache og gjenbruk. Utsted én gang, gjenbruk til omtrent 60 sekunder før utløp, og utsted så på nytt. Utsted aldri per forespørsel.

Å bruke tokenet

Send det på hver forespørsel som Authorization: Bearer <access_token>. Tokenet virker bare på instansen det ble utstedt for, og scopene håndheves per forespørsel: trygge metoder krever read-scopet, endringer krever write-scopet.

Exchange a credential for an access token

POST /{instanceName}/auth/api/v1/token

Standard OAuth 2.0 client_credentials grant. Authenticate with HTTP Basic (clientId as user name, clientSecret as password) or with client_id/client_secret form fields. The scope parameter is mandatory and must be a subset of the scopes the credential holds — the platform never picks a default.

There is no refresh token: when the token expires, run the same request again. Cache the token and reuse it until shortly before expires_in runs out.

Forespørselskropp

application/x-www-form-urlencodedobject

Svar

Status Beskrivelse
200 The access token.
TokenResponse · application/json
400 invalid_scope — scope missing or not held by this credential; invalid_request/invalid_grant — malformed body or wrong grant type.
401 invalid_client — wrong client_id/client_secret, or the credential was revoked.

Dette endepunktet svarer ikke med et problemdokument. Det feiler på OAuth 2.0-måten, med en error-kode og en error_description — se Feil og feilsøking.

Eksempel

Request — 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"
Response — 200 OK
{
  "access_token": "PhVYGf3qK9t2Zx0CmW8rNbL5aTuJdEwSyAoQiHkXgMfDzUcRvBnOl46E…",
  "scope": "read write",
  "token_type": "Bearer",
  "expires_in": 86399
}

Objektstrukturer

Kroppene tokenutvekslingen returnerer. Alle andre objektstrukturer er dokumentert på ressurssiden som bruker dem.

TokenResponse

Felt Type Beskrivelse
access_token required string The bearer token. Opaque — send it back verbatim.
token_type required string
expires_in required integer Seconds until the token expires. Read it from every response; never hardcode a lifetime.
scope required string The scopes actually granted, space-separated.

OAuthError

Felt Type Beskrivelse
error required string Machine-readable OAuth 2.0 error code, e.g. invalid_client, invalid_scope.
error_description string Human-readable explanation.

URL-struktur

Alt herfra og ned deles av hvert endepunkt på hver ressursside. Ressurssidene tar det for gitt og gjentar det aldri.

Forretningsendepunktene ligger på /{instanceName}/api/v1/{locale}/…, og de to stiparameterne er grunnen til at ingen endepunkttabell lister dem. {instanceName} er kundeinstansen legitimasjonen din hører til — et token utstedt for én instans får 403 alle andre steder, og et instansnavn som ikke finnes får 404 på alle endepunkter samtidig. {locale} (en eller no) velger språket i den menneskelesbare teksten, tydeligst i detail på en feil; det endrer aldri feltnavn, formater eller oppførsel.

Headere

Header Verdi
Authorization Bearer <access_token> — on every request.
Content-Type application/json on POST and PUT · application/merge-patch+json on PATCH · multipart/form-data on file uploads · omit on GET and DELETE.

Id-er, tidsstempler, felter

  • Maskerte id-er. Hver id er en ugjennomsiktig streng som xK9mQ2. Lagre og send den tilbake ordrett; parse, sorter eller konstruer aldri en. En feilformet id svarer 400; en velformet id som ikke finnes svarer 404 som sti-id, eller 422 som referanse inne i en kropp.
  • Tidsstempler. created og modified er ISO-8601-tidspunkter med offset. Rene datofelter, for eksempel dueDate, er YYYY-MM-DD.
  • Fraværende betyr fraværende. Valgfrie felter uten verdi utelates fra svar-JSON, de sendes ikke som null.
  • Overstyring av sporingsdata. Kropper som oppretter tar valgfrie created/createdBy, og kropper som oppdaterer modified/modifiedBy, for å tilskrive en endring når du migrerer data; standardverdiene er tjener-nå og eieren av legitimasjonen. En personreferanse som ikke finnes svarer 422.
  • actedBy. Endringer gjort med et på-vegne-av-token gjengir den handlende brukerens maskerte id i svarkroppen.

Oppdateringer: PUT mot PATCH

PUT erstatter hele posten — alt du utelater behandles som tomt. PATCH er JSON Merge Patch etter RFC 7396 og krever Content-Type: application/merge-patch+json; alt annet svarer 415. Et felt du tar med oppdateres, et felt du setter til null tømmes, et felt du utelater røres ikke, og en tom kropp {} er en gyldig ikke-endring.

Paginering — tre lesemoduser

Hver samling tilbyr opptil tre listevarianter. Kontrakten er den samme på tvers av ressurser, så strukturen nedenfor er den du får på /company og /activity også; ressurssidene legger bare til sine egne filtre og projeksjoner. Hvilken modus som passer til hvilken jobb — og hvordan du bygger en synk som ikke mister rader — står under Lister, paginering og synk.

Modus Sti Pagineringsparametere Svarkonvolutt
Offset GET /person offset (standard 0) · limit Elementer, et reelt totalantall og navigasjonslenker.
Cursor GET /person/cursor cursor · limit Elementer, nextCursor/prevCursor og lenker. Ingen totalsum — keyset-paginering hopper over opptellingen.
Timeline GET /person/timeline since · key (created eller modified) · cursor · limit Markørkonvolutten, over alt som er opprettet eller endret siden den nedre grensen.

Utelat cursor for den første siden; en markør utstedt for én key avvises på en annen med 400. På person og company tar alle tre variantene også view, som velger projeksjonen av hvert element: lean (standarden) gir den kompakte listeraden, full gir for hver rad den samme kroppen som oppslaget på én post gir, og view=full setter et tak på limit på 100.

Offset envelope
{
  "totalItems": 143,
  "totalPages": 8,
  "page": 0,
  "size": 20,
  "items": [ { "id": "xK9mQ2", … }, … ],
  "links": {
    "self":  "/acme/api/v1/en/person?offset=0&limit=20",
    "first": "/acme/api/v1/en/person?offset=0&limit=20",
    "next":  "/acme/api/v1/en/person?offset=20&limit=20",
    "last":  "/acme/api/v1/en/person?offset=140&limit=20"
  }
}
Cursor envelope
{
  "items": [ { "id": "xK9mQ2", … }, … ],
  "nextCursor": "Qm5PbDQ2RXhLOW1RMnRaeDBDbVc4…",
  "prevCursor": "TmJMNWFUdUpkRXdTeUFvUWlIa1hn…",
  "links": {
    "self": "/acme/api/v1/en/person/cursor?limit=20",
    "next": "/acme/api/v1/en/person/cursor?cursor=Qm5PbDQ2RXhLOW1RMnRaeDBDbVc4…&limit=20"
  }
}
Medlem Hva det er
items Radene på denne siden, i projeksjonen ressursens view-parameter velger der den finnes. Markør- og tidslinjesider er i stigende nøkkelrekkefølge.
totalItems totalPages page size Bare i offset-modus: antall rader som matcher, antall sider ved gjeldende sidestørrelse, nullbasert indeks for denne siden, og sidestørrelsen som faktisk ble brukt.
nextCursor prevCursor Bare i markør- og tidslinjemodus. Ugjennomsiktige sidemarkører; nextCursor mangler på den siste siden og prevCursor på den første.
links Navigasjonslenker etter RFC 8288 i kroppen: self, next og prev der de gjelder, og i tillegg first og last på offset-endepunktet.

Følg links, ikke bygg URL-er. Hver lenke tar vare på filtrene dine og er en gyldig sti mot samme base-URL. Mangler next, er dette den siste siden, og markørene er ugjennomsiktige — rediger aldri en. Dokumenter har i tillegg en egen endringsstrøm på plasseringsnivå oppå disse tre: Document changes.

Feil

Alt som ikke er 2xx fra forretnings-API-et er et problemdokument etter RFC 9457, med Content-Type: application/problem+json. Forgren på status og type; vis detail til mennesker — den oversettes av {locale}-segmentet og navngir feltet som feilet ved validering — men parse den aldri.

Problem document
{
  "timestamp": "2026-08-21T11:58:21.123Z",
  "status": 422,
  "type": "urn:visena:validation:illegal-argument",
  "errorType": "ILLEGAL_ARGUMENT",
  "title": "Unprocessable Entity",
  "detail": "companyId 'bQ4wR8' does not resolve to an existing company",
  "instance": "/acme/api/v1/en/person"
}

Dokumentet medlem for medlem, hva du gjør med hver statuskode, og en gjenforsøkspolicy verdt å kopiere står under Feil og feilsøking. Token-endepunktet er unntaket beskrevet over: det feiler på OAuth 2.0-måten istedenfor med et problemdokument.

Fellesfeil — alle endepunkter

Ressurssidene lister bare svarene som er spesifikke for et endepunkt. I tillegg til dem kan hvert endepunkt svare med disse fire:

Status Betydning
401 Missing, expired or revoked token. Mint a fresh token and retry once.
403 The token lacks the scope this method requires, or it was minted for another instance.
404 Unknown instance name in the URL.
500 Unexpected server error. Retry with exponential backoff, and report the problem body's timestamp if it persists.

Et endepunkt kan gi den samme koden en smalere betydning — de fleste 404 handler om id-en i stien, ikke om instansnavnet. Der et endepunkt dokumenterer en kode selv, er dets egen svartabell autoriteten; de fire over er dokumentert én gang, i sin helhet, under Fellesfeil.