MVA (VAT) filing workflow
MVA (merverdiavgift, Norwegian VAT) filing through Apier runs in four steps: discover the company's MVA obligation, dry-run the submission to validate the payload without submitting, mint a single-use human-approved token, and submit. Obligation discovery and dry-run validation are available today; live submission is gated pending Maskinporten production validation and Altinn scope approval.
Jurisdiction: Norway · Verified against Skatteetaten as of 2026-05-25
Periods are terminer, not quarters
The MVA period identifier uses Norwegian MVA terminer in the form YYYY-Tn with n from 1 to 6 (e.g. 2026-T1) — six two-month terms per year, not calendar quarters.
Step 1 — discover the obligation
GET /api/v1/company/{org}/obligations returns the company's obligations; the MVA obligation's obligation_id identifies the MVA filing rule, alongside its evaluation_result and deadline. An evaluation_result of insufficient_data means the company has not delegated Altinn access to Apier — turnover-dependent MVA rules cannot be evaluated until it does.
Step 2 — dry-run the submission
Always dry-run first: POST /api/v1/actions/execute?dry_run=true with action_type mva_melding validates the payload against the action's preflight checks without submitting anything. A successful dry-run returns HTTP 200 with an outcome object; outcome.all_passed reports whether every preflight check passed. A 200 with all_passed false is still the success path — individual check verdicts are content, not transport errors.
Step 3 — approval token
Live submission requires a single-use, human-approved token minted via POST /api/v1/auth/approval-token with the org_number and the action_id being approved (e.g. mva_melding:<org>:<period>). The token is single-use and short-lived; an expired token is rejected with APPROVAL_TOKEN_EXPIRED.
Step 4 — submit (gated)
The live path requires both an Idempotency-Key header (so a network retry cannot double-submit) and an X-Approval-Token header (the human-in-the-loop gate). A successful response carries a signed receipt with the upstream altinn_receipt_id and a _meta.rulebook_version so the active rule version at submission time is auditable. Live submission is not yet enabled — the contract is published ahead of the gate lifting.
Use cases
- Discover whether and when a company must file MVA for a given termin
- Validate an MVA payload against preflight checks without submitting (dry-run)
- Prepare a human-in-the-loop approval flow for an eventual live submission
Requirements
- An API key with the read:actions scope
- The organisation number of the company to file for
- For the live path: a delegated Altinn system user carrying the skatteetaten:mva_melding/write scope (the canonical delegated scope validated for the mva_melding action; the tier baseline skatteetaten:mva is not sufficient)
- For the live path: an Idempotency-Key header and a fresh approval token per submission
Authentication
Method: api_key · Scopes: read:actions
Dry-run validation is served under read:actions with layered non-scope gates on the live path (approval token + idempotency key). Write scopes (act:*) are reserved and not assignable at v1.
Common errors
APPROVAL_TOKEN_REQUIRED
A live submission was attempted without a human-approved token.
Fix: Mint a token via POST /api/v1/auth/approval-token and pass it in the X-Approval-Token header promptly.
APPROVAL_TOKEN_EXPIRED
The approval token's short lifetime elapsed before submission.
Fix: Mint a fresh token and submit promptly — tokens are single-use and short-lived by design.
IDEMPOTENCY_KEY_REQUIRED
A write was attempted without an Idempotency-Key header.
Fix: Generate a unique key per logical submission and send it on every retry of that submission.
DEADLINE_PASSED
The obligation deadline for the period is in the past.
Fix: Escalate to a human — late filing has consequences the agent must not decide on alone.
Related topics
Related APIs
Capability ids — resolve each against the machine-readable manifest at /api/v1/capabilities for the endpoint, auth mode, and tier.
- company.obligations
- actions.execute_dry_run
- auth.approval_token
Related MCP tools
Registered tools on the Apier MCP server.
- get_company_obligations
- validate_action
- submit_vat_return
- explain_compliance_error