A-melding Submissions
A-melding (arbeidsgiver-melding) is the mandatory Norwegian employment and income report that employers must submit to Skatteetaten (the Norwegian Tax Administration) for each payroll period. The API allows you to preview, submit, and track a-melding submissions.
Submissions are created from posted payroll runs and sent to Skatteetaten via the Altinn/Maskinporten integration.
Endpoints
List Submissions
GET /api/v2/payroll/amelding-submissions
Retrieves a paginated list of a-melding submissions.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | Filter by client account |
| period_year | integer | No | Filter by year |
| period_month | integer | No | Filter by month (1–12) |
| status | string | No | Filter by status: DRAFT, SUBMITTED, ACCEPTED, REJECTED, or SEND_FAILED |
| page | integer | No | Page number (default: 1) |
| per_page | integer | No | Items per page (default: 100) |
Submissions are returned newest period first — period_year, period_month
and id are all sorted descending — so the current period’s newest attempt is
the first row and a replaced attempt follows it. The last row is the oldest.
Response
{
"data": [
{
"id": 1,
"created_by_id": 7,
"created_at": "2024-06-01T10:00:00Z",
"client_account_id": 7,
"period_year": 2024,
"period_month": 6,
"meldings_id": "m-1234567890",
"erstatter_meldings_id": null,
"status": "ACCEPTED",
"idempotency_key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": { },
"response": { },
"feedback": { },
"error_details": null,
"submitted_at": "2024-06-01T10:05:00Z",
"submitted_by_id": 7,
"dialog_id": null,
"transmission_id": null,
"dialogporten_dialog_id": null
}
],
"meta": {
"page": 1,
"pages": 1,
"per_page": 100,
"records": 1
}
}
Get Submission
GET /api/v2/payroll/amelding-submissions/{id}
Retrieves a specific a-melding submission by ID.
Response
Returns a single submission object (same shape as the list response items).
Preview Submission
POST /api/v2/payroll/amelding-submissions/preview
Generates a preview of the a-melding payload that would be sent to Skatteetaten, without actually submitting it. Use this to review the data before submitting.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | The client account ID |
| period_year | integer | Yes | The reporting year (2020–2100) |
| period_month | integer | Yes | The reporting month (1–12) |
Example Request
{
"client_account_id": 7,
"period_year": 2024,
"period_month": 6
}
Response
{
"payload": { },
"warnings": [
{
"contract_id": 42,
"business_partner_id": 56,
"employee_name": "Ola Nordmann",
"missing_fields": ["work_percentage", "last_salary_change_date"],
"invalid_fields": []
}
]
}
The payload object contains the full a-melding JSON structure that would be sent to Skatteetaten, including employee income details, tax deductions, and employer information.
warnings lists the ordinary employment contracts in the period that Skatteetaten
will flag with an immediate deviation (MAGNET_EDAG-291) even though it accepts the
submission. Each entry covers one contract:
| Field | Type | Description |
|---|---|---|
| contract_id | integer | The employment contract the warning is about |
| business_partner_id | integer | The employee |
| employee_name | string | The employee’s name, or #<business_partner_id> when the partner has no name |
| missing_fields | array | Contract fields required for an ordinary arbeidsforhold that are empty: occupation_code_lv, work_percentage, weekly_hours, work_time_arrangement_lv, employment_form, last_salary_change_date |
| invalid_fields | array | Contains occupation_code_lv when the occupation code is not in SSB’s current catalogue |
warnings is an empty array when nothing needs attention. Only contracts with
employment_type EMPLOYED and an employee with a personal number are checked —
employees without one are left out of the payload, so they raise no warning.
Submit A-melding
POST /api/v2/payroll/amelding-submissions
Prepares and submits an a-melding to Skatteetaten for a given payroll period. The submission is created, then immediately sent to Skatteetaten via the Altinn integration.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | The client account ID |
| period_year | integer | Yes | The reporting year (2020–2100) |
| period_month | integer | Yes | The reporting month (1–12) |
Example Request
{
"client_account_id": 7,
"period_year": 2024,
"period_month": 6
}
Response
Returns the created submission object with status SUBMITTED on success. A
submission that never reached Skatteetaten (authentication, network, or API
error) is still returned with 200 OK, but with status SEND_FAILED and the
reason in error_details — check status rather than the HTTP code.
{
"id": 1,
"created_by_id": 7,
"created_at": "2024-06-01T10:00:00Z",
"client_account_id": 7,
"period_year": 2024,
"period_month": 6,
"meldings_id": "m-1234567890",
"erstatter_meldings_id": null,
"status": "SUBMITTED",
"idempotency_key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": { },
"response": { },
"feedback": null,
"error_details": null,
"submitted_at": "2024-06-01T10:05:00Z",
"submitted_by_id": 7,
"dialog_id": "d-abcdef123456",
"transmission_id": "t-abcdef123456",
"dialogporten_dialog_id": null
}
Submission Flow
- The system prepares the a-melding payload from posted payroll runs for the specified period
- The payload is sent to Skatteetaten via the Altinn/Maskinporten integration
- On success, the status is set to
SUBMITTEDand background tasks are queued to sync feedback from Skatteetaten - If the send fails, the status is set to
SEND_FAILEDanderror_detailsrecords the upstream status code, message, and response body - If Skatteetaten already received a submission for the same period, the new submission replaces it:
erstatter_meldings_idreferences the latestSUBMITTEDorACCEPTEDattempt, skipping newer failed or rejected ones
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 (read-only) |
| period_year | integer | Reporting year (read-only) |
| period_month | integer | Reporting month, 1–12 (read-only) |
| meldings_id | string | Skatteetaten-assigned submission ID (read-only) |
| erstatter_meldings_id | string | ID of the previous submission this one replaces, if any (read-only) |
| status | string | Current status: DRAFT, SUBMITTED, ACCEPTED, REJECTED, or SEND_FAILED (read-only) |
| idempotency_key | string | UUID used for idempotent submission (read-only) |
| payload | object | The a-melding payload sent to Skatteetaten (read-only) |
| response | object | The response from Skatteetaten (read-only) |
| feedback | object | Feedback received from Skatteetaten after processing (read-only) |
| error_details | object | Details about the submission’s outcome (read-only). Set on failures, but also on an ACCEPTED submission that Skatteetaten flagged with non-blocking deviations — branch on status, never on error_details being non-null. Four shapes: a failed send carries status_code, message, and a truncated response_body; an a-melding that could not be built carries only message; A03 feedback carries mottakstatus (avvist, mottatt, or erstattet) and the avvik deviation list, on REJECTED and ACCEPTED rows; a finding from an uploaded A07 reconciliation report carries source, status, altinn_reference, and reconciled_at |
| submitted_at | datetime | When the submission was sent (read-only) |
| submitted_by_id | integer | ID of the user who submitted (read-only) |
| dialog_id | string | Dialogporten dialog ID for tracking (read-only) |
| transmission_id | string | Transmission ID from Altinn (read-only) |
| dialogporten_dialog_id | integer | Internal Dialogporten dialog reference (read-only) |
Submission Statuses
| Value | Description |
|---|---|
| DRAFT | Submission prepared but not yet sent to Skatteetaten |
| SUBMITTED | Sent to Skatteetaten, awaiting processing and feedback |
| ACCEPTED | Accepted by Skatteetaten. error_details may still be set, carrying the non-blocking avvik deviations Skatteetaten reported |
| REJECTED | Received by Skatteetaten and refused (A03 “avvist”) |
| SEND_FAILED | Never reached Skatteetaten — an authentication, network, or API error, or an a-melding that could not be built. Retryable. Only the scheduled submission task records the build-failure case; an interactive POST answers 400 instead (see Error Responses) |
Error Responses
| Status Code | Description |
|---|---|
| 400 | Invalid request (missing required fields, invalid year/month range) |
| 400 | payroll.amelding_invalid_contract_value — an employment contract holds a value the a-melding cannot report (an unmapped enum, or an arbeidstidsordning Skatteetaten does not know). POST and POST .../preview answer this instead of returning a submission |
| 403 | Forbidden (no access to client account). The list endpoint requires client_account_id — omitting it answers 403 for ordinary API callers |
| 404 | Submission not found |
Business Rules
- A-meldinger are built from posted payroll runs — you must have completed payroll runs for the period before submitting
period_yearmust be between 2020 and 2100, andperiod_monthmust be between 1 and 12- Submitting a new a-melding for a period Skatteetaten has already received creates a replacement (korrigert a-melding). Failed and rejected attempts are skipped when picking what to replace, so a retry after a
SEND_FAILEDdoes not replace anything - After successful submission, background tasks automatically sync feedback from Skatteetaten
- A
REJECTEDfinding never overrides anACCEPTEDsubmission — a late rejection for an a-melding that has since been accepted is logged and the status left alone - All fields on the submission are read-only — the system builds the payload automatically from payroll data
Related Resources
- Payroll Runs — the payroll data used to build the a-melding
- Payroll Reports — aggregated payroll report views
- Payroll Contracts — employment contracts
- NAV Forespørsler — NAV inquiries related to employees
- Integrations — Altinn and Maskinporten integration setup