Payroll Contracts API
Employment contracts represent the formal employment agreements between a company and its employees. Each contract captures salary details, working arrangements, pension configuration, and is used as the basis for payroll runs and A-melding reporting to Norwegian tax authorities.
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /payroll/contracts | List employment contracts |
| GET | /payroll/contracts/{id} | Get an employment contract |
| POST | /payroll/contracts | Create an employment contract |
| PUT | /payroll/contracts/{id} | Update an employment contract |
List Employment Contracts
GET /payroll/contracts
Retrieve a paginated list of employment contracts with filtering options.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | Filter by client account ID (must be from user’s eligible accounts) |
| business_partner_id | integer | No | Filter by employee (business partner) ID |
| is_active | boolean | No | Filter by active status |
| page | integer | No | Page number for pagination (default: 1) |
| per_page | integer | No | Number of items per page (default: 100) |
| with | string | No | Comma-separated list of relations to include |
Response
{
"data": [
{
"id": 1,
"business_partner_id": 56,
"client_account_id": 7,
"employment_type": "ORDINAERT",
"start_date": "2024-01-15",
"end_date": null,
"job_title": "Accountant",
"occupation_code": "2411",
"employment_form": "FAST",
"work_time_arrangement": "IKKE_SKIFT",
"work_percentage": "100.00",
"weekly_hours": "37.50",
"salary_type": "MONTHLY_FIXED",
"monthly_salary": "45000.000000",
"hourly_rate": null,
"vacation_pay_rate": "0.1200",
"pension_rate": "0.0200",
"employee_pension_rate": "0.0200",
"pension_provider_id": null,
"union_dues_amount": null,
"is_primary_employer": true,
"is_active": true,
"is_payroll_default": true,
"arbeidsforhold_id": "a1b2c3d4e5f6g7h8i9j0",
"created_by_id": 7,
"created_at": "2024-01-15T10:00:00Z"
}
],
"meta": {
"page": 1,
"pages": 1,
"per_page": 100,
"records": 1
}
}
Get Employment Contract
GET /payroll/contracts/{id}
Retrieve a single employment contract by ID.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | Contract ID |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| with | string | No | Comma-separated list of relations to include |
Create Employment Contract
POST /payroll/contracts
Creates a new employment contract. Automatically triggers a background task to fetch tax cards from Skatteetaten for the current tax year.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | The client account ID |
| business_partner_id | integer | Yes | The employee (business partner) ID |
| employment_type | string | Yes | Type of employment (max 50 characters) |
| start_date | date | Yes | Employment start date |
| salary_type | string | Yes | MONTHLY_FIXED or HOURLY |
| monthly_salary | decimal | Conditional | Required when salary_type is MONTHLY_FIXED |
| hourly_rate | decimal | Conditional | Required when salary_type is HOURLY |
| end_date | date | No | Employment end date |
| end_date_reason | string | No | Reason for end date (max 50 characters) |
| job_title | string | No | Job title (max 200 characters) |
| occupation_code | string | No | Occupation code per SSB standard (max 10 characters) |
| employment_form | string | No | Employment form (max 50 characters) |
| work_time_arrangement | string | No | Working hours arrangement (max 50 characters) |
| work_percentage | decimal | No | Work percentage (e.g. 100.00 for full-time) |
| weekly_hours | decimal | No | Weekly working hours |
| remuneration_type | string | No | Remuneration type (max 50 characters) |
| last_salary_change_date | date | No | Date of last salary change |
| last_work_pct_change_date | date | No | Date of last work percentage change |
| vacation_pay_rate | decimal | No | Vacation pay rate (e.g. 0.1200 for 12%) |
| pension_rate | decimal | No | Employer pension rate |
| employee_pension_rate | decimal | No | Employee pension rate |
| pension_provider_id | integer | No | Pension provider business partner ID |
| union_dues_amount | decimal | No | Monthly union dues amount |
| is_primary_employer | boolean | No | Whether this is the primary employer (default: true) |
| is_active | boolean | No | Whether the contract is active (default: true) |
| is_payroll_default | boolean | No | Whether this is the default contract for payroll (default: false) |
Example Request
{
"client_account_id": 7,
"business_partner_id": 56,
"employment_type": "ORDINAERT",
"start_date": "2024-01-15",
"salary_type": "MONTHLY_FIXED",
"monthly_salary": "45000.00",
"job_title": "Accountant",
"occupation_code": "2411",
"employment_form": "FAST",
"work_percentage": "100.00",
"weekly_hours": "37.50",
"vacation_pay_rate": "0.1200",
"pension_rate": "0.0200",
"is_primary_employer": true,
"is_payroll_default": true
}
Response
Returns the created employment contract with status 201 Created.
Update Employment Contract
PUT /payroll/contracts/{id}
Updates an existing employment contract. Only provided fields are updated.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | Contract ID |
Request Body
Same fields as create, except client_account_id and business_partner_id which cannot be changed after creation.
Side Effects
- Setting
is_activefromfalsetotruetriggers a background task to fetch tax cards. - Setting
is_activefromtruetofalsetriggers an A-melding submission to Skatteetaten with the end date.
Response
Returns the updated employment contract.
Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | Unique identifier (read-only) |
| business_partner_id | integer | Employee (business partner) ID |
| client_account_id | integer | Client account ID |
| employment_type | string | Type of employment |
| start_date | date | Employment start date |
| end_date | date | Employment end date (null if ongoing) |
| end_date_reason | string | Reason for end date |
| job_title | string | Job title |
| occupation_code | string | Occupation code per SSB standard |
| employment_form | string | Employment form |
| work_time_arrangement | string | Working hours arrangement |
| work_percentage | decimal | Work percentage (e.g. 100.00) |
| weekly_hours | decimal | Weekly working hours |
| remuneration_type | string | Remuneration type |
| salary_type | string | MONTHLY_FIXED or HOURLY |
| last_salary_change_date | date | Date of last salary change |
| last_work_pct_change_date | date | Date of last work percentage change |
| monthly_salary | decimal | Monthly salary amount |
| hourly_rate | decimal | Hourly rate amount |
| vacation_pay_rate | decimal | Vacation pay rate |
| pension_rate | decimal | Employer pension rate |
| employee_pension_rate | decimal | Employee pension rate |
| pension_provider_id | integer | Pension provider business partner ID |
| union_dues_amount | decimal | Monthly union dues amount |
| arbeidsforhold_id | string | Employment relationship ID (auto-generated UUID) |
| is_primary_employer | boolean | Whether this is the primary employer |
| is_active | boolean | Whether the contract is active |
| is_payroll_default | boolean | Whether this is the default contract for payroll |
| created_by_id | integer | ID of the creating user (read-only) |
| created_at | datetime | Creation timestamp (read-only) |
Relationships
The following related objects can be included using the with parameter:
business_partner- The employee associated with the contract
Validation Rules
business_partner_idis requiredclient_account_idis requiredemployment_typeis requiredstart_dateis requiredsalary_typemust beMONTHLY_FIXEDorHOURLY- When
salary_typeisMONTHLY_FIXED,monthly_salaryis required - When
salary_typeisHOURLY,hourly_rateis required
Error Responses
| Status Code | Description |
|---|---|
| 400 | Validation error (missing or invalid fields) |
| 403 | Forbidden (no access to client account) |
| 404 | Contract not found |