Payroll Runs
Payroll runs represent individual payroll processing cycles. Each run covers a specific period and contains payroll lines for each employee. Payroll runs are a subtype of Documents with document_type set to PRRUN.
Endpoints
List Payroll Runs
GET /api/v2/payroll-runs
Retrieves a paginated list of payroll runs.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | ID of the client account |
| from_date | date | No | Filter runs with period_start on or after this date |
| to_date | date | No | Filter runs with period_end on or before this date |
Response
{
"data": [
{
"id": 1,
"created_by_id": 7,
"created_at": "2024-03-15T10:00:00Z",
"client_account_id": 7,
"document_date": "2024-03-31",
"document_number": "3",
"period_start": "2024-03-01",
"period_end": "2024-03-31",
"uploaded_file_id": 456,
"is_draft": false,
"document_type": "PRRUN"
}
],
"meta": {
"page": 1,
"pages": 1,
"per_page": 100,
"records": 1
}
}
Create Payroll Run
POST /api/v2/payroll-runs
Creates a new payroll run. The run is created as a draft (is_draft: true).
When a run is created, the system automatically seeds it with employees from active employment contracts that have is_payroll_default set to true. For each default contract, a base earning line (fixed salary or hourly pay) is created, and any configured default payroll lines are also added. After seeding, derived amounts (tax withholding, employer costs, etc.) are automatically recalculated.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | The client account ID |
| document_date | date | No | Date of the payroll run |
| document_number | string | No | Run number (e.g. “3” for the third run of the year) |
| period_start | date | No | Start date of the payroll period |
| period_end | date | No | End date of the payroll period |
Example Request
{
"client_account_id": 7,
"document_date": "2024-03-31",
"document_number": "3",
"period_start": "2024-03-01",
"period_end": "2024-03-31"
}
Response
Returns the created payroll run with status 201 Created.
Update Payroll Run
POST /api/v2/payroll-runs/{id}
PUT /api/v2/payroll-runs/{id}
Updates an existing payroll run. Both POST and PUT methods are accepted.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| document_date | date | No | Date of the payroll run |
| document_number | string | No | Run number |
| period_start | date | No | Start date of the payroll period |
| period_end | date | No | End date of the payroll period |
Response
Returns the updated payroll run.
Delete Payroll Run
DELETE /api/v2/payroll-runs/{id}
Deletes a payroll run. Only draft runs can be deleted (is_draft must be true).
Response
Returns 204 No Content on success. Returns 400 Bad Request if the payroll run is not a draft.
Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | Unique identifier (read-only) |
| created_by_id | integer | ID of the creating user (read-only) |
| created_at | datetime | Creation timestamp (read-only) |
| client_account_id | integer | ID of the client account |
| document_date | date | Date of the payroll run |
| document_number | string | Run number within the year |
| period_start | date | Start date of the payroll period |
| period_end | date | End date of the payroll period |
| uploaded_file_id | integer | Associated voucher/file ID (read-only) |
| is_draft | boolean | Whether this is a draft run (read-only) |
| document_type | string | Always PRRUN (read-only) |
Relationships
The following related objects can be included using the with parameter:
payroll_lines- Employee payroll lines for this run
Payroll lines support nested relations using dot notation (e.g. with=payroll_lines.item_type):
payroll_lines.item_type- The payroll item type definitionpayroll_lines.business_partner- The employeepayroll_lines.contract- The employment contractpayroll_lines.tax_card- The employee’s tax cardpayroll_lines.garnishment- The linked garnishment
Payroll Line Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | Unique identifier (read-only) |
| created_by_id | integer | ID of the creating user (read-only) |
| created_at | datetime | Creation timestamp (read-only) |
| document_id | integer | Parent payroll run ID (read-only) |
| business_partner_id | integer | Employee ID |
| item_type_id | integer | Payroll item type ID |
| contract_id | integer | Employment contract ID |
| tax_card_id | integer | Employee tax card ID |
| garnishment_id | integer | Linked garnishment ID (read-only) |
| description | string | Line description |
| quantity | decimal | Quantity (e.g. hours worked) |
| rate | decimal | Rate (e.g. hourly rate) |
| amount | decimal | Calculated amount |
| currency_code | string | Currency code |
| sort_order | integer | Display order |
| relation_type | string | Type of related object (read-only) |
| relation_id | integer | ID of related object (read-only) |
Error Responses
| Status Code | Description |
|---|---|
| 400 | Invalid request (missing required fields) |
| 403 | Forbidden (no access to client account) |
| 404 | Payroll run not found |
Payroll Run Items
Payroll run items are the individual salary components (earnings, deductions, employer costs) within a payroll run. When items are added, updated, or deleted, the system automatically recalculates derived amounts (tax withholding, employer costs, etc.) for all employees in the run.
List Items
GET /api/v2/payroll/runs/{document_id}/items
Retrieves a paginated list of payroll line items for a specific run. The item_type relation is included by default.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | integer | No | Page number (default: 1) |
| per_page | integer | No | Items per page (default: 1000) |
| with | string | No | Include related resources (supported: item_type, business_partner, contract, tax_card, garnishment) |
Response
{
"data": [
{
"id": 501,
"created_by_id": 7,
"created_at": "2024-03-15T10:30:00Z",
"document_id": 1,
"business_partner_id": 56,
"item_type_id": 10,
"contract_id": 3,
"tax_card_id": 12,
"garnishment_id": null,
"description": "Fastlønn",
"quantity": "1.000000",
"rate": "45000.000000",
"amount": "45000.000000",
"currency_code": "NOK",
"sort_order": 1,
"relation_type": null,
"relation_id": null,
"item_type": {
"id": 10,
"code": "FIXED_SALARY",
"name_nob": "Fastlønn",
"category": "EARNING"
}
}
],
"meta": {
"page": 1,
"pages": 1,
"per_page": 1000,
"records": 1
}
}
Add Item
POST /api/v2/payroll/runs/{document_id}/items
Adds a new payroll line item to a draft run. If this is the first item for a given employee, their default payroll lines are automatically seeded. After adding, the system recalculates all derived amounts for the run.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| business_partner_id | integer | Yes | Employee ID |
| item_type_id | integer | Yes | Payroll item type ID |
| contract_id | integer | No | Employment contract ID |
| tax_card_id | integer | No | Employee tax card ID |
| description | string | No | Line description |
| quantity | decimal | No | Quantity (e.g. hours worked) |
| rate | decimal | No | Rate (e.g. hourly rate) |
| amount | decimal | No | Amount (auto-calculated if quantity and rate are set) |
| currency_code | string | No | Currency code (default: account currency) |
| sort_order | integer | No | Display order |
Example Request
{
"business_partner_id": 56,
"item_type_id": 10,
"contract_id": 3,
"description": "Fastlønn",
"quantity": "1",
"rate": "45000",
"amount": "45000"
}
Response
Returns the created item with status 201 Created.
Error Responses
| Status Code | Description |
|---|---|
| 400 | Cannot add items to a finalized (non-draft) document |
| 403 | Access denied to client account |
| 404 | Payroll document not found |
Update Item
POST /api/v2/payroll/runs/{document_id}/items/{item_id}
PUT /api/v2/payroll/runs/{document_id}/items/{item_id}
Updates an existing payroll line item. Both POST and PUT methods are accepted. After updating, the system recalculates all derived amounts for the run.
Request Body
Same fields as Add Item. Only provided fields are updated.
Response
Returns the updated item.
Error Responses
| Status Code | Description |
|---|---|
| 400 | Cannot edit items on a finalized document |
| 403 | Access denied to client account |
| 404 | Payroll document or line item not found |
Delete Item
DELETE /api/v2/payroll/runs/{document_id}/items/{item_id}
Removes a payroll line item from a draft run. After deletion, the system recalculates derived amounts. If the deleted item is a base earning (FIXED_SALARY or HOURLY_PAY), auto-recalculation skips regenerating that employee’s base earning to avoid re-seeding it.
Response
Returns 204 No Content on success.
Error Responses
| Status Code | Description |
|---|---|
| 400 | Cannot delete items from a finalized document |
| 403 | Access denied to client account |
| 404 | Payroll document or line item not found |
Posting and Reversal
Once a payroll run’s items are finalized, it can be posted to the general ledger. Posting creates journal entries with employee dimensions and generates a PDF voucher. If the earning period and payment date fall in different calendar months, periodization (accrual and reversal) entries are automatically generated.
Preview Posting
GET /api/v2/payroll/runs/{document_id}/posting-preview
Returns a preview of the journal entry that would be created when posting, without persisting anything. Useful for reviewing before committing. The response follows the same shape as GET /api/v2/journal-entries/{id} with lines and dimensions included, plus an account_name field on each line.
Example Response
{
"id": null,
"client_account_id": 7,
"memo": "Lønnskjøring 3",
"lines": [
{
"line_id": 1,
"posting_date": "2024-03-31",
"account_code": "5000",
"account_name": "Lønn til ansatte",
"currency_code": "NOK",
"debit": "45000.000000",
"credit": "0.000000",
"description": "",
"dimensions": [
{
"relation_type": "BusinessPartner",
"relation_id": 56
}
]
},
{
"line_id": 2,
"posting_date": "2024-03-31",
"account_code": "2610",
"account_name": "Skattetrekk",
"currency_code": "NOK",
"debit": "0.000000",
"credit": "15300.000000",
"description": "",
"dimensions": []
}
]
}
Post Payroll Run
POST /api/v2/payroll/runs/{document_id}/post
Creates journal entries from the payroll document, generates a PDF voucher, and marks the run as finalized (is_draft becomes false). Also triggers automatic payslip email delivery and A-melding submission for the period.
Response
{
"document_id": 1,
"journal_entry_id": 42
}
Error Responses
| Status Code | Description |
|---|---|
| 400 | Document has already been posted, or has no items to post |
| 403 | Access denied to client account |
| 404 | Payroll document not found |
Reverse Payroll Run
POST /api/v2/payroll/runs/{document_id}/reverse
Reverses a posted payroll document’s journal entry and returns the run to draft status (is_draft becomes true), allowing items to be edited again.
Response
{
"document_id": 1,
"reversal_journal_entry_id": 43
}
Error Responses
| Status Code | Description |
|---|---|
| 400 | Cannot reverse a draft document, or no journal entry found |
| 403 | Access denied to client account |
| 404 | Payroll document not found |
Payslips
Generate and distribute payslips for employees in a payroll run.
List Payslips
GET /api/v2/payroll/runs/{document_id}/payslips
Returns payslip summaries for all employees in the payroll run.
Response
{
"payslips": [
{
"employee_id": 56,
"employee_name": "Ola Nordmann",
"total_gross": "45000.000000",
"total_deductions": "15300.000000",
"net_pay": "29700.000000",
"total_employer_costs": "6345.000000"
}
]
}
Download Payslip PDF
GET /api/v2/payroll/runs/{document_id}/payslips/{bp_id}/pdf
Downloads a single employee’s payslip as a PDF file.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| document_id | integer | Payroll run document ID |
| bp_id | integer | Employee business partner ID |
Response
Returns a PDF file with Content-Type: application/pdf and Content-Disposition: attachment headers. The filename follows the pattern lonnsslipp_{period_from}_{period_to}_{bp_id}.pdf.
Error Responses
| Status Code | Description |
|---|---|
| 403 | Access denied to client account |
| 404 | Payroll document not found, or no payslip found for this employee |
Send Payslips
POST /api/v2/payroll/runs/{document_id}/payslips/send
Queues payslip emails for all employees in the payroll run. Emails are sent asynchronously. Employees without an email address on file are skipped.
Response
{
"message": "Payslip emails queued for delivery"
}
Returns status 202 Accepted.
Error Responses
| Status Code | Description |
|---|---|
| 400 | Cannot send payslips for a draft document |
| 403 | Access denied to client account |
| 404 | Payroll document not found |