Visena Dokumentasjon
Partner API

Ressurs

Person

Menneskene i instansen — kontakter, ansatte og brukerkontoer. Full CRUD, duplikatsøk, planlagt slettedato og en funksjonsstyrt GDPR-sletting.

Endepunktreferansen under 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.

Endepunkter

Tolv endepunkter, i samme rekkefølge som de er dokumentert nedenfor.

Alle endepunktene på denne siden kan i tillegg svare med fellesfeilene — 401, 403, 404 (ukjent instans) og 500. De er dokumentert én gang, under Feil og feilsøking.

Create a person

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

Creates a person and returns the full entity. 201 with a Location header.

RESTORING AN EXPORT: created/createdBy are accepted here and nowhere else — a later replace ignores them — and the identifiers of the person and of its email aliases and external ids are always newly minted.

Forespørselskropp

application/jsonPersonCreateDto

Svar

Status Beskrivelse
201 Person created.
PersonResponseDto · application/json
400 Request body failed validation.
422 A referenced entity (createdBy, modifiedBy, company, country, group) does not exist.

Eksempel

curl
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"
  }'

Get a person

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

Returns the full entity. 404 if unknown; 400 if the id cannot be unmasked.

Parametere

Parameter Plassering Type Beskrivelse
personId required path string Masked person id.

Svar

Status Beskrivelse
200 The person.
PersonResponseDto · application/json
400 The id is not a valid id.
404 No person with that id.

Eksempel

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

List persons (offset-paginated)

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

The default collection view: offset/limit paging with a real total. Optional query (name/email/employeeNumber full-text), isActive, companyId (main relation), groupId (primary group), employeeNumber (exact, user accounts only), externalReference (exact), email (exact) filters and a created/modified/lastName sort. RFC 8288 navigation links are in the body. view selects the item projection: set view=full to receive, for every row, the same body the per-person read returns (createdBy/modifiedBy included) instead of the lean list item; allowed values are lean and full, the default is lean, and view=full caps limit at 100.

Parametere

Parameter Plassering Type Beskrivelse
offset query integer
default 0
Zero-based item offset.
limit query integer Maximum items to return per page.
query query string Free-text filter; the endpoint description lists the fields it matches.
isActive query boolean Filter on active state.
companyId query string Masked company id.
groupId query string Masked group id.
employeeNumber query string Exact employee-number filter.
externalReference query string Exact external-reference filter.
email query string Exact email-address filter.
sort query string Sort key; the endpoint description lists the allowed values.
view query string, one of lean full
default lean
Item projection: lean (default) for the compact list item, full for the same body the per-person read returns. full caps limit at 100.

Svar

Status Beskrivelse
200 A page of persons with totals and navigation links.
PersonOffsetListResponse · application/json
400 Invalid paging or sort parameter, or a filter id (companyId/groupId) is not a valid id.
404 Under view=full, a person on this page no longer exists: it was deleted between the page query and the record read. Retry the request.

Eksempel

curl
curl "https://api.visena.example/acme/api/v1/en/person?offset=0&limit=20" \
  -H "Authorization: Bearer $TOKEN"

List persons (cursor-paginated, insert-stable)

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

Keyset paging over the monotonic entity id (insertion order). Pass the opaque cursor from a previous page's nextCursor/prevCursor; omit it for the first page. No total — keyset skips the count. Optional filters: query (name/email/employeeNumber full-text), isActive, companyId (main relation), groupId (primary group), employeeNumber (exact, user accounts only), externalReference (exact), email (exact, at most one match). Filters narrow the result but are not bound into the cursor. view selects the item projection: set view=full to receive, for every row, the same body the per-person read returns (createdBy/modifiedBy included) instead of the lean list item; allowed values are lean and full, the default is lean, and view=full caps limit at 100.

SYNC SEMANTICS: this is snapshot paging — a stable traversal of the persons that exist while you walk it — and not a resumable sync substrate. The entity id is allocated when a person is first written, not when that write is committed, so allocation order is not commit order: if a page is served while a lower-id person is still uncommitted, that person is never delivered to this traversal, and no later page recovers it. Walk it start to finish for a one-off extract; for ongoing synchronisation use the time-windowed list (listPersonsByTime), whose imprecision repeats rows instead of dropping them. Deleted persons never appear on any list, cursor or timeline response, and no list response reports a deletion — reconciling disappearances is the consumer's own responsibility.

Parametere

Parameter Plassering Type Beskrivelse
cursor query string Opaque page cursor from the previous response's links.next; omit for the first page.
limit query integer Maximum items to return per page.
query query string Free-text filter; the endpoint description lists the fields it matches.
isActive query boolean Filter on active state.
companyId query string Masked company id.
groupId query string Masked group id.
employeeNumber query string Exact employee-number filter.
externalReference query string Exact external-reference filter.
email query string Exact email-address filter.
view query string, one of lean full
default lean
Item projection: lean (default) for the compact list item, full for the same body the per-person read returns. full caps limit at 100.

Svar

Status Beskrivelse
200 A page of persons with next/prev cursors and links.
PersonCursorListResponse · application/json
400 Invalid or expired cursor, invalid limit, or a filter id (companyId/groupId) is not a valid id.
404 Under view=full, a person on this page no longer exists: it was deleted between the page query and the record read. Retry the request.

Eksempel

curl
curl "https://api.visena.example/acme/api/v1/en/person/cursor?limit=100" \
  -H "Authorization: Bearer $TOKEN"

List persons (time-windowed, cursor-paginated)

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

Keyset paging from an optional since lower bound (open-ended upper bound) on a selectable key (created|modified). RFC 9557 Z timestamps. A cursor minted for a different key is rejected with 400. view selects the item projection: set view=full to receive, for every row, the same body the per-person read returns (createdBy/modifiedBy included) instead of the lean list item; allowed values are lean and full, the default is lean, and view=full caps limit at 100.

SYNC SEMANTICS: delivery is at-least-once. The seek timestamp is read back at millisecond precision from a column stored at microsecond precision, so a person whose key value carries sub-millisecond digits can be delivered again on the following page. The imprecision repeats rows, never omissions, so an overlapping re-scan always recovers the full window — but you must de-duplicate by person id. Resume by re-issuing the request with since set slightly behind the last value you observed; the lower bound is inclusive, which is what makes that overlap expressible. Deleted persons never appear on any list, cursor or timeline response, and no list response reports a deletion — a GDPR erasure reaches change consumers as a person update, never as a delete, so reconciling disappearances is the consumer's own responsibility.

Parametere

Parameter Plassering Type Beskrivelse
since query string (date-time) Inclusive lower bound — an RFC 3339 timestamp.
key query string Which timestamp to page on: created or modified.
cursor query string Opaque page cursor from the previous response's links.next; omit for the first page.
limit query integer Maximum items to return per page.
view query string, one of lean full
default lean
Item projection: lean (default) for the compact list item, full for the same body the per-person read returns. full caps limit at 100.

Svar

Status Beskrivelse
200 A page of persons with next/prev cursors and links.
PersonCursorListResponse · application/json
400 Invalid timestamp, key, cursor, or limit.
404 Under view=full, a person on this page no longer exists: it was deleted between the page query and the record read. Retry the request.

Eksempel

curl
curl "https://api.visena.example/acme/api/v1/en/person/timeline?since=2026-08-20T02:00:00Z" \
  -H "Authorization: Bearer $TOKEN"

Search for potential duplicate persons

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

Duplicate-detection probe for the create flow. Matches by full name (token-based, case-insensitive; optionally narrowed by an exact birthDate) and/or by exact email address (any of the person's addresses, case-insensitive). At least one of firstName, lastName or email is required; birthDate is only accepted together with a name. Exact email matches are listed first; results are capped by limit (default 20; values above 100 are clamped to 100).

Parametere

Parameter Plassering Type Beskrivelse
firstName query string
lastName query string
birthDate query string (date)
email query string Exact email-address filter.
limit query integer Maximum items to return per page.

Svar

Status Beskrivelse
200 The potential duplicates (empty when none match).
PersonDuplicateListResponse · application/json
400 No search signal (firstName/lastName/email all absent), birthDate without a name, an invalid email, or a limit below 1.

Eksempel

curl
curl "https://api.visena.example/acme/api/v1/en/person/duplicates?email=kari.nordmann%40example.com" \
  -H "Authorization: Bearer $TOKEN"

Replace a person

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

Full replace (PUT): omitted optional fields are cleared.

Parametere

Parameter Plassering Type Beskrivelse
personId required path string Masked person id.

Forespørselskropp

application/jsonPersonUpdateDto

Svar

Status Beskrivelse
200 The replaced person.
PersonResponseDto · application/json
400 Request body failed validation, or the id is not a valid id.
404 No person with that id.
422 A referenced entity (modifiedBy, company, country, group) does not exist.

Eksempel

curl
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"
  }'

Partially update a person (RFC 7396 JSON Merge Patch)

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

Absent fields are unchanged, JSON null clears, a value sets. An empty body {} is a no-op. Wrong content type → 415.

Parametere

Parameter Plassering Type Beskrivelse
personId required path string Masked person id.

Forespørselskropp

application/merge-patch+jsonobject

Svar

Status Beskrivelse
200 The updated person.
PersonResponseDto · application/json
400 A patched field had an invalid value, or the id is not a valid id.
404 No person with that id.
415 Content-Type was not application/merge-patch+json.
422 A referenced entity (modifiedBy, company, country, group) does not exist.

Eksempel

curl
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
  }'

Delete a person

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

Hard delete. 204 on success; a repeat delete → 404.

Parametere

Parameter Plassering Type Beskrivelse
personId required path string Masked person id.

Svar

Status Beskrivelse
204 Person deleted; no body.
400 The id is not a valid id.
404 No person with that id (or already deleted).

Eksempel

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

Set a person's planned deletion date

PUT /{instanceName}/api/v1/{locale}/person/{personId}/planned-deletion-date

Sets the person's planned deletion date — GDPR bookkeeping used to plan future deletions: the date is shown and filterable in Visena's person lists, and nothing is deleted automatically on that date (deletion itself is the separate GDPR-delete operation). Requires the GDPR person delete feature to be enabled for the instance. Returns the updated person.

Parametere

Parameter Plassering Type Beskrivelse
personId required path string Masked person id.

Forespørselskropp

application/jsonPersonPlannedDeletionDto

Svar

Status Beskrivelse
200 The updated person, plannedDeletionDate included.
PersonResponseDto · application/json
400 Missing or invalid plannedDeletionDate, or the id is not a valid id.
403 GDPR person delete is not enabled for the instance.
404 No person with that id (or already deleted).

Eksempel

curl
curl -X PUT "https://api.visena.example/acme/api/v1/en/person/xK9mQ2/planned-deletion-date" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "plannedDeletionDate": "2027-01-01"
  }'

Clear a person's planned deletion date

DELETE /{instanceName}/api/v1/{locale}/person/{personId}/planned-deletion-date

Removes only the planned deletion date from the person — the person itself is NOT deleted and nothing else changes. Idempotent: 204 also when no date was set. Requires the GDPR person delete feature to be enabled for the instance.

Parametere

Parameter Plassering Type Beskrivelse
personId required path string Masked person id.

Svar

Status Beskrivelse
204 Planned deletion date cleared; no body.
400 The id is not a valid id.
403 GDPR person delete is not enabled for the instance.
404 No person with that id (or already deleted).

Eksempel

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

GDPR-delete a person

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

Marks the person deleted (PII is scrubbed immediately) and enqueues the asynchronous GDPR erasure job that removes associated data (emails, documents, customer controls, AML reports, budget lines, relations, ...). Requires the GDPR person delete feature to be enabled for the instance and an API client that is permitted to GDPR-delete persons (403 otherwise). excludeUsers (default true) selects how persons holding a Visena user account are treated: true rejects them with 409, false GDPR-deletes them together with their user account. 202 on enqueue; a repeat GDPR delete → 404.

Parametere

Parameter Plassering Type Beskrivelse
personId required path string Masked person id.
excludeUsers query boolean
default true
To delete only CRM person entities that are not licensed Visena users, keep excludeUsers set to true (the default, even when not set) — a licensed user is then rejected with 409. Only when you explicitly want to delete a person who is a licensed Visena user of this system, set excludeUsers to false — and do so cautiously: their login and account data will be deleted too.

Svar

Status Beskrivelse
202 GDPR delete accepted: person marked deleted, erasure job enqueued; no body.
400 The id is not a valid id.
403 GDPR person delete is not enabled for the instance, or the API client is not permitted to GDPR-delete persons.
404 No person with that id (or already deleted).
409 The person holds a Visena user account and excludeUsers was true (the default). Remove the user account first, or retry with excludeUsers=false to delete the user account together with the person.

Eksempel

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

Objektstrukturer

Forespørsels- og svarkroppene som brukes over, i den rekkefølgen de først refereres.

PersonCreateDto

Felt Type Beskrivelse
firstName string Given name. At least one of firstName/lastName is required.
lastName string Family name. At least one of firstName/lastName is required.
initials string
jobTitle string
jobPercent number
employeeNumber string
employedStart string (date)
employedEnd string (date)
birthDate string (date)
description string
primaryEmail string Primary email address.
mobilePhone string Mobile phone. Digits, spaces, +, -, ( ) only.
directPhone string Direct phone. Digits, spaces, +, -, ( ) only.
workPhone string Work phone. Digits, spaces, +, -, ( ) only.
homePhone string Home phone. Digits, spaces, +, -, ( ) only.
fax string Fax. Digits, spaces, +, -, ( ) only.
homeAddress string
homeZipCode string
homeCity string
homePlace string
invoiceAddress string
invoiceZipCode string
invoiceCity string
invoicePlace string
countryCode string, one of NO SE DK GB CH ISO 3166-1 alpha-2 country code (see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Resolved server-side; unknown → 422.
responsiblePersonId string (masked id)
companyId string (masked id)
groupId string (masked id)
isActive object
isResource object
isPrivate object
isPortalLoginEnabled object
isAccessControlled object
isMaster object
duplicatesPersonId string (masked id)
pepValue string, one of NOT_ASSESSED YES YES_EXPIRED NO DONT_KNOW NOT_APPLICABLE
sanctionValue string, one of NOT_ASSESSED YES NO NOT_APPLICABLE
emailAliases array of EmailAliasDto
externalIds array of ExternalIdDto
created string (date-time) override: creation timestamp to attribute. Defaults to server-now (UTC) when absent.
createdBy string (masked id)
modified string (date-time) override: modification timestamp (set alongside creation when provided).
modifiedBy string (masked id)

EmailAliasDto

Felt Type Beskrivelse
id string (masked id)
address string The email address. Trimmed on write; must be non-blank and valid like primaryEmail, otherwise rejected 400. Omit the alias entry to remove it.
label string, one of EMAIL_ADDRESS_LABEL_WORK EMAIL_ADDRESS_LABEL_PRIVATE EMAIL_ADDRESS_LABEL_OTHER
isPrimary boolean Whether this is the primary address. Exactly one alias should be primary.

ExternalIdDto

Felt Type Beskrivelse
id string (masked id)
systemName string Name/code of the external system.
externalId string The person's id within that external system.

PersonResponseDto

Felt Type Beskrivelse
id string (masked id)
firstName string
lastName string
initials string
jobTitle string
jobPercent number
employeeNumber string
employedStart string (date)
employedEnd string (date)
birthDate string (date)
description string
primaryEmail string
mobilePhone string
directPhone string
workPhone string
homePhone string
fax string
homeAddress string
homeZipCode string
homeCity string
homePlace string
invoiceAddress string
invoiceZipCode string
invoiceCity string
invoicePlace string
country CountryRefDto
responsiblePersonId string (masked id)
company CompanyRefDto
group GroupRefDto
isActive boolean
isResource boolean
isPrivate boolean
isPortalLoginEnabled boolean
isAccessControlled boolean
isMaster boolean
duplicatesPersonId string (masked id)
socialSecurityNumberSet boolean Whether a social security number is on file (the value itself is never returned).
pepValue string, one of NOT_ASSESSED YES YES_EXPIRED NO DONT_KNOW NOT_APPLICABLE
sanctionValue string, one of NOT_ASSESSED YES NO NOT_APPLICABLE
plannedDeletionDate string (date) Planned deletion date (GDPR bookkeeping); null when not set.
emailAliases array of EmailAliasDto
externalIds array of ExternalIdDto
created string (date-time) Creation timestamp (UTC).
createdBy string (masked id)
modified string (date-time) Last-modification timestamp (UTC); null until first modified.
modifiedBy string (masked id)
actedBy string (masked id)

CountryRefDto

Country this organizational number is registered in.

Felt Type Beskrivelse
id string (masked id)
name string Country display name.
code string ISO 3166-1 alpha-2 country code, e.g. "NO".

CompanyRefDto

The company the owning project belongs to, if any.

Felt Type Beskrivelse
id string (masked id)
name string Company display name.
organizationalNumbers array of OrgNumberDto Active organizational (registration) numbers; at most one per company.

OrgNumberDto

Active organizational (registration) numbers; at most one per company.

Felt Type Beskrivelse
orgNumber string The organizational (registration) number.
country CountryRefDto

GroupRefDto

Owning group / department.

Felt Type Beskrivelse
id string (masked id)
name string Group display name.

PersonOffsetListResponse

Felt Type Beskrivelse
totalItems integer Total number of matching persons.
totalPages integer Total number of pages at the current page size.
page integer Zero-based index of the current page.
size object Page size actually applied.
items array of PersonListItem The persons on this page, in the projection selected by view.
links PersonListLinks

PersonListItem

A person as returned by a list operation. Which of the two shapes is returned is chosen by the view query parameter: lean (the default) yields the compact list item, full yields the same body the per-person read returns.

No fields of its own: the shape is either PersonListItemDto (view=lean) or PersonResponseDto (view=full).

PersonListItemDto

Felt Type Beskrivelse
id string (masked id)
firstName string First name.
lastName string Last name.
initials string Initials.
jobTitle string Job title.
primaryEmail string Primary email address.
mobilePhone string Mobile phone number.
company CompanyRefDto
country CountryRefDto
group GroupRefDto
isActive boolean Whether the person is active.
isResource boolean Whether the person is a resource.
isMaster boolean Whether the person is a master record.
created string (date-time) Creation timestamp (UTC).
modified string (date-time) Last-modification timestamp (UTC); null until first modified.

RFC 8288 navigation links.

Felt Type Beskrivelse
self string URL of the current page.
first string URL of the first page (offset endpoint).
prev string URL of the previous page, if any.
next string URL of the next page, if any.
last string URL of the last page (offset endpoint).

PersonCursorListResponse

Felt Type Beskrivelse
items array of PersonListItem The persons on this page, in ascending key order, in the projection selected by view.
nextCursor string Opaque cursor for the next page; absent on the last page.
prevCursor string Opaque cursor for the previous page; absent on the first page.
links PersonListLinks

PersonDuplicateListResponse

Felt Type Beskrivelse
items array of PersonListItemDto Potential duplicate persons, exact email matches before name matches.

PersonUpdateDto

Felt Type Beskrivelse
firstName string Given name. At least one of firstName/lastName is required.
lastName string Family name. At least one of firstName/lastName is required.
initials string
jobTitle string
jobPercent number
employeeNumber string
employedStart string (date)
employedEnd string (date)
birthDate string (date)
description string
primaryEmail string Primary email address.
mobilePhone string Mobile phone. Digits, spaces, +, -, ( ) only.
directPhone string Direct phone. Digits, spaces, +, -, ( ) only.
workPhone string Work phone. Digits, spaces, +, -, ( ) only.
homePhone string Home phone. Digits, spaces, +, -, ( ) only.
fax string Fax. Digits, spaces, +, -, ( ) only.
homeAddress string
homeZipCode string
homeCity string
homePlace string
invoiceAddress string
invoiceZipCode string
invoiceCity string
invoicePlace string
countryCode string, one of NO SE DK GB CH ISO 3166-1 alpha-2 country code (see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Resolved server-side; unknown → 422.
responsiblePersonId string (masked id)
companyId string (masked id)
groupId string (masked id)
isActive object
isResource object
isPrivate object
isPortalLoginEnabled object
isAccessControlled object
isMaster object
duplicatesPersonId string (masked id)
pepValue string, one of NOT_ASSESSED YES YES_EXPIRED NO DONT_KNOW NOT_APPLICABLE
sanctionValue string, one of NOT_ASSESSED YES NO NOT_APPLICABLE
emailAliases array of EmailAliasDto
externalIds array of ExternalIdDto
created string (date-time) Audit override: creation timestamp. Immutable on update — ignored.
createdBy string (masked id)
modified string (date-time) Audit override: modification timestamp to attribute. Defaults to server-now (UTC) when absent.
modifiedBy string (masked id)

PersonPlannedDeletionDto

Felt Type Beskrivelse
plannedDeletionDate required string (date) The planned deletion date. Required; use DELETE on the same path to clear it.