Menu

Owner tax

Bolaget: the K10 underlag per owner and income year (3:12 rules from 2026, each figure with its source), loans between the company and its owners, board, VD and related persons with the loan prohibition check (ABL 21 kap.) and the ledger reconciliation, and the KU20 status for interest paid to them. Nothing books. The KU20 file is downloaded in Accounted only.

Endpoints


GET /api/v1/companies/:companyId/k10/:year

k10.get · scope payroll:read

Read the K10 underlag per delägare for an inkomstår: gränsbelopp, lönebaserat utrymme, dividend and sparat utdelningsutrymme.

For every natural-person holder: shares at the start of the year (aktiebok), the grundbelopp (4 IBB split per share), the lönebaserat utrymme from the payroll's cash pay the year before (50 % of the owner's share above 8 IBB, at most 50 times their own pay), interest on the omkostnadsbelopp above 100 000 kr, the dividend received, and what is carried forward. Each line names its source. The 3:12 rules after SFS 2025:1361; inkomstår 2026 onward.

Use when: An owner asks how much dividend is taxed at 20 %, or prepares K10.

Don't use for: Deciding a dividend (POST /dividends) or the company's own tax (INK2).

Pitfalls

  • The owner files K10; this is the underlag. Figures the books do not hold (sparat utdelningsutrymme, an omkostnadsbelopp from before the aktiebok) are entered with PUT /k10/{year}/owners/{party_id}.
  • supported false: the year's inkomstbasbelopp or statslåneränta is not in Accounted yet, or the year is before the 2026 rules.

Risk: low · Idempotent: yes · Reversible: no · Dry-run supported: no

Response fields

NameTypeDescription
income_yearnumber
supportedboolean
supported_yearsnumber[]
unsupported_reason_svstring | null
start_datestringThe aktiebok day the holdings are read on: 31 December the year before.
famansforetagobject
total_shares_at_startnumber
payrollobject
ownersobject[]
company_holdersobject[]

Example response

{
  "data": {
    "income_year": 2026,
    "supported": true,
    "owners": [
      {
        "party_id": "9c1e…",
        "name": "Anna Ek",
        "result": {
          "total_limit": 750000,
          "saved_space_carried_forward": 650000
        }
      }
    ]
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}

GET /api/v1/companies/:companyId/ku20/:year

ku20.status.get · scope companies:read

Read the KU20 status of an inkomstår: interest the company paid to natural persons on their loans, the tax withheld, and what blocks the file.

Per recipient the year's interest (field 503) and tax withheld (field 001) in whole kronor, whether field 061 is marked, the 30 % a fåmansföretag withholds on interest to a delägare, and the blockers. The file itself is downloaded in Accounted by an owner or administrator: it carries personnummer.

Use when: Before 31 January, to see whether KU20 for last year can be filed.

Don't use for: Getting the file: there is no machine door for it. KU31 (GET /ku31/{year}) for dividends.

Pitfalls

  • KU20_NO_RECIPIENTS: enter the year's interest per loan first (POST /owner-loans/{id}/interest).

Risk: low · Idempotent: yes · Reversible: no · Dry-run supported: no

Response fields

NameTypeDescription
income_yearnumber
deadlinestring
file_supportedboolean
famansforetagobjectWhether the company is a fåmansföretag in the year: the answer confirmed for KU31, else what the aktiebok suggests.
recipientsobject[]
legal_person_interestnumber
contactobject
blockersobject[]
warningsobject[]
readyboolean

Example response

{
  "data": {
    "income_year": 2026,
    "deadline": "2027-01-31",
    "ready": false,
    "blockers": [
      {
        "code": "KU20_CONTACT_MISSING",
        "message_sv": "Ange kontaktperson…"
      }
    ]
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}

GET /api/v1/companies/:companyId/owner-loans

owner-loans.get · scope companies:read

Read the owner loan register: loans and security between the company and its owners, board, VD and related persons, with the låneförbud check and the ledger reconciliation.

Every loan with its counterparty (name and masked identity), direction, BAS account, principal and outstanding, terms, the ABL 21 kap. assessment (in the circle, the exception, whether it goes on the 21:10 special list) and the interest per year; and per account, the register against the ledger balance on as_of. Read-only.

Use when: Before booking a payment to or from an owner, at year end, or when asked whether a loan to an owner is allowed.

Don't use for: Aktieägartillskott (GET /capital-events) or ordinary supplier debts.

Pitfalls

  • loan_ban.status prohibited is a warning: the check cannot see every relation; the person decides.
  • A reconciliation difference means the register or the ledger needs an update; nothing is corrected automatically.

Risk: low · Idempotent: yes · Reversible: no · Dry-run supported: no

Query parameters

NameTypeRequiredDescription
as_ofstring | nullnoThe day to reconcile on (YYYY-MM-DD); today when omitted.

Response fields

NameType
as_ofstring
loansobject[]
reconciliationobject[]
flaggednumber

Example response

{
  "data": {
    "as_of": "2026-12-31",
    "loans": [
      {
        "owner_loan_id": "2f4a…",
        "direction": "borrows",
        "account": "2893",
        "outstanding": 200000
      }
    ],
    "reconciliation": [
      {
        "account": "2893",
        "register_amount": 200000,
        "ledger_amount": 200000,
        "matches": true
      }
    ],
    "flagged": 0
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}

POST /api/v1/companies/:companyId/owner-loans

owner-loans.create · scope companies:write

Register a loan between the company and an owner, board member, VD or related person, or security the company gave for one; checked against the låneförbud (ABL 21 kap.).

Records the counterparty, direction, BAS account (1685 or 2893 when omitted), principal, interest, terms and the exception claimed. A loan from the company to someone in the ABL 21:1 circle without an exception is warned about (LOAN_BAN_PROHIBITED), never refused. Nothing is booked: the payout is booked as any verifikat. Dry-runnable.

Use when: An owner lends money to the company, or the company lends to or guarantees for an insider.

Don't use for: Aktieägartillskott (POST /shareholder-contributions) or dividends.

Pitfalls

  • OWNER_LOAN_ACCOUNT_INVALID: a loan the company gives sits on 1360-1368 or 1680-1689, one it takes on 2390-2399 or 2890-2899.
  • A personnummer is never sent: name a new person, and the personnummer is added in Accounted.

Risk: medium · Idempotent: yes · Reversible: no · Dry-run supported: yes · Stage for approval: yes (?stage=true)

Query parameters

NameTypeRequiredDescription
dry_runstringnotrue (any case) previews the write without committing it, like the X-Dry-Run: true header. Any other value commits.
stagestringnotrue stages the write for approval instead of committing it: 202 with the pending operation to approve via POST /pending-operations/{id}/approve. Absent or false commits; other values are 400. A reason in the body (why you propose it, at most 500 characters) is shown to the approver as agent_reason and kept with the decision.

Request body

NameTypeRequiredDescription
party_idstring | nullnoThe counterparty (from gnubok_get_share_register or the roles).
party_namestring | nullnoOr the counterparty's name, when new.
party_kind"person" | "company" | nullno
party_org_numberstring | nullnoA company counterparty's org number. Never a personnummer.
kind"loan" | "security" | nullnoloan (default), or security the company gave for the party's debt (ABL 21:3).
direction"lends" | "borrows"yeslends: the company lends to the party; borrows: the party lends to the company.
relation"none" | "group_insider" | "related_person" | "controlled_entity" | nullnoWhat the registers cannot tell: group_insider, related_person or controlled_entity (with related_to_party_id). Default none.
related_to_party_idstring | nullnoThe holder, board member or VD a related person or controlled entity goes through.
relation_detailstring | nullnoE.g. make, sambo, barn.
accountstring | nullnoBAS account: 1360-1368 or 1680-1689 (the company lends), 2390-2399 or 2890-2899 (it borrows). Default 1685 or 2893.
principalnumberyesThe amount lent or secured, SEK.
outstandingnumber | nullnoStill owed; the principal when omitted.
interest_ratenumber | nullnoYearly interest in percent, e.g. 4.5.
start_datestringyesThe day the loan was paid out or the security given (YYYY-MM-DD).
maturity_datestring | nullno
termsstring | nullnoThe main terms: repayment, security, notice.
document_idstring | nullnoThe loan agreement in the archive.
exception"none" | "group_company" | "business_loan" | "dispensation" | nullnoThe låneförbud exception the loan is granted under: group_company, business_loan or dispensation.
exception_notestring | nullnoWhy the exception applies (e.g. Skatteverket's decision).
notestring | nullno

Response fields

NameType
owner_loan_idstring
party_idstring
kind"loan" | "security"
direction"lends" | "borrows"
accountstring | null
principalnumber
outstandingnumber
loan_banobject

Example request

{
  "party_id": "9c1e…",
  "direction": "borrows",
  "principal": 200000,
  "interest_rate": 5,
  "start_date": "2026-03-01"
}

Example response

{
  "data": {
    "owner_loan_id": "2f4a…",
    "party_id": "9c1e…",
    "kind": "loan",
    "direction": "borrows",
    "account": "2893",
    "principal": 200000,
    "outstanding": 200000,
    "loan_ban": {
      "status": "not_applicable",
      "exception": null,
      "special_list": false
    }
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}

POST /api/v1/companies/:companyId/owner-loans/:id/interest

owner-loans.set-interest · scope companies:write

Record the interest on an owner loan for an inkomstår and the tax withheld: the figures KU20 reports.

Upserts the year's interest paid (company borrows) or received (company lends) and the preliminary tax withheld. Warns when a fåmansföretag did not withhold 30 % on interest to a delägare (SFL 10:15). Nothing is booked. Dry-runnable.

Use when: At year end, before KU20, or when the interest was paid.

Don't use for: Booking the interest (a verifikat on 8400-8499 or 8300-8399).

Pitfalls

  • The tax withheld cannot exceed the interest.

Risk: low · Idempotent: yes · Reversible: yes · Dry-run supported: yes · Stage for approval: yes (?stage=true)

Query parameters

NameTypeRequiredDescription
dry_runstringnotrue (any case) previews the write without committing it, like the X-Dry-Run: true header. Any other value commits.
stagestringnotrue stages the write for approval instead of committing it: 202 with the pending operation to approve via POST /pending-operations/{id}/approve. Absent or false commits; other values are 400. A reason in the body (why you propose it, at most 500 characters) is shown to the approver as agent_reason and kept with the decision.

Request body

NameTypeRequiredDescription
income_yearnumberyes
interest_amountnumberyesInterest paid (or received) on the loan in the year, SEK.
tax_withheldnumber | nullnoPreliminary tax withheld on interest the company paid (KU20 field 001).
notestring | nullno

Response fields

NameType
owner_loan_idstring
income_yearnumber
interest_amountnumber
tax_withheldnumber

Example request

{
  "owner_loan_id": "2f4a…",
  "income_year": 2026,
  "interest_amount": 8000,
  "tax_withheld": 2400
}

Example response

{
  "data": {
    "owner_loan_id": "2f4a…",
    "income_year": 2026,
    "interest_amount": 8000,
    "tax_withheld": 2400
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}

PATCH /api/v1/companies/:companyId/owner-loans/:id

owner-loans.update · scope companies:write

Update an owner loan: outstanding after a repayment, terms, the exception claimed, or mark it repaid or cancelled.

Changes only what is sent (null clears a field). Status repaid needs repaid_on and sets outstanding to 0; cancelled is for a loan registered by mistake and is final. The låneförbud check runs again and warns. Nothing is booked. Dry-runnable.

Use when: An owner loan was partly or fully repaid, or its terms changed.

Don't use for: The year's interest (POST /owner-loans/{id}/interest).

Pitfalls

  • OWNER_LOAN_STATUS_INVALID: a cancelled loan does not change.

Risk: medium · Idempotent: yes · Reversible: no · Dry-run supported: yes · Stage for approval: yes (?stage=true)

Query parameters

NameTypeRequiredDescription
dry_runstringnotrue (any case) previews the write without committing it, like the X-Dry-Run: true header. Any other value commits.
stagestringnotrue stages the write for approval instead of committing it: 202 with the pending operation to approve via POST /pending-operations/{id}/approve. Absent or false commits; other values are 400. A reason in the body (why you propose it, at most 500 characters) is shown to the approver as agent_reason and kept with the decision.

Request body

NameTypeRequiredDescription
relation"none" | "group_insider" | "related_person" | "controlled_entity" | nullno
related_to_party_idstring | nullno
relation_detailstring | nullno
accountstring | nullnoBAS account: 1360-1368 or 1680-1689 (the company lends), 2390-2399 or 2890-2899 (it borrows). Default 1685 or 2893.
principalnumber | nullno
outstandingnumber | nullnoStill owed after a repayment.
interest_ratenumber | nullnoYearly interest in percent, e.g. 4.5.
maturity_datestring | nullno
termsstring | nullno
document_idstring | nullno
exception"none" | "group_company" | "business_loan" | "dispensation" | nullno
exception_notestring | nullno
status"active" | "repaid" | "cancelled" | nullnorepaid (with repaid_on) or cancelled (registered by mistake).
repaid_onstring | nullno
notestring | nullno

Response fields

NameType
owner_loan_idstring
status"active" | "repaid" | "cancelled"
outstandingnumber
loan_banobject

Example request

{
  "owner_loan_id": "2f4a…",
  "status": "repaid",
  "repaid_on": "2026-11-30"
}

Example response

{
  "data": {
    "owner_loan_id": "2f4a…",
    "status": "repaid",
    "outstanding": 0,
    "loan_ban": {
      "status": "not_applicable",
      "exception": null,
      "special_list": false
    }
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}

PUT /api/v1/companies/:companyId/k10/:year/owners/:partyId

k10-inputs.set · scope companies:write

Save what a delägare enters for the K10 underlag of a year: sparat utdelningsutrymme, an omkostnadsbelopp, a löneunderlag or own pay that differs from the payroll.

Upserts the owner's figures for the inkomstår (omitted fields keep their value; null clears an override) and answers the recomputed underlag. Nothing is booked or filed. Dry-runnable.

Use when: The owner gives last year's sparat utdelningsutrymme, or the K10 shows a warning that a figure is missing.

Don't use for: Changing the aktiebok or the payroll: correct them where they are kept.

Pitfalls

  • K10_OWNER_NOT_FOUND: the party held no shares at the start of the year and received no dividend in it.

Risk: low · Idempotent: yes · Reversible: yes · Dry-run supported: yes · Stage for approval: yes (?stage=true)

Query parameters

NameTypeRequiredDescription
dry_runstringnotrue (any case) previews the write without committing it, like the X-Dry-Run: true header. Any other value commits.
stagestringnotrue stages the write for approval instead of committing it: 202 with the pending operation to approve via POST /pending-operations/{id}/approve. Absent or false commits; other values are 400. A reason in the body (why you propose it, at most 500 characters) is shown to the approver as agent_reason and kept with the decision.

Request body

NameTypeRequiredDescription
saved_dividend_spacenumber | nullnoSparat utdelningsutrymme brought forward from your K10 for the year before.
cost_basis_overridenumber | nullnoYour omkostnadsbelopp for the shares held at the start of the year; null clears it.
payroll_base_overridenumber | nullnoThe löneunderlag when it differs from the payroll here (subsidiaries, state-subsidised pay); null clears it.
own_pay_overridenumber | nullnoYour and your närståendes cash pay from the company the year before; null clears it.
uses_basic_amountboolean | nullnoFalse when you use the grundbelopp in another company this year.
notestring | nullno

Response fields

NameType
party_idstring
income_yearnumber
inputsobject
resultobject | null

Example request

{
  "party_id": "9c1e…",
  "income_year": 2026,
  "saved_dividend_space": 120000
}

Example response

{
  "data": {
    "party_id": "9c1e…",
    "income_year": 2026,
    "inputs": {
      "saved_dividend_space": 120000
    },
    "result": {
      "total_limit": 870000
    }
  },
  "meta": {
    "request_id": "req_…",
    "api_version": "2026-05-12"
  }
}