12
API Reference
samantha edited this page 2026-03-21 17:19:04 +00:00

API Reference

Base URL: http://localhost:8080/api/v1

All request and response bodies are JSON. All endpoints return Content-Type: application/json.


Health

GET /health

Returns 200 if the database is reachable.

Response:

{"status": "ok"}

Returns 503 if the database ping fails.


Reference Data

Reference data (departments and GL accounts) must be created before budget lines or actuals, as they are foreign-key parents.


Departments

POST /department/create

Create a department.

Request body:

{
  "code": "ENG",
  "name": "Engineering",
  "cost_center": "idk",
  "active":  true  
}

GET /department/list

List all departments.

Response:

[
  {"id": 1, "code": "ENG", "name": "Engineering", "cost_center": "CC-1100", "active": true},
  {"id": 2, "code": "MKT", "name": "Marketing", "cost_center": "CC-1100", "active": true}
]

GET /department/

Getting department by identifier.

Request bodys examples:

Only one may be used, as no conflict is permitted in same request

[
  { "code": "ENG"},
]
[
  { "name": "Marketing"},
]
[
  { "cost_center": "CC-1100"},
]

POST /department/activity

Setting activity by identifier.

Request bodys examples:

Only one may be used, as no conflict is permitted in same request

[
  { 
  "code": "ENG",
  "active": false
},
]
[
  { 
  "name": "Marketing",
  "active": true
},
]
[
  { 
  "cost_center": "CC-1100",
   "active": true
  },
]

DELETE /departments/delete

Request body:

{
  "id": "2",
}

Delete a department by ID.


GL Accounts

POST /gl-accounts

Create a GL account.

Request body:

{
  "code": "6100",
  "description": "Salaries & Wages",
  "type": "headcount",
  "favour_high": false
}

favour_high drives the favourability logic. Set to true for revenue accounts (higher actual = good), false for cost accounts (lower actual = good).

Account types: revenue, cogs, opex, capex, headcount

GET /gl-accounts

List all GL accounts.

DELETE /gl-accounts/delete

Delete a GL account by ID.


Budgets

POST /budget/create

Create a budget line.

Request body:

{
  "department_id": 1,
  "gl_account_id": 3,
  "fiscal_year": 2024,
  "fiscal_period": 9,
  "version": "original",
  "amount": 4200000,
  "currency": "DKK",
  "notes": "Headcount plan P09"
}

Budget versions: original, forecast1, forecast2, forecast3

PUT /budgets/update

Update a budget line's amount or notes.

Request body:

{
  "amount": 4350000,
  "notes": "Revised after headcount change"
}

DELETE /budgets/delete

Delete a budget line by ID.


Actuals

POST /actuals/ingest

Upsert an actual. Idempotent by (fiscal_year, fiscal_period, department_id, gl_account_id) - posting the same period twice updates the amount rather than creating a duplicate.

Request body:

{
  "department_id": 1,
  "gl_account_id": 3,
  "fiscal_year": 2024,
  "fiscal_period": 9,
  "amount": 4380000,
  "currency": "DKK",
  "source": "SAP_EXPORT"
}

Designed to accept bulk ERP export feeds. POST each line individually or build a batch wrapper around the endpoint.


Variance

Query Parameters (both variance endpoints)

Parameter Example Description
year 2024 Fiscal year (required)
period 9 Fiscal period 1-12 (required)
dept ENG Department code - omit to return all departments
version original Budget version (defaults to original)

GET /variance

Full variance report for the given filters.

Example:

GET /api/v1/variance?year=2024&period=9&dept=ENG

Response:

{
  "department": "ENG",
  "fiscal_year": 2024,
  "fiscal_period": 9,
  "version": "original",
  "currency": "DKK",
  "total_budget": 6740000,
  "total_actual": 7074600,
  "total_variance": -334600,
  "total_variance_pct": -4.97,
  "lines": [
    {
      "gl_code": "6100",
      "gl_description": "Salaries & Wages",
      "gl_type": "headcount",
      "budget": 4200000,
      "actual": 4380000,
      "variance_abs": -180000,
      "variance_pct": -4.29,
      "status": "unfavourable",
      "currency": "DKK"
    },
    {
      "gl_code": "5000",
      "gl_description": "Cloud Infrastructure",
      "gl_type": "cogs",
      "budget": 850000,
      "actual": 791000,
      "variance_abs": 59000,
      "variance_pct": 6.94,
      "status": "favourable",
      "currency": "DKK"
    }
  ]
}

variance_abs = actual - budget. Positive means over-budget for costs, under-budget for revenue.

status is "favourable" or "unfavourable" based on the account's favour_high flag - see Finance Concepts.


GET /variance/alerts

Returns only the GL lines where absolute variance percentage exceeds the threshold.

Additional query parameter:

Parameter Example Description
threshold 15 Alert threshold as a percentage (default: 10)

Example:

GET /api/v1/variance/alerts?year=2024&period=9&threshold=15

Returns the same line-level structure as the full variance report, filtered to lines where abs(variance_pct) > threshold.