HRM Norway Employee API (1.0.0)

Download OpenAPI specification:

HRM Norway Employee Core management service API.

Authentication

All endpoints require Bearer token authentication.

To integrate with Employee API you have to register on Visma Developer Portal and request access to the API along with the required scopes.

Authentication uses OAuth tokens from Visma Connect. Authorization is done on tenant level, so one OAuth token is needed per tenant.

Entity Hierarchy

Entity Timeline Description
Employee - Core employee record
├── additionalAccounts[] flexible Secondary bank accounts for payments
├── carLinks[] flexible Company car links
├── children[] none Employee's children with period tracking
├── creditorClaims[] flexible Wage garnishments and deductions
├── pensionLinks[] flexible Pension provider links
├── personalInformation singleton Personal details (name, address, contact info) — 1:1 per employee
├── sicknessAndAbsence none Chronically ill periods only (see position-level for prepaid/redundancy)
├── taxAndContributionRules[] flexible Special tax and contribution rules
├── taxInformation[] strict Tax card and withholding settings
├── unionLinks[] flexible Union memberships
└── positions[] flexible Employment positions and job assignments
    ├── costUnitLinks[] flexible Cost center allocations
    ├── salaryInformation[] strict Salary, hourly rates, and pay details
    ├── sicknessAndAbsence none Prepaid sickness, other absence, and redundancy periods
    ├── taxUnitLinks[] strict Tax unit assignments for A-melding reporting
    └── workArrangements[] strict Working hours and schedule arrangements

Employees

The root aggregate entity representing an employee within an organization. An employee holds non-timelined core fields (identity, draft status, notes) and embeds settings objects (contactDetails, payrollSettings, sicknessAndAbsence, linkedUserData). It serves as the parent for all timeline-based sub-entities such as personal information, positions, tax information, and more.

An employee is always created together with at least one position via the combined POST /employees/with-positions endpoint.

Property Type Required Description
id UUID Yes (read-only) Unique employee identifier. Can be client-provided on create, otherwise server-generated.
number string No Employee number (Ansattnummer). Max 12 characters, unique within the organization.
tenantId string (read-only) Organization tenant identifier. Derived from authentication token.
isDraft boolean No Draft employees have relaxed validation and are excluded from payroll. Cannot revert to true.
notes string No Free-text administrator notes. Must not contain personal or sensitive data.
mergedCompanyEmployeeStartDate date No Original start date when employee transferred from a merged company.
etag string (read-only) Opaque version token for optimistic concurrency. Must be included in PATCH requests.
updatedAt datetime (read-only) Timestamp of last modification.

Embedded Objects

The following objects are part of the Employee record and are read/written inline via the Employee PATCH endpoint. Each has its own documentation page.

Object Description
contactDetails Address, phone numbers, email addresses, emergency contacts
emergencyContacts Emergency contact persons (name, phone, email, primary flag)
payrollSettings Bank account, payment method, payslip preferences
linkedUserData Read-only user account data from Visma Connect
sicknessAndAbsence Employee-level chronically ill periods

Sub-Entities (Related Collections)

Timeline-based entities managed through dedicated endpoints under /employees/{employeeId}/.... Can be embedded in GET responses using the ?embed query parameter (e.g. GET /employees/{id}?embed=positions,personalInformation).

Collection Timeline Description
personalInformation None Name, national ID, gender, date of birth
positions Flexible Employment positions / job roles
additionalAccounts Flexible Secondary bank accounts for partial salary payments
carLinks Flexible Company vehicle assignments
children None Children (affects sick leave entitlements)
creditorClaims Flexible Wage garnishments and creditor deductions
pensionLinks Flexible Pension provider assignments
taxAndContributionRules Flexible Special tax rules (nettlonn, sjofolk, Svalbard)
taxInformation Strict Tax cards and withholding settings
unionLinks Flexible Union memberships and insurance

Key Validation Rules

  • An employee cannot be created without at least one position — use the combined POST /employees/with-positions endpoint. This rule does not apply for Draft Employees.
  • number, when provided, must be unique within the organization and is immutable after creation (except for draft employees).
  • Only draft employees (isDraft = true) can be hard-deleted. Non-draft employees are terminated by ending their positions.
  • isDraft cannot be changed from false back to true.
  • etag must be included in every PATCH request and must match the server's current version.
  • Contact details: when any address field is provided, countryCode is required.
  • Payroll settings: paymentType determines which bank fields are required/prohibited.

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the employee record. When omitted on create, the server generates a UUID. Supplying a duplicate UUID returns 409 Conflict.

Note: This is subject for change - Client-provided IDs are useful for idempotent creation (retry-safe), data migration, and offline-first architectures. This will be supported after EmpMan monolith is discontinued.

number

  • Type: string
  • Required: No

Human-readable employee number. Max 12 characters. Must be unique within the organization. If not provided on create, the system assigns the next available number.

Validation

  • Immutable after creation (except for draft employees).

isDraft

  • Type: boolean
  • Required: No (defaults to false)

Draft mode flag. Draft employees have relaxed validation (lookup validation like managerId is skipped), are excluded from payroll runs, and are excluded from A-melding reporting. Draft employees can be hard-deleted via the API; non-draft employees can only be terminated by ending their positions.

Validation

  • Cannot change from false to true. The transition is one-way.

notes

  • Type: string
  • Required: No

Free-text administrator notes about the employee. Should not contain personal or sensitive data (advisory — not system-enforced).

mergedCompanyEmployeeStartDate

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No

Original employment start date from a merged company. Only relevant when the employee was transferred from a merged/acquired company and seniority calculations require the true start date.

etag

  • Type: string
  • Required: Yes (on PATCH requests)

Opaque version identifier for optimistic concurrency control. Returned in every GET response and must be echoed back in PATCH requests. If the value does not match the server's current version, the request returns 409 Conflict.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the employee record or any embedded object. Set by the service on every write.

Contact Details

Property Type Required Description
address1 string No Street address (Gateadresse). Max 200 characters.
postalLocation string No Postal location (Poststed). Max 200 characters.
postalCode string No Postal code (Postnummer). For Norwegian addresses, must be a valid 4-digit code.
countryCode string Conditional Country code, ISO 3166-1 alpha-2 (Landkode). Required when any address field is provided.
homePhone string No Private phone number (Hjemmetelefon). 8–16 characters.
workPhone string No Work phone number (Jobbtelefon). 8–16 characters.
homeEmail string No Personal email address (Privat e-post). Max 135 characters. Must be a valid email format.
workEmail string No Work email address (Jobb e-post). Max 135 characters. Must be a valid email format.
emergencyContacts array No Array of emergency contact persons (Nødkontakter). See EmergencyContacts.

For more information refer to Contact Details

Emergency Contacts

Property Type Required Description
firstName string Yes Emergency contact's first name.
lastName string Yes Emergency contact's last name.
mainContact boolean No Whether this is the primary emergency contact.
phoneNumber string No Contact phone number. null when not provided.
email string No Contact email address. Must be a valid email. null allowed.

For more information refer to emergencyContacts

Payroll Settings

Property Type Required Description
payslipOnPaper boolean No Generate a paper payslip in addition to the electronic one. Default: false.
payslipLanguage enum No Payslip language: norwegian (default) or english.
paymentType enum Yes Salary payment method: bank or cash.
norwegianBankAccount string Conditional Norwegian bank account number. 11 digits with MOD11 check digit. Required when paymentType = bank and internationalBank is not provided.
internationalBank object Conditional International bank account details (IBAN, SWIFT, country, remittance country). Required when paymentType = bank and payment is to a foreign bank account.
internationalBank.iban string Yes IBAN for international transfers. Length and format depend on the country (e.g. Norwegian IBAN: NO + 2 check digits + 11-digit account number, 15 characters total).
internationalBank.swift string Yes BIC/SWIFT code identifying the bank. 8 or 11 characters (e.g. DNBANOKKXXX).
internationalBank.country string Yes Country where the bank is located. ISO 3166-1 alpha-2 code.
internationalBank.remittanceCountry string Yes Remittance destination country. ISO 3166-1 alpha-2 code. May differ from country.
retrieveTaxCardOnWageRun boolean No When true, the tax card is fetched from Skatteetaten at the start of each wage run. Default: true.
lastTaxCardRetrieveDate date No (read-only) Date the tax card was last retrieved from Skatteetaten. Managed by the service.

For more information refer to payrollSettings

Linked User Data

Property Type Required Description
firstName string No (read-only) User account first name from Visma Connect.
lastName string No (read-only) User account last name from Visma Connect.
email string (email) No (read-only) User account login email from Visma Connect.
status string No (read-only) User account status (e.g. active, pending, inactive, suspended).
odpUserId string No (read-only) Visma Connect (ODP) user account identifier. Set once the account has been successfully created.

For more information refer to linkedUserData

Sickness and Absence

Property Type Required Description
chronicallyIllPeriods array No Periods when the employee has chronic illness status. See period shape below.
chronicallyIllPeriods[].id UUID Yes (read-only) Unique period identifier.
chronicallyIllPeriods[].from date Yes Period effective from date.
chronicallyIllPeriods[].to date No Period effective until date. null means ongoing.
lastModified datetime Yes (read-only) Timestamp of the most recent modification. null when no periods exist.

For more information refer to sicknessAndAbsence

Events

Event Trigger Consumers
employee.created New employee registered (with initial position) Payroll, A-melding, Reporting
employee.updated Employee root fields modified (contactDetails, payrollSettings, etc.) Payroll, A-melding
employee.deleted Draft employee hard-deleted Payroll

Create employee with positions

Creates a new employee with initial positions in a single atomic transaction.

Draft Mode:

  • Set employee.isDraft to true to create a draft employee with relaxed validation.
  • Draft mode skips lookup validation (e.g., managerId verification).
  • Use PATCH to later transition from draft to non-draft, which will apply full validation.

Response: Returns the created Employee with positions embedded in the response.

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

Request Body schema: application/json
required
required
object (Employee)

The employee to create. The isDraft flag controls validation behavior.

Array of objects (Position)
Default: []

Initial positions to create for the employee. Optional - can be empty or omitted. Each position will be validated according to the existing Position schema rules.

Responses

Request samples

Content type
application/json
{
  • "employee": {
    },
  • "positions": [ ]
}

Response samples

Content type
application/json
{
  • "number": "string",
  • "tenantId": "string",
  • "isDraft": true,
  • "notes": "string",
  • "mergedCompanyEmployeeStartDate": "2019-08-24",
  • "contactDetails": {
    },
  • "payrollSettings": {
    },
  • "linkedUserData": {
    },
  • "sicknessAndAbsence": {
    },
  • "positions": [
    ],
  • "personalInformation": {
    },
  • "children": [
    ],
  • "legacyIds": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Create employee with all entities

Creates an employee and all of its child entities atomically in a single transaction.

Draft Mode:

  • Set employee.isDraft to true to skip all validation and save the record as-is.
  • Use PATCH to later transition from draft to non-draft (full validation applies then).

Not included: taxUnitLinks and costUnitLinks (position-level entities) are not part of this endpoint. Create them separately after the employee is created.

Response: Returns the created Employee root only. Use the embed query parameter on GET to retrieve nested entities.

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

Request Body schema: application/json
required
required
object (Employee)

The employee root. Set isDraft=true to skip FluentValidation and manager ID lookup.

Array of objects (Position)
Default: []

Positions to create. Each may include salaryInformation and workArrangements.

object or null
Array of objects (TaxInformationCreate)
Default: []
Array of objects (ChildCreate)
Default: []
Array of objects (UnionLinkCreate)
Default: []
Array of objects (CarLinkCreate)
Default: []
Array of objects (CreditorClaimCreate)
Default: []
Array of objects (TaxAndContributionRuleCreate)
Default: []
Array of objects (PensionLinkCreate)
Default: []
Array of objects (AdditionalAccountCreate)
Default: []

Responses

Request samples

Content type
application/json
{
  • "employee": {
    },
  • "positions": [ ],
  • "personalInformation": {
    },
  • "taxInformation": [ ],
  • "children": [ ],
  • "unionLinks": [ ],
  • "carLinks": [ ],
  • "creditorClaims": [ ],
  • "taxAndContributionRules": [ ],
  • "pensionLinks": [ ],
  • "additionalAccounts": [ ]
}

Response samples

Content type
application/json
{
  • "number": "string",
  • "tenantId": "string",
  • "isDraft": true,
  • "notes": "string",
  • "mergedCompanyEmployeeStartDate": "2019-08-24",
  • "contactDetails": {
    },
  • "payrollSettings": {
    },
  • "linkedUserData": {
    },
  • "sicknessAndAbsence": {
    },
  • "positions": [
    ],
  • "personalInformation": {
    },
  • "children": [
    ],
  • "legacyIds": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

List all employees

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

embed
string

Comma-separated list of related entities to embed in response.

For Employee: positions, personalInformation, taxInformation, children, unionLinks, carLinks, creditorClaims, taxAndContributionRules, pensionLinks, additionalAccounts

Example: ?embed=positions,personalInformation

includeLegacyIds
boolean
Default: false

When true, requests that legacy system identifiers be included in the response. Note: legacyIds may still be null if the underlying data source does not carry legacy IDs (see the legacyIds field description for details). Intended for short-term use by clients migrating from legacy systems.

Example: ?includeLegacyIds=true

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create a new employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

number
string or null (number)

Employee number (Ansattnummer) - company-assigned identifier


Monolith notes: Field "_Employee ID" (00000000-0000-4002-0101-000000000000).


isDraft
boolean
Default: false

Draft employees are not included in payroll runs

notes
string or null (notes)

Free-text notes about the employee


Monolith notes: Field "Notes" (c911e43b-1856-416a-a7a2-88e3e9639226).


mergedCompanyEmployeeStartDate
string or null <date> (mergedCompanyEmployeeStartDate)

Original start date when employee transferred from merged company


Monolith notes: Field "Employee start date in merged company" (0c036557-11a2-4d23-b059-c6b2ce530d4f).


object (ContactDetails)
object (PayrollSettings)

Payroll and payment settings (Lønnsinnstillinger).

object (LinkedUserData)

Link to user account in identity system

object (SicknessAndAbsence)

Employee-level sickness and absence configuration (chronicallyIllPeriods only). Use asOfDate query parameter to filter to periods active on a specific date.

PATCH semantics: Omitting a property from a PATCH request preserves existing periods unchanged. Providing an empty array ([]) clears all periods of that type. Providing a non-empty array fully replaces periods of that type.

Breaking change: prepaidSicknessPeriods, prepaidOtherAbsencePeriods, and redundancyPeriods have been moved to the position-level endpoint (positions/{positionId}/sickness-and-absence). Sending those fields here will return 400.

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "number": "string",
  • "isDraft": false,
  • "notes": "string",
  • "mergedCompanyEmployeeStartDate": "2019-08-24",
  • "contactDetails": {
    },
  • "payrollSettings": {
    },
  • "linkedUserData": {
    },
  • "sicknessAndAbsence": {
    }
}

Response samples

Content type
application/json
{
  • "number": "string",
  • "tenantId": "string",
  • "isDraft": true,
  • "notes": "string",
  • "mergedCompanyEmployeeStartDate": "2019-08-24",
  • "contactDetails": {
    },
  • "payrollSettings": {
    },
  • "linkedUserData": {
    },
  • "sicknessAndAbsence": {
    },
  • "positions": [
    ],
  • "personalInformation": {
    },
  • "children": [
    ],
  • "legacyIds": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Get employee by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

embed
string

Comma-separated list of related entities to embed in response.

For Employee: positions, personalInformation, taxInformation, children, unionLinks, carLinks, creditorClaims, taxAndContributionRules, pensionLinks, additionalAccounts

Example: ?embed=positions,personalInformation

includeLegacyIds
boolean
Default: false

When true, requests that legacy system identifiers be included in the response. Note: legacyIds may still be null if the underlying data source does not carry legacy IDs (see the legacyIds field description for details). Intended for short-term use by clients migrating from legacy systems.

Example: ?includeLegacyIds=true

Responses

Response samples

Content type
application/json
{
  • "number": "string",
  • "tenantId": "string",
  • "isDraft": true,
  • "notes": "string",
  • "mergedCompanyEmployeeStartDate": "2019-08-24",
  • "contactDetails": {
    },
  • "payrollSettings": {
    },
  • "linkedUserData": {
    },
  • "sicknessAndAbsence": {
    },
  • "positions": [
    ],
  • "personalInformation": {
    },
  • "children": [
    ],
  • "legacyIds": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Partially update an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
etag
required
string

Opaque version identifier for optimistic concurrency control.

number
string

Employee number (Ansattnummer) - company-assigned identifier

isDraft
boolean

Draft employees are not included in payroll runs

notes
string

Free-text notes about the employee

mergedCompanyEmployeeStartDate
string <date>

Original start date when employee transferred from merged company

object (ContactDetails)
object (PayrollSettings)

Payroll and payment settings (Lønnsinnstillinger).

object (LinkedUserData)

Link to user account in identity system

object (SicknessAndAbsence)

Employee-level sickness and absence configuration (chronicallyIllPeriods only). Use asOfDate query parameter to filter to periods active on a specific date.

PATCH semantics: Omitting a property from a PATCH request preserves existing periods unchanged. Providing an empty array ([]) clears all periods of that type. Providing a non-empty array fully replaces periods of that type.

Breaking change: prepaidSicknessPeriods, prepaidOtherAbsencePeriods, and redundancyPeriods have been moved to the position-level endpoint (positions/{positionId}/sickness-and-absence). Sending those fields here will return 400.

Responses

Request samples

Content type
application/json
{
  • "etag": "1",
  • "number": "string",
  • "isDraft": true,
  • "notes": "string",
  • "mergedCompanyEmployeeStartDate": "2019-08-24",
  • "contactDetails": {
    },
  • "payrollSettings": {
    },
  • "linkedUserData": {
    },
  • "sicknessAndAbsence": {
    }
}

Response samples

Content type
application/json
{
  • "number": "string",
  • "tenantId": "string",
  • "isDraft": true,
  • "notes": "string",
  • "mergedCompanyEmployeeStartDate": "2019-08-24",
  • "contactDetails": {
    },
  • "payrollSettings": {
    },
  • "linkedUserData": {
    },
  • "sicknessAndAbsence": {
    },
  • "positions": [
    ],
  • "personalInformation": {
    },
  • "children": [
    ],
  • "legacyIds": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Delete an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

AdditionalAccounts

Secondary bank accounts for splitting an employee's salary payment across multiple destinations. Each account specifies how much to transfer per payroll period and to which Norwegian bank account.

Only Norwegian bank accounts (norwegianBank payment type) are supported. Changes take effect for future payments only — there is no retroactive recalculation.

Timeline type: Flexible — gaps and overlaps allowed. Max 10 overlapping additional accounts per employee.

Property Type Required Description
id UUID Yes (read-only) Unique additional-account identifier.
employeeId UUID (read-only) Employee this account belongs to.
from date Yes Account effective from date.
to date No Allocation effective until date. null means ongoing.
bankAccountNumber string Yes Norwegian bank account number (11 digits, MOD11 check).
bankHolderName string No Account holder name. Max 70 characters.
amount string One-of Fixed amount per payroll period. Exactly one of amount or payCodeId must be provided.
payCodeId UUID One-of Reference to a pay code. Exactly one of amount or payCodeId must be provided.
description string No Free-text description of the account purpose.
updatedAt datetime (read-only) Timestamp of last modification.

The monolith persists an internal deductionMethod enum (amount or paycode) for legacy UI reasons. The Employee Core Service does not expose this field — it is inferred from whichever of amount or payCodeId is provided on write.

Amount calculation, payment ordering, and sequence-number assignment (range 61–70) are performed by the payroll system, not this service. This service stores the accounts and enforces validation only.

Key Validation Rules

  • bankAccountNumber must be an 11-digit Norwegian account number with a valid MOD11 check digit.
  • Exactly one of amount or payCodeId must be supplied — never both, never neither.
  • An employee may have at most 10 additional accounts with overlapping date ranges.
  • to, when provided, must be on or after from.
  • Once created, an additional account cannot be modified — only ended (set to) or deleted. To change values, end the existing account and create a new one.

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the additional account record. Generated by the service on create; never supplied by clients.

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date the additional account becomes effective. Future dates are allowed.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes on create, nullable on read

Date the additional account ends. Required when creating; null on read indicates no set end date.

bankAccountNumber

  • Type: string
  • Required: Yes

Norwegian bank account number. 11-digit numeric string where the first 4 digits are the bank office code and the 11th digit is a MOD11 check digit. Stored without spaces; typical display format is 1234 56 78901.

bankHolderName

  • Type: string
  • Required: No

Name of the person or entity owning the receiving account (Kontoinnehaver).

Validation

  • If provided, max 70 characters.
  • Must not contain backslash characters.

amount

  • Type: string
  • Required: Conditional — exactly one of amount or payCodeId must be provided

Fixed amount transferred to this account each payroll period. Use this field when the employee wants a constant amount (e.g. monthly savings, rent).

When amount is provided, the monolith internally records the deduction method as amount.

Validation

  • Must be provided when payCodeId is absent.
  • Must not be provided together with payCodeId.

payCodeId

  • Type: UUID
  • Required: Conditional — exactly one of amount or payCodeId must be provided

Reference to a paycode from the Payroll API whose output determines the transfer amount each payroll period. Use this field when the amount is variable and should follow a specific pay code.

When payCodeId is provided, the monolith internally records the deduction method as paycode.

Validation

  • Must be provided when amount is absent.
  • Must not be provided together with amount.
  • Must reference a valid pay code with PaymentRule type.
  • The account's from/to must lie within the pay code's valid period.
  • Note: The Payroll API does not track employee usage, so pay-code deletion or date changes can silently break the reference.

description

  • Type: string
  • Required: No

Free-text description of the account's purpose (e.g. "Monthly savings", "Rent payment"). Useful on payslips and for historical reference.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Example: Create Additional Account

Fixed-amount deduction (monthly savings):

POST /tenants/{tenantId}/employees/{employeeId}/additional-accounts
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "to": "2026-12-31",
  "bankAccountNumber": "12345678903",
  "bankHolderName": "Ola Nordmann",
  "amount": "5000.00",
  "description": "Monthly savings"
}

Pay-code-driven deduction (amount determined by a pay code):

{
  "from": "2026-05-01",
  "to": "2026-12-31",
  "bankAccountNumber": "12345678903",
  "payCodeId": "550e8400-e29b-41d4-a716-446655440000",
  "description": "Travel allowance"
}

A successful request returns 201 Created with the full AdditionalAccount resource, including the server-generated id and updatedAt.

Events

Event Trigger Consumers
additionalAccount.created New additional account registered Payroll
additionalAccount.updated Existing account modified (e.g. to date set) Payroll
additionalAccount.deleted Additional account removed Payroll

List additional accounts for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create additional account entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

bankHolderName
string or null (bankHolderName)

Account holder name


Monolith notes: Field "Bankholder name" (227f152c-3cf0-46dc-8099-f33a8511ed90).


bankAccountNumber
required
string or null (bankAccountNumber)

Bank account number


Monolith notes: Field "Bank account number" (5c7e8234-cd7c-4e3f-b64d-6dba4ac3a239).


deductionMethod
required
string or null (paymentDeductionMethod)
Enum: "paycode" "amount"

How to determine payment amount:

  • paycode: Use specific pay code output
  • amount: Fixed amount per payroll

Monolith notes: Field "Deduction method" (103dca57-eacb-439d-9349-52075b626941).


deductionAmount
string (deductionAmount)

Fixed amount when method is 'amount'


Monolith notes: Field "Amount" (6c3fb0d6-5193-4ba0-872f-b4dcb082d6f1).


deductionPayCodeId
string or null <uuid> (deductionPayCodeId)

Pay code reference when method is 'paycode'


Monolith notes: Field "Paycode" (663c3975-4422-4929-9d9d-d2f33840bc26).


description
string or null (accountDescription)

Purpose description (e.g., savings, rent payment)


Monolith notes: Field "Description" (989e8ef6-c262-4ff1-8bc8-835f33339b4e).


from
required
string <date>

Effective-from date

to
required
string or null <date>

Effective-until date

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "bankHolderName": "string",
  • "bankAccountNumber": "string",
  • "deductionMethod": "paycode",
  • "deductionAmount": "string",
  • "deductionPayCodeId": "c98152e9-3278-41b5-8ccc-b434820bcf47",
  • "description": "string",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "bankHolderName": "string",
  • "bankAccountNumber": "string",
  • "deductionMethod": "paycode",
  • "deductionAmount": "string",
  • "deductionPayCodeId": "c98152e9-3278-41b5-8ccc-b434820bcf47",
  • "description": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Get additional account by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

additionalAccountId
required
string <uuid>

Additional account unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "bankHolderName": "string",
  • "bankAccountNumber": "string",
  • "deductionMethod": "paycode",
  • "deductionAmount": "string",
  • "deductionPayCodeId": "c98152e9-3278-41b5-8ccc-b434820bcf47",
  • "description": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Partially update additional account

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

additionalAccountId
required
string <uuid>

Additional account unique identifier

Request Body schema: application/json
required
bankHolderName
string or null (bankHolderName)

Account holder name


Monolith notes: Field "Bankholder name" (227f152c-3cf0-46dc-8099-f33a8511ed90).


bankAccountNumber
string or null (bankAccountNumber)

Bank account number


Monolith notes: Field "Bank account number" (5c7e8234-cd7c-4e3f-b64d-6dba4ac3a239).


deductionMethod
string or null (paymentDeductionMethod)
Enum: "paycode" "amount"

How to determine payment amount:

  • paycode: Use specific pay code output
  • amount: Fixed amount per payroll

Monolith notes: Field "Deduction method" (103dca57-eacb-439d-9349-52075b626941).


deductionAmount
string (deductionAmount)

Fixed amount when method is 'amount'


Monolith notes: Field "Amount" (6c3fb0d6-5193-4ba0-872f-b4dcb082d6f1).


deductionPayCodeId
string or null <uuid> (deductionPayCodeId)

Pay code reference when method is 'paycode'


Monolith notes: Field "Paycode" (663c3975-4422-4929-9d9d-d2f33840bc26).


description
string or null (accountDescription)

Purpose description (e.g., savings, rent payment)


Monolith notes: Field "Description" (989e8ef6-c262-4ff1-8bc8-835f33339b4e).


etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

from
required
string <date>

Effective-from date

to
string or null <date>

Effective-until date

Responses

Request samples

Content type
application/json
{
  • "bankHolderName": "string",
  • "bankAccountNumber": "string",
  • "deductionMethod": "paycode",
  • "deductionAmount": "string",
  • "deductionPayCodeId": "c98152e9-3278-41b5-8ccc-b434820bcf47",
  • "description": "string",
  • "etag": "1",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "bankHolderName": "string",
  • "bankAccountNumber": "string",
  • "deductionMethod": "paycode",
  • "deductionAmount": "string",
  • "deductionPayCodeId": "c98152e9-3278-41b5-8ccc-b434820bcf47",
  • "description": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Delete additional account entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

additionalAccountId
required
string <uuid>

Additional account unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

Calculation Method

Value Norwegian When to use
listprice Listeprismetoden Standard method — benefit is a percentage of the car's list price. mileage not required.
kilometers Kilometermetoden Benefit based on private km driven. mileage is required.

Benefit amount calculation and A-melding reporting are performed by the payroll system, not this service. This service only stores the assignment.

Key Validation Rules

  • carId must reference an active car in the Org API.
  • A car can only be assigned to one employee at a time, except pool cars (CarPool = "Yes" in Org API), which may be assigned concurrently.
  • Assignment period must fall within both the car's active period and the employee's position/contract period.
  • to, when provided, must be on or after from.

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the car assignment record. Generated by the service on create; never supplied by clients.

carId

  • Type: string
  • Required: Yes

Foreign key to a company car defined in the Org API. The referenced car must exist and be active for the entire assignment period. Non-pool cars can only be linked to one employee at a time; pool cars (CarPool = "Yes" in Org API) may be shared across employees concurrently.

Validation

  • Must be provided.
  • Must reference an existing, active company car in the Org API.
  • Uniqueness: no overlapping assignments of the same carId across employees, unless the car is flagged as a pool car.
  • The car in the Org API cannot be deleted or have its active period narrowed while this assignment is active (enforced by Org API).

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date the assignment starts. Must fall within both the car's active period in the Org API and the employee's position/contract period. Future dates are allowed.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No

Date the assignment ends. null (or omitted) means the assignment is ongoing. When provided, must be on or after from and within the car's and employee's active periods. Setting to is the standard way to close an open-ended assignment.

calculationMethod

  • Type: enum — listprice | kilometers
  • Required: Yes

Tells payroll how to compute the taxable benefit:

  • listprice (Listeprismetoden) — standard method; benefit is a percentage of the car's list price. mileage is not required.
  • kilometers (Kilometermetoden) — benefit is based on private kilometres driven. mileage must be provided.

The actual benefit amount is computed by the payroll system, not by this service.

mileage

  • Type: integer (kilometres)
  • Required: Conditional — required when calculationMethod is kilometers, optional otherwise

Annual private-use mileage. Must be a positive integer, maximum 999999. Ignored by payroll when calculationMethod is listprice, but may still be stored for reference.

listPrice

  • Type: integer (NOK)
  • Required: Conditional — required when calculationMethod is listPrice, optional otherwise

List price of the car (Listepris) used as the basis for the taxable benefit when calculationMethod is listPrice. Must be a positive integer, maximum 999999. Ignored by payroll when calculationMethod is kilometers, but may still be stored for reference.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Example: Create Car Link

POST /tenants/{tenantId}/employees/{employeeId}/car-links
Authorization: Bearer <token>
Content-Type: application/json

{
  "carId": "a3f1c2d4-5e6b-7a8c-9d0e-1f2a3b4c5d6e",
  "from": "2026-05-01",
  "calculationMethod": "kilometers",
  "mileage": 15000
}

A successful request returns 201 Created with the full CarLink resource, including the server-generated id and updatedAt.

Events

Event Trigger Consumers
carLink.created New assignment registered Payroll
carLink.updated Existing assignment modified (e.g. to date set) Payroll
carLink.deleted Assignment removed Payroll

Get car link by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

carLinkId
required
string <uuid>

Car link unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "carId": "string",
  • "mileagePeriods": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Children

Stores information about an employee's children (Barn), including periods for sole custody and chronic illness that directly affect sick leave entitlements under Norwegian labour law.

Children were separated from the legacy relatives entity into their own dedicated sub-entity. This reflects their distinct business purpose: children carry sole custody and chronically ill period data that directly affects sick leave rights, while relatives serve a broader family contact role.

Timeline type: None (entity-level) — each child is a simple collection item. Two sub-timeline period arrays (soleCustodyPeriods and chronicallyIllPeriods) track date-bounded periods.

Property Type Required Description
employeeId UUID (read-only) Employee this child belongs to.
firstName string Yes First name (Fornavn).
lastName string Yes Last name (Etternavn).
birthYear date Yes Date of birth of the child (Fødselsdato).
soleCustodyPeriods array of { from, to } No Date periods of sole custody (Aleneomsorg). Managed via PATCH on the child object.
chronicallyIllPeriods array of { from, to } No Date periods of chronic illness (Kronisk syk). Managed via PATCH on the child object.
updatedAt datetime (read-only) Timestamp of last modification.

Period Entry

Each entry within soleCustodyPeriods and chronicallyIllPeriods is a simple date range with two properties:

Property Type Required Description
from date Yes Period start date (inclusive).
to date No Period end date (inclusive). null or omitted means ongoing.

Key Validation Rules

  • firstName and lastName are required and must not be empty.
  • birthYear is required and must not be a future date.
  • Period to, when provided, must be on or after from.
  • Periods within the same array must not overlap.
  • Period from year must not precede the child's birthYear.

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the child record. Generated by the service on create; never supplied by clients. Clients may optionally provide a UUID on create — if the ID already exists, a 409 Conflict is returned.

firstName

  • Type: string
  • Required: Yes

First name of the child (Fornavn). Required on create and must not be empty or whitespace-only.

lastName

  • Type: string
  • Required: Yes

Last name of the child (Etternavn). Required on create and must not be empty or whitespace-only.

birthYear

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date of birth of the child (Fødselsdato). The date of birth is used to determine age-based sick leave entitlements (e.g. under 12, under 18 for chronically ill).

soleCustodyPeriods

  • Type: array of { from, to } date periods
  • Required: No

Array of date periods indicating when the employee has sole custody of this child. Each entry has a from (required) and to (optional, null = ongoing) date. The existence of a period implies sole custody during that timespan, which doubles the employee's sick leave entitlement.

These periods are not a separate resource — there is no dedicated endpoint for them. To add, modify, or remove sole custody periods, PATCH the child object and include the full replacement array in soleCustodyPeriods. Omitting the property from the PATCH preserves existing periods. Providing an empty array ([]) clears all periods.

Validation

  • Each period's from is required and must be a valid date between 1910-04-15 and 2089-09-17.
  • Each period's to, if provided, must be on or after from and between 1910-04-15 and 2089-09-17.
  • Periods within the array must not overlap.
  • Each period's from must not precede the child's birthYear.

chronicallyIllPeriods

  • Type: array of { from, to } date periods
  • Required: No

Array of date periods indicating when the child is chronically ill. Each entry has a from (required) and to (optional, null = ongoing) date. The existence of a period grants additional sick leave days and extends the age limit to 18 years. These periods are not a separate resource — there is no dedicated endpoint for them. To add, modify, or remove chronically ill periods, PATCH the child object and include the full replacement array in chronicallyIllPeriods. Omitting the property from the PATCH preserves existing periods. Providing an empty array ([]) clears all periods.

Validation

  • Periods within the array must not overlap.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Benefit amount calculation and sick leave quota are performed by the payroll system, not this service. This service only stores the child data and periods.

Example: Create Child

POST /tenants/{tenantId}/employees/{employeeId}/children
Authorization: Bearer <token>
Content-Type: application/json

{
  "firstName": "Emma",
  "lastName": "Nordmann",
  "birthYear": "2018-06-15",
  "soleCustodyPeriods": [],
  "chronicallyIllPeriods": []
}

For a child with sole custody and chronic illness, include period entries:

{
  "firstName": "Lars",
  "lastName": "Nordmann",
  "birthYear": "2015-03-22",
  "soleCustodyPeriods": [{ "from": "2023-06-01" }],
  "chronicallyIllPeriods": [{ "from": "2020-01-01" }]
}

A successful request returns 201 Created with the full Child resource, including the server-generated id and updatedAt.

Events

Event Trigger Consumers
child.created New child registered Payroll
child.updated Child data modified (including soleCustodyPeriods/chronicallyIllPeriods) Payroll
child.deleted Child removed Payroll

List children for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create child entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

firstName
required
string or null (firstName-2)

First name (Fornavn)


Monolith notes: Field "First name" (8760f996-ac90-4823-9c5e-e4248a61e47f).


lastName
required
string or null (lastName-2)

Last name (Etternavn)


Monolith notes: Field "Last name" (9a14b378-9703-444f-a287-664b654716bf).


birthYear
required
string <date>

Date of birth of the child (Fødselsdato)


Monolith notes: Field "Date of birth" (9fc9af3a-38d5-4f07-8ddc-ea1e0fdadef2).


Array of objects (ChildPeriod)

Periods of sole custody (Aleneomsorg)

Array of objects (ChildPeriod)

Periods of chronic illness (Kronisk syk)

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "firstName": "string",
  • "lastName": "string",
  • "birthYear": "2019-08-24",
  • "soleCustodyPeriods": [
    ],
  • "chronicallyIllPeriods": [
    ]
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "firstName": "string",
  • "lastName": "string",
  • "birthYear": "2019-08-24",
  • "soleCustodyPeriods": [
    ],
  • "chronicallyIllPeriods": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Get child by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

childId
required
string <uuid>

Child unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "firstName": "string",
  • "lastName": "string",
  • "birthYear": "2019-08-24",
  • "soleCustodyPeriods": [
    ],
  • "chronicallyIllPeriods": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Partially update child

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

childId
required
string <uuid>

Child unique identifier

Request Body schema: application/json
required
firstName
string or null (firstName-2)

First name (Fornavn)


Monolith notes: Field "First name" (8760f996-ac90-4823-9c5e-e4248a61e47f).


lastName
string or null (lastName-2)

Last name (Etternavn)


Monolith notes: Field "Last name" (9a14b378-9703-444f-a287-664b654716bf).


birthYear
string or null <date> (birthYear)

Date of birth of the child (Fødselsdato)


Monolith notes: Field "Date of birth" (9fc9af3a-38d5-4f07-8ddc-ea1e0fdadef2).


Array of objects (ChildPeriod)

Periods of sole custody (Aleneomsorg) - affects sick leave rights


Monolith notes: Field "Sole custody" (1ea5f79b-567a-4ac5-bbc9-71d4e5b92fd8).


Array of objects (ChildPeriod)

Periods of chronic illness (Kronisk syk) - affects sick leave rights


Monolith notes: Field "Chronically, long-term ill or disabled child" (81d238b7-b65c-4e4f-8514-3c8f5c92f888).


etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

Responses

Request samples

Content type
application/json
{
  • "firstName": "string",
  • "lastName": "string",
  • "birthYear": "2019-08-24",
  • "soleCustodyPeriods": [
    ],
  • "chronicallyIllPeriods": [
    ],
  • "etag": "1"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "firstName": "string",
  • "lastName": "string",
  • "birthYear": "2019-08-24",
  • "soleCustodyPeriods": [
    ],
  • "chronicallyIllPeriods": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Delete child entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

childId
required
string <uuid>

Child unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

ContactDetails

Non-timelined contact information embedded in the Employee entity. Contains address, phone numbers, and email addresses.

In the legacy system, phones and emails were stored as typed arrays; in the new service they are flattened into named fields for simplicity.

Entity type: Embedded object (no timeline) — updated via the Employee PATCH endpoint.

Property Type Required Description
address1 string No Street address (Gateadresse). Max 200 characters.
postalLocation string No Postal location (Poststed). Max 200 characters.
postalCode string No Postal code (Postnummer). For Norwegian addresses, must be a valid 4-digit code.
countryCode string Conditional Country code, ISO 3166-1 alpha-2 (Landkode). Required when any address field is provided.
homePhone string No Private phone number (Hjemmetelefon). 8–16 characters.
workPhone string No Work phone number (Jobbtelefon). 8–16 characters.
homeEmail string No Personal email address (Privat e-post). Max 135 characters. Must be a valid email format.
workEmail string No Work email address (Jobb e-post). Max 135 characters. Must be a valid email format.
emergencyContacts array No Array of emergency contact persons (Nødkontakter). See EmergencyContacts.

Key Validation Rules

  • When any address field (address1, postalLocation, postalCode) is provided, countryCode is required.
  • For Norwegian addresses (countryCode = NO), postalCode must be a valid 4-digit postal code.
  • Phone numbers must be 8–16 characters and unique across the employee's phone numbers.
  • Email addresses must be valid, max 135 characters, and unique across the employee's emails (case-insensitive domain comparison).

address1

  • Type: string
  • Required: No

Street address line. Max 200 characters. Named address1 to allow for a future address2 field — a single address line is not sufficient for many Norwegian addresses.

In the legacy system this was called streetName, which was misleading because it holds the full street address including house number (there is no separate house number field).

postalLocation

  • Type: string
  • Required: No

Postal location name. Max 200 characters. Most Norwegian postal locations are not cities, so postalLocation is more accurate than the legacy cityName.

Note: When countryCode is NO, the legacy system auto-populated this field from a reference table based on the postal code.

postalCode

  • Type: string
  • Required: No

Postal code. For Norwegian addresses (countryCode = NO), must be a valid 4-digit Norwegian postal code.

countryCode

  • Type: string (ISO 3166-1 alpha-2)
  • Required: Conditional — required when any address field (address1, postalLocation, postalCode) is provided.

Validation

  • Required when any address field is provided.
  • Must be a valid ISO 3166-1 alpha-2 code.

homePhone

  • Type: string
  • Required: No

Private phone number. Must be 8–16 characters. Must be unique across the employee's phone numbers (no duplicate with workPhone).

Norwegian phone numbers are 8 digits. International format: +47 followed by 8 digits.

workPhone

  • Type: string
  • Required: No

Work phone number. Must be 8–16 characters. Must be unique across the employee's phone numbers (no duplicate with homePhone).

Renamed from legacy businessPhone — shorter, same meaning, and avoids common misspellings.

homeEmail

  • Type: string (email)
  • Required: No

Personal email address. Max 135 characters. Must be a valid email format. Must be unique across the employee's email addresses (case-insensitive domain comparison).

workEmail

  • Type: string (email)
  • Required: No

Work email address. Max 135 characters. Must be a valid email format. Must be unique across the employee's email addresses.

Renamed from legacy businessEmail — shorter, same meaning.

Emergency Contacts

Emergency contacts are stored as an array within contactDetails. In the legacy system, emergency contacts and children were in the same relatives list; in the new service they are separated — children are managed in the Children entity.

Property Type Required Description
firstName string Yes Emergency contact's first name (Fornavn).
lastName string Yes Emergency contact's last name (Etternavn).
mainContact boolean No Whether this is the primary emergency contact (Hovedkontakt).
phoneNumber string No Contact phone number (Telefonnummer).
email string No Contact email address (E-post).

Example: Create Employee with Contact Details

Contact details are embedded in the Employee entity. Supply them in the contactDetails object when creating an employee:

POST /tenants/{tenantId}/employees/with-positions
Authorization: Bearer <token>
Content-Type: application/json

{
  "employee": {
    "number": "1001",
    "isDraft": false,
    "contactDetails": {
      "address1": "Storgata 1",
      "postalLocation": "Oslo",
      "postalCode": "0155",
      "countryCode": "NO",
      "homePhone": "+4712345678",
      "workPhone": "+4787654321",
      "homeEmail": "ola.nordmann@example.com",
      "workEmail": "ola.nordmann@company.no",
      "emergencyContacts": [
        {
          "firstName": "Kari",
          "lastName": "Nordmann",
          "mainContact": true,
          "phoneNumber": "+4798765432",
          "email": "kari.nordmann@example.com"
        }
      ]
    }
  },
  "positions": [
    {
      "from": "2026-05-01",
      "jobId": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e"
    }
  ]
}

A successful request returns 201 Created with the full Employee resource, including the server-generated id and updatedAt.

CreditorClaims

Wage deductions ordered by enforcement authorities. Employers are legally obligated to deduct and remit these amounts from the employee's salary. Each claim represents a single claim order with defined period and deduction parameters.

Creditor master data (name, account number, etc.) lives in the Org API and is out of scope here — this entity only stores the claim link and deduction parameters.

Timeline type: Flexible — gaps and overlaps allowed, to may be open-ended. Multiple concurrent claims are permitted (max 10 per type).

Property Type Required Description
id UUID (read-only) Unique claim identifier.
employeeId UUID (read-only) Employee this claim belongs to.
type enum Yes Claim type determining creditor, validation rules, and A-melding reporting. See Claim Types.
creditorId string Yes Foreign key to a creditor in the Org API. System-defined for most types; user-selectable for userDefined.
from date Yes Deduction start date.
to date No Deduction end date. null means ongoing.
startAmount string Conditional Original total debt amount. Optional for legalOffence, tax, governmentClaim, userDefined; prohibited otherwise.
amount string One-of Fixed deduction per pay period. Exactly one of amount or percentage must be provided (except childSupport: amount-only).
percentage string One-of Percentage of tax basis. Exactly one of amount or percentage must be provided.
incomeYear integer Conditional Income/tax year. Optional when type is tax; prohibited otherwise.
kidNumber string Conditional Norwegian payment reference number (KID-nummer). Mandatory when type is coordinated; optional otherwise.
description string Conditional Free-text description. Prohibited when type is coordinated; optional otherwise.
priority integer (read-only) Deduction priority order among concurrent claims. Lower values are deducted first. System-calculated.
etag string (read-only) Opaque version identifier for optimistic concurrency. Must be included in PATCH request body.
updatedAt datetime (read-only) Timestamp of last modification.

The legacy monolith exposes a deductionMethod enum (amount or percentage). The Employee Core Service does not expose this field — it is inferred from whichever of amount or percentage is provided on write, following the same pattern as Additional Accounts.

Sequence number assignment, protected income enforcement, and actual deduction calculations are performed by the payroll system, not this service. This service stores the claims — including deduction priority — and enforces validation only.

Key Validation Rules

  • creditorId must reference a valid creditor in the Org API, matching the system-defined ID for the given type.
  • Exactly one of amount or percentage must be provided — never both, never neither.
  • When type is childSupport, only amount is allowed (percentage-based deductions are prohibited).
  • A coordinated claim must be the only active creditor claim for the employee during its active period (no overlapping claims of any type).
  • to, when provided, must be on or after from.
  • Maximum 10 concurrent active claims per type per employee.
  • To modify a claim's values, end the existing claim (set to) and create a new one.

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the creditor claim record. Generated by the service on create; never supplied by clients.

type

  • Type: enum — childSupport | legalOffence | governmentClaim | tax | coordinated | userDefined
  • Required: Yes

Determines the kind of garnishment, which creditor is valid, and how the claim is reported. See Claim Types table above. The type field determines:

  • Which creditorId is valid (system-defined types have a fixed creditor; userDefined references a user-created creditor in the Org API)
  • Which other fields are required, optional, or prohibited
  • How the claim is reported in A-melding
Value Description Creditor ID in Monolith
childSupport Child support payments 2/0 (system-defined)
legalOffence Compensation for legal offence 3/0 (system-defined)
governmentClaim Claims from state-owned company 4/0 (system-defined)
tax Unpaid tax debt 8/0 (system-defined)
coordinated Coordinated attachment of earnings 10/0 (system-defined)
userDefined Other legal deductions User-defined (Org API)

Validation

  • Must be provided.
  • Must be one of the six defined values.
  • Immutable after creation — to change type, end the existing claim and create a new one.

When a coordinated claim is active:

  • No other creditor claims (of any type) may overlap with it
  • All existing claims must be ended before creating a coordinated claim
  • The kidNumber field is mandatory
  • The description field is prohibited
  • Priority follows the coordinating authority's instructions rather than conventional priority ordering

creditorId

  • Type: string
  • Required: Yes

Foreign key to a creditor defined in the Org API. For system-defined claim types (childSupport, legalOffence, governmentClaim, tax, coordinated), a fixed creditor ID is mandated (see Claim Types table). For userDefined, this must reference a valid user-created creditor in the Org API.

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date the deduction starts. Future dates are allowed.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No

Date the deduction ends. null (or omitted) means the claim is ongoing. Setting to is the standard way to end an active claim.

startAmount

  • Type: string
  • Required: Conditional — optional for legalOffence, tax, governmentClaim, userDefined; prohibited for childSupport and coordinated

Original total debt amount. Informational only — the actual deduction is governed by amount or percentage.

amount

  • Type: string
  • Required: One-of — exactly one of amount or percentage must be provided

Fixed deduction amount per pay period. When provided, the backend infers the deduction method (in EmpMan monolith) as amount.

For childSupport, only amount is allowed (percentage is prohibited).

Validation

  • Must be provided when percentage is absent.
  • Must not be provided together with percentage.

percentage

  • Type: string
  • Required: One-of — exactly one of amount or percentage must be provided

Percentage of tax basis to deduct each period. When provided, the backend infers the deduction method as percentage.

Validation

  • Must be provided when amount is absent.
  • Must not be provided together with amount.

incomeYear

  • Type: integer
  • Required: Conditional — optional when type is tax; prohibited otherwise

The income/tax year the claim relates to.

Validation

  • Only allowed when type is tax.
  • If provided, must be between 1900 and 9999.

kidNumber

  • Type: string
  • Required: Conditional — mandatory when type is coordinated; optional otherwise

Norwegian payment reference number (KID-nummer — KundeIDentifikasjonsnummer). This is a structured payment reference following Norwegian banking standards, used by banks and creditors to identify the payment. It is a specific financial routing identifier.

Validation

  • Required when type is coordinated.
  • Must pass MOD11 or MOD10 check digit validation.

description

  • Type: string
  • Required: Conditional — prohibited when type is coordinated; optional otherwise

Free-text description of the claim (e.g., "Unpaid tax 2023", "Credit card debt collection").

Validation

  • Must not be provided when type is coordinated.

priority

  • Type: integer
  • Required: Yes (read-only, system calculated)

Deduction priority order among concurrent claims for the same employee. Lower values indicate higher priority (deducted first). When multiple active claims exist, the payroll system processes deductions in ascending priority order, respecting the protected income limit (livsoppholdssats).

Conventional priority ordering follows Norwegian enforcement authority guidelines:

Priority Claim Type Norwegian Term Sequence Range
1st Coordinated Samordnet utleggstrekk 1–10
2nd Child support Barnebidrag 11–20
3rd Legal offence Erstatning ved lovbrudd 21–30
4th Unpaid tax Restskatt 31–40
5th Government claim Statens innkrevingssentral 41–50
6th User-defined Andre trekk 51–60

For coordinated claims during the 2026–2029 transition period, priority follows the coordinating authority's instructions and is not bound by conventional ordering.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Coordinated Claims (2026–2029 Transition)

From 2026, Norwegian authorities are transitioning to coordinated garnishments (samordnet utleggstrekk), consolidating multiple public creditor claims into a single deduction per employee. The coordinated type is expected to become the only public-creditor claim type by 2029, fully replacing individual tax, governmentClaim, and legalOffence claims.

Example

Create Tax creditor claim (fixed amount):

POST /tenants/{tenantId}/employees/{employeeId}/creditor-claims
Authorization: Bearer <token>
Content-Type: application/json

{
  "type": "tax",
  "creditorId": "8/0",
  "from": "2026-01-01",
  "to": "2027-12-31",
  "startAmount": "50000.00",
  "amount": "2500.00",
  "incomeYear": 2024,
  "description": "Unpaid tax 2024"
}

Coordinated claim (percentage-based):

{
  "type": "coordinated",
  "creditorId": "10/0",
  "from": "2026-06-01",
  "percentage": "15.00",
  "kidNumber": "12345678903"
}

A successful request returns 201 Created with the full CreditorClaim resource, including the server-generated id and updatedAt.

Events

Event Trigger Consumers
creditorClaim.created New claim registered Payroll
creditorClaim.updated Existing claim modified (e.g. to date set to end claim) Payroll
creditorClaim.deleted Claim removed Payroll

Coordinated Claims (2026–2029 Transition)

From 2026, Norwegian authorities are transitioning to coordinated garnishments (samordnet utleggstrekk), consolidating multiple public creditor claims into a single deduction per employee. The coordinated type is expected to become the only public-creditor claim type by 2029, fully replacing individual tax, governmentClaim, and legalOffence claims.

Example

Create Tax creditor claim (fixed amount):

POST /tenants/{tenantId}/employees/{employeeId}/creditor-claims
Authorization: Bearer <token>
Content-Type: application/json

{
  "type": "tax",
  "creditorId": "8/0",
  "from": "2026-01-01",
  "to": "2027-12-31",
  "startAmount": "50000.00",
  "amount": "2500.00",
  "incomeYear": 2024,
  "description": "Unpaid tax 2024"
}

Coordinated claim (percentage-based):

{
  "type": "coordinated",
  "creditorId": "10/0",
  "from": "2026-06-01",
  "percentage": "15.00",
  "kidNumber": "12345678903"
}

A successful request returns 201 Created with the full CreditorClaim resource, including the server-generated id and updatedAt.

Events

Event Trigger Consumers
creditorClaim.created New claim registered Payroll
creditorClaim.updated Existing claim modified (e.g. to date set to end claim) Payroll
creditorClaim.deleted Claim removed Payroll

List creditor claims for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create creditor claim entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

creditor
string or null (creditor)

Creditor name (Kreditor) - e.g., NAV, Skatteetaten, private creditor


Monolith notes: Field "Creditor" (5f7c9e6a-8c04-40d3-80b7-04287ae4a694).


creditorPaymentType
string or null (creditorPaymentType)

Payment reference type for creditor


Monolith notes: Field "Creditor payment type" (4697d649-b786-49f4-a052-5df6d8f4495d).


startAmount
string (startAmount)

Original debt amount (Opprinnelig beløp)


Monolith notes: Field "Start amount" (b5253714-9650-42d6-88a4-6468109f6652).


deductionMethod
string or null (creditorDeductionMethod)
Enum: "amount" "percentage"

How to calculate deduction:

  • amount: Fixed amount per period (Fast beløp)
  • percentage: Percentage of salary (Prosent av lønn)

Monolith notes: Field "Deduction method" (103dca57-eacb-439d-9349-52075b626941).


amount
string (amount)

Deduction amount when method is 'amount'


Monolith notes: Field "Amount" (6c3fb0d6-5193-4ba0-872f-b4dcb082d6f1).


percentage
string <decimal-13-2> (percentage-2) ^-?\d{1,11}(\.\d{1,2})?$

Deduction percentage when method is 'percentage'


Monolith notes: Field "Percentage" (20837836-1af4-4afa-a7df-27c8661e16e7).


incomeYear
integer (incomeYear)

Income year the claim relates to (Inntektsår)


Monolith notes: Field "Income year" (837d9c6c-0c4b-47c9-93c4-96d7c17640f9).


description
string or null (claimDescription)

Description of the claim


Monolith notes: Field "Description" (989e8ef6-c262-4ff1-8bc8-835f33339b4e).


referenceNumber
string or null (referenceNumber)

Case/reference number from enforcement authority (Saksnummer)


Monolith notes: Field "Reference number" (f3313acd-5720-4a07-8de2-23421afd8fd3).


from
required
string <date>

Effective-from date

to
string or null <date>

Effective-until date

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "creditor": "string",
  • "creditorPaymentType": "string",
  • "startAmount": "string",
  • "deductionMethod": "amount",
  • "amount": "string",
  • "percentage": "string",
  • "incomeYear": 0,
  • "description": "string",
  • "referenceNumber": "string",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "creditor": "string",
  • "creditorPaymentType": "string",
  • "startAmount": "string",
  • "deductionMethod": "amount",
  • "amount": "string",
  • "percentage": "string",
  • "incomeYear": 0,
  • "description": "string",
  • "referenceNumber": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Get creditor claim by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

creditorClaimId
required
string <uuid>

Creditor claim unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "creditor": "string",
  • "creditorPaymentType": "string",
  • "startAmount": "string",
  • "deductionMethod": "amount",
  • "amount": "string",
  • "percentage": "string",
  • "incomeYear": 0,
  • "description": "string",
  • "referenceNumber": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Partially update creditor claim

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

creditorClaimId
required
string <uuid>

Creditor claim unique identifier

Request Body schema: application/json
required
creditor
string or null (creditor)

Creditor name (Kreditor) - e.g., NAV, Skatteetaten, private creditor


Monolith notes: Field "Creditor" (5f7c9e6a-8c04-40d3-80b7-04287ae4a694).


creditorPaymentType
string or null (creditorPaymentType)

Payment reference type for creditor


Monolith notes: Field "Creditor payment type" (4697d649-b786-49f4-a052-5df6d8f4495d).


startAmount
string (startAmount)

Original debt amount (Opprinnelig beløp)


Monolith notes: Field "Start amount" (b5253714-9650-42d6-88a4-6468109f6652).


deductionMethod
string or null (creditorDeductionMethod)
Enum: "amount" "percentage"

How to calculate deduction:

  • amount: Fixed amount per period (Fast beløp)
  • percentage: Percentage of salary (Prosent av lønn)

Monolith notes: Field "Deduction method" (103dca57-eacb-439d-9349-52075b626941).


amount
string (amount)

Deduction amount when method is 'amount'


Monolith notes: Field "Amount" (6c3fb0d6-5193-4ba0-872f-b4dcb082d6f1).


percentage
string <decimal-13-2> (percentage-2) ^-?\d{1,11}(\.\d{1,2})?$

Deduction percentage when method is 'percentage'


Monolith notes: Field "Percentage" (20837836-1af4-4afa-a7df-27c8661e16e7).


incomeYear
integer (incomeYear)

Income year the claim relates to (Inntektsår)


Monolith notes: Field "Income year" (837d9c6c-0c4b-47c9-93c4-96d7c17640f9).


description
string or null (claimDescription)

Description of the claim


Monolith notes: Field "Description" (989e8ef6-c262-4ff1-8bc8-835f33339b4e).


referenceNumber
string or null (referenceNumber)

Case/reference number from enforcement authority (Saksnummer)


Monolith notes: Field "Reference number" (f3313acd-5720-4a07-8de2-23421afd8fd3).


etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

from
required
string <date>

Effective-from date

to
string or null <date>

Effective-until date

Responses

Request samples

Content type
application/json
{
  • "creditor": "string",
  • "creditorPaymentType": "string",
  • "startAmount": "string",
  • "deductionMethod": "amount",
  • "amount": "string",
  • "percentage": "string",
  • "incomeYear": 0,
  • "description": "string",
  • "referenceNumber": "string",
  • "etag": "1",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "creditor": "string",
  • "creditorPaymentType": "string",
  • "startAmount": "string",
  • "deductionMethod": "amount",
  • "amount": "string",
  • "percentage": "string",
  • "incomeYear": 0,
  • "description": "string",
  • "referenceNumber": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Delete creditor claim entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

creditorClaimId
required
string <uuid>

Creditor claim unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

EmergencyContacts

People to contact in case of an employee emergency. Typically a spouse, partner, parent, or close relative.

Emergency contacts are not a standalone resource — they are stored as an array on the embedded contactDetails object of an Employee. In the legacy system they shared the relatives list with children; in the new service they are separated — children are managed as their own entity (see Children).

Entity type: Embedded array (no timeline, no id) — managed via the Employee PATCH endpoint by sending the full replacement array on contactDetails.emergencyContacts.

Property Type Required Description
firstName string Yes Emergency contact's first name.
lastName string Yes Emergency contact's last name.
mainContact boolean No Whether this is the primary emergency contact.
phoneNumber string No Contact phone number. null when not provided.
email string No Contact email address. Must be a valid email. null allowed.

Key Validation Rules

  • firstName and lastName are required on every entry and must not be empty.
  • email, when provided, must be a valid email format.
  • The full array is replaced on PATCH — omitting emergencyContacts from a PATCH preserves the existing array; providing an empty array ([]) clears all contacts.

firstName

  • Type: string
  • Required: Yes

First name of the emergency contact. Required on every entry in the array and must not be empty or whitespace-only.

lastName

  • Type: string
  • Required: Yes

Last name of the emergency contact. Required on every entry in the array and must not be empty or whitespace-only.

mainContact

  • Type: boolean
  • Required: No

Marks this entry as the primary emergency contact — the person to call first. When omitted, defaults to false. At most one contact per employee should have mainContact = true; when multiple are marked, the first one in the array is treated as primary.

phoneNumber

  • Type: string
  • Required: No (nullable)

Phone number to reach the contact.

email

  • Type: string
  • Required: No (nullable)

Email address for the contact.

Events

Emergency contacts are embedded in the Employee resource and do not publish a dedicated event topic. Changes are surfaced through the Employee's employee.updated event.

Event Trigger Consumers
employee.updated Emergency contacts added, modified, or cleared via Employee PATCH Payroll, A-melding

LinkedUserData

Read-only view of the Visma Connect user account linked to this employee. Provides the identity-system details (first name, last name, email, account status) so clients can correlate an HR employee record with the corresponding SSO/login account.

The fields are sourced from Visma Connect and managed externally through Visma.net Admin — Employee Core never writes to them. Attempts to set linkedUserData in a create or update request are ignored.

Entity type: Embedded object (no timeline) — appears as the linkedUserData property on the Employee resource.

Property Type Required Description
firstName string (read-only) User account first name from Visma Connect.
lastName string (read-only) User account last name from Visma Connect.
email string (email) (read-only) User account login email from Visma Connect.
status string (read-only) User account status (e.g. active, pending, inactive, suspended).
odpUserId string (read-only) Visma Connect (ODP) user account identifier. Set once the account has been successfully created.

Lifecycle

linkedUserData is populated by Visma Connect, not by callers of this API. The typical flow is:

  1. Create the employee with a valid contactDetails.workEmail (business email).
  2. A Visma Connect user account is provisioned for that email.
  3. Visma Connect sends an activation invitation to the employee.
  4. Once Connect confirms successful account creation, linkedUserData.odpUserId is populated with the account identifier.
  5. Once the employee activates the account, the remaining linkedUserData fields are populated.
  6. Status transitions (activation, suspension, deactivation) flow back into linkedUserData.status.
  7. When user account is provisioned, Employee service will update account details on name and last name changes, assuming master data role.

Until the account exists and is activated, linkedUserData is null on the Employee resource.

Initiating user account creation

Status: Planned — not yet implemented. The endpoint described below is on the roadmap; integrators cannot call it today. In the current service, Visma Connect provisioning must still be initiated through Visma.net Admin.

Employee Core will expose a dedicated endpoint for triggering Visma Connect user account creation, so integrators do not need to switch tools to onboard an employee end-to-end:

POST /tenants/{tenantId}/employees/{employeeId}/user
Authorization: Bearer <token>

Planned behavior:

  • Preconditions: the employee must have a valid contactDetails.workEmail, and the organization must have user creation enabled in Visma Connect.
  • On success, Employee Core forwards the request to Visma Connect, which provisions the account and sends an activation invitation to the business email.
  • The response will return 202 Accepted — account provisioning is asynchronous. linkedUserData on the Employee resource becomes populated once Visma Connect finishes activation (see the Lifecycle flow above).
  • Default roles are assigned based on organization configuration in Visma Connect.

Until this endpoint ships, integrators should treat linkedUserData as pure read-only and drive user creation through Visma.net Admin.

Key Validation Rules

  • linkedUserData and all of its fields are read-only. Values supplied by clients on POST/PATCH are ignored — no error is returned, but the data is not persisted.
  • contactDetails.workEmail must not match linkedUserData.email. The business email is separate from the identity-system login email.
  • Employee's personalInformation.firstName / personalInformation.lastName should match linkedUserData.firstName / linkedUserData.lastName (case-insensitive) — mismatches surface as a warning, not a blocking error.

firstName

  • Type: string
  • Required: No (read-only)

User's first name as registered in the Visma Connect identity system. May differ from personalInformation.firstName (legal name) — for example, a preferred name used in IT systems.

lastName

  • Type: string
  • Required: No (read-only)

User's last name as registered in the Visma Connect identity system. May differ from personalInformation.lastName for the same reasons as firstName.

email

  • Type: string (email)
  • Required: No (read-only)

Login email for the Visma Connect user account. This is the address the employee uses to sign in and receive activation/notification messages from Connect. It is distinct from contactDetails.workEmail and contactDetails.homeEmail, and must not equal contactDetails.workEmail.

status

  • Type: string
  • Required: No (read-only)

Current state of the Visma Connect user account. Typical values:

Value Meaning
active Account is provisioned and the user can sign in.
pending Invitation sent; awaiting employee activation.
inactive Account exists but is disabled.
suspended Account temporarily blocked (e.g. by admin).

Status changes are driven by Visma Connect and Visma.net Admin, not by this service.

odpUserId

  • Type: string
  • Required: No (read-only)

Identifier of the linked Visma Connect (ODP) user account. Set by Connect once the user account has been successfully created — the presence of this value is the signal that provisioning completed. While the account is being provisioned, or if no account exists for the employee, odpUserId is null.

Exposed as a string because the underlying value is a 64-bit integer and can exceed the JavaScript safe-integer range (2^53). Clients that need to treat the value numerically must use a big-integer-safe representation.

Events

linkedUserData is an embedded part of the Employee resource and has no events of its own. Changes to it — driven by Visma Connect — are surfaced through the standard Employee event stream.

Event Trigger Consumers
employee.updated Any change to the Employee resource, including updates to linkedUserData. Downstream services

PayrollSettings

Payroll and payment settings for the employee (Lønnsinnstillinger). Covers salary payment method, bank account details, payslip format, and tax-card retrieval preferences. This entity is an embedded object on the Employee resource — it is not timelined, and changes only affect future payments.

Payroll Settings does not compute tax, deductions, or payment runs. Those are performed by the payroll system; this service only stores the configuration used by payroll.

Entity type: Embedded object (no timeline) — appears as the payrollSettings property on the Employee resource.

Property Type Required Description
payslipOnPaper boolean No Generate a paper payslip in addition to the electronic one. Default: false.
payslipLanguage enum No Payslip language: norwegian (default) or english.
paymentType enum Yes Salary payment method: bank or cash.
norwegianBankAccount string Conditional Norwegian bank account number. 11 digits with MOD11 check digit. Required when paymentType = bank and internationalBank is not provided.
internationalBank object Conditional International bank account details (IBAN, SWIFT, country, remittance country). Required when paymentType = bank and payment is to a foreign bank account.
internationalBank.iban string Yes IBAN for international transfers. Length and format depend on the country (e.g. Norwegian IBAN: NO + 2 check digits + 11-digit account number, 15 characters total).
internationalBank.swift string Yes BIC/SWIFT code identifying the bank. 8 or 11 characters (e.g. DNBANOKKXXX).
internationalBank.country string Yes Country where the bank is located. ISO 3166-1 alpha-2 code.
internationalBank.remittanceCountry string Yes Remittance destination country. ISO 3166-1 alpha-2 code. May differ from country.
retrieveTaxCardOnWageRun boolean No When true, the tax card is fetched from Skatteetaten at the start of each wage run. Default: true.
lastTaxCardRetrieveDate date (read-only) Date the tax card was last retrieved from Skatteetaten. Managed by the service.

Tax card retrieval, payment execution, and A-melding reporting are performed by the payroll system and a background process, not by this service. This service stores the configuration and enforces validation only.

Key Validation Rules

  • paymentType is required. Must be bank or cash.
  • When paymentType = bank, exactly one of norwegianBankAccount or internationalBank must be provided.
  • When paymentType = cash, neither norwegianBankAccount nor internationalBank may be provided.
  • norwegianBankAccount, when provided, must be an 11-digit numeric string with a valid MOD11 check digit.
  • internationalBank, when provided, must contain all four sub-fields (iban, swift, country, remittanceCountry).
  • internationalBank.country and internationalBank.remittanceCountry must be valid ISO 3166-1 alpha-2 codes.
  • lastTaxCardRetrieveDate is read-only and must not be supplied on create or update.

payslipOnPaper

  • Type: boolean
  • Required: No (default false)

Whether the payroll system should generate a paper payslip in addition to the electronic one. A paper payslip is a PDF artefact intended for print — the service does not physically print anything.

Feedback (pending schema change): this property is proposed to be renamed from printPayslip to payslipOnPaper to avoid the implication that the service itself triggers printing. The YAML schema still uses printPayslip — the rename will be applied in a follow-up change.

payslipLanguage

  • Type: enum — norwegian | english
  • Required: No (default norwegian)

Language used when the payroll system renders the payslip. Intended to make the default locale explicit and to leave room for additional languages later.

Value Description
norwegian Render payslip in Norwegian (default).
english Render payslip in English — typically for non-Norwegian speakers.

Feedback (pending schema change): this property is proposed to be renamed from the boolean payslipInEnglish to the enum payslipLanguage, so that the default is explicit (Norwegian) and additional languages can be added without introducing new boolean flags. The YAML schema still uses payslipInEnglish — the rename will be applied in a follow-up change.

paymentType

  • Type: enum — bank | cash
  • Required: Yes

How the employee's salary is paid out.

Value Norwegian Description
bank Bankoverføring Salary paid by bank transfer. Requires exactly one of norwegianBankAccount or internationalBank.
cash Kontant Salary paid in cash. No bank account fields may be provided. Cash payments have additional documentation requirements for the employer.

norwegianBankAccount

  • Type: string (11-digit numeric, MOD11)
  • Required: Conditional — required when paymentType = bank and internationalBank is not provided; prohibited otherwise

Norwegian bank account number. Stored as an 11-digit numeric string.

The 11th digit is a check digit calculated using the Norwegian MOD11 algorithm and is validated on write.

internationalBank

  • Type: object
  • Required: Conditional — required when paymentType = bank and the employee is paid to a foreign bank account; prohibited otherwise

International bank account details for salary paid outside Norway. Grouped as a nested object so the related fields stay together and the caller can tell at a glance which fields belong to an international payment.

Sub-property Type Required Description
iban string Yes IBAN for international transfers. Length and format depend on the country (e.g. Norwegian IBAN: NO + 2 check digits + 11-digit account number, 15 characters total).
swift string Yes BIC/SWIFT code identifying the bank. 8 or 11 characters (e.g. DNBANOKKXXX).
country string Yes Country where the bank is located. ISO 3166-1 alpha-2 code.
remittanceCountry string Yes Remittance destination country. ISO 3166-1 alpha-2 code. May differ from country.

retrieveTaxCardOnWageRun

  • Type: boolean
  • Required: No (default true)

When true, the payroll system automatically fetches this employee's tax card from Skatteetaten (via Altinn/EDAG) at the start of each wage run. When false, the tax card properties must be updated manually.

lastTaxCardRetrieveDate

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No (read-only)

Date on which the tax card was last retrieved from Skatteetaten. Set by the service whenever a retrieval completes (either triggered manually or by a wage run with retrieveTaxCardOnWageRun = true). Clients may read this field but may not set it.

Example: Create Employee with Payroll Settings (Norwegian bank account)

POST /tenants/{tenantId}/employees
Authorization: Bearer <token>
Content-Type: application/json

{
  "number": "1001",
  "payrollSettings": {
    "paymentType": "bank",
    "norwegianBankAccount": "12345678903",
    "payslipOnPaper": false,
    "payslipLanguage": "norwegian",
    "retrieveTaxCardOnWageRun": true
  }
}

Example: Create Employee with Payroll Settings (international bank account)

POST /tenants/{tenantId}/employees
Authorization: Bearer <token>
Content-Type: application/json

{
  "number": "1002",
  "payrollSettings": {
    "paymentType": "bank",
    "internationalBank": {
      "iban": "SE3550000000054910000003",
      "swift": "ESSESESS",
      "country": "SE",
      "remittanceCountry": "SE"
    },
    "payslipLanguage": "english"
  }
}

A successful request returns 201 Created with the full Employee resource, including the persisted payrollSettings.

Events

payrollSettings is an embedded part of the Employee resource and has no events of its own. Changes to it are surfaced through the standard Employee event stream.

Event Trigger Consumers
employee.updated Any change to the Employee resource, including updates to payrollSettings. Payroll, A-melding exporter

Get pension link by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

pensionLinkId
required
string <uuid>

Pension link unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "pensionLinkId": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

PersonalInformation

Identity and personal details for an employee — legal name, government-issued identification, gender, and date of birth.

Contact details (address, email, phone) are managed separately under the contactDetails entity and are not part of personalInformation.

Singleton — at most one PersonalInformation record per employee, no timeline. Manage it via the dedicated personal-information endpoint (GET, POST, PATCH, DELETE); creating a second record for the same employee returns 409 Conflict.

Property Type Required Description
firstName string Yes Legal first name (Fornavn). Max 100 characters.
lastName string Yes Legal last name (Etternavn). Max 100 characters.
nationalId string At-most-one Norwegian national identity number (Fødselsnummer). Max 20 characters.
dNumber string At-most-one D-number (D-nummer) for foreign workers without a permanent Norwegian ID. Max 20 characters.
internationalId object At-most-one International identification. See sub-fields below.
internationalId.type enum Yes (within) Type: Pass, SocialSecurity, TaxNo, or ValueAddedTaxNo.
internationalId.value string Yes (within) The identification number. Max 50 characters.
internationalId.countryCode string No Country code of issuance. Max 10 characters.
gender enum No Female or Male.
dateOfBirth date No Date of birth (ISO 8601, YYYY-MM-DD). Must not be a future date.
etag string (read-only) Opaque version identifier for optimistic concurrency. Must be included in PATCH body and DELETE request.
updatedAt datetime (read-only) Timestamp of last modification.

At most one of nationalId, dNumber, or internationalId may be provided. All three may also be omitted.

Key Validation Rules

  • firstName and lastName are required, must not be empty or whitespace-only, and are limited to 100 characters.
  • At most one of nationalId, dNumber, or internationalId may be provided (mutual exclusivity, not strictly required).
  • nationalId and dNumber: max 20 characters. Format-level validation (e.g. MOD11 check digits) is not enforced by this service.
  • When internationalId is provided:
    • type is required and must be a valid enum value.
    • value is required, must not be empty, and is limited to 50 characters.
    • countryCode, when provided, is limited to 10 characters.
  • dateOfBirth, when provided, must not be a future date.
  • The service does not derive dateOfBirth or gender from nationalId or dNumber — clients must provide them explicitly if needed.
  • etag must match the current version on PATCH and DELETE (optimistic concurrency); a mismatch returns 409 Conflict.
  • Only one PersonalInformation record may exist per employee. Posting a second record returns 409 Conflict.

firstName

  • Type: string
  • Required: Yes

Legal first name of the employee. Must not be empty or whitespace-only. Max 100 characters.

lastName

  • Type: string
  • Required: Yes

Legal last name of the employee. Must not be empty or whitespace-only. Max 100 characters.

nationalId

  • Type: string
  • Required: No — at most one of nationalId, dNumber, or internationalId

Norwegian national identity number (Fødselsnummer). Max 20 characters. 11 digits with valid MOD11 check digits.

Validation

  • Mutually exclusive with dNumber and internationalId.

dNumber

  • Type: string
  • Required: No — at most one of nationalId, dNumber, or internationalId

D-number for foreign workers without a permanent Norwegian national ID. Max 20 characters. 11 digits with valid MOD11 check digits.

Validation

  • Mutually exclusive with nationalId and internationalId.

internationalId

  • Type: object
  • Required: No — at most one of nationalId, dNumber, or internationalId

International identification for employees without a Norwegian ID. The countryCode naming aligns with the convention already used in contactDetails.countryCode.

Sub-fields

  • internationalId.type — enum (Pass | SocialSecurity | TaxNo | ValueAddedTaxNo). Required.
  • internationalId.value — string, max 50 characters. Required, must not be empty.
  • internationalId.countryCode — string, max 10 characters. Optional.

Validation

  • type must be a valid enum value when internationalId is provided.
  • value is required and must not be empty when internationalId is provided.
  • Mutually exclusive with nationalId and dNumber.

gender

  • Type: enum — Female | Male
  • Required: No

Employee's gender. The service does not derive gender from nationalId or dNumber values.

dateOfBirth

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No

Employee's date of birth. Must not be a future date. The service does not derive dateOfBirth from nationalId or dNumber.

etag

  • Type: string
  • Required: Yes on PATCH (in body) and DELETE (as parameter); returned on every read

Opaque version identifier used for optimistic concurrency control. If the value does not match the server's current version, the request returns 409 Conflict.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Example: Create Personal Information

National ID:

POST /tenants/{tenantId}/employees/{employeeId}/personal-information
Authorization: Bearer <token>
Content-Type: application/json

{
  "firstName": "Ola",
  "lastName": "Nordmann",
  "nationalId": "12345678901",
  "gender": "Male",
  "dateOfBirth": "1985-03-15"
}

International ID:

{
  "firstName": "Jan",
  "lastName": "Kowalski",
  "internationalId": {
    "type": "Pass",
    "value": "AB1234567",
    "countryCode": "PL"
  },
  "gender": "Male",
  "dateOfBirth": "1990-07-22"
}

A successful request returns 201 Created with the full PersonalInformation resource, including the id, employeeId, etag, and updatedAt. Posting a second record for the same employee returns 409 Conflict.

Events

Event Trigger Consumers
personalInformation.created New personal information record registered Payroll, A-melding
personalInformation.updated Record modified (e.g. name change) Payroll, A-melding
personalInformation.deleted Record removed Payroll, A-melding

Get personal information for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "firstName": "string",
  • "lastName": "string",
  • "nationalId": "string",
  • "dNumber": "string",
  • "internationalId": {
    },
  • "gender": "Female",
  • "dateOfBirth": "2019-08-24",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Create personal information for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
id
string <uuid>
firstName
required
string or null (firstName)
lastName
required
string or null (lastName)
nationalId
string or null (nationalId)
dNumber
string or null (dNumber)
object or null (internationalId)
gender
string or null (gender)
Enum: "Female" "Male"
dateOfBirth
string or null <date> (dateOfBirth)

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "firstName": "string",
  • "lastName": "string",
  • "nationalId": "string",
  • "dNumber": "string",
  • "internationalId": {
    },
  • "gender": "Female",
  • "dateOfBirth": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "firstName": "string",
  • "lastName": "string",
  • "nationalId": "string",
  • "dNumber": "string",
  • "internationalId": {
    },
  • "gender": "Female",
  • "dateOfBirth": "2019-08-24",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Partially update personal information

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
firstName
string or null (firstName)
lastName
string or null (lastName)
nationalId
string or null (nationalId)
dNumber
string or null (dNumber)
object or null (internationalId)
gender
string or null (gender)
Enum: "Female" "Male"
dateOfBirth
string or null <date> (dateOfBirth)
etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

Responses

Request samples

Content type
application/json
{
  • "firstName": "string",
  • "lastName": "string",
  • "nationalId": "string",
  • "dNumber": "string",
  • "internationalId": {
    },
  • "gender": "Female",
  • "dateOfBirth": "2019-08-24",
  • "etag": "1"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "firstName": "string",
  • "lastName": "string",
  • "nationalId": "string",
  • "dNumber": "string",
  • "internationalId": {
    },
  • "gender": "Female",
  • "dateOfBirth": "2019-08-24",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z"
}

Delete personal information

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

SicknessAndAbsence

Employee-level sickness and absence configuration that tracks periods when the employee holds chronically ill status. The status allows the employer to claim NAV reimbursement from day one of a sick leave instead of waiting the usual employer period, and is approved by NAV based on medical documentation.

Prepaid sickness, prepaid other absence, and redundancy periods are managed on position-level via endpoint (positions/{positionId}/sickness-and-absence). Only chronicallyIllPeriods is stored on the employee.

Timeline type: Flexible — multiple periods allowed with gaps between them, but overlaps are not allowed. to may be open-ended.

Property Type Required Description
chronicallyIllPeriods array No Periods when the employee has chronic illness status. See period shape below.
chronicallyIllPeriods[].id UUID Yes (read-only) Unique period identifier.
chronicallyIllPeriods[].from date Yes Period effective from date.
chronicallyIllPeriods[].to date No Period effective until date. null means ongoing.
lastModified datetime (read-only) Timestamp of the most recent modification. null when no periods exist.

Key Validation Rules

  • from is required on every period and must be a valid date.
  • to, when provided, must be on or after from.
  • Periods within chronicallyIllPeriods must not overlap each other. Gaps between periods are allowed; a new period may start on the day after a previous period's to, but not on or before it.
  • Only chronicallyIllPeriods is accepted at the employee level. Sending prepaidSicknessPeriods, prepaidOtherAbsencePeriods, or redundancyPeriods here returns 400 — post those to the position-level endpoint instead.
  • Use the asOfDate query parameter on GET to retrieve only periods active on a specific date (from <= asOfDate AND (to is null OR to >= asOfDate)).

chronicallyIllPeriods

  • Type: array of period objects
  • Required: No

Array of periods when the employee has chronic illness status recognised by NAV. When the current date falls within an active period, the employer can apply for NAV reimbursement from day one of a sick leave instead of after the standard employer period (typically day 17).

Multiple periods may be recorded to reflect changes over time — for example, if the status lapses and is later reinstated. Gaps between periods are allowed, but periods must not overlap: at any given date the employee is either chronically ill or not.

PATCH semantics

  • Omitting chronicallyIllPeriods from a PATCH request preserves the existing periods unchanged.
  • Providing an empty array ([]) clears all chronically ill periods.
  • Providing a non-empty array fully replaces the existing periods.

chronicallyIllPeriods[].id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the period. Generated by the service; never supplied by clients.

chronicallyIllPeriods[].from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date the chronic illness status starts. Future dates are allowed.

chronicallyIllPeriods[].to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No (nullable)

Date the chronic illness status ends. null (or omitted) means the status is ongoing. When provided, must be on or after from.

lastModified

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to any period on this object. Set by the service on every write. null when no periods have ever been recorded.

Example:

The employee-level sickness and absence resource is not created directly — it is created together with the employee. Include sicknessAndAbsence.chronicallyIllPeriods in the POST /employees body:

POST /tenants/{tenantId}/employees
Authorization: Bearer <token>
Content-Type: application/json

{
  "number": "1001",
  "sicknessAndAbsence": {
    "chronicallyIllPeriods": [
      {
        "from": "2026-06-15"
      }
    ]
  }
}

A successful request returns 201 Created with the full Employee resource. Each period in the response includes the server-generated id, and sicknessAndAbsence.lastModified is set to the creation timestamp.

To add, replace, or clear periods on an existing employee, use PATCH /tenants/{tenantId}/employees/{employeeId}/sickness-and-absence with a sicknessAndAbsence body following the same shape.

Events

Employee-level sickness and absence is embedded in the Employee resource and does not publish a dedicated event topic. Changes to chronicallyIllPeriods are surfaced through the Employee's employee.updated event.

Event Trigger Consumers
employee.updated chronicallyIllPeriods added, modified, or cleared via Employee or SaA PATCH Payroll, NAV

Get sickness and absence configuration for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

Responses

Response samples

Content type
application/json
{
  • "chronicallyIllPeriods": [
    ],
  • "lastModified": "2019-08-24T14:15:22Z"
}

Update sickness and absence configuration for an employee

Partially replaces sickness and absence periods. Only period types explicitly included in the request body are replaced; omitted types are preserved.

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
Array of objects (SicknessAndAbsencePeriod)

Chronically ill periods (Kronisk syk) - affects sick leave quota. PATCH: omit to preserve existing; [] to clear; non-empty array to replace.


Monolith notes: Field "Chronically ill" (0546c71c-3a0e-40f2-923a-8e48c1218577).


Responses

Request samples

Content type
application/json
{
  • "chronicallyIllPeriods": [
    ]
}

Response samples

Content type
application/json
{
  • "chronicallyIllPeriods": [
    ],
  • "lastModified": "2019-08-24T14:15:22Z"
}

TaxAndContributionRules

Tracks special tax and contribution rules that apply to an employee (Særregler for skatt og avgift) — net salary arrangements, seafarer's deduction, Svalbard and Jan Mayen tax schemes. Each rule affects how payroll calculates withholding and employer contributions, and is reported to A-melding under spesielleInntektsforhold.

The A-melding report itself is generated by the payroll system; this service only stores the rule data and publishes events.

Timeline type: Flexible — gaps allowed, to may be open-ended. Multiple rules of different types may be active concurrently, but two rules of the same taxAndContributionRuleType must not overlap.

Property Type Required Description
id UUID Yes (read-only) Unique rule identifier. Server-generated on create.
from date Yes Rule effective from date.
to date No Rule effective until date. null means ongoing.
taxAndContributionRuleType enum Yes Type of special rule: JanMayen, netSalary, netSalaryForSeafarers, specialAllowanceForSeafarers, Svalbard.
etag string (read-only) Opaque version identifier for optimistic concurrency. Must be included in PATCH request body.
updatedAt datetime (read-only) Timestamp of last modification.

The actual tax, withholding and A-melding values are computed by the payroll system, not this service. This service only stores the rule and publishes events so payroll can act on it.

Key Validation Rules

  • from is required and must be a valid date between 1910-04-15 and 2089-09-17.
  • to, when provided, must be on or after from and within the same date bounds. Defaults to null (ongoing) when unspecified.
  • taxAndContributionRuleType is required and must be one of the enum values listed above.
  • No same-type overlap: two rules with the same taxAndContributionRuleType must not have overlapping date ranges on the same employee.
  • Rules of different types are allowed to overlap (e.g. nettoloenn and saerskiltFradragForSjoefolk active at the same time).
  • etag must match the current version on updates (optimistic concurrency).

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the rule record. Generated by the service on create; never supplied by clients.

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date the rule starts applying. Future dates are allowed. Must be a valid date between 1910-04-15 and 2089-09-17.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No

Date the rule stops applying. null (or omitted) means the rule is ongoing. When provided, must be on or after from. Setting to is the standard way to close an open-ended rule — the only in-place modification supported on an existing rule. To change any other field, end the current rule and create a new one.

taxAndContributionRuleType

  • Type: enum — JanMayen | netSalary | netSalaryForSeafarers | specialAllowanceForSeafarers | Svalbard
  • Required: Yes

Classifies the special rule. The value is passed through to A-melding as the spesielleInntektsforhold code for the employment relationship:

Rule Types

Value Norwegian Description
JanMayen Jan Mayen og bilandene Separate tax rules for employees on Jan Mayen and Norwegian dependencies.
netSalary Nettolønn Net salary arrangement — employer pays the employee's income tax on their behalf.
netSalaryForSeafarers Nettolønn for sjøfolk Net salary arrangement for seafarers — employer pays tax for maritime employees.
specialAllowanceForSeafarers Særskilt fradrag for sjøfolk Seafarer's deduction — 30% special deduction from maritime income (capped annually).
Svalbard Svalbardskatteloven Svalbard Tax Act — flat-rate taxation for employees working on Svalbard.

etag

  • Type: string
  • Required: Yes

Opaque version identifier used for optimistic concurrency control. Returned by the service on every read and must be included in PATCH request bodies. If the etag does not match the current version, the update is rejected with 409 Conflict.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Example: Create Tax and Contribution Rule

POST /tenants/{tenantId}/employees/{employeeId}/tax-and-contribution-rules
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "to": "2027-12-31",
  "taxAndContributionRuleType": "netSalary"
}

A successful request returns 201 Created with the full TaxAndContributionRule resource, including the server-generated id, employeeId, etag, and updatedAt. Omit to to register an open-ended rule.

Events

Event Trigger Consumers
taxAndContributionRule.created New special rule registered on employee Payroll
taxAndContributionRule.updated Existing rule modified (e.g. to date set to end rule) Payroll
taxAndContributionRule.deleted Rule removed from employee Payroll

List tax and contribution rules for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create tax and contribution rule entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

taxAndContributionRuleType
string or null (taxAndContributionRuleType)
Enum: "JanMayen" "nettoloenn" "nettoloennForSjoefolk" "saerskiltFradragForSjoefolk" "Svalbard"

Type of special rule:

  • JanMayen: Jan Mayen and dependencies
  • nettoloenn: Net salary arrangement (Nettolønn) - employer pays employee's tax
  • nettoloennForSjoefolk: Net salary for seafarers (Nettolønn for sjøfolk)
  • saerskiltFradragForSjoefolk: Seafarer's deduction (Særskilt fradrag for sjøfolk) - 30% deduction
  • Svalbard: Svalbard tax scheme - separate flat-rate taxation

Monolith notes: Field "Tax and contribution rule type" (ac7c9f8d-517e-4d9d-ad20-72a885208c46).


from
required
string <date>

Effective-from date

to
string or null <date>

Effective-until date

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "taxAndContributionRuleType": "JanMayen",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "taxAndContributionRuleType": "JanMayen",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Get tax and contribution rule by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

taxAndContributionRuleId
required
string <uuid>

Tax and contribution rule unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "taxAndContributionRuleType": "JanMayen",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Partially update tax and contribution rule

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

taxAndContributionRuleId
required
string <uuid>

Tax and contribution rule unique identifier

Request Body schema: application/json
required
taxAndContributionRuleType
string or null (taxAndContributionRuleType)
Enum: "JanMayen" "nettoloenn" "nettoloennForSjoefolk" "saerskiltFradragForSjoefolk" "Svalbard"

Type of special rule:

  • JanMayen: Jan Mayen and dependencies
  • nettoloenn: Net salary arrangement (Nettolønn) - employer pays employee's tax
  • nettoloennForSjoefolk: Net salary for seafarers (Nettolønn for sjøfolk)
  • saerskiltFradragForSjoefolk: Seafarer's deduction (Særskilt fradrag for sjøfolk) - 30% deduction
  • Svalbard: Svalbard tax scheme - separate flat-rate taxation

Monolith notes: Field "Tax and contribution rule type" (ac7c9f8d-517e-4d9d-ad20-72a885208c46).


etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

from
required
string <date>

Effective-from date

to
string or null <date>

Effective-until date

Responses

Request samples

Content type
application/json
{
  • "taxAndContributionRuleType": "JanMayen",
  • "etag": "1",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "taxAndContributionRuleType": "JanMayen",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Delete tax and contribution rule entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

taxAndContributionRuleId
required
string <uuid>

Tax and contribution rule unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

TaxInformation

Tax Information contains the employee's tax deduction settings from their tax card. This entity uses a strict timeline, meaning changes create new records with no gaps or overlaps.

Timeline type: Strict

Property Type Required Description
id UUID Yes (read-only) Unique record identifier
from date Yes Effective date for these tax settings
to date (read-only) Calculated end date of this record's validity period. Automatically set to the day before the next record's from. Null if this is the most recent record.
mainEmployer boolean No Is this the main employer?
borderCommuter boolean No Is employee a border commuter?
borderCommuterTaxPercentage number No Border commuter tax percentage
table string No Tax table number from tax card (4-digit pattern)
percentage decimal No Tax deduction percentage. Mandatory if table is set, otherwise optional. Default 50 if required but not set.
payeTaxPercentage decimal No PAYE withholding percentage for foreign workers
hasExemptionCard boolean No Employee has tax exemption card
exemptionCardAmount decimal No Remaining exemption card amount. Mandatory if hasExemptionCard is true, otherwise prohibited.
isFullyWithholdingChristmasTax boolean No Apply full tax withholding before Christmas (overrides the default Christmas exemption)
taxCardId string No Tax card identifier from Skatteetaten
taxCardIncomeYear string (read-only) Income year the tax card applies to
taxCardIssuedDate date No Date tax card was issued by Skatteetaten
lastTaxCardRetrieveDate date No Date tax card was last retrieved by the service
isPostedFromUsCanada boolean No Employee posted from US/Canada with tax treaty benefits
taxFromFirstKroneForTaxFreeOrg boolean No Apply tax from first krone for tax-free organizations
isReceivingPension boolean No Whether the employee receives pension through this employer. Gates all pension-related fields (pensionTable, pensionPercentage, etc.).
pensionTable string No Pension tax table number (4-digit pattern)
pensionPercentage decimal No Pension tax percentage. Mandatory if pensionTable is set, otherwise optional. Default 30 if required but not set.
pensionPercentagePaye decimal No Pension PAYE tax percentage for source-tax pensioners
hasPensionExemptionCard boolean No Pension exemption card (Frikort for pension)
updatedAt datetime (read-only) Timestamp of last modification

Tax deduction amounts, A-melding reporting, and tax card retrieval from Skatteetaten are performed by the payroll system and a background process, not by this service. This service stores tax settings and enforces validation only.

Key Validation Rules

  • percentage is mandatory when table is set. If required but not supplied, default to 50.
  • exemptionCardAmount is mandatory when hasExemptionCard is true, prohibited otherwise.
  • borderCommuterTaxPercentage — only allowed when borderCommuter is true; mandatory when payrollSettings.retrieveTaxCardOnWageRun is also false.
  • pensionPercentage is mandatory when pensionTable is set. If required but not supplied, default to 30.
  • Pension fields (pensionTable, pensionPercentage, pensionPercentagePaye, hasPensionExemptionCard) are only relevant when isReceivingPension is true.
  • table and pensionTable, when provided, must match the 4-digit pattern ^[0-9]{4}$.
  • Percentage fields must parse as decimals between 0 and 100; pensionPercentagePaye allows at most 1 decimal digit, the others allow 2.
  • exemptionCardAmount must be non-negative with at most 2 decimal places.
  • Strict timeline: no gaps, no overlaps. to is calculated automatically — only one record is active at any date.
  • When payrollSettings.retrieveTaxCardOnWageRun is true, the system-managed fields (table, percentage, payeTaxPercentage, borderCommuterTaxPercentage, hasExemptionCard, exemptionCardAmount, pensionTable, pensionPercentage, pensionPercentagePaye, hasPensionExemptionCard) must not be overwritten by external API consumers — they are updated by the Skatteetaten retrieval background process.

id

  • Type: UUID
  • Required: Yes (read-only, optionally client-provided on create)

Unique identifier for the tax information record. If the client supplies an id on create that already exists, the service returns 409 Conflict.

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Effective date the tax settings become active. Future dates are allowed.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No (read-only)

End date of this record's validity period. Calculated by the service as the day before the next record's from. null when this is the most recent record (currently active).

mainEmployer

  • Type: boolean
  • Required: No

Is this the main employer (Hovedarbeidsgiver)? Only main employers use table-based tax deduction; secondary employers use percentage-based deduction. An employee should have only one main employer at any time.

Feedback (pending schema change): this property is proposed to be renamed from isMainEmployer to mainEmployer (dropping the is prefix). The YAML schema has not yet been updated — the rename will be applied in a follow-up change.

borderCommuter

  • Type: boolean
  • Required: No

Is the employee a border commuter (Grensependler)? Border commuters living in a neighbouring country may qualify for a special tax rate set via borderCommuterTaxPercentage.

borderCommuterTaxPercentage

  • Type: string (decimal-13-2)
  • Required: Conditional

Border commuter tax percentage. Dependency on payrollSettings.retrieveTaxCardOnWageRun and borderCommuter:

retrieveTaxCardOnWageRun borderCommuter Behavior
true true Optional
false true Mandatory
true false Prohibited
false false Prohibited

Skatteetaten schema: prosentsats where trekkode is loennKunTrygdeavgiftTilUtenlandskBorgerSomGrensegjenger.

table

  • Type: string (4-digit pattern ^[0-9]{4}$)
  • Required: No

Tax table number (Trekktabell) from the tax card. Tax tables change annually — always use tables from the current year's tax card.

Skatteetaten schema: tabellnummer where trekkode is loennFraHovedarbeidsgiver.

percentage

  • Type: string (decimal-13-2), range 0–100
  • Required: Conditional — mandatory when table is set, optional otherwise

Tax deduction percentage (Trekkprosent). If a value is required but not supplied, default to 50.

Skatteetaten schema: prosentsats where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver.

payeTaxPercentage

  • Type: string (decimal-13-2), range 0–100
  • Required: No

PAYE withholding percentage for foreign workers (Kildeskattprosent). PAYE is a simplified flat-rate scheme (currently 25 %) on gross income with no deductions or allowances.

Skatteetaten schema: prosentsats where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver and a tilleggsopplysning is kildeskattPaaLoenn.

hasExemptionCard

  • Type: boolean
  • Required: No

Employee has a tax exemption card (Frikort) — no tax is deducted up to the exemptionCardAmount limit. Typically used by students and part-time workers.

Skatteetaten schema: true if frikortbeloep is set where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver.

exemptionCardAmount

  • Type: string (decimal-13-2), non-negative, max 2 decimals
  • Required: Conditional — mandatory when hasExemptionCard is true, prohibited otherwise

Remaining exemption card amount (Frikortbeløp). Once exhausted, normal tax deduction resumes.

Skatteetaten schema: frikortbeloep where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver.

isFullyWithholdingChristmasTax

  • Type: boolean (only true accepted; absence implies false)
  • Required: No

Override the default Christmas tax withholding exemption — when true, taxes before Christmas are fully withheld. See the Christmas Tax Withholding Exemption section below.

taxCardId

  • Type: string (nullable)
  • Required: No

Skatteetaten's identifier for this tax card.

Skatteetaten schema: skattekortidentifikator.

Feedback (pending schema change): this property — together with taxCardIssuedDate, and possibly taxCardIncomeYear — is proposed to move out of the strict taxInformation timeline. taxCardId and taxCardIssuedDate describe the tax-card document itself and do not need an active timeline; they fit better alongside the proposed entity for lastTaxCardRetrieveDate. taxCardIncomeYear may still need an active timeline, pending design confirmation. The YAML schema has not yet been updated.

taxCardIncomeYear

  • Type: string (integer-15)
  • Required: Yes (read-only)

Income year the tax card applies to.

Skatteetaten schema: inntektsaar.

Feedback (pending schema change): same as taxCardId — candidate for moving out of the timeline. Whether this field needs an active timeline of its own is an open design question.

taxCardIssuedDate

  • Type: date
  • Required: No

Date Skatteetaten issued the tax card. May be misleading if the parent record's values were changed manually after issuance.

Skatteetaten schema: utstedtDato.

Feedback (pending schema change): same as taxCardId — candidate for moving out of the timeline alongside the proposed lastTaxCardRetrieveDate entity.

lastTaxCardRetrieveDate

  • Type: date
  • Required: No (Read-Only)

Date when Tax Card was last retrieved from Skatteetaten. Tax Card retrieval process is initiated from Payroll UI by users.

Pending (not yet implemented): a method to initiate the tax card retrieval process from Skatteetaten needs to be added to this service. It is planned but not yet implemented.

isPostedFromUsCanada

  • Type: boolean
  • Required: No

Employee posted from US or Canada under a tax treaty. May qualify for treaty-based benefits and special social security arrangements.

taxFromFirstKroneForTaxFreeOrg

  • Type: boolean (only true accepted; absence implies false)
  • Required: No

For tax-free organizations only. Deducts tax from the first krone to avoid a large catch-up withholding in the month total payments exceed 10 000 NOK, or when the employee would otherwise have underpaid tax. Payroll always reports from the first krone using the tax and contribution rule "Tax-free organisation"; this field controls the employee-side withholding.

pensionTable

  • Type: string (4-digit pattern ^[0-9]{4}$)
  • Required: No

Pension tax table number. The value is not validated against the actual Skatteetaten deduction-table catalogue. Relevant only when isReceivingPension is true.

Skatteetaten schema: tabellnummer where trekkode is pensjon.

pensionPercentage

  • Type: string (decimal-13-2), range 0–100
  • Required: Conditional — mandatory when pensionTable is set, optional otherwise

Pension tax percentage. If a value is required but not supplied, default to 30.

Skatteetaten schema: prosentsats where trekkode is pensjon.

pensionPercentagePaye

  • Type: string (decimal-13-1), pattern ^(100(\.0)?|[0-9]{1,2}(\.[0-9])?)$
  • Required: No

Pension PAYE tax percentage for source-tax pensioners (Kildeskattpensjonist). Only one digit after the decimal separator is allowed (unlike the other percentage fields, which allow two).

Skatteetaten schema: prosentsats where trekkode is pensjon and a tilleggsopplysning is kildeskattpensjonist.

hasPensionExemptionCard

  • Type: boolean (only true accepted; absence implies false)
  • Required: No

Pension exemption card (Frikort for pension).

Skatteetaten schema: true if frikortbeloep is set where trekkode is pensjon.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Strict Timeline Behavior

Tax information uses a strict timeline.

  1. No gaps: Tax settings must be continuous
  2. No overlaps: Only one record active at any date
  3. Calculated end: The to field is automatically calculated as the day before the next record's from
  4. History preserved: All versions kept for audit

Example: Annual Tax Card Update

Record 1: from: 2024-01-01, to: 2024-12-31, table: "7100"
Record 2: from: 2025-01-01, to: null, table: "7150"

Record 1's to is automatically set to 2024-12-31.

Example: Create Tax Information

POST /tenants/{tenantId}/employees/{employeeId}/tax-information
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-01-01",
  "mainEmployer": true,
  "table": "7100",
  "percentage": "22.00",
  "taxCardId": "SK-2026-123456",
  "taxCardIssuedDate": "2025-12-15"
}

A successful request returns 201 Created with the full TaxInformation resource, including the server-generated id, calculated to, etag, and updatedAt.

Events

Event Trigger Consumers
tax-information-created-v1 New tax information record registered Payroll
tax-information-updated-v1 Existing record modified Payroll
tax-information-deleted-v1 Record hard-deleted Payroll

List tax information for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create tax information entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

isMainEmployer
boolean (isMainEmployer)

Is this the main employer (Hovedarbeidsgiver)? Only main employer uses table-based tax deduction.


Monolith notes: Field "Main employer" (a2cf27eb-e1f4-44d3-8cd7-e15016ff433c)


isBorderCommuter
boolean (isBorderCommuter)

Is employee a border commuter (Grensependler)? Special tax rate applies.


Monolith notes: Field "Border commuter employee" (0a4247ee-64c5-490f-871d-fb247eefa4d5).


borderCommuterTaxPercentage
string <decimal-13-2> (borderCommuterTaxPercentage) ^-?\d{1,11}(\.\d{1,2})?$

Depending on retrieveTaxCardOnWageRun and isBorderCommuter:

  • true and true: optional
  • false and true: mandatory
  • true and false: prohibited
  • false and false: prohibited

Skatteetaten schema: prosentsats where trekkode is loennKunTrygdeavgiftTilUtenlandskBorgerSomGrensegjenger


Monolith notes: Field "Border commuter tax percentage" (c37085f5-8d19-4792-8338-06c4ee13147a).


table
string or null (table) ^[0-9]{4}$

Skatteetaten schema: tabellnummer where trekkode is loennFraHovedarbeidsgiver (TBD: verify). References:


Monolith notes: Field "Tax table" (48148e6a-1864-40e8-9172-b3f5edee9d48).


percentage
string <decimal-13-2> (percentage) [ 0 .. 100 ]

Mandatory if table is set, otherwise optional.

If no explicit value is set and a value is required, use 50.

Skatteetaten schema: prosentsats where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver (TBD: verify).


Monolith notes: Field "Tax percentage" (d06a1507-ca8e-4c12-9188-23a7fb612f4b).


payeTaxPercentage
string <decimal-13-2> (payeTaxPercentage) [ 0 .. 100 ]

PAYE withholding percentage for foreign workers (Kildeskattprosent) Skatteetaten schema: prosentsats where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver and a tilleggsopplysning is kildeskattPaaLoenn. (TBD: verify).

https://www.skatteetaten.no/en/person/foreign/are-you-intending-to-work-in-norway/tax-deduction-cards/paye/


Monolith notes: Field "PAYE tax percentage" (c4d57402-34be-4fba-8876-8820ea4ffe3f).


hasExemptionCard
boolean (hasExemptionCard)

Employee has tax exemption card (Frikort) - no tax deduction up to limit Skatteetaten schema: true if frikortbeloep is set where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver (TBD: verify).

https://www.skatteetaten.no/en/person/taxes/tax-deduction-card-and-advance-tax/exemption-card/exemption-card-or-tax-deduction-card/


Monolith notes: Field "Freecard" (554d7abb-679b-4d71-8a7d-2e19ce09ae8b).


exemptionCardAmount
string <decimal-13-2> (exemptionCardAmount)

Remaining exemption card amount (Frikortbeløp) Mandatory if hasExemptionCard is true, otherwise prohibited.

Skatteetaten schema: frikortbeloep where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver (TBD: verify).

https://www.skatteetaten.no/en/person/taxes/tax-deduction-card-and-advance-tax/exemption-card/exemption-card-or-tax-deduction-card/


Monolith notes: Field "Freecard amount" (ffdc30d2-f067-4ceb-a816-ef5b32b2eb01).


isFullyWithholdingChristmasTax
boolean (isFullyWithholdingChristmasTax)

Also known as Full tax in Nov/Dec. Only true is accepted. Absence of value implies false. By law, employers can exempt their employees from withholding taxes for a period "before Christmas". They do so by default. When this property is active, the Christmas exemption will not apply and taxes before Christmas will be fully withheld. Employers in Norway are required to withhold their employees' taxes on behalf of the government. Tax card parameters are normally set so the expected tax is withheld in 10.5 months of the year, so the remaining 1.5 months are exempt from withholding tax. By law, the periods are 4 weeks of vacation and approximately 2 weeks for Christmas. (Note that other rules may apply, eg. for pensions.) (Note that some tax cards have a 12 month period for withholding tax.) Some employees must always have their tax withheld by law or regulation. Other employees may elect not use the exemption -- ie they want their taxes before Christmas fully withheld -- for a variety of reasons, for example:

  • Higher than normal salary in the exemption period.
  • Too little tax withheld earlier in the year.
  • Change of employer on eg. December 1st.
    • From an employer that had an early exemption of withheld taxes
    • To an employer that will have a late exemption of withholding taxes.
    • Employee wants to avoid two exemptions in withholding taxes with a resulting underpaid tax. By regulation, the employer can choose an early or late period for Christmas tax exemption. This is controlled by the company setting periodForChristmasTaxWithholdingExemption. The exact period for the Christmas tax withholding exemption depends on
  • salaryTypeTimeline
  • whether payment happens every 14 days (not currently supported)
  • employmentType (whether it's pension) (TBD: or isReceivingPension?) References:
  • Law on withholding taxes: https://lovdata.no/lov/2005-06-17-67/§5-7
  • Regulation on withholding taxes: https://lovdata.no/forskrift/2007-12-21-1766/§5-7-2

Monolith notes: Field "Full tax in Nov/Dec" (d066796a-26d4-473b-bf52-edf13d90b130). Mapping to values in reference table 10040 No / Yes:

  • (not set): No (or anything which is not Yes)
  • true: Yes

taxCardId
string or null (taxCardId)

Skatteetaten's ID for this tax card.

Skatteetaten schema: skattekortidentifikator


Monolith notes: Field "Taxcard ID" (dee3ab67-ab4e-449c-95b2-33f647bb387e).


taxCardIncomeYear
string <integer-15>

Income year the tax card applies to (Inntektsår).

taxCardIssuedDate
string <date> (taxCardIssuedDate)

The date Skatteetaten issued this tax card.

This may be misleading because the parent object's values could have been changed manually since then.

Skatteetaten schema: utstedtDato


Monolith notes: Field "Taxcard date" (1ca9b054-e960-462f-b7eb-431d2d6bb764).


isPostedFromUsCanada
boolean (isPostedFromUsCanada)

Employee posted from US/Canada with tax treaty benefits


Monolith notes: Field "Posted from US/Canada" (9f437c4b-0bc6-44b0-9160-3b7b37e1afb9).


taxFromFirstKroneForTaxFreeOrg
boolean (taxFromFirstKroneForTaxFreeOrg)

Only true is accepted. Absence of value implies false.

Field should only applies for tax free organizations. Note that payroll always reports from first krone, using tax and contribution rule "Tax-free organisation". This field is used to deduct tax for the employee from the first payment, to avoid withholding much the month that total payments exceed 10 000 and/or the employee having underpaid tax.

https://www.skatteetaten.no/en/business-and-organisation/employer/the-a-melding/the-a-melding-guide/special-groups/tax-free-organisations/


Monolith notes: Field "Tax from the 1st NOK" (954b6779-4c16-45f4-bcc0-b75dfab081e4).


isReceivingPension
boolean (isReceivingPension)

Only true is accepted. Absence of value implies false.


Monolith notes: Field "Pension benefits paid out to this person" (0b674566-0004-479e-a735-a86aff426964).


pensionTable
string (pensionTable) ^[0-9]{4}$

It is not validated whether this is a real deduction table number. Skatteetaten schema: tabellnummer where trekkode is pensjon (TBD: verify). References:


Monolith notes: Field "Pension tax table" (86f929f0-6780-4eb2-9518-c5a787a21c78). Known issue: It is not validated whether this is an actual tax table. Vintage UI hides this field if isReceivingPension is false.


pensionPercentage
string <decimal-13-2> (pensionPercentage) [ 0 .. 100 ]

Mandatory if pensionTable is set, otherwise optional. If no explicit value is set and a value is required, use 30. Skatteetaten schema: prosentsats where trekkode is pensjon (TBD: verify).


Monolith notes: Field "Pension tax percentage" (65a40dd9-4d88-43fe-a21a-e916e0365db0). Vintage UI hides this field if isReceivingPension is false.


pensionPercentagePaye
string <decimal-13-1> (pensionPercentagePaye) ^(100(\.0)?|[0-9]{1,2}(\.[0-9])?)$

Skatteetaten schema: prosentsats where trekkode is pensjon and a tilleggsopplysning is kildeskattpensjonist. (TBD: verify). Note: A maximum of 1 digit after the decimal separator is allowed, unlike other decimal values.


Monolith notes: Field "Pension PAYE tax percentage" (58f48566-6b6b-47db-a8c8-4df82de4b345). Known issue (discrepancy): Minimum and maximum are not defined, unlike all other percentages. Known issue (TBD: possibly): Only allows a 1 digit after the decimal separator, unlike all other fields with of type decimal (which allow 2 digits). Vintage UI hides this field if isReceivingPension is false.


hasPensionExemptionCard
boolean (hasPensionExemptionCard)

Only true is accepted. Absence of value implies false. Skatteetaten schema: true if frikortbeloep is set where trekkode is pensjon (TBD: verify).


Monolith notes: Field "Pension freecard" (ad3a4a83-748b-4ac5-8e0c-8f34e06fac40). Vintage UI hides this field if isReceivingPension is false.


from
required
string <date>

Effective-from date for this timeline version.

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "isMainEmployer": true,
  • "isBorderCommuter": true,
  • "borderCommuterTaxPercentage": "string",
  • "table": "string",
  • "percentage": "string",
  • "payeTaxPercentage": "string",
  • "hasExemptionCard": true,
  • "exemptionCardAmount": "string",
  • "isFullyWithholdingChristmasTax": true,
  • "taxCardId": "string",
  • "taxCardIncomeYear": "string",
  • "taxCardIssuedDate": "2019-08-24",
  • "isPostedFromUsCanada": true,
  • "taxFromFirstKroneForTaxFreeOrg": true,
  • "isReceivingPension": true,
  • "pensionTable": "string",
  • "pensionPercentage": "string",
  • "pensionPercentagePaye": "string",
  • "hasPensionExemptionCard": true,
  • "from": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "isMainEmployer": true,
  • "isBorderCommuter": true,
  • "borderCommuterTaxPercentage": "string",
  • "table": "string",
  • "percentage": "string",
  • "payeTaxPercentage": "string",
  • "hasExemptionCard": true,
  • "exemptionCardAmount": "string",
  • "isFullyWithholdingChristmasTax": true,
  • "taxCardId": "string",
  • "taxCardIncomeYear": "string",
  • "taxCardIssuedDate": "2019-08-24",
  • "isPostedFromUsCanada": true,
  • "taxFromFirstKroneForTaxFreeOrg": true,
  • "isReceivingPension": true,
  • "pensionTable": "string",
  • "pensionPercentage": "string",
  • "pensionPercentagePaye": "string",
  • "hasPensionExemptionCard": true,
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Get tax information by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

taxInformationId
required
string <uuid>

Tax information unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "isMainEmployer": true,
  • "isBorderCommuter": true,
  • "borderCommuterTaxPercentage": "string",
  • "table": "string",
  • "percentage": "string",
  • "payeTaxPercentage": "string",
  • "hasExemptionCard": true,
  • "exemptionCardAmount": "string",
  • "isFullyWithholdingChristmasTax": true,
  • "taxCardId": "string",
  • "taxCardIncomeYear": "string",
  • "taxCardIssuedDate": "2019-08-24",
  • "isPostedFromUsCanada": true,
  • "taxFromFirstKroneForTaxFreeOrg": true,
  • "isReceivingPension": true,
  • "pensionTable": "string",
  • "pensionPercentage": "string",
  • "pensionPercentagePaye": "string",
  • "hasPensionExemptionCard": true,
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Partially update tax information

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

taxInformationId
required
string <uuid>

Tax information unique identifier

Request Body schema: application/json
required
isMainEmployer
boolean (isMainEmployer)

Is this the main employer (Hovedarbeidsgiver)? Only main employer uses table-based tax deduction.


Monolith notes: Field "Main employer" (a2cf27eb-e1f4-44d3-8cd7-e15016ff433c)


isBorderCommuter
boolean (isBorderCommuter)

Is employee a border commuter (Grensependler)? Special tax rate applies.


Monolith notes: Field "Border commuter employee" (0a4247ee-64c5-490f-871d-fb247eefa4d5).


borderCommuterTaxPercentage
string <decimal-13-2> (borderCommuterTaxPercentage) ^-?\d{1,11}(\.\d{1,2})?$

Depending on retrieveTaxCardOnWageRun and isBorderCommuter:

  • true and true: optional
  • false and true: mandatory
  • true and false: prohibited
  • false and false: prohibited

Skatteetaten schema: prosentsats where trekkode is loennKunTrygdeavgiftTilUtenlandskBorgerSomGrensegjenger


Monolith notes: Field "Border commuter tax percentage" (c37085f5-8d19-4792-8338-06c4ee13147a).


table
string or null (table) ^[0-9]{4}$

Skatteetaten schema: tabellnummer where trekkode is loennFraHovedarbeidsgiver (TBD: verify). References:


Monolith notes: Field "Tax table" (48148e6a-1864-40e8-9172-b3f5edee9d48).


percentage
string <decimal-13-2> (percentage) [ 0 .. 100 ]

Mandatory if table is set, otherwise optional.

If no explicit value is set and a value is required, use 50.

Skatteetaten schema: prosentsats where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver (TBD: verify).


Monolith notes: Field "Tax percentage" (d06a1507-ca8e-4c12-9188-23a7fb612f4b).


payeTaxPercentage
string <decimal-13-2> (payeTaxPercentage) [ 0 .. 100 ]

PAYE withholding percentage for foreign workers (Kildeskattprosent) Skatteetaten schema: prosentsats where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver and a tilleggsopplysning is kildeskattPaaLoenn. (TBD: verify).

https://www.skatteetaten.no/en/person/foreign/are-you-intending-to-work-in-norway/tax-deduction-cards/paye/


Monolith notes: Field "PAYE tax percentage" (c4d57402-34be-4fba-8876-8820ea4ffe3f).


hasExemptionCard
boolean (hasExemptionCard)

Employee has tax exemption card (Frikort) - no tax deduction up to limit Skatteetaten schema: true if frikortbeloep is set where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver (TBD: verify).

https://www.skatteetaten.no/en/person/taxes/tax-deduction-card-and-advance-tax/exemption-card/exemption-card-or-tax-deduction-card/


Monolith notes: Field "Freecard" (554d7abb-679b-4d71-8a7d-2e19ce09ae8b).


exemptionCardAmount
string <decimal-13-2> (exemptionCardAmount)

Remaining exemption card amount (Frikortbeløp) Mandatory if hasExemptionCard is true, otherwise prohibited.

Skatteetaten schema: frikortbeloep where trekkode is loennFraHovedarbeidsgiver or loennFraBiarbeidsgiver (TBD: verify).

https://www.skatteetaten.no/en/person/taxes/tax-deduction-card-and-advance-tax/exemption-card/exemption-card-or-tax-deduction-card/


Monolith notes: Field "Freecard amount" (ffdc30d2-f067-4ceb-a816-ef5b32b2eb01).


isFullyWithholdingChristmasTax
boolean (isFullyWithholdingChristmasTax)

Also known as Full tax in Nov/Dec. Only true is accepted. Absence of value implies false. By law, employers can exempt their employees from withholding taxes for a period "before Christmas". They do so by default. When this property is active, the Christmas exemption will not apply and taxes before Christmas will be fully withheld. Employers in Norway are required to withhold their employees' taxes on behalf of the government. Tax card parameters are normally set so the expected tax is withheld in 10.5 months of the year, so the remaining 1.5 months are exempt from withholding tax. By law, the periods are 4 weeks of vacation and approximately 2 weeks for Christmas. (Note that other rules may apply, eg. for pensions.) (Note that some tax cards have a 12 month period for withholding tax.) Some employees must always have their tax withheld by law or regulation. Other employees may elect not use the exemption -- ie they want their taxes before Christmas fully withheld -- for a variety of reasons, for example:

  • Higher than normal salary in the exemption period.
  • Too little tax withheld earlier in the year.
  • Change of employer on eg. December 1st.
    • From an employer that had an early exemption of withheld taxes
    • To an employer that will have a late exemption of withholding taxes.
    • Employee wants to avoid two exemptions in withholding taxes with a resulting underpaid tax. By regulation, the employer can choose an early or late period for Christmas tax exemption. This is controlled by the company setting periodForChristmasTaxWithholdingExemption. The exact period for the Christmas tax withholding exemption depends on
  • salaryTypeTimeline
  • whether payment happens every 14 days (not currently supported)
  • employmentType (whether it's pension) (TBD: or isReceivingPension?) References:
  • Law on withholding taxes: https://lovdata.no/lov/2005-06-17-67/§5-7
  • Regulation on withholding taxes: https://lovdata.no/forskrift/2007-12-21-1766/§5-7-2

Monolith notes: Field "Full tax in Nov/Dec" (d066796a-26d4-473b-bf52-edf13d90b130). Mapping to values in reference table 10040 No / Yes:

  • (not set): No (or anything which is not Yes)
  • true: Yes

taxCardId
string or null (taxCardId)

Skatteetaten's ID for this tax card.

Skatteetaten schema: skattekortidentifikator


Monolith notes: Field "Taxcard ID" (dee3ab67-ab4e-449c-95b2-33f647bb387e).


taxCardIssuedDate
string <date> (taxCardIssuedDate)

The date Skatteetaten issued this tax card.

This may be misleading because the parent object's values could have been changed manually since then.

Skatteetaten schema: utstedtDato


Monolith notes: Field "Taxcard date" (1ca9b054-e960-462f-b7eb-431d2d6bb764).


isPostedFromUsCanada
boolean (isPostedFromUsCanada)

Employee posted from US/Canada with tax treaty benefits


Monolith notes: Field "Posted from US/Canada" (9f437c4b-0bc6-44b0-9160-3b7b37e1afb9).


taxFromFirstKroneForTaxFreeOrg
boolean (taxFromFirstKroneForTaxFreeOrg)

Only true is accepted. Absence of value implies false.

Field should only applies for tax free organizations. Note that payroll always reports from first krone, using tax and contribution rule "Tax-free organisation". This field is used to deduct tax for the employee from the first payment, to avoid withholding much the month that total payments exceed 10 000 and/or the employee having underpaid tax.

https://www.skatteetaten.no/en/business-and-organisation/employer/the-a-melding/the-a-melding-guide/special-groups/tax-free-organisations/


Monolith notes: Field "Tax from the 1st NOK" (954b6779-4c16-45f4-bcc0-b75dfab081e4).


isReceivingPension
boolean (isReceivingPension)

Only true is accepted. Absence of value implies false.


Monolith notes: Field "Pension benefits paid out to this person" (0b674566-0004-479e-a735-a86aff426964).


pensionTable
string (pensionTable) ^[0-9]{4}$

It is not validated whether this is a real deduction table number. Skatteetaten schema: tabellnummer where trekkode is pensjon (TBD: verify). References:


Monolith notes: Field "Pension tax table" (86f929f0-6780-4eb2-9518-c5a787a21c78). Known issue: It is not validated whether this is an actual tax table. Vintage UI hides this field if isReceivingPension is false.


pensionPercentage
string <decimal-13-2> (pensionPercentage) [ 0 .. 100 ]

Mandatory if pensionTable is set, otherwise optional. If no explicit value is set and a value is required, use 30. Skatteetaten schema: prosentsats where trekkode is pensjon (TBD: verify).


Monolith notes: Field "Pension tax percentage" (65a40dd9-4d88-43fe-a21a-e916e0365db0). Vintage UI hides this field if isReceivingPension is false.


pensionPercentagePaye
string <decimal-13-1> (pensionPercentagePaye) ^(100(\.0)?|[0-9]{1,2}(\.[0-9])?)$

Skatteetaten schema: prosentsats where trekkode is pensjon and a tilleggsopplysning is kildeskattpensjonist. (TBD: verify). Note: A maximum of 1 digit after the decimal separator is allowed, unlike other decimal values.


Monolith notes: Field "Pension PAYE tax percentage" (58f48566-6b6b-47db-a8c8-4df82de4b345). Known issue (discrepancy): Minimum and maximum are not defined, unlike all other percentages. Known issue (TBD: possibly): Only allows a 1 digit after the decimal separator, unlike all other fields with of type decimal (which allow 2 digits). Vintage UI hides this field if isReceivingPension is false.


hasPensionExemptionCard
boolean (hasPensionExemptionCard)

Only true is accepted. Absence of value implies false. Skatteetaten schema: true if frikortbeloep is set where trekkode is pensjon (TBD: verify).


Monolith notes: Field "Pension freecard" (ad3a4a83-748b-4ac5-8e0c-8f34e06fac40). Vintage UI hides this field if isReceivingPension is false.


etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

from
required
string <date>

Effective-from date for this timeline version.

Responses

Request samples

Content type
application/json
{
  • "isMainEmployer": true,
  • "isBorderCommuter": true,
  • "borderCommuterTaxPercentage": "string",
  • "table": "string",
  • "percentage": "string",
  • "payeTaxPercentage": "string",
  • "hasExemptionCard": true,
  • "exemptionCardAmount": "string",
  • "isFullyWithholdingChristmasTax": true,
  • "taxCardId": "string",
  • "taxCardIssuedDate": "2019-08-24",
  • "isPostedFromUsCanada": true,
  • "taxFromFirstKroneForTaxFreeOrg": true,
  • "isReceivingPension": true,
  • "pensionTable": "string",
  • "pensionPercentage": "string",
  • "pensionPercentagePaye": "string",
  • "hasPensionExemptionCard": true,
  • "etag": "1",
  • "from": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "isMainEmployer": true,
  • "isBorderCommuter": true,
  • "borderCommuterTaxPercentage": "string",
  • "table": "string",
  • "percentage": "string",
  • "payeTaxPercentage": "string",
  • "hasExemptionCard": true,
  • "exemptionCardAmount": "string",
  • "isFullyWithholdingChristmasTax": true,
  • "taxCardId": "string",
  • "taxCardIncomeYear": "string",
  • "taxCardIssuedDate": "2019-08-24",
  • "isPostedFromUsCanada": true,
  • "taxFromFirstKroneForTaxFreeOrg": true,
  • "isReceivingPension": true,
  • "pensionTable": "string",
  • "pensionPercentage": "string",
  • "pensionPercentagePaye": "string",
  • "hasPensionExemptionCard": true,
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Delete tax information entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

taxInformationId
required
string <uuid>

Tax information unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

Get union link by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

unionLinkId
required
string <uuid>

Union link unique identifier

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "unionId": "string",
  • "unionMemberNumber": "string",
  • "includedInCollectiveInsurance": true,
  • "includedInUnionsInsurance": true,
  • "employeeAmountForCollectiveInsurance": "string",
  • "employeeAmountForUnionsInsurance": "string",
  • "employeeReferenceNumber": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Positions

Represents an employment role held by an employee (Stilling / Arbeidsforhold). Positions hold the contract-specific data — type of employment, dates, appointment form, and maritime details — and act as the parent for related salary, work arrangement, tax unit, and cost unit records.

An employee can have one or more positions. At least one position is required per employee. While the data model supports multiple concurrent positions, overlapping active periods are currently not allowed (rule L-010) — this will be lifted once payroll supports concurrent positions.

Timeline type: Flexible — gaps allowed, explicit to, open-ended (to = null) permitted. Timelines cannot overlap

Property Type Required Description
id UUID Yes (read-only) Unique position identifier.
from date Yes Position start date (Startdato). Must be on or after 1973-01-01.
to date No Position end date (Sluttdato). null means ongoing. When set, must be on or after from.
positionNumber integer (read-only) Sequence number within employee (1, 2, 3 ...). Auto-incremented on create.
employmentType enum Yes Type of employment discriminator (Arbeidsforholdtype). Immutable after creation. Determines which other fields are required, optional, or forbidden.
appointmentType enum Conditional Type of appointment (Ansettelsesform). Required for Ordinary and Maritime; must not be set for Freelancer, Pension, or PermanentlyAdaptedWork.
positionEndReason enum Conditional Reason the position ended (Sluttårsak). Required when to is set, employmentType is Ordinary or Maritime, and to is on or after 2020-01-01.
managerId UUID No Employee ID of the direct manager (Nærmeste leder). Must reference an employee in the same tenant.
maritimeWorker object Conditional Maritime employment details (ship register, vessel type, shipping area). Required when employmentType is Maritime; must not be set for other types.
tagLinks UUID[] No Tag identifiers assigned to this position (Etiketter).
updatedAt datetime (read-only) Timestamp of the last modification.

Related Entities

Each position has its own timeline-based sub-resources, managed via dedicated endpoints after creation:

Entity Timeline Path suffix Purpose
SalaryInformation Strict /salary-information Compensation details (monthly / hourly / yearly, rates).
WorkArrangements Strict /work-arrangements Working hours, part-time factor, working-time agreement.
TaxUnitLinks Strict /tax-unit-links Links the position to an organisational sub-entity (virksomhet) for A-melding reporting.
CostUnitLinks Flexible /cost-unit-links Wage-cost allocation across accounting dimensions.

At position creation:

  • SalaryInformation — at least one record required for Ordinary, Maritime, Freelancer. Optional for Pension (only rate4 used) and PermanentlyAdaptedWork.
  • WorkArrangement — at least one record required for Ordinary, Maritime, Freelancer. Not allowed for Pension or PermanentlyAdaptedWork.
  • The first SalaryInformation / WorkArrangement from must match the position's from.

Key Validation Rules

  • Start datefrom must be on or after 1973-01-01. Cannot be changed if transactions or expense claims exist before the new date.
  • End dateto, when provided, must be on or after from.
  • Type immutableemploymentType cannot be changed after creation; end the position and create a new one instead.
  • End reason ↔ end datepositionEndReason requires to to be set, and vice versa (bidirectional).
  • End reason required — when closing an Ordinary or Maritime position with to >= 2020-01-01, positionEndReason must be supplied.
  • Minimum one position — the last remaining position of an employee cannot be deleted.
  • Wage-run lock — a non-draft, non-future position that is part of a paid wage run cannot be deleted. Positions with from in the future can always be deleted.
  • No overlapping positions (temporary) — a position's active range must not overlap with any other position for the same employee. This restriction is scheduled to be removed once payroll supports concurrent positions.

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the position record. Generated by the service on create; never supplied by clients.

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date the position becomes active (Startdato). Drives the employee's effective start date and acts as the anchor for child records — the first SalaryInformation and WorkArrangement must start on the same date.

Validation

  • Must be on or after 1973-01-01.
  • Cannot be changed if transactions or expense claims exist before the new date.
  • Must be on or before to when to is set.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No

Date the position ends (Sluttdato). null means the position is ongoing. Setting to is the standard way to close an open-ended position — combined with positionEndReason, this triggers A-melding termination reporting.

Validation

  • When provided, must be on or after from (same date is allowed).
  • Cannot be cleared (set back to null) while positionEndReason still has a value — clear the reason first.
  • When closing an Ordinary or Maritime position with to on or after 2020-01-01, positionEndReason is required.

positionNumber

  • Type: integer
  • Required: read-only, system generated

Sequence number within the employee (1, 2, 3 ...). Auto-incremented on create and never supplied by clients. Used in the A-melding reported position ID computation together with the tax unit link.

employmentType

  • Type: enum — Ordinary | Maritime | Freelancer | Pension | PermanentlyAdaptedWork
  • Required: Yes

Primary discriminator — drives field applicability, validation, and A-melding reporting. Immutable after creation; changing the type requires ending the position and creating a new one.

Value Norwegian When to use A-melding mapping
Ordinary Ordinært arbeidsforhold Standard employment contract. Default value. ordinaertArbeidsforhold
Maritime Maritimt arbeidsforhold Seafarer employment. maritimeWorker sub-object becomes mandatory. maritimtArbeidsforhold
Freelancer Frilanser, oppdragstaker Freelance, contractor, or honorarium-only arrangements. Fewer mandatory fields than Ordinary/Maritime. frilanserOppdragstakerHonorarPersonerMm
Pension Pensjon og andre ytelser Post-employment pension and other remunerations without active employment. Salary (apart from rate4) and work arrangements not allowed. pensjonOgAndreTyterIArbeidsforhold
PermanentlyAdaptedWork Varig tilrettelagt arbeid Permanently adapted work for recipients of disability benefits (NAV scheme). Minimal field requirements. — (reported as tiltak)

Maritime Worker

Required when employmentType is Maritime; must not be set for other types. All three sub-fields are required when the object is present.

Sub-field Values
shipRegister NorwegianShipRegister (Norwegian Ship Register), NorwegianInternationalShipRegister (NIS), InternationalShipRegister (foreign / international)
vesselType CruiseShip (Turistskip), DrillingPlatform (Boreplattform), Other (Annet)
shippingArea Domestic (Innenriks), International (Utenriks)

appointmentType

  • Type: enum — Permanent | Temporary | PermanentHiredOut | TemporaryHiredOut | OncallStaff
  • Required: Conditional — required for Ordinary and Maritime, must not be set for Freelancer, Pension, or PermanentlyAdaptedWork

Maps directly to A-melding. Required for Ordinary and Maritime; forbidden for Freelancer, Pension, and PermanentlyAdaptedWork.

Value Norwegian Description
Permanent Fast ansatt Permanent employment. Default.
Temporary Midlertidig ansatt Temporary / fixed-term employment.
PermanentHiredOut Fast ansatt og utleid Permanent, hired out to another company.
TemporaryHiredOut Midlertidig ansatt og utleid Temporary, hired out.
OncallStaff Tilkallingsvikar On-call / substitute staff.

positionEndReason

  • Type: enum — EmployeeResigned | EmployerTerminated | ContractEnded | ShouldNeverHaveBeenReported | OrganisationalChangeOrInternalJobSwap | PayrollSystemOrAccountantChanged
  • Required: Conditional — required when employmentType is Ordinary or Maritime, set to date.

Reason the position ended. Maps to the A-melding <sluttaarsak> element. Positions ended before 2020-01-01 do not require an end reason — A-melding did not mandate it for older records.

Required when closing an Ordinary or Maritime position with to >= 2020-01-01. Not applicable for Freelancer, Pension, or PermanentlyAdaptedWork.

Value Label Norwegian A-melding code
EmployeeResigned The employee has resigned from his/her position Arbeidstaker har sagt opp selv 1
EmployerTerminated The employer has terminated the employment relationship Arbeidsgiver har sagt opp arbeidstaker 2
ContractEnded Contract, temporary appointment or temporary position has been terminated Kontrakt, engasjement eller vikariat er utløpt 3
ShouldNeverHaveBeenReported The employment should never have been reported Arbeidsforholdet skulle aldri vært rapportert 4
OrganisationalChangeOrInternalJobSwap Changes in organisational structure or internal job swap Endring i organisasjonsstruktur eller byttet jobb internt 5
PayrollSystemOrAccountantChanged Changed payroll system or accountant Byttet lønnssystem eller regnskapsfører 6

Maritime fields follow the parent position timeline — if ship or route details change, the position must be ended and a new one created.

Validation

  • Can only be set when to has a value.
  • Not applicable for Freelancer, Pension, or PermanentlyAdaptedWork.
  • Bidirectional with to: setting an end reason requires an end date, and clearing the end date requires clearing the reason first.

managerId

  • Type: UUID
  • Required: No

Employee ID of the direct manager (Nærmeste leder). Used for organisational hierarchy only — not reported to A-melding.

Validation

  • If provided, must reference an existing employee in the same tenant.

maritimeWorker

  • Type: object — see Maritime Worker
  • Required: Conditional — required when employmentType is Maritime, must not be set otherwise

Embedded object holding seafarer-specific details (shipRegister, vesselType, shippingArea). Follows the parent position's lifecycle; if maritime details change, the position must be ended and a new one created. See the dedicated MaritimeWorker documentation for per-field details.

Validation

  • When present, all three sub-fields must be supplied together.
  • Type: array of UUID
  • Required: No

Tag identifiers (Etiketter) assigned to this position. Free-form classification used for reporting and filtering; has no effect on payroll or A-melding.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Cascading Effects on the Employee

Trigger Employee-level effect
Position from created / updated / position deleted Employee effective start date = earliest from across all positions.
Position to created / updated / cleared / position deleted Employee effective end date = latest to across all positions, or null if any position is open-ended.

Example: Create an Ordinary Position

POST /tenants/{tenantId}/employees/{employeeId}/positions
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "employmentType": "Ordinary",
  "appointmentType": "Permanent",
  "managerId": "b1c2d3e4-5f6a-7b8c-9d0e-1f2a3b4c5d6e",
  "salaryInformation": [
    {
      "from": "2026-05-01",
      "compensationMethod": "Period",
      "salaryBasis": "Monthly",
      "salary": "54166.67"
    }
  ],
  "workArrangements": [
    {
      "from": "2026-05-01",
      "occupationCode": "2512102",
      "setOfAccount": "White",
      "workTimeAgreementId": "NotShift",
      "workingHoursWeek": "37.50",
      "ftePercentage": "100.00"
    }
  ]
}

A successful request returns 201 Created with the full Position resource, including the server-generated id, positionNumber, and updatedAt.

Events

Event Trigger Consumers
position.created New position registered Payroll
position.updated Existing position modified (e.g. to date set, rename) Payroll
position.deleted Position removed Payroll

List all positions for an employee

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create a new position for an employee

Creates a new position with initial salary information and work arrangements. Child entities (salaryInformation, workArrangements) are created atomically with the position. After creation, child entities are managed through their dedicated endpoints.

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

positionEndReason
string or null (positionEndReason)
Enum: "EmployeeResigned" "EmployerTerminated" "ContractEnded" "ShouldNeverHaveBeenReported" "OrganisationalChangeOrInternalJobSwap" "PayrollSystemOrAccountantChanged"

Reason the position ended (Sluttårsak). Maps to A-melding sluttaarsak. Required when an Ordinary or Maritime position has to >= 2020-01-01.


Monolith notes: Field "Position end reason" (51dbd5a3-b28b-4522-b2df-38fb1ad3c447).


managerId
string or null <uuid> (managerId)

Employee ID of direct manager (Narmeste leder)


Monolith notes: Field "Manager" (e82bbb69-937f-4f67-b667-0629bd6cf860).


appointmentType
string or null (appointmentType)
Enum: "Permanent" "Temporary" "PermanentHiredOut" "TemporaryHiredOut" "OncallStaff"

Type of appointment (Ansettelsesform). Required when employmentType is Ordinary or Maritime; must not be set otherwise.

  • Permanent: Permanent employment (Fast ansatt)
  • Temporary: Temporary employment (Midlertidig ansatt)
  • PermanentHiredOut: Permanent and hired out (Fast ansatt og utleid)
  • TemporaryHiredOut: Temporary and hired out (Midlertidig ansatt og utleid)
  • OncallStaff: On-call / substitute staff (Tilkallingsvikar)

Monolith notes: Field "Employment form" (c19fc3ca-b644-439c-9801-24691a7ebf39).


employmentType
required
string (employmentType)
Enum: "Ordinary" "Maritime" "Freelancer" "Pension" "PermanentlyAdaptedWork"

Type of employment discriminator (Arbeidsforholdtype). Determines which fields are required/applicable. Required on POST. Immutable after creation — PATCH requests that target this field are rejected; changing type requires ending the position and creating a new one.

  • Ordinary: Standard employment (Ordinært arbeidsforhold)
  • Maritime: Maritime employment (Maritimt arbeidsforhold)
  • Freelancer: Freelance/contractor (Frilanser)
  • Pension: Pension and other remunerations without employment (Pensjon og andre ytelser)
  • PermanentlyAdaptedWork: Varig tilrettelagt arbeid (NAV scheme)

Monolith notes: Field "Employment type" (e7b5dcb2-11cb-401c-9332-89fc645e4ec6).


object or null

Maritime employment details. Required only for Maritime positions; must be null for all other employment types.

Array of objects (SalaryInformationCreate)
Array of objects (WorkArrangementCreate)
Array of objects (SicknessAndAbsencePeriod)

Initial prepaid sickness periods for this position. Defaults to empty.

Array of objects (SicknessAndAbsencePeriod)

Initial prepaid other absence periods for this position. Defaults to empty.

Array of objects (RedundancyPeriod)

Initial redundancy periods for this position. Defaults to empty.

tagLinks
Array of strings or null <uuid> [ items <uuid > ]

Tag identifiers to assign to this position.

from
required
string <date>

Effective-from date

to
string or null <date>

Effective-until date

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "positionEndReason": "EmployeeResigned",
  • "managerId": "b2c2c359-55f3-4680-a660-901475c7a693",
  • "appointmentType": "Permanent",
  • "employmentType": "Ordinary",
  • "maritimeWorker": {
    },
  • "salaryInformation": [
    ],
  • "workArrangements": [
    ],
  • "prepaidSicknessPeriods": [
    ],
  • "prepaidOtherAbsencePeriods": [
    ],
  • "redundancyPeriods": [
    ],
  • "tagLinks": [
    ],
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "positionNumber": 0,
  • "positionEndReason": "EmployeeResigned",
  • "managerId": "b2c2c359-55f3-4680-a660-901475c7a693",
  • "appointmentType": "Permanent",
  • "employmentType": "Ordinary",
  • "maritimeWorker": {
    },
  • "tagLinks": [
    ],
  • "salaryInformation": [
    ],
  • "workArrangements": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Get position by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

query Parameters
embed
string

Comma-separated list of related entities to embed in the position response.

Available values: salaryInformation, workArrangements

By default, child entities are not included in GET responses. Use this parameter to request them.

Example: ?embed=salaryInformation,workArrangements

Responses

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "positionNumber": 0,
  • "positionEndReason": "EmployeeResigned",
  • "managerId": "b2c2c359-55f3-4680-a660-901475c7a693",
  • "appointmentType": "Permanent",
  • "employmentType": "Ordinary",
  • "maritimeWorker": {
    },
  • "tagLinks": [
    ],
  • "salaryInformation": [
    ],
  • "workArrangements": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Partially update a position

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

Request Body schema: application/json
required
etag
required
string

Opaque version identifier for optimistic concurrency control.

from
string <date>

Position start date (Startdato)

to
string or null <date>

Position end date (Sluttdato). Send null to clear an existing end date.

positionEndReason
string or null (positionEndReason)
Enum: "EmployeeResigned" "EmployerTerminated" "ContractEnded" "ShouldNeverHaveBeenReported" "OrganisationalChangeOrInternalJobSwap" "PayrollSystemOrAccountantChanged"

Reason the position ended (Sluttårsak). Maps to A-melding sluttaarsak. Required when an Ordinary or Maritime position has to >= 2020-01-01.


Monolith notes: Field "Position end reason" (51dbd5a3-b28b-4522-b2df-38fb1ad3c447).


managerId
string or null <uuid> (managerId)

Employee ID of direct manager (Narmeste leder)


Monolith notes: Field "Manager" (e82bbb69-937f-4f67-b667-0629bd6cf860).


appointmentType
string or null (appointmentType)
Enum: "Permanent" "Temporary" "PermanentHiredOut" "TemporaryHiredOut" "OncallStaff"

Type of appointment (Ansettelsesform). Required when employmentType is Ordinary or Maritime; must not be set otherwise.

  • Permanent: Permanent employment (Fast ansatt)
  • Temporary: Temporary employment (Midlertidig ansatt)
  • PermanentHiredOut: Permanent and hired out (Fast ansatt og utleid)
  • TemporaryHiredOut: Temporary and hired out (Midlertidig ansatt og utleid)
  • OncallStaff: On-call / substitute staff (Tilkallingsvikar)

Monolith notes: Field "Employment form" (c19fc3ca-b644-439c-9801-24691a7ebf39).


object or null

Maritime employment details. Send null to clear when ending the position or correcting historic data. (employmentType itself is immutable post-creation.)

tagLinks
Array of strings or null <uuid> [ items <uuid > ]

Tag identifiers to assign to this position. Replaces existing tag links entirely.

Responses

Request samples

Content type
application/json
{
  • "etag": "1",
  • "from": "2019-08-24",
  • "to": "2019-08-24",
  • "positionEndReason": "EmployeeResigned",
  • "managerId": "b2c2c359-55f3-4680-a660-901475c7a693",
  • "appointmentType": "Permanent",
  • "maritimeWorker": {
    },
  • "tagLinks": [
    ]
}

Response samples

Content type
application/json
{
  • "employeeId": "b0e78c8f-8c8b-4410-8293-9239e39d9e17",
  • "positionNumber": 0,
  • "positionEndReason": "EmployeeResigned",
  • "managerId": "b2c2c359-55f3-4680-a660-901475c7a693",
  • "appointmentType": "Permanent",
  • "employmentType": "Ordinary",
  • "maritimeWorker": {
    },
  • "tagLinks": [
    ],
  • "salaryInformation": [
    ],
  • "workArrangements": [
    ],
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

Delete a position

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

Flexible Timeline Behavior

Cost units use a flexible (loose) timeline:

  1. Gaps allowed — periods without any cost allocation are valid; allocation is optional for all position types.
  2. Overlaps allowed — multiple cost units of different dimensions can be active on the same date (e.g. Department + Project + Location running in parallel).
  3. Open-endedto is nullable; null means no set end date.
  4. Future-dated records are permitted.

Example

POST /tenants/{tenantId}/employees/{employeeId}/positions/{positionId}/cost-unit-links
Authorization: Bearer <token>
Content-Type: application/json

{
  "costUnitType": "Department",
  "costUnit": "100",
  "from": "2026-05-01"
}

An employee's position allocated to a department and a temporary project in parallel:

CostUnit 1: costUnitType: "Department", costUnit: "100",        from: 2025-01-01, to: null
CostUnit 2: costUnitType: "Project",    costUnit: "PRJ-2025-01", from: 2025-03-01, to: 2025-08-31

A successful request returns 201 Created with the full CostUnitLink resource, including the server-generated id, positionId, etag, and updatedAt.

Events

Event Trigger Consumers
costUnitLink.created New cost allocation added to a position Payroll, Accounting
costUnitLink.updated Existing cost allocation modified (e.g. to set) Payroll, Accounting
costUnitLink.deleted Cost allocation removed from a position Payroll, Accounting

Get cost unit link by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

costUnitLinkId
required
string <uuid>

Cost unit link unique identifier

Responses

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "costUnitType": "string",
  • "costUnit": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24",
  • "to": "2019-08-24"
}

MaritimeWorkers

Captures seafarer-specific details (maritimt arbeidsforhold) required by A-melding when a position represents maritime employment.

Maritime Worker is an embedded object on Position, not a standalone resource. It is created, updated, and deleted with its parent Position and has no endpoints of its own.

Timeline type: None — Maritime Worker follows the parent Position's lifecycle. If maritime details change, the Position must be ended and a new one created.

Property Type Required Description
shipRegister enum Conditional Ship register (Skipsregister): InternationalShipRegister, NorwegianInternationalShipRegister, or NorwegianShipRegister.
vesselType enum Conditional Type of vessel (Fartøytype): CruiseShip, DrillingPlatform, or Other.
shippingArea enum Conditional Shipping area (Fartsområde): Domestic or International.

The entire maritimeWorker object is required when employmentType is Maritime and must not be set for any other position type. When the object is present, all three fields must be supplied together.

Ship Register (Skipsregister)

Value Description
NorwegianShipRegister Norwegian Ship Register (Norsk Ordinært Skipsregister). Norwegian-flagged.
NorwegianInternationalShipRegister Norwegian International Ship Register. International shipping, tax relief.
InternationalShipRegister International ship register. Foreign-flagged vessels.

Vessel Type (Fartøytype)

Value Norwegian Description
CruiseShip Turistskip Cruise and passenger vessels.
DrillingPlatform Boreplattform Offshore drilling platforms and rigs.
Other Annet All other vessel classifications (cargo, tankers, supply, etc.).

Shipping Area (Fartsområde)

Value Description
Domestic Coastal and inland shipping within Norwegian territory.
International International trade and shipping routes.

The taxable seafarer's deduction (særskilt fradrag for sjøfolk) and A-melding reporting are performed by the payroll system, not this service. Employee Core only stores the maritime details so payroll and A-melding can consume them.

Key Validation Rules

  • maritimeWorker is required when employmentType is Maritime and prohibited for Ordinary, Freelancer, Pension, and PermanentlyAdaptedWork.
  • When maritimeWorker is present, all three fields (shipRegister, vesselType, shippingArea) must be supplied.
  • employmentType is immutable — switching a position to or from Maritime is not allowed; end the position and create a new one instead.
  • Each enum value must match the allowed set above.

shipRegister

  • Type: enum — NorwegianShipRegister | NorwegianInternationalShipRegister | InternationalShipRegister
  • Required: Conditional — required when employmentType is Maritime, prohibited otherwise

Indicates which national ship register the vessel is enrolled in. Determines downstream tax and social-security treatment in A-melding:

  • NorwegianShipRegister — standard Norwegian register; ships in domestic and international trade. Subject to full Norwegian labour regulations.
  • NorwegianInternationalShipRegister — international register with more flexible crew rules and tax advantages for shipowners; primarily cargo and specialised vessels.
  • InternationalShipRegister — foreign ship register; Norwegian tax treatment depends on flag state, tax treaties, and residency.

vesselType

  • Type: enum — CruiseShip | DrillingPlatform | Other
  • Required: Conditional — required when employmentType is Maritime, prohibited otherwise

Classification of the vessel the seafarer is assigned to. Drives tax-calculation rules applied by payroll (for example, cruise-ship and drilling-platform crews have distinct provisions).

shippingArea

  • Type: enum — Domestic | International
  • Required: Conditional — required when employmentType is Maritime, prohibited otherwise

Whether the vessel operates in domestic or international waters. Affects the employer's National Insurance contribution zone and which A-melding codes apply.

Example: Create Maritime Position

Maritime Worker is submitted as part of the parent Position create request. The service rejects the request if employmentType is Maritime and maritimeWorker is missing, or if maritimeWorker is supplied for any other position type.

POST /tenants/{tenantId}/employees/{employeeId}/positions
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "employmentType": "Maritime",
  "appointmentType": "Permanent",
  "maritimeWorker": {
    "shipRegister": "NorwegianInternationalShipRegister",
    "vesselType": "CruiseShip",
    "shippingArea": "International"
  },
  "salaryInformation": [
    {
      "from": "2026-05-01",
      "compensationMethod": "Period",
      "salaryBasis": "Monthly",
      "salary": "52000.00"
    }
  ],
  "workArrangements": [
    {
      "from": "2026-05-01",
      "occupationCode": "5120108",
      "setOfAccount": "White",
      "workTimeAgreementId": "RoundTheClockShift355",
      "workingHoursWeek": "35.50",
      "ftePercentage": "100.00"
    }
  ]
}

A successful request returns 201 Created with the full Position resource, including the embedded maritimeWorker block.

Events

Maritime Worker does not emit its own events. Changes are published as part of the parent Position's position.created and position.updated events.

Ship Register (Skipsregister)

Value Description
NorwegianShipRegister Norwegian Ship Register (Norsk Ordinært Skipsregister). Norwegian-flagged.
NorwegianInternationalShipRegister Norwegian International Ship Register. International shipping, tax relief.
InternationalShipRegister International ship register. Foreign-flagged vessels.

Vessel Type (Fartøytype)

Value Norwegian Description
CruiseShip Turistskip Cruise and passenger vessels.
DrillingPlatform Boreplattform Offshore drilling platforms and rigs.
Other Annet All other vessel classifications (cargo, tankers, supply, etc.).

Shipping Area (Fartsområde)

Value Description
Domestic Coastal and inland shipping within Norwegian territory.
International International trade and shipping routes.

The taxable seafarer's deduction (særskilt fradrag for sjøfolk) and A-melding reporting are performed by the payroll system, not this service. Employee Core only stores the maritime details so payroll and A-melding can consume them.

Key Validation Rules

  • maritimeWorker is required when employmentType is Maritime and prohibited for Ordinary, Freelancer, Pension, and PermanentlyAdaptedWork.
  • When maritimeWorker is present, all three fields (shipRegister, vesselType, shippingArea) must be supplied.
  • employmentType is immutable — switching a position to or from Maritime is not allowed; end the position and create a new one instead.
  • Each enum value must match the allowed set above.

shipRegister

  • Type: enum — NorwegianShipRegister | NorwegianInternationalShipRegister | InternationalShipRegister
  • Required: Conditional — required when employmentType is Maritime, prohibited otherwise

Indicates which national ship register the vessel is enrolled in. Determines downstream tax and social-security treatment in A-melding:

  • NorwegianShipRegister — standard Norwegian register; ships in domestic and international trade. Subject to full Norwegian labour regulations.
  • NorwegianInternationalShipRegister — international register with more flexible crew rules and tax advantages for shipowners; primarily cargo and specialised vessels.
  • InternationalShipRegister — foreign ship register; Norwegian tax treatment depends on flag state, tax treaties, and residency.

vesselType

  • Type: enum — CruiseShip | DrillingPlatform | Other
  • Required: Conditional — required when employmentType is Maritime, prohibited otherwise

Classification of the vessel the seafarer is assigned to. Drives tax-calculation rules applied by payroll (for example, cruise-ship and drilling-platform crews have distinct provisions).

shippingArea

  • Type: enum — Domestic | International
  • Required: Conditional — required when employmentType is Maritime, prohibited otherwise

Whether the vessel operates in domestic or international waters. Affects the employer's National Insurance contribution zone and which A-melding codes apply.

Example: Create Maritime Position

Maritime Worker is submitted as part of the parent Position create request. The service rejects the request if employmentType is Maritime and maritimeWorker is missing, or if maritimeWorker is supplied for any other position type.

POST /tenants/{tenantId}/employees/{employeeId}/positions
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "employmentType": "Maritime",
  "appointmentType": "Permanent",
  "maritimeWorker": {
    "shipRegister": "NorwegianInternationalShipRegister",
    "vesselType": "CruiseShip",
    "shippingArea": "International"
  },
  "salaryInformation": [
    {
      "from": "2026-05-01",
      "compensationMethod": "Period",
      "salaryBasis": "Monthly",
      "salary": "52000.00"
    }
  ],
  "workArrangements": [
    {
      "from": "2026-05-01",
      "occupationCode": "5120108",
      "setOfAccount": "White",
      "workTimeAgreementId": "RoundTheClockShift355",
      "workingHoursWeek": "35.50",
      "ftePercentage": "100.00"
    }
  ]
}

A successful request returns 201 Created with the full Position resource, including the embedded maritimeWorker block.

Events

Maritime Worker does not emit its own events. Changes are published as part of the parent Position's position.created and position.updated events.

PositionSicknessAndAbsence

Position-level sickness and absence configuration that tracks periods where the employer prepays NAV benefits on behalf of the employee, along with severance (redundancy) periods. Each period type is an independent array with effective date ranges, so history is preserved and can be filtered with asOfDate.

Chronic illness status (Kronisk syk) is not stored here — it lives on the employee-level sicknessAndAbsence object because it applies to the person, not the position.

Timeline type: Flexible — multiple periods per type allowed with gaps between them, but overlaps are not allowed within the same array. to may be open-ended.

Property Type Required Description
prepaidSicknessPeriods array No Periods when employer prepays NAV sick leave for this position.
prepaidSicknessPeriods[].id UUID Yes (read-only) Unique period identifier.
prepaidSicknessPeriods[].from date Yes Period effective from date.
prepaidSicknessPeriods[].to date No Period effective until date. null means ongoing.
prepaidOtherAbsencePeriods array No Periods when employer prepays other NAV benefits (parental, care, training).
prepaidOtherAbsencePeriods[].id UUID Yes (read-only) Unique period identifier.
prepaidOtherAbsencePeriods[].from date Yes Period effective from date.
prepaidOtherAbsencePeriods[].to date No Period effective until date. null means ongoing.
redundancyPeriods array No Redundancy / severance periods (Etterlønn) with a leave percentage.
redundancyPeriods[].id UUID Yes (read-only) Unique period identifier.
redundancyPeriods[].from date Yes Period effective from date.
redundancyPeriods[].to date No Period effective until date. null means ongoing.
redundancyPeriods[].leavePercentage string (decimal, 2 dp) Yes Leave percentage for the redundancy period. Range 0100.
lastModified datetime (read-only) Timestamp of the most recent modification across all period types. null when no periods exist.

Key Validation Rules

  • from is required on every period and must be a valid date.
  • to, when provided, must be on or after from.
  • Periods must not overlap within the same array. Gaps are allowed; a new period may start on the day after a previous period's to, but not on or before it.
  • redundancyPeriods[].leavePercentage is required and must be between 0 and 100 (inclusive).
  • Chronic illness periods are not accepted here — send chronicallyIllPeriods to the employee-level sickness-and-absence endpoint instead.
  • Use the asOfDate query parameter on GET to retrieve only periods active on a specific date (from <= asOfDate AND (to is null OR to >= asOfDate)).

prepaidSicknessPeriods

  • Type: array of period objects
  • Required: No

Multiple periods may be recorded to reflect changes over time; gaps are allowed, but the periods must not overlap.

PATCH semantics

  • Omitting prepaidSicknessPeriods from a PATCH request preserves the existing periods unchanged.
  • Providing an empty array ([]) clears all periods.
  • Providing a non-empty array fully replaces the existing periods.

prepaidOtherAbsencePeriods

  • Type: array of period objects
  • Required: No

Periods during which the employer prepays other NAV benefits on behalf of the employee. Typically covers parental leave, care days for sick children, care for seriously ill children, training benefits.

Same PATCH semantics and overlap rules as prepaidSicknessPeriods.

redundancyPeriods

  • Type: array of redundancy period objects
  • Required: No

Redundancy / severance arrangements for the position — for example redundancy, early retirement, or a negotiated termination. Each period carries a leavePercentage that drives A-melding reporting.

Deleting a redundancy period triggers a new A-melding submission for all periods within the affected timespan, because the reported redundancy percentage changes.

Same PATCH semantics and overlap rules as the prepaid arrays.

redundancyPeriods[].leavePercentage

  • Type: string (decimal, 2 decimal places)
  • Required: Yes
  • Range: 0100

Percentage of leave for the redundancy period. Transported as a string to preserve decimal precision; values like "75.50" are valid.

lastModified

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to any period on this object. Set by the service on every write. null when no periods have ever been recorded.

Example: Create Position with Sickness and Absence Periods

Position-level sickness and absence is not a stand-alone resource — it is created together with the position. The period arrays are accepted at the top level of the POST /positions body:

POST /tenants/{tenantId}/employees/{employeeId}/positions
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "employmentType": "Ordinary",
  "appointmentType": "Permanent",
  "salaryInformation": [
    { "from": "2026-05-01", "compensationMethod": "Period", "salaryBasis": "Monthly", "salary": "45000.00" }
  ],
  "workArrangements": [
    { "from": "2026-05-01", "occupationCode": "2512102", "setOfAccount": "White", "workTimeAgreementId": "NotShift", "workingHoursWeek": "37.50", "ftePercentage": "100.00" }
  ],
  "prepaidSicknessPeriods": [
    { "from": "2026-05-01" }
  ],
  "prepaidOtherAbsencePeriods": [
    { "from": "2026-05-01" }
  ],
  "redundancyPeriods": [
    { "from": "2026-06-01", "to": "2026-08-31", "leavePercentage": "75.50" }
  ]
}

A successful request returns 201 Created with the full Position resource. Each period in the response includes the server-generated id, and sicknessAndAbsence.lastModified is set to the creation timestamp.

To add, replace, or clear periods on an existing position afterwards, use PATCH /tenants/{tenantId}/employees/{employeeId}/positions/{positionId}/sickness-and-absence with a body in the shape of this schema (period arrays at the top level).

Events

Position-level sickness and absence is embedded in the Position resource and does not publish a dedicated event topic. Changes are surfaced through the Position's position.updated event; redundancy changes additionally trigger A-melding re-submission.

Event Trigger Consumers
position.updated Any period in prepaidSicknessPeriods, prepaidOtherAbsencePeriods, or redundancyPeriods changes Payroll, A-melding

Get sickness and absence periods for a position

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

Responses

Response samples

Content type
application/json
{
  • "prepaidSicknessPeriods": [
    ],
  • "prepaidOtherAbsencePeriods": [
    ],
  • "redundancyPeriods": [
    ],
  • "lastModified": "2019-08-24T14:15:22Z"
}

Update sickness and absence periods for a position

Partially replaces position-level sickness and absence periods. Only period types explicitly included in the request body are replaced; omitted types are preserved.

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

Request Body schema: application/json
required
Array of objects (SicknessAndAbsencePeriod)

Periods when employer prepays sick leave for this position (Forskutterer sykepenger). PATCH: omit to preserve existing; [] to clear; non-empty array to replace.


Monolith notes: Field "Prepaid sickness" (a39dbd0f-ee89-4f84-88fb-dd3963ec2433).


Array of objects (SicknessAndAbsencePeriod)

Periods when employer prepays other leave for this position (Forskutterer andre ytelser). PATCH: omit to preserve existing; [] to clear; non-empty array to replace.


Monolith notes: Field "Prepaid other absence" (2534dd2f-ff2e-41d9-aecc-b0bafa44acfb).


Array of objects (RedundancyPeriod)

Redundancy/severance periods for this position (Etterlonn). PATCH: omit to preserve existing; [] to clear; non-empty array to replace.


Monolith notes: Was on position, part of absence object as a decimal timeline. No single field GUID available.


Responses

Request samples

Content type
application/json
{
  • "prepaidSicknessPeriods": [
    ],
  • "prepaidOtherAbsencePeriods": [
    ],
  • "redundancyPeriods": [
    ]
}

Response samples

Content type
application/json
{
  • "prepaidSicknessPeriods": [
    ],
  • "prepaidOtherAbsencePeriods": [
    ],
  • "redundancyPeriods": [
    ],
  • "lastModified": "2019-08-24T14:15:22Z"
}

SalaryInformation

Salary and compensation configuration for a Position: compensation method, base salary amount, and company-configurable supplementary rates. Used by payroll for wage calculation and by A-melding reporting (avloenningstype, sisteLoennsendringsdato).

Salary amounts feed gross pay which is then distributed across payment destinations (creditor claims, union fees, additional accounts, salary account) during payroll processing. Deduction sequencing and A-melding mapping are owned by the payroll system, not this service — this entity only stores the compensation timeline and publishes events.

Parent entity: Position

Timeline type: Strict — no gaps, no overlaps; to is implicit (the day before the next record's from). The last record has no end date.

At least one record is required for Ordinary, Maritime, and Freelancer position types. For Pension positions, only rate4 is permitted; compensationMethod, salaryBasis, salary, and rate5rate9 must not be set.

Property Type Required Description
id UUID Yes (read-only) Unique record identifier. Server-generated on create (clients may optionally supply).
from date Yes Effective-from date. First record's from must equal the position's from.
to date (read-only) Computed end of validity — day before the next record's from. null when this is the latest record.
compensationMethod enum (Period/Hourly) Conditional How salary is paid (Avlønningstype). Required for Ordinary, Maritime. Optional for Freelancer, PermanentlyAdaptedWork. Prohibited for Pension.
salaryBasis enum (Hourly/Monthly/Yearly) Conditional Salary basis in employment contract (Kontraktstype lønn). Determines the unit of salary. Required for Ordinary, Maritime. Optional for Freelancer, PermanentlyAdaptedWork. Prohibited for Pension.
salary string (decimal, 2 places) Conditional Base salary amount (Grunnlønn) in units defined by salaryBasis. Required when compensationMethod is set. Prohibited for Pension.
rate4 string (decimal, 2 places) No Company-configurable supplementary rate 4 (Sats 4). Permitted for all position types, including Pension.
rate5 string (decimal, 2 places) No Company-configurable supplementary rate 5 (Sats 5). Prohibited for Pension.
rate6 string (decimal, 2 places) No Company-configurable supplementary rate 6 (Sats 6). Prohibited for Pension.
rate7 string (decimal, 2 places) No Company-configurable supplementary rate 7 (Sats 7). Prohibited for Pension.
rate8 string (decimal, 2 places) No Company-configurable supplementary rate 8 (Sats 8). Prohibited for Pension.
rate9 string (decimal, 2 places) No Company-configurable supplementary rate 9 (Sats 9). Prohibited for Pension.
etag string (read-only) Opaque version identifier for optimistic concurrency. Must be included in PATCH request bodies.
updatedAt datetime (read-only) Timestamp of last modification.

Benefit amount, deduction sequencing, and A-melding reporting are produced by the payroll system, not this service. This service only stores the salary timeline and publishes events.

Key Validation Rules

  • First record's from must equal the parent position's from; no gaps or overlaps across the timeline.
  • from must not be earlier than 1973-01-01.
  • compensationMethod + salaryBasis must be consistent: Period requires Monthly or Yearly; Hourly requires Hourly.
  • salary is required whenever compensationMethod is set; must be >= 0, 2 decimal places.
  • Pension positions may only set rate4; all other salary fields must be absent.
  • The last remaining salary record cannot be deleted for Ordinary, Maritime, and Freelancer positions.
  • etag must match the current version on updates.

id

  • Type: UUID
  • Required: Yes (read-only on response). Optional on create — if supplied, must be unique; otherwise a 409 Conflict is returned.

Unique identifier for the salary record. Generated by the service on create when not supplied by the client.

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date this salary configuration takes effect. The first record on a position must start on the same date as the position itself. Subsequent records must be strictly later than any existing record's from (strict timeline — no gaps, no overlaps). Must not be earlier than 1973-01-01. The most recent from across all records on a position feeds A-melding <sisteLoennsendringsdato>.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No (read-only)

Implicit end date — the day before the next record's from. null when this is the latest record on the position. Clients never supply to; timeline progression is managed by adding new records.

compensationMethod

  • Type: enum — Period | Hourly
  • Required: Conditional — required for Ordinary, Maritime; optional for Freelancer, PermanentlyAdaptedWork; prohibited for Pension

Must be consistent with salaryBasis: Period requires Monthly or Yearly; Hourly requires Hourly.

Value Norwegian A-melding mapping When to use
Period Fastlønn fastloenn / provisjon / akkord / honorar Fixed periodic salary. Payroll picks the fine-grained A-melding sub-code.
Hourly Timelønn timeloenn Paid per hour worked.

salaryBasis

  • Type: enum — Hourly | Monthly | Yearly
  • Required: Conditional — required for Ordinary, Maritime; optional for Freelancer, PermanentlyAdaptedWork; prohibited for Pension

Unit in which salary is expressed in the employment contract (Kontraktstype lønn). Drives how downstream consumers interpret the salary value — the service does not convert between units.

Value Norwegian salary represents
Hourly Timesats Per-hour rate.
Monthly Månedslønn Monthly salary at 100% position.
Yearly Årslønn Annual salary at 100% position.

salary

  • Type: string (decimal, 2 decimal places)
  • Required: Conditional — required whenever compensationMethod is set; prohibited for Pension

Base salary amount (Grunnlønn) expressed in the unit defined by salaryBasis. Must be >= 0. Maximum is type-dependent: 99,999,999.99 for Monthly, 1,199,999,999.88 for Yearly. Represented as a string to preserve precision beyond JavaScript's safe integer range.

rate4

  • Type: string (decimal, 2 decimal places)
  • Required: No — optional for all position types, including Pension

Company-configurable supplementary rate (Sats 4). The meaning is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Must be >= 0. rate4 is the only salary field permitted for Pension positions.

rate5rate9

  • Type: string (decimal, 2 decimal places) — same shape for each
  • Required: No — optional for Ordinary, Maritime, Freelancer, PermanentlyAdaptedWork; prohibited for Pension

Five additional company-configurable supplementary rates (Sats 5 – Sats 9). Like rate4, their business meaning is entirely up to the company's payroll configuration. Typical uses include overtime supplements, shift allowances, bonus rates, or other company-specific compensation components. Must be >= 0. Supplementary rates are not reported in A-melding.

etag

  • Type: string
  • Required: Yes

Opaque version identifier used for optimistic concurrency control. Returned by the service on every read and must be included in PATCH request bodies. A mismatched etag results in 409 Conflict.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Example: Create Salary Information

POST /tenants/{tenantId}/employees/{employeeId}/positions/{positionId}/salary-information
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "compensationMethod": "Period",
  "salaryBasis": "Monthly",
  "salary": "50000.00",
  "rate4": "375.00"
}

A successful request returns 201 Created with the full SalaryInformation resource, including the server-generated id, positionId, etag, and updatedAt. For hourly employees, set compensationMethod to Hourly, salaryBasis to Hourly, and salary to the per-hour rate (e.g. "250.00"). For Pension positions, omit compensationMethod, salaryBasis, and salary — only from and (optionally) rate4 are permitted. The first record on a position must use the position's from date.

Events

Event Trigger Consumers
salaryInformation.created New salary record added to a position Payroll
salaryInformation.updated Existing salary record modified Payroll
salaryInformation.deleted Salary record removed from a position Payroll

List salary information for a position

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create salary information entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

compensationMethod
required
string or null (compensationMethod)
Enum: "Period" "Hourly"

How salary is paid (Avlønningstype):

  • Period: Fixed periodic salary (Fastlønn)
  • Hourly: Paid per hour worked (Timelønn) Required for Ordinary, Maritime positions. Optional for Freelancer, VTA. Prohibited for Pension.

Monolith notes: Field "SalaryType" (117a92a4-992e-4d71-9b5e-ad690f526ae0). Renamed from: salaryType.


salaryBasis
required
string or null (salaryBasis)
Enum: "Hourly" "Monthly" "Yearly"

Salary basis in employment contract (Kontraktstype lønn). Determines the unit of salary:

  • Hourly: Hourly rate (Timesats) — salary contains the per-hour rate
  • Monthly: Monthly salary (Månedslønn) — salary contains the monthly salary at 100% position
  • Yearly: Annual salary (Årslønn) — salary contains the yearly salary at 100% position Required for Ordinary, Maritime positions. Optional for Freelancer, VTA. Prohibited for Pension.

Monolith notes: Field "ContractSalaryType" (43368bbd-e463-479d-8015-3351fff67272). Renamed from: contractSalaryType.


salary
string (salary)

Base salary amount (Grunnlønn) in units defined by salaryBasis. Required when compensationMethod is set. Must be >= 0. Max: 99,999,999.99 (Monthly), 1,199,999,999.88 (Yearly). 2 decimal places. Prohibited for Pension.


Monolith notes: Fields "MonthlySalary" (a7d2628e-e52f-491e-a1bb-1616595d5913), "HourlySalary" (f9d00ecd-ae37-42f0-8768-416570b29c2c), "YearlySalary" (1bf17d28-faf7-480b-ae86-0519396da64d). Which field is used depends on salaryBasis.


rate4
string (rate4)

Company-configurable supplementary rate 4 (Sats 4). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for all position types including Pension — this is the only salary field permitted for Pension positions. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate4" (efd20632-0c3d-45f3-a830-5c90fe50b600).


rate5
string (rate5)

Company-configurable supplementary rate 5 (Sats 5). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate5" (ff353df2-f569-48db-9437-1621793d0578).


rate6
string (rate6)

Company-configurable supplementary rate 6 (Sats 6). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate6" (61527c31-13c2-42b8-90d9-4c679b41506f).


rate7
string (rate7)

Company-configurable supplementary rate 7 (Sats 7). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate7" (517b603c-e71b-49b7-b87a-52e62f7e37a8).


rate8
string (rate8)

Company-configurable supplementary rate 8 (Sats 8). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate8" (3653b0fa-ee03-4e79-9938-66875ca6441f).


rate9
string (rate9)

Company-configurable supplementary rate 9 (Sats 9). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate9" (63bcdead-854b-4369-bcf2-99e0f4b31bea). New field in v2 (no legacy equivalent).


from
required
string <date>

Effective-from date for this timeline version.

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "compensationMethod": "Period",
  • "salaryBasis": "Hourly",
  • "salary": "string",
  • "rate4": "string",
  • "rate5": "string",
  • "rate6": "string",
  • "rate7": "string",
  • "rate8": "string",
  • "rate9": "string",
  • "from": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "compensationMethod": "Period",
  • "salaryBasis": "Hourly",
  • "salary": "string",
  • "rate4": "string",
  • "rate5": "string",
  • "rate6": "string",
  • "rate7": "string",
  • "rate8": "string",
  • "rate9": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Get salary information by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

salaryInformationId
required
string <uuid>

Salary information unique identifier

Responses

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "compensationMethod": "Period",
  • "salaryBasis": "Hourly",
  • "salary": "string",
  • "rate4": "string",
  • "rate5": "string",
  • "rate6": "string",
  • "rate7": "string",
  • "rate8": "string",
  • "rate9": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Partially update salary information

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

salaryInformationId
required
string <uuid>

Salary information unique identifier

Request Body schema: application/json
required
compensationMethod
string or null (compensationMethod)
Enum: "Period" "Hourly"

How salary is paid (Avlønningstype):

  • Period: Fixed periodic salary (Fastlønn)
  • Hourly: Paid per hour worked (Timelønn) Required for Ordinary, Maritime positions. Optional for Freelancer, VTA. Prohibited for Pension.

Monolith notes: Field "SalaryType" (117a92a4-992e-4d71-9b5e-ad690f526ae0). Renamed from: salaryType.


salaryBasis
string or null (salaryBasis)
Enum: "Hourly" "Monthly" "Yearly"

Salary basis in employment contract (Kontraktstype lønn). Determines the unit of salary:

  • Hourly: Hourly rate (Timesats) — salary contains the per-hour rate
  • Monthly: Monthly salary (Månedslønn) — salary contains the monthly salary at 100% position
  • Yearly: Annual salary (Årslønn) — salary contains the yearly salary at 100% position Required for Ordinary, Maritime positions. Optional for Freelancer, VTA. Prohibited for Pension.

Monolith notes: Field "ContractSalaryType" (43368bbd-e463-479d-8015-3351fff67272). Renamed from: contractSalaryType.


salary
string (salary)

Base salary amount (Grunnlønn) in units defined by salaryBasis. Required when compensationMethod is set. Must be >= 0. Max: 99,999,999.99 (Monthly), 1,199,999,999.88 (Yearly). 2 decimal places. Prohibited for Pension.


Monolith notes: Fields "MonthlySalary" (a7d2628e-e52f-491e-a1bb-1616595d5913), "HourlySalary" (f9d00ecd-ae37-42f0-8768-416570b29c2c), "YearlySalary" (1bf17d28-faf7-480b-ae86-0519396da64d). Which field is used depends on salaryBasis.


rate4
string (rate4)

Company-configurable supplementary rate 4 (Sats 4). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for all position types including Pension — this is the only salary field permitted for Pension positions. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate4" (efd20632-0c3d-45f3-a830-5c90fe50b600).


rate5
string (rate5)

Company-configurable supplementary rate 5 (Sats 5). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate5" (ff353df2-f569-48db-9437-1621793d0578).


rate6
string (rate6)

Company-configurable supplementary rate 6 (Sats 6). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate6" (61527c31-13c2-42b8-90d9-4c679b41506f).


rate7
string (rate7)

Company-configurable supplementary rate 7 (Sats 7). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate7" (517b603c-e71b-49b7-b87a-52e62f7e37a8).


rate8
string (rate8)

Company-configurable supplementary rate 8 (Sats 8). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate8" (3653b0fa-ee03-4e79-9938-66875ca6441f).


rate9
string (rate9)

Company-configurable supplementary rate 9 (Sats 9). The meaning of this rate is defined by the company's payroll configuration — the Employee Core Service stores the value without interpreting it. Optional for Ordinary, Maritime, Freelancer, VTA. Prohibited for Pension. Must be >= 0. 2 decimal places.


Monolith notes: Field "SalaryRate9" (63bcdead-854b-4369-bcf2-99e0f4b31bea). New field in v2 (no legacy equivalent).


etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

from
required
string <date>

Effective-from date for this timeline version.

Responses

Request samples

Content type
application/json
{
  • "compensationMethod": "Period",
  • "salaryBasis": "Hourly",
  • "salary": "string",
  • "rate4": "string",
  • "rate5": "string",
  • "rate6": "string",
  • "rate7": "string",
  • "rate8": "string",
  • "rate9": "string",
  • "etag": "1",
  • "from": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "compensationMethod": "Period",
  • "salaryBasis": "Hourly",
  • "salary": "string",
  • "rate4": "string",
  • "rate5": "string",
  • "rate6": "string",
  • "rate7": "string",
  • "rate8": "string",
  • "rate9": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Delete salary information entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

salaryInformationId
required
string <uuid>

Salary information unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

Strict Timeline Behaviour

Tax unit links use a strict timeline. See Timeline Types for comprehensive documentation.

  1. No gaps: records must be continuous from the position's start date.
  2. No overlaps: only one record active at any date.
  3. Calculated end: the to field is automatically the day before the next record's from.
  4. History preserved: all versions kept for audit.

Example: Office Transfer

Record 1: from: 2024-01-01, to: 2024-06-30, taxUnitId: "987654321" (Oslo)
Record 2: from: 2024-07-01, to: null,       taxUnitId: "876543210" (Bergen)

The employee transferred from Oslo to Bergen on 1 July. Record 1's to is automatically set to 2024-06-30. A new reportedPositionId is normally issued when the tax unit changes, per Skatteetaten's employment-ID guidance.

Norwegian Context

Sub-unit structure (Hovedenhet / Underenhet). Norwegian companies have one main unit (Hovedenhet, 9-digit org number) and one or more sub-units (Underenhet, each with its own 9-digit org number) — branches, departments, or locations. A-melding and employer's national insurance are reported per sub-unit.

Employer's national insurance (Arbeidsgiveravgift). The tax unit's location determines the applicable zone rate (Zone 1 — Oslo and major cities — 14.1 %; lower rates in Zones 2–5; 0 % for Svalbard). Correct tax unit assignment is therefore not just a reporting concern but a payroll-cost concern.

A-melding accuracy. Employees must be reported to the correct sub-unit so the municipal tax, employer-tax zone, and NAV Aa-register records stay accurate. When an employee transfers between offices belonging to different org numbers, create a new record with the transfer date as from.

Example: Create Tax Unit Link

POST /tenants/{tenantId}/employees/{employeeId}/positions/{positionId}/tax-unit-links
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "taxUnitId": "987654321",
  "reportedPositionId": "POS-2026-001"
}

A successful request returns 201 Created with the full TaxUnitLink resource, including the server-generated id, positionId, calculated to, etag, and updatedAt. For the very first record on a position, from must equal the position's own from.

Events

Event Trigger Consumers
taxUnitLink.created New tax unit link registered on a position Payroll, A-melding exporter
taxUnitLink.updated Existing link modified (e.g. reportedPositionId changed) Payroll, A-melding exporter
taxUnitLink.deleted Link removed from position Payroll, A-melding exporter

Get tax unit link by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

taxUnitLinkId
required
string <uuid>

Tax unit link unique identifier

Responses

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "taxUnitId": "string",
  • "reportedPositionId": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

WorkArrangements

Captures the working-time configuration of a Position: occupation code, worker classification, work time agreement, weekly full-time hours, and part-time factor. Used by payroll for wage calculation and by A-melding reporting (yrke, arbeidstidsordning, antallTimerPerUkeSomEnFullStillingTilsvarer, stillingsprosent).

Work time agreement master data (the company's catalogue of WTAs and their normal weekly hours) lives outside this entity. STYRK-08 occupation codes are maintained by Statistics Norway (SSB) and are out of scope here — this entity only stores the code reference chosen for the position.

Parent entity: Position

Timeline type: Strict — no gaps, no overlaps; to is implicit (the day before the next record's from). The last record has no end date.

At least one record is required for Ordinary, Maritime, and Freelancer position types. Work Arrangement is forbidden for Pension and PermanentlyAdaptedWork position types.

Property Type Required Description
id UUID Yes (read-only) Unique record identifier. Server-generated on create.
from date Yes Effective-from date of this record. Must equal the position's from for the first record.
to date No (read-only) Computed end of validity — day before the next record's from. null when this is the latest record.
occupationCode string Conditional 7-digit STYRK-08 occupation code (Yrkeskode).
setOfAccount enum (White/Blue/Other) No Worker category for payroll accounting (Kontosett).
personType enum (see below) No Special person type for tax purposes (Persontype).
workTimeAgreementId string Conditional Work time agreement code (Arbeidstidsavtale) referencing a WTA defined for the tenant/company.
workingHoursWeek string (decimal, up to 13.2) Conditional Normal weekly hours for the position (Antall timer per uke som en full stilling tilsvarer).
ftePercentage string (decimal, up to 13.2) Conditional Part-time percentage (Stillingsprosent); 100 means full-time. Range 0.00–100.00.
etag string Yes Opaque version identifier for optimistic concurrency. Must be included in PATCH request bodies.
updatedAt datetime (read-only) Timestamp of last modification.

Payroll calculations, A-melding reporting, and NAV Aa-register reporting are produced by the payroll system, not this service. This service only stores the work-arrangement timeline and publishes events.

Key Validation Rules

  • First record's from must equal the parent position's from; no gaps or overlaps across the timeline.
  • from must not be earlier than 1973-01-01.
  • occupationCode, when provided, must be a valid 7-digit STYRK-08 occupation code; required for Ordinary, Maritime, and Freelancer.
  • workTimeAgreementId and workingHoursWeek are required for Ordinary and Maritime; workTimeAgreementId is optional for Freelancer.
  • When workTimeAgreementId is set, workingHoursWeek must match the WTA's required normal weekly hours (see Work Time Agreement Codes).
  • ftePercentage must be in the range 0.00–100.00 and must be consistent with workingHoursWeek / normal weekly hours (±0.01 tolerance).
  • etag must match the current version on updates.

id

  • Type: UUID
  • Required: Yes (read-only)

Unique identifier for the work-arrangement record. Generated by the service on create; never supplied by clients.

from

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: Yes

Date this work arrangement takes effect. The first record on a position must start on the same date as the position itself. Subsequent records must be strictly later than any existing record's from (strict timeline — no gaps, no overlaps). Must not be earlier than 1973-01-01.

to

  • Type: date (ISO 8601, YYYY-MM-DD)
  • Required: No (read-only)

Implicit end date — the day before the next record's from. null when this is the latest record on the position. Clients never supply to; timeline progression is managed by adding new records.

occupationCode

  • Type: string (7-digit STYRK-08 code)
  • Required: Conditional — required for Ordinary, Maritime, Freelancer; prohibited for Pension, PermanentlyAdaptedWork

Occupation code (Yrkeskode) classifying the type of work performed. Must be a valid 7-digit code from Statistics Norway's STYRK-08 classification (based on ISCO-08). Reported to A-melding as <yrke>.

Level Digits Example Meaning
Major group 1 2 Professionals
Sub-major group 2 25 ICT professionals
Minor group 3 251 Software developers
Unit group (full) 7 2512102 Software developer

setOfAccount

  • Type: enum — White | Blue | Other
  • Required: No (optional for Ordinary, Maritime, Freelancer; prohibited for Pension, PermanentlyAdaptedWork)

Worker category for payroll accounting (Kontosett). Determines which payroll accounts wages and related costs are posted to, and can influence pension scheme and collective-agreement applicability.

Value Norwegian Description
White Funksjonar Office / administrative / salaried workers (white collar).
Blue Arbeider Manual / production / hourly workers (blue collar).
Other Annet Workers who do not fit the white/blue classification.

personType

  • Type: enum — see values below
  • Required: No (optional for Ordinary, Maritime, Freelancer; prohibited for Pension, PermanentlyAdaptedWork)

Special person type for tax purposes (Persontype). Identifies employees with special tax treatment such as commuters, expatriates, or offshore workers. Affects A-melding indirectly — payroll maps the value to reporting codes.

Value Norwegian Description
Commuter Pendler Norwegian resident commuting to workplace; may qualify for tax deductions.
CommuterForeign Utenlandsk pendler Foreign resident commuting to Norway; home abroad.
CommuterForeignTaxcard Utenlandsk pendler med skattekort Foreign commuter holding a Norwegian tax card without standard deduction.
ExpatNorway Utlending i Norge Foreign national on expatriate assignment in Norway.
Offshore Sokkelarbeider Worker on the Norwegian continental shelf; special tax-zone rules apply.

workTimeAgreementId

  • Type: string (WTA code defined for the tenant/company)
  • Required: Conditional — required for Ordinary, Maritime; optional for Freelancer; prohibited for Pension, PermanentlyAdaptedWork

Reference to the company's defined work time agreement (Arbeidstidsavtale). The selected WTA determines the required workingHoursWeek and drives the A-melding <arbeidstidsordning> mapping.

Work Time Agreement Codes

WTA Code Norwegian Required workingHoursWeek A-melding value
NotShift Ikke skift Per company settings (typically 37.5 or 40) ikkeSkift
offshore336 Offshore 33.6 offshore336
RoundTheClockShift355 Dognkontinuerlig skift og turnus 35.5 doegnkontinuerligSkiftOgTurnus355
ContinuousShift336 Helkontinuerlig skift og andre ordninger 33.6 helkontinuerligSkiftOgAndreOrdninger336
Shift365 Skift 36.5 skift365

For shift-based WTA types, the required normal weekly hours are fixed values defined by Norwegian working time regulations. For NotShift, normal hours are taken from the company's configured weekly hours (typically 37.5 or 40 for Norway).

workingHoursWeek

  • Type: string (decimal — up to 11 integer digits, up to 2 decimal places)
  • Required: Conditional — required for Ordinary, Maritime; optional for Freelancer; prohibited for Pension, PermanentlyAdaptedWork

Normal weekly hours that correspond to a 100% position (Antall timer per uke som en full stilling tilsvarer). For shift-based work time agreements, the value is fixed by the WTA (see Work Time Agreement Codes above). For NotShift, normal hours follow the company's configured weekly hours (typically 37.50 or 40.00 in Norway). Reported to A-melding as <antallTimerPerUkeSomEnFullStillingTilsvarer>.

ftePercentage

  • Type: string (decimal — up to 11 integer digits, up to 2 decimal places; effective range 0.00–100.00)
  • Required: Conditional — required for Ordinary, Maritime; optional for Freelancer; prohibited for Pension, PermanentlyAdaptedWork

Part-time percentage (Stillingsprosent) expressing the position as a fraction of full-time. 100 is full-time. When both workingHoursWeek and the applicable normal weekly hours are known, the value must be consistent with (workingHoursWeek / normalWeeklyHours) × 100 within a ±0.01 tolerance. Reported to A-melding as <stillingsprosent>.

etag

  • Type: string
  • Required: Yes

Opaque version identifier used for optimistic concurrency control. Returned by the service on every read and must be included in PATCH request bodies. A mismatched etag results in 409 Conflict.

updatedAt

  • Type: datetime (ISO 8601, UTC)
  • Required: Yes (read-only)

Timestamp of the last modification to the record. Set by the service on every write.

Example: Create Work Arrangement

POST /tenants/{tenantId}/employees/{employeeId}/positions/{positionId}/work-arrangements
Authorization: Bearer <token>
Content-Type: application/json

{
  "from": "2026-05-01",
  "occupationCode": "2512102",
  "setOfAccount": "White",
  "personType": "Commuter",
  "workTimeAgreementId": "NotShift",
  "workingHoursWeek": "37.50",
  "ftePercentage": "80.00"
}

A successful request returns 201 Created with the full WorkArrangement resource, including the server-generated id, positionId, etag, and updatedAt. Omit personType when the employee has no special tax status; the first record on a position must use the position's from date.

Events

Event Trigger Consumers
workArrangement.created New work-arrangement record added to a position Payroll
workArrangement.updated Existing work-arrangement record modified Payroll
workArrangement.deleted Work-arrangement record removed Payroll

List work arrangements for a position

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

query Parameters
asOfDate
string <date>

Filter timeline entities active as of this date

pageSize
integer [ 1 .. 1000 ]

Parameter indicates the number of results that the client would like to see in the response.

header Parameters
x-cursor
string or null

Pagination token used to query for the next part of a list.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create work arrangement entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

Request Body schema: application/json
required
id
string <uuid>

Optional client-provided identifier. If omitted, a server-generated UUID is assigned. If the ID already exists, a 409 Conflict is returned.

occupationCode
required
string or null (occupationCode)

Job title or occupation code (Stillingstittel/Yrkeskode)


Monolith notes: Field "Type of work" (f52a569c-6e1c-4cc8-a707-bac4b9905913). Renamed from: typeOfWork.


setOfAccount
required
string or null (setOfAccount)
Enum: "White" "Blue" "Other"

Worker category for payroll accounting:

  • White: Office/administrative workers (Funksjonar)
  • Blue: Manual/production workers (Arbeider)
  • Other: Other categories

Monolith notes: Field "Set of account" (6c6fe9f2-8582-4866-bd8e-0514a890f70f).


personType
required
string or null (personType)
Enum: "Commuter" "CommuterForeign" "CommuterForeignTaxcard" "ExpatNorway" "Offshore"

Special person type for tax purposes:

  • Commuter: Norwegian commuter (Pendler)
  • CommuterForeign: Foreign commuter with home abroad
  • CommuterForeignTaxcard: Foreign commuter with Norwegian tax card
  • ExpatNorway: Expatriate working in Norway
  • Offshore: Offshore/continental shelf worker

Monolith notes: Field "Persontype" (659a59f5-f70a-4567-bfd3-97f6cb6ad221). Renamed from: typeOfPerson.


workTimeAgreementId
required
string or null (workTimeAgreementId)

Work time agreement code (Arbeidstidsavtale)


Monolith notes: Outer container field "Work time agreement link position" (7f1210d2-37f2-4e9d-baac-518cf643cb50); value read from inner field "Work time agreement id" (2382efa5-524e-47c1-8e6f-ccc0ec97a1cf). Renamed from: workTimeAgreement.


workingHoursWeek
string <decimal-5-2> (workingHoursWeek) ^-?\d{1,3}(\.\d{1,2})?$

Weekly working hours for full-time (Arbeidstimer per uke)


Monolith notes: Field "Working hours a week" (df224c37-5efc-4b07-864a-12658cc478a2).


ftePercentage
string <decimal-13-2> (ftePercentage) ^-?\d{1,11}(\.\d{1,2})?$

Part-time percentage (Stillingsprosent) - 100 = 100%


Monolith notes: Field "Part-time factor" (71778e37-6f41-49e0-b094-c8cb721f9bb2). Renamed from: partTimeFactor.


from
required
string <date>

Effective-from date for this timeline version.

Responses

Request samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "occupationCode": "string",
  • "setOfAccount": "White",
  • "personType": "Commuter",
  • "workTimeAgreementId": "string",
  • "workingHoursWeek": "string",
  • "ftePercentage": "string",
  • "from": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "occupationCode": "string",
  • "setOfAccount": "White",
  • "personType": "Commuter",
  • "workTimeAgreementId": "string",
  • "workingHoursWeek": "string",
  • "ftePercentage": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Get work arrangement by ID

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

workArrangementId
required
string <uuid>

Work arrangement unique identifier

Responses

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "occupationCode": "string",
  • "setOfAccount": "White",
  • "personType": "Commuter",
  • "workTimeAgreementId": "string",
  • "workingHoursWeek": "string",
  • "ftePercentage": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Partially update work arrangement

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

workArrangementId
required
string <uuid>

Work arrangement unique identifier

Request Body schema: application/json
required
occupationCode
string or null (occupationCode)

Job title or occupation code (Stillingstittel/Yrkeskode)


Monolith notes: Field "Type of work" (f52a569c-6e1c-4cc8-a707-bac4b9905913). Renamed from: typeOfWork.


setOfAccount
string or null (setOfAccount)
Enum: "White" "Blue" "Other"

Worker category for payroll accounting:

  • White: Office/administrative workers (Funksjonar)
  • Blue: Manual/production workers (Arbeider)
  • Other: Other categories

Monolith notes: Field "Set of account" (6c6fe9f2-8582-4866-bd8e-0514a890f70f).


personType
string or null (personType)
Enum: "Commuter" "CommuterForeign" "CommuterForeignTaxcard" "ExpatNorway" "Offshore"

Special person type for tax purposes:

  • Commuter: Norwegian commuter (Pendler)
  • CommuterForeign: Foreign commuter with home abroad
  • CommuterForeignTaxcard: Foreign commuter with Norwegian tax card
  • ExpatNorway: Expatriate working in Norway
  • Offshore: Offshore/continental shelf worker

Monolith notes: Field "Persontype" (659a59f5-f70a-4567-bfd3-97f6cb6ad221). Renamed from: typeOfPerson.


workTimeAgreementId
string or null (workTimeAgreementId)

Work time agreement code (Arbeidstidsavtale)


Monolith notes: Outer container field "Work time agreement link position" (7f1210d2-37f2-4e9d-baac-518cf643cb50); value read from inner field "Work time agreement id" (2382efa5-524e-47c1-8e6f-ccc0ec97a1cf). Renamed from: workTimeAgreement.


workingHoursWeek
string <decimal-5-2> (workingHoursWeek) ^-?\d{1,3}(\.\d{1,2})?$

Weekly working hours for full-time (Arbeidstimer per uke)


Monolith notes: Field "Working hours a week" (df224c37-5efc-4b07-864a-12658cc478a2).


ftePercentage
string <decimal-13-2> (ftePercentage) ^-?\d{1,11}(\.\d{1,2})?$

Part-time percentage (Stillingsprosent) - 100 = 100%


Monolith notes: Field "Part-time factor" (71778e37-6f41-49e0-b094-c8cb721f9bb2). Renamed from: partTimeFactor.


etag
required
string

Opaque version identifier for optimistic concurrency control. Must be included in PATCH request body.

from
required
string <date>

Effective-from date for this timeline version.

Responses

Request samples

Content type
application/json
{
  • "occupationCode": "string",
  • "setOfAccount": "White",
  • "personType": "Commuter",
  • "workTimeAgreementId": "string",
  • "workingHoursWeek": "string",
  • "ftePercentage": "string",
  • "etag": "1",
  • "from": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "positionId": "da3402dc-13f8-45f9-83a6-bde06dd8eb35",
  • "occupationCode": "string",
  • "setOfAccount": "White",
  • "personType": "Commuter",
  • "workTimeAgreementId": "string",
  • "workingHoursWeek": "string",
  • "ftePercentage": "string",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "to": "2019-08-24",
  • "etag": "1",
  • "updatedAt": "2019-08-24T14:15:22Z",
  • "from": "2019-08-24"
}

Delete work arrangement entry

Authorizations:
BearerAuth
path Parameters
tenantId
required
string

Tenant identifier

employeeId
required
string <uuid>

Employee identifier (UUID). On the monolith data-source path this is the employmentId from the legacy HRM system — always use the id from the current list or get response rather than a previously cached value. The original employee public Guid is available via legacyIds[] when the request includes includeLegacyIds=true.

positionId
required
string <uuid>

Position unique identifier

workArrangementId
required
string <uuid>

Work arrangement unique identifier

query Parameters
etag
required
string
Example: etag=1

Opaque version identifier for optimistic concurrency control. Obtain from the most recent GET or PATCH response.

Responses

Response samples

Content type
application/json
{
  • "code": "VALIDATION_ERROR",
  • "group": "PrimaryValidation",
  • "message": "The request contains invalid data. See details for specific field errors.",
  • "target": "email",
  • "details": [
    ],
  • "innerError": {
    },
  • "correlationId": "0HNHLQAAPC0J6",
  • "etag": "2",
  • "resourceUpdatedAt": "2019-08-24T14:15:22Z"
}

Timeline Types

The Employee Core API uses different timeline models to manage historical data. Understanding these models is essential for correctly working with time-sensitive employee information.

Overview

Timeline Type Gaps Allowed Overlaps Allowed End Date Entities
Strict No No Calculated TaxInformation, SalaryInformation, WorkArrangement, TaxUnitLink
Flexible Yes Yes Explicit Position, CostUnitLink, AdditionalAccount, UnionLink, CarLink, CreditorClaim, TaxAndContributionRule, PensionLink, SicknessAndAbsence periods
None N/A N/A N/A Personal Information, Children, embedded objects (ContactDetails, PayrollSettings)

Strict Timeline

Strict timeline entities maintain a continuous history with no gaps or overlaps. Used for data that must always have exactly one active value.

Characteristics

  1. No gaps: Records must be continuous from the first entry
  2. No overlaps: Only one record can be active at any given date
  3. Calculated end date: The to field is automatically calculated as the day before the next record's from
  4. History preserved: All versions are kept for audit purposes

The to Field

The to field indicates when a record's validity period ends:

  • to is null: This is the most recent (current) record with no scheduled end
  • to has a date value: The record ends on that date (inclusive), and the next record begins on the following day

The to value is automatically calculated by the system and returned in API responses. You do not need to provide it when creating or updating records.

Creating Records

When you create a new strict timeline record:

Existing: from: 2024-01-01, to: null
New:      from: 2024-07-01

Result:
Record 1: from: 2024-01-01, to: 2024-06-30
Record 2: from: 2024-07-01, to: null

The system automatically sets the previous record's to to the day before the new record's from.

Inserting Records in the Middle

When you insert a record between existing records, all to values are recalculated:

Before:
Record 1: from: 2024-01-01, to: 2024-06-30
Record 2: from: 2024-07-01, to: null

Insert new record with from: 2024-04-01

After:
Record 1: from: 2024-01-01, to: 2024-03-31  (updated)
Record N: from: 2024-04-01, to: 2024-06-30  (new, calculated)
Record 2: from: 2024-07-01, to: null        (unchanged)

The system automatically adjusts the previous record's to to accommodate the new record.

Deleting Records

When you delete a strict timeline record, the previous record inherits the deleted record's to:

Before deletion:
Record 1: from: 2024-01-01, to: 2024-06-30
Record 2: from: 2024-07-01, to: 2024-12-31
Record 3: from: 2025-01-01, to: null

Delete Record 2:

After deletion:
Record 1: from: 2024-01-01, to: 2024-12-31  (inherited from deleted record)
Record 3: from: 2025-01-01, to: null

This maintains timeline continuity by extending the previous record to cover the period that was occupied by the deleted record.

Common Scenarios

Annual Updates (Tax Cards, Salaries)

When updating records at the start of a new year:

POST /tenants/{tenantId}/employees/{id}/tax-information
{
  "from": "2025-01-01",
  "table": "7150",
  "mainEmployer": true
}

The 2024 record automatically gets to: 2024-12-31.

Mid-year Salary Adjustment

When an employee receives a raise effective mid-year:

POST /tenants/{tenantId}/employees/{id}/positions/{positionId}/salary-information
{
  "from": "2024-06-15",
  "compensationMethod": "Period",
  "salaryBasis": "Monthly",
  "salary": "55000.00"
}

The previous record gets to: 2024-06-14, preserving the historical compensation.

Backdated Corrections

When you need to correct historical data by inserting a record in the past:

POST /tenants/{tenantId}/employees/{id}/salary-information
{
  "from": "2024-03-01",
  "compensationMethod": "Period",
  "salaryBasis": "Monthly",
  "salary": "52000.00"
}

The system recalculates all to values to maintain timeline integrity.

Example: Tax Information

POST /tenants/{tenantId}/employees/{id}/tax-information
{
  "from": "2024-01-01",
  "mainEmployer": true,
  "table": "7100"
}

POST /tenants/{tenantId}/employees/{id}/tax-information
{
  "from": "2024-06-15",
  "mainEmployer": true,
  "table": "7150"
}

Result: table 7100 until June 14 (to: 2024-06-14), table 7150 from June 15 (to: null).

Querying at a Date

To get the active record at a specific date, use the asOfDate query parameter:

GET /tenants/{tenantId}/employees/{id}/tax-information?asOfDate=2024-03-01

Returns the record where from <= 2024-03-01 and (to is null OR to >= 2024-03-01).

Important: If asOfDate is not provided, it defaults to today's date. This means queries without an explicit asOfDate will always return the currently active record.

Strict Timeline Entities

Entity Parent Norwegian
TaxInformation Employee Skatteopplysninger
SalaryInformation Position Lonnsinformasjon
WorkArrangement Position Arbeidstidsordning
TaxUnitLink Position Underenhet

Flexible Timeline

Flexible timeline entities allow gaps and overlaps. Used for data where multiple records can be active simultaneously or where there may be periods with no active records.

Characteristics

  1. Gaps allowed: Periods without any active record are valid
  2. Overlaps allowed: Multiple records can be active at the same time
  3. Explicit end date: to field must be set when known
  4. Independent records: Each record stands alone

Understanding to

The to field indicates when a record's validity period ends:

  • to is null: The record is open-ended with no scheduled end. There are no following timeline values—this is the current and ongoing state.
  • to has a date value: The record ends on that date (inclusive), and there may be a new value or a gap starting after the to date.

Tip: When processing timeline data, check if to is null to determine if this is the final/current record. A non-null to indicates the record has a defined end and you should look for subsequent records if needed.

Creating Records

Flexible timeline records are independent:

POST /tenants/{tenantId}/employees/{id}/positions
{
  "from": "2024-01-01",
  "employmentType": "Ordinary",
  "appointmentType": "Permanent"
}

POST /tenants/{tenantId}/employees/{id}/positions
{
  "from": "2024-06-01",
  "to": "2024-12-31",
  "employmentType": "Ordinary",
  "appointmentType": "Temporary"
}

Both positions exist independently. Position 2 overlaps with Position 1.

Ending Records

Explicit end date required:

PATCH /tenants/{tenantId}/employees/{id}/positions/{positionId}
{
  "to": "2024-12-31",
  "positionEndReason": "ContractEnded"
}

Example: Multiple Cost Units

An employee's salary split between departments:

POST /tenants/{tenantId}/employees/{id}/positions/{positionId}/cost-unit-links
{
  "from": "2024-01-01",
  "costUnitType": "Department",
  "costUnit": "100"
}

POST /tenants/{tenantId}/employees/{id}/positions/{positionId}/cost-unit-links
{
  "from": "2024-01-01",
  "costUnitType": "Department",
  "costUnit": "200"
}

Both active simultaneously - overlapping allocations.

Querying Active Records

To get all currently active records:

GET /tenants/{tenantId}/employees/{id}/positions?active=true

Returns records where from <= today AND (to is null OR to >= today).

To query records active at a specific date, use the asOfDate parameter:

GET /tenants/{tenantId}/employees/{id}/positions?asOfDate=2024-06-15

Important: If asOfDate is not provided, it defaults to today's date. This means queries without an explicit asOfDate will return records active as of today.

Flexible Timeline Entities

Entity Parent Norwegian
Position Employee Stilling
CostUnitLink Position Kostnadsfordeling
AdditionalAccount Employee Tilleggskonto
UnionLink Employee Fagforeningsmedlemskap
CarLink Employee Firmabil
CreditorClaim Employee Utleggstrekk
TaxAndContributionRule Employee Saerregler
PensionLink Employee Pensjonsleverandor

No Timeline

Entities without timeline management. Each entity instance is a current-state record.

Characteristics

  1. Single record: One current version per instance
  2. Direct updates: Changes modify existing record
  3. No history: Previous values not tracked
  4. Delete removes: Deleting removes the record entirely

Example: Children

POST /tenants/{tenantId}/employees/{id}/children
{
  "firstName": "Emma",
  "lastName": "Nordmann",
  "birthYear": "2018-05-15",
  "soleCustodyPeriods": [],
  "chronicallyIllPeriods": []
}

PATCH /tenants/{tenantId}/employees/{id}/children/{childId}
{
  "firstName": "Emma",
  "lastName": "Hansen"
}

The update modifies the existing record directly.

No Timeline Entities

Entity Norwegian
Children Barn

Embedded Objects

The following are embedded objects within Employee:

Object Norwegian Has Periods
ContactDetails Kontaktopplysninger No
PayrollSettings Lonnsinnstillinger No
SicknessAndAbsence Sykefravars- og fraversinnstillinger Yes (flexible)

Date Handling

Date Format

All dates use ISO 8601 format: YYYY-MM-DD

Examples:

  • 2024-01-15
  • 2024-12-31

Timezone

Dates are interpreted as Norwegian local dates (Europe/Oslo timezone).

Date Comparisons

  • Start date: Inclusive (record active from this date)
  • End date: Inclusive (record active through this date)

Example: from: 2024-01-01, to: 2024-01-31

  • Active on January 1: Yes
  • Active on January 31: Yes
  • Active on February 1: No

Common Patterns

Annual Updates

For entities that change annually (e.g., tax information, salary):

POST /tenants/{tenantId}/employees/{id}/tax-information
{
  "from": "2025-01-01",
  "table": "7150",
  "mainEmployer": true
}

The previous year's record automatically gets to set to 2024-12-31.

Temporary Assignments

For temporary roles or allocations:

POST /tenants/{tenantId}/employees/{id}/positions
{
  "from": "2024-03-01",
  "to": "2024-08-31",
  "employmentType": "Ordinary",
  "appointmentType": "Temporary",
  "positionEndReason": "ContractEnded"
}

Set both dates upfront for temporary arrangements.

Corrections

To correct a historical record (strict timeline):

  1. You typically cannot modify historical records directly
  2. Create a new record with the correct from
  3. This creates a new version from that date
  4. Consider impact on reporting for closed periods

Retroactive Changes

Handle retroactive changes carefully:

  1. Strict timeline: New record creates history from that date
  2. Flexible timeline: Can update existing record's dates
  3. Consider: Payroll/reporting implications for past periods

Best Practices

Strict Timeline

  • Always provide from
  • Let the system calculate to automatically
  • The to field is read-only and returned in API responses
  • Keep records immutable after creation
  • Use corrections for errors

Flexible Timeline

  • Set to when known
  • Review and end expired records
  • Monitor for overlapping records when not intended
  • Clean up completed temporary records

General

  • Use appropriate entity types for your use case
  • Understand timeline implications for reporting
  • Test date boundary conditions
  • Consider audit trail requirements