Visena Dokumentasjon
Partner API

Guide

Å gjøre kall

Alle kall følger samme oppskrift: URL-en med instansnavnet først, bearer-tokenet ditt, JSON inn, JSON ut. Denne siden følger én personoppføring gjennom oppretting, lesing, oppdatering og sletting, og stopper ved det ene som er verdt å lese to ganger — hva PUT og PATCH gjør forskjellig.

Anatomien i en URL

Alle forretningsendepunkter er bygget av de samme delene i samme rekkefølge. Ingenting må oppdages under kjøring: kan du skrive URL-en, kan du kalle API-et.

https://api.visena.example/acme/api/v1/en/person/xK9mQ2
/acmeinstansnavn /enlocale /personressurs

Instansnavnet kommer først, og det er nettopp det som gjør at én integrasjon kan betjene flere Visena-instanser ved å bytte ett enkelt segment. Tokenet ditt utstedes for én instans, så tokenet og stien må stemme — er de ulike, får du 403, ikke en stille lesing på tvers av instanser.

Locale-segmentet (en eller no) velger språket i den menneskelesbare teksten i svaret, tydeligst i detail på en feil. Det endrer aldri feltnavn, formater eller oppførsel, så velg ett og bruk det konsekvent. Så kommer ressursen, og etter den en maskert id.

Ressurser er i entall, og stien har ikke noe partner/-segment: den er /{instanceName}/api/v1/{locale}/person. Ni ressursstier utgjør flaten i dag — person, company, company-template, project, project-template, activity, document, document/folder og document/changes. Hver av dem er dokumentert endepunkt for endepunkt i endepunktreferansen.

Headere på alle kall

Tre headere avgjør om et kall i det hele tatt blir forstått. To av dem setter du selv; den tredje er verdt å kjenne fordi det er slik en feil melder seg.

Header Verdi
Authorization Bearer <access_token> — på alle kall, uten unntak. Tokener er kortlevde og bundet til én instans; se Legitimasjon og tokener.
Content-Type application/jsonPOST og PUT · application/merge-patch+jsonPATCH · multipart/form-data når du laster opp et dokument · utelat den helt på GET og DELETE.
Accept Valgfri. Et vellykket svar er application/json; en feil er application/problem+json — problemdokumentet etter RFC 9457, beskrevet i Feil og feilsøking.

Opprette

POST /{instanceName}/api/v1/{locale}/person

POST /acme/api/v1/en/person
curl -X POST "https://api.visena.example/acme/api/v1/en/person" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Kari",
    "lastName": "Nordmann",
    "primaryEmail": "kari.nordmann@example.com",
    "jobTitle": "Operations Manager"
  }'
HTTP/1.1 201 Created
HTTP/1.1 201 Created
Location: /acme/api/v1/en/person/xK9mQ2

{
  "id": "xK9mQ2",
  "firstName": "Kari",
  "lastName": "Nordmann",
  "primaryEmail": "kari.nordmann@example.com",
  "jobTitle": "Operations Manager",
  "created": "2026-08-21T08:02:44Z",
  "createdBy": "pQ7hL4",
  "modified": null,
  "modifiedBy": null
}

To ting i det svaret former resten av integrasjonen din. Location bærer stien til den nye ressursen, og id er den maskerte id-en du bruker fra nå av: lagre den akkurat som du fikk den, og send den tilbake ordrett. Den er opak — den har ingen rekkefølge, ingen betydning utenfor API-et, og kan ikke konstrueres. Alle de andre feltene på ressursen ligger også i svaret, og de du ikke sendte kom tilbake som null; tidsstempler er RFC 3339, normalisert til UTC av serveren.

En import kan beholde sin egen historikk: send created, createdBy, modified eller modifiedBy, og de blir oppføringens attribusjon i stedet for «nå» og eieren av legitimasjonen. En createdBy eller modifiedBy som ikke lar seg slå opp som en person i instansen avvises med 422, og ingenting skrives.

i

Sjekk for duplikater før du oppretter. GET /…/person/duplicates?email=kari.nordmann@example.com (eller navn pluss fødselsdato) returnerer sannsynlige treff, slik at en synk ikke oppretter samme person to ganger. Selskaper har samme sjekk med organisasjonsnummer som nøkkel — og der er det mer enn et råd: å opprette et selskap med et organisasjonsnummer som allerede finnes, avvises med 409.

Lese

GET /{instanceName}/api/v1/{locale}/person/{personId}

GET /acme/api/v1/en/person/xK9mQ2
curl "https://api.visena.example/acme/api/v1/en/person/xK9mQ2" \
  -H "Authorization: Bearer $TOKEN"

Et oppslag på id returnerer hele entiteten, samme kropp som en oppretting eller en oppdatering returnerer. En id som ikke finnes gir 404; en streng som ikke er en maskert id i det hele tatt gir 400, fordi den feiler før noe oppslag. Å lese mange oppføringer — offset-paginering, cursor-paginering og endringsstrømmen — er et eget tema: se Lister, paginering og synk.

Oppdatere — to varianter

Begge verbene adresserer samme oppføring med id, og begge svarer 200 med den oppdaterte entiteten. De skiller seg i hva som skjer med feltene du ikke nevner, og det er forskjellen du må avklare før du skriver en synk.

PUT erstatter

PUT med Content-Type: application/json er en full erstatning: alle skrivbare felt du utelater blir tømt. Send hele oppføringen hver gang. Bruk det når systemet ditt eier oppføringen fullt ut og kopien der er sannheten.

PUT /acme/api/v1/en/person/xK9mQ2
curl -X PUT "https://api.visena.example/acme/api/v1/en/person/xK9mQ2" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Kari",
    "lastName": "Nordmann",
    "primaryEmail": "kari.nordmann@example.com",
    "jobTitle": "Head of Operations"
  }'

Det kallet setter stillingstittelen — og hadde denne personen en directPhone, er nummeret nå borte, fordi kroppen ikke nevnte det. created og createdBy er det ene unntaket: de er uforanderlige ved oppdatering og blir stille ignorert.

PATCH fletter

PATCH er en JSON Merge Patch (RFC 7396), sendt som application/merge-patch+json. Den endrer bare det kroppen nevner, og tre regler dekker det:

  • Et felt du tar med og gir en verdi settes til den verdien.
  • Et felt du setter til null blir tømt.
  • Et felt du utelater står akkurat som det sto.
PATCH /acme/api/v1/en/person/xK9mQ2
# sets jobTitle, clears directPhone, touches nothing else
curl -X PATCH "https://api.visena.example/acme/api/v1/en/person/xK9mQ2" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{
    "jobTitle": "Head of Operations",
    "directPhone": null
  }'

Ordet å passe på er null. Under PUT betyr en eksplisitt null og et utelatt felt det samme — begge tømmer verdien — fordi en erstatning ikke har noen måte å si «la denne være» på. Under PATCH er de motsetninger: null tømmer, utelatelse bevarer. Derfor er en klient som bygger én forespørselskropp og gjenbruker den for begge verbene den klassiske måten å viske ut et felt ingen mente å ta i. Har systemet ditt bare deler av oppføringen, bruk PATCH.

Medietypen for PATCH er ikke application/json. Den må være application/merge-patch+json; ren JSON avvises med 415 før kroppen leses i det hele tatt. En tom kropp {} er lovlig og en ren nulloperasjon — oppføringen kommer tilbake uendret, og ingenting skrives.

Slette

DELETE /{instanceName}/api/v1/{locale}/person/{personId}

DELETE /acme/api/v1/en/person/xK9mQ2
curl -X DELETE "https://api.visena.example/acme/api/v1/en/person/xK9mQ2" \
  -H "Authorization: Bearer $TOKEN"

# 204 No Content

Ikke alle slettinger ødelegger, og standardvalgene er bevisst de trygge. Å slette et selskap deaktiverer det med mindre du sier noe annet: ?mode=deactivate er standard og reversibelt, ?mode=delete er den harde slettingen. For en aktivitet er standarden ?mode=close. Å slette et prosjekt er alltid en myk lukking. En mode endepunktet ikke kjenner igjen gir 400 i stedet for en gjetning.

Ingenting kaskaderer i stillhet. Å slette en dokumentmappe som fortsatt inneholder dokumenter, eller et dokument med plasseringer under andre oppføringer, avvises med 409, og detail teller opp nøyaktig hva som ville fulgt med. Send på nytt med acknowledgeCascade=true for å bekrefte.

Svarkonvensjoner det er verdt å kjenne

  • Et tomt felt er null, ikke fraværende. En full entitetskropp bærer alle feltene på ressursen, og de uten verdi er JSON null. At en nøkkel finnes forteller deg derfor ingenting — les verdien. Listekonvoluttene er det bevisste unntaket: en pagineringslenke eller cursor som ikke gjelder utelates, og fraværet er signalet om at det ikke finnes flere sider.
  • created / modified og createdBy / modifiedBy bærer den lagrede revisjonsattribusjonen: RFC 3339-tidsstempler normalisert til UTC, og maskerte person-id-er. Sender du dem ved en skriving, blir de attribusjonen; utelater du dem, stempler serveren «nå» og eieren av legitimasjonen.
  • actedBy er den maskerte id-en til brukeren en endring ble gjort som. Den fylles bare ut for kall gjort med en på-vegne-av-legitimasjon; en vanlig legitimasjon lar den stå som null.
  • Referanser slås opp, ikke stoles på. En companyId, groupId, responsiblePersonId eller modifiedBy som ikke lar seg slå opp i instansen feiler hele kallet med 422. En avvist skriving etterlater ingenting halvskrevet.
  • Maskerte id-er er strenger. Sammenlign dem for likhet og ingenting annet: ingen rekkefølge, ingen regning, ingen konstruksjon av én fra et tall du har et sted.