Accounting Rules
An accounting rule is a standing instruction to the Snapbooks automation: “when this happens, do this”. A company writes rules for its own books, and an accounting firm (regnskapsbyrå) writes rules for the companies it keeps the books for, optionally narrowed to an industry. Snapbot carries out a rule when a document arrives, when a bank transaction arrives, or on a schedule.
Rules are written with Snapbot, in the app’s chat or through the save_accounting_rule tool on the MCP server. The API does not create or edit rules. It lists and reads them, and it switches a rule on or off.
Versions
Rules are versioned. Editing a rule retires the live row (it gets a deleted_at and is_deleted: true) and inserts a new row with the same sequence_number. Each version has its own id, so a run of a rule can point to the version it carried out. The list returns live versions by default. GET /api/v2/accounting-rules/{id} returns any version, live or retired.
Who can read a rule
| Scope | Readable by |
|---|---|
CLIENT |
Users of the owning company, and staff of accounting firms with contract access to it |
PROVIDER |
Active members of the owning firm only. A company’s own users never see their firm’s rules |
Endpoints
List Accounting Rules
GET /api/v2/accounting-rules
Returns a paginated list of the rules the caller may read, ordered by owner, then rule number, then version.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | No | Only rules owned by this client account. Without it, every rule the caller may read is returned |
| applies_to_client_account_id | integer | No | Only rules that apply to this company: its own CLIENT rules, plus the PROVIDER rules of the firm holding its active accounting contract whose industry codes match it, whether active or not. A company’s own users still get only its CLIENT rules |
| scope | string | No | PROVIDER or CLIENT |
| sequence_number | integer | No | Only versions of the rule with this number. Combine with client_account_id and is_deleted=null to get a rule’s full history |
| is_active | boolean | No | true or false. null or omitted returns both |
| is_deleted | boolean | No | false (default) returns live versions, true returns retired versions, null returns both |
| page | integer | No | Page number (default: 1) |
| per_page | integer | No | Items per page (default: 100) |
| with | string | No | Related data to include: client_account, created_by, industries |
Example Request
GET /api/v2/accounting-rules?client_account_id=456&scope=PROVIDER&with=industries
Authorization: Bearer <token>
Response
{
"data": [
{
"id": 812,
"client_account_id": 456,
"sequence_number": 3,
"scope": "PROVIDER",
"industry_codes_lv": ["86"],
"name": "Helfo settlements",
"is_active": true,
"trigger": "BANK_TRANSACTION_RECEIVED",
"condition": "Incoming payments from Helfo",
"schedule": null,
"instruction": "Post the payment against account 3110 with no VAT.",
"created_at": "2026-11-02T09:14:00Z",
"created_by_id": 789,
"updated_at": null,
"updated_by_id": null,
"deleted_at": null,
"deleted_by_id": null,
"is_deleted": false,
"industries": [
{ "code": "86", "name": "Helsetjenester" }
]
}
],
"meta": {
"page": 1,
"pages": 1,
"per_page": 100,
"records": 1
}
}
Get Accounting Rule
GET /api/v2/accounting-rules/{id}
Returns one version of a rule, live or retired.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| id | integer | The ID of the rule version |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| with | string | No | Related data to include: client_account, created_by, industries |
Response
A single rule object. A scheduled rule has a schedule and no condition:
{
"id": 915,
"client_account_id": 123,
"sequence_number": 1,
"scope": "CLIENT",
"industry_codes_lv": [],
"name": "Monthly accruals",
"is_active": true,
"trigger": "SCHEDULE",
"condition": null,
"schedule": "0 7 1 * *",
"instruction": "Accrue last month's rent and reverse it on the first of the next month.",
"created_at": "2026-11-10T12:00:00Z",
"created_by_id": 789,
"updated_at": null,
"updated_by_id": null,
"deleted_at": null,
"deleted_by_id": null,
"is_deleted": false
}
Switch a Rule On or Off
PATCH /api/v2/accounting-rules/{id}
Switches the live version of a rule on or off in place, without creating a new version. The body must contain is_active and nothing else. Any other field, or a value that is not a JSON boolean, is rejected with accounting_rule.unsupported_update. Sending the state the rule already has changes nothing, including updated_at and updated_by_id.
Who may switch a rule:
- A
PROVIDERrule: active members of the owning firm. - A
CLIENTrule: the company’s users with an owner (CAorAA) or bookkeeper (BK) role, and staff of accounting firms with contract access to it.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| is_active | boolean | Yes | true to switch the rule on, false to switch it off |
Example Request
{
"is_active": false
}
Response
The updated rule object.
The Accounting Rule Object
| Field | Type | Description |
|---|---|---|
| id | integer | ID of this version |
| client_account_id | integer | The owner: the firm for a PROVIDER rule, the company for a CLIENT rule |
| sequence_number | integer | The rule’s number within its owner. Every version of a rule keeps its number |
| scope | string | Whose books the rule is for (see below) |
| industry_codes_lv | string[] | SN2025 industry code prefixes a client’s code must start with for a PROVIDER rule to cover it. Empty means every client. Always empty for a CLIENT rule |
| name | string | Short name of the rule (max 100 characters) |
| is_active | boolean | Whether the rule runs |
| trigger | string | When the rule runs (see below) |
| condition | string | null | What the rule applies to, in the words of the person who wrote it. null for a SCHEDULE rule |
| schedule | string | null | For a SCHEDULE rule: five crontab fields in Norwegian time (Europe/Oslo), at most once a day. null otherwise |
| instruction | string | What Snapbot should do with what the rule applies to |
| created_at | string | When this version was saved (ISO 8601) |
| created_by_id | integer | User who saved this version |
| updated_at | string | null | When the version was last switched on or off |
| updated_by_id | integer | null | User who last switched it |
| deleted_at | string | null | When the version was retired by a newer one |
| deleted_by_id | integer | null | User who retired it |
| is_deleted | boolean | Whether the version is retired |
| client_account | object | The owning client account. Only with with=client_account |
| created_by | object | The user who saved the version. Only with with=created_by |
| industries | object[] | Each of industry_codes_lv with its official SN2025 name, as {"code", "name"}. Only with with=industries |
Scope Values
| Value | Description |
|---|---|
PROVIDER |
The owner is an accounting or auditing firm, and the rule is for the companies it keeps the books for under an active accounting contract, optionally narrowed by industry_codes_lv |
CLIENT |
The rule is for the owner’s own books |
Trigger Values
| Value | Description |
|---|---|
DOCUMENT_RECEIVED |
Runs when a document arrives and waits for its posting, if the document matches condition |
BANK_TRANSACTION_RECEIVED |
Runs when a bank transaction arrives, before its ordinary matching, if the transaction matches condition |
SCHEDULE |
Runs at the times schedule gives, for each company the rule covers |
Which Rule Wins
When several rules match the same document or bank transaction, the most specific level with a match wins: the company’s own CLIENT rules first, then the firm’s PROVIDER rules by longest matching industry code, then the firm’s rules without industry codes.
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | common.validation_error |
An invalid scope value |
| 400 | accounting_rule.unsupported_update |
The PATCH body is not exactly {"is_active": true\|false} |
| 400 | accounting_rule.retired |
PATCH on a retired version. Switch the live version instead |
| 403 | accounting_rule.access_denied |
No access to client_account_id or applies_to_client_account_id, the caller may not read the rule, or (on PATCH) may not change it |
| 404 | accounting_rule.not_found |
No rule version with this ID |
See Error Handling for the error envelope.
Related Resources
- MCP server -
get_accounting_rulesandsave_accounting_rule, the tools that read and write rules - Worker Tasks - each run of a rule is an
ACCOUNTING_RULEworker task - Contracts - the accounting contracts that decide which companies a firm’s rules cover
- Client Accounts - rule owners