API Reference

This guide is intended for developers who wish to build their own frontend applications or integrations on top of the Calyntro API.

The API is built with FastAPI and follows RESTful principles. All responses are JSON-formatted.

Note

The Base URL for all endpoints is /v1.

Common Concepts

Request Format

Most analysis endpoints accept POST requests to allow for complex filtering parameters in the body. Dates should be provided in ISO 8601 format (e.g., 2023-01-01T00:00:00).

Standard Filter Parameters:

Many endpoints use a common filter structure:

  • start_date: The beginning of the analysis time window.

  • end_date: The end of the analysis time window.

  • module_name: Optional. Filter results to a specific architectural component/module.

Note

Some older endpoints use from (aliased from from_) and to instead of start_date and end_date. These are noted in the respective sections.

Response Format

Most list-based responses wrap the results in an items array:

{
  "items": [
    { ... },
    { ... }
  ]
}

Repository & Files

Get Repository Info

Retrieves metadata and statistics for the entire repository, including time span, last import, total commits, active committers, and file type distribution.

  • URL: /v1/repository/info

  • Method: GET

Response:

{
  "items": {
    "project_name": "mongodb",
    "time_span": {
      "start": "01.01.2024",
      "end": "17.04.2026",
      "days": 837
    },
    "last_import": "2026-04-17 14:30:00",
    "total_commits": 5676,
    "committers": 42,
    "file_types": [
      {
        "name": "TypeScript",
        "value": 45.2,
        "color": "#3178c6",
        "extension": ".ts, .tsx"
      },
      {
        "name": "Python",
        "value": 20.5,
        "color": "#3572A5",
        "extension": ".py"
      },
      {
        "name": "Other",
        "value": 34.3,
        "color": "#cccccc",
        "extension": ""
      }
    ]
  }
}
Response Fields (items)

Field

Description

project_name

Name of the analyzed project as configured in config.yaml (project.name).

time_span

Object containing start, end (formatted dates) and days (total span).

last_import

Timestamp of the most recent data import.

total_commits

Total number of commits in the analysis database.

committers

Number of distinct active committers.

file_types

Top-5 file type distribution by commit share. Each entry has name, value (%), color (hex), extension.

Get File Details

Returns comprehensive metrics, KPIs, and activity history for a specific file.

  • URL: /v1/files/details

  • Method: POST

Request Body (JSON):

  • file_path (required): The full path of the file.

  • start_date (optional): Analysis start date.

  • end_date (optional): Analysis end date.

Response:

{
  "meta": {
    "file_path": "src/core/main.py",
    "module": "core",
    "last_modified": "2024-03-15T10:00:00",
    "contributor_count": 5,
    "contributor_names": ["Alice", "Bob"]
  },
  "kpis": {
    "complexity": { "value": 42.0, "trend_pct": 5.0 },
    "churn_rate": { "value": 12.5, "trend_pct": -2.1 },
    "hotspot_score": { "value": 0.85, "trend_pct": 0.0 },
    "silo_risk_pct": { "value": 0.0, "trend_pct": 0.0 }
  },
  "metrics": {
    "loc": 450,
    "cyclomatic": 25,
    "cognitive": 18
  },
  "activity": {
    "commits": 124,
    "churn": 1540,
    "file_age_days": 450
  },
  "functions": [
    {
      "name": "validate_token",
      "start_line": 10,
      "end_line": 50,
      "cognitive": 30,
      "cyclomatic": 5,
      "loc": 40
    }
  ]
}

functions is sorted by cognitive descending (highest maintenance burden first).

Supported languages: C/C++ (via rust-code-analysis metrics + regex name extraction), C# (csharpmetrics), QML (qmlmetrics), and all other languages supported by rust-code-analysis (Python, TypeScript, Rust, Go, Java, Kotlin, …).

The array is empty when no function-level data has been recorded yet — typically because the file has not been re-imported after upgrading to v1.9.0+.

Get File Blast Radius

Returns all files that historically co-change with a given file, ranked by coupling strength. Useful for impact analysis: “if I change this file, what else is likely to be affected?”

  • URL: /v1/files/blast-radius

  • Method: POST

Request Body (JSON):

  • file_path (required): The full path of the file to analyse.

  • min_co_changes (optional, default: 2): Minimum number of co-changes required to include a partner. Set to 1 to include all historically co-changed files.

  • limit (optional, default: 20, max: 100): Maximum number of results to return.

Response:

{
  "file_path": "src/core/auth.py",
  "total_partners": 3,
  "blast_radius": [
    {
      "coupled_file": "src/core/session.py",
      "module": "core",
      "co_changes": 47,
      "coupling_score": 1.0
    },
    {
      "coupled_file": "src/api/middleware.py",
      "module": "api",
      "co_changes": 12,
      "coupling_score": 0.255
    }
  ]
}

Response fields:

  • file_path: The queried file.

  • total_partners: Number of files in the result set (after min_co_changes filter and limit).

  • blast_radius: List of co-changed files, ordered by co_changes descending.

  • blast_radius[].coupled_file: Path of the co-changed file.

  • blast_radius[].module: Module the coupled file belongs to (latest assignment), or null if unassigned.

  • blast_radius[].co_changes: Number of commits in which both files changed together.

  • blast_radius[].coupling_score: Normalised coupling strength (0.0–1.0) relative to the strongest partner in this result set.


Lines of Code (LOC)

Endpoints for analyzing the size of the codebase.

Get LOC per File

Returns the Lines of Code count for each file, based on the latest commit within the selected timeframe.

  • URL: /v1/analysis/loc/files

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "module_name": "optional_module_name"
}

Response:

{
  "items": [
    {
      "name": "src/main.py",
      "loc": 150
    }
  ]
}

Get LOC per Module

Returns the aggregated Lines of Code for each defined module.

  • URL: /v1/analysis/loc/modules

  • Method: POST

Request Body: Same as Get LOC per File.

Response:

{
  "items": [
    {
      "name": "src/core/",
      "loc": 5240
    }
  ]
}

Get Total LOC

Returns the grand total Lines of Code for the entire project (or filtered selection).

  • URL: /v1/analysis/loc/total

  • Method: POST

  • Request Body: Same as Get LOC per File.

Response:

{
  "items": [
    {
      "name": "Total",
      "loc": 15420
    }
  ]
}

Evolution & Pulse

Endpoints for analyzing how the codebase changes over time.

Change Frequency (Files)

Retrieves commit activity for files, including commit counts, author metrics, and last modification details.

  • URL: /v1/analyze/commits

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "module_name": "optional_module_name"
}

Response:

{
  "items": [
    {
      "file_path": "src/core/analysis.py",
      "commit_count": 42,
      "last_modified": "2023-12-01T10:00:00",
      "main_contributor": "John Doe",
      "author_count": 3,
      "last_commit_message": "Refactor analysis engine"
    }
  ]
}

Change Frequency (Modules)

Retrieves commit activity aggregated by module.

  • URL: /v1/analyze/modules/commits

  • Method: POST

  • Request Body: Same as Change Frequency (Files).

Response:

{
  "items": [
    {
      "module_name": "src/api/",
      "commit_count": 85,
      "last_modified": "2023-12-15T14:30:00",
      "main_contributor": "Jane Smith",
      "author_count": 5,
      "last_commit_message": "Fix API authentication"
    }
  ]
}

Change Recency (Files)

Returns the age of files (time since first and last commit).

  • URL: /v1/analyze/age

  • Method: POST

Request Body:

{
  "from_": "2023-01-01T00:00:00",
  "to": "2023-12-31T23:59:59",
  "module": "optional_module_name",
  "nbr_items": 50
}

Response:

{
  "items": [
    {
      "file_path": "src/utils.py",
      "first_commit": "2021-01-01T12:00:00",
      "last_commit": "2023-11-15T09:30:00",
      "age_days": 1048,
      "revisions": 15
    }
  ]
}

Change Recency (Modules)

Returns the age aggregated by module.

  • URL: /v1/analyze/modules/age

  • Method: POST

  • Request Body: Same as Change Recency (Files).

Response:

{
  "items": [
    {
      "module_name": "src/core/",
      "first_commit": "2020-05-10T08:00:00",
      "last_commit": "2023-12-01T16:45:00",
      "age_days": 1300,
      "revisions": 450
    }
  ]
}

Absolute Churn

Returns the absolute churn (added + deleted lines) per file.

  • URL: /v1/analyze/abs_churn/files

  • Method: POST

Request Body:

{
  "from": "2023-01-01T00:00:00",
  "to": "2023-12-31T23:59:59",
  "module": "optional_module_name",
  "nbr_items": 100
}

Response:

{
  "items": [
    {
      "file_path": "src/db/connection.py",
      "abs_churn": 1250,
      "total_added": 800,
      "total_deleted": 450,
      "first_change": "2023-01-15T10:00:00",
      "last_change": "2023-11-20T15:30:00",
      "revisions": 12
    }
  ]
}

Absolute Churn (Modules)

Returns the absolute churn aggregated by module.

  • URL: /v1/analyze/abs_churn/modules

  • Method: POST

  • Request Body: Same as Absolute Churn.

Development Trend

Analyzes the evolution of hotspots by comparing a baseline time window with a current time window.

  • URL: /v1/analyze/hotspot_trends

  • Method: POST

Request Body:

{
  "baseline": {
    "from": "2023-01-01T00:00:00",
    "to": "2023-06-30T23:59:59"
  },
  "current": {
    "from": "2023-07-01T00:00:00",
    "to": "2023-12-31T23:59:59"
  },
  "module": "optional_module_name",
  "nbr_items": 50
}

Response:

{
  "items": [
    {
      "file_path": "src/core/analysis.py",
      "churn_baseline": 450,
      "churn_current": 820,
      "scores": {
        "structural": {
          "baseline": 0.45,
          "current": 0.82,
          "delta": 0.37,
          "delta_norm": 0.5,
          "norm": 0.6,
          "trend": "up"
        },
        "activity": {
          "baseline": 15,
          "current": 25,
          "delta": 10,
          "delta_norm": 0.4,
          "norm": 0.5,
          "trend": "up"
        }
      }
    }
  ]
}

File Trend History

Returns the historical development of metrics for a specific file.

  • URL: /v1/analyze/file_trend

  • Method: POST

Request Body:

{
  "file_path": "src/core/service.py",
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "bucket_days": 14,
  "metric": "churn"
}

Response:

{
  "items": [
    {
      "file_path": "src/core/service.py",
      "metric": "churn",
      "from_date": "2023-01-01T00:00:00",
      "to_date": "2023-12-31T23:59:59",
      "bucket_days": 14,
      "series": [
        {
          "t": "2023-01-01T00:00:00",
          "value": 150
        },
        {
          "t": "2023-01-15T00:00:00",
          "value": 240
        }
      ]
    }
  ]
}

Module Trend History

Returns the historical development of a single churn-based metric for one module.

  • URL: /v1/analyze/module_trend

  • Method: POST

Request Body:

{
  "module_name": "src/api/",
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "bucket_days": 14,
  "metric": "churn"
}

Response: Same structure as File Trend History.


Quality & Risk

Hotspot Analysis (Age & Churn)

Identifies “Hotspots” based on the intersection of high churn and file age.

  • URL: /v1/analyze/hotspots/churnage

  • Method: POST

Request Body:

{
  "from": "2023-01-01T00:00:00",
  "to": "2023-12-31T23:59:59",
  "module": "optional_module_name",
  "nbr_items": 50
}

Response:

{
  "items": [
    {
      "file_path": "src/core/logic.py",
      "age_days": 450,
      "churn": 1200,
      "hotspot_score": 0.89
    }
  ]
}

Hotspot Analysis (Complexity & Churn)

Identifies hotspots by combining cognitive complexity with churn metrics.

  • URL: /v1/analyze/hotspots/complexity

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "component_name": "optional_module_name"
}

Response:

[
  {
    "file_path": "src/complex_logic.py",
    "complexity": 150,
    "churn": 2500,
    "hotspot_score": 0.85
  }
]

Hotspot Complexity — Tracker-Enriched

Tracker-enriched hotspot analysis. Replaces commit-message keyword heuristics with resolved ticket types from the configured issue tracker.

Churn weights: bug / defect → 2.0 · feature / task / other → 1.0 · no ticket reference → 1.2. The coverage block shows what fraction of commits could be enriched; low coverage (<40 %) means results should be interpreted with caution.

  • URL: /v1/analyze/hotspots/complexity/tracker

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date":   "2023-12-31T23:59:59",
  "component_name": "optional_module_name"
}

Response:

{
  "methodology":   "git+tracker",
  "tracker_type":  "jira",
  "coverage": {
    "commits_total":     1240,
    "commits_with_type":  906,
    "coverage_pct":       73.1
  },
  "items": [
    {
      "file_path":             "src/db/wiredtiger.cpp",
      "ticket_weighted_churn": 4820.0,
      "revisions":             148,
      "bug_commits":            89,
      "feature_commits":        41,
      "untracked_commits":      18,
      "cyclomatic":             25,
      "cognitive":              30,
      "efforts":              1250.0,
      "loc":                   566,
      "hotspot_score":       144600.0
    }
  ]
}

Response fields:

Field

Description

methodology

Always "git+tracker" — identifies the scoring method used.

tracker_type

Configured tracker type: "jira", "jira_public", or "github_issues". null if no provider is configured.

coverage.commits_total

Total commits in the requested time window.

coverage.commits_with_type

Commits where the ticket type was successfully resolved from the tracker.

coverage.coverage_pct

Percentage of commits with a resolved ticket type.

bug_commits

Commits linked to a ticket of type bug or defect.

feature_commits

Commits linked to any other resolved ticket type.

untracked_commits

Commits with no ticket reference in the tracker.

hotspot_score

ticket_weighted_churn × cognitive — analogous to the base hotspot score but uses tracker-based weights.

Tracker Coverage Diagnostic

Three-level diagnostic endpoint for evaluating tracker integration quality before relying on the enriched hotspot analysis. Returns the confidence field as a ready-to-use signal for the UI (high / medium / low / none).

  • URL: /v1/analysis/tracker/coverage

  • Method: GET

Query Parameters:

Parameter

Type

Description

start_date

datetime (optional)

Restrict to commits on or after this date.

end_date

datetime (optional)

Restrict to commits on or before this date.

Response:

{
  "commits_total":              1240,
  "commits_with_ref":            980,
  "commits_with_resolved_type":  906,
  "commits_no_ref":              260,
  "tickets_extracted":           342,
  "tickets_resolved":            315,
  "coverage_pct":               73.1,
  "resolution_rate_pct":        92.1,
  "confidence":                "high"
}

Response fields:

Field

Description

commits_total

All commits in the requested window.

commits_with_ref

Commits where at least one ticket ID pattern was found by regexp.

commits_with_resolved_type

Commits where the ticket type was confirmed by the tracker API.

commits_no_ref

commits_total commits_with_ref — commits with no ticket pattern. These are counted as untracked work in the enriched hotspot score.

tickets_extracted

Distinct ticket IDs found across all commits by regexp.

tickets_resolved

Ticket IDs confirmed by the tracker API (type successfully fetched).

coverage_pct

commits_with_resolved_type / commits_total × 100

resolution_rate_pct

tickets_resolved / tickets_extracted × 100 — quality indicator for the regexp configuration. null when no ticket IDs were extracted (no tracker configured or no matches found).

confidence

Composite signal: high (coverage ≥ 80 % and resolution ≥ 85 %), medium (directional), low (below useful threshold), none (no ticket data).

Interpreting resolution_rate_pct:

Rate

Interpretation

≥ 90 %

Regexp matches well — data is reliable.

70–89 %

Some false positives or deleted tickets — check project_prefix.

< 70 %

Regexp may be misconfigured — base hotspot is the safer reference.


Structure & Logic

Combined Complexity (Files)

Returns complexity metrics (Cyclomatic, Cognitive, Efforts, LOC) combined with a trend indicator.

  • URL: /v1/analysis/complexity/combined

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "module_name": "optional_module_name"
}

Response:

{
  "items": [
    {
      "file_path": "src/main.py",
      "cognitive": 12,
      "cyclomatic": 8,
      "loc": 150,
      "efforts": 450.5,
      "trend_indicator": 2.0
    }
  ]
}

Combined Complexity (Modules)

Returns aggregated complexity metrics for modules.

  • URL: /v1/analysis/complexity/modules

  • Method: POST

  • Request Body: Same as Combined Complexity (Files).

Response:

{
  "items": [
    {
      "file_path": "src/core/",
      "cognitive": 120,
      "cyclomatic": 85,
      "loc": 5240,
      "efforts": 12500.0,
      "trend_indicator": 1.5
    }
  ]
}

Complexity Trend History

Returns the historical complexity trend for a specific file.

  • URL: /v1/analyze/hotspots/complexity/trend

  • Method: POST

Request Body:

{
  "file_path": "src/core/service.py",
  "module_name": null,
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59"
}

Response:

{
  "items": [
    {
      "author_date": "2023-01-15T10:00:00",
      "complexity": 15,
      "cognitive": 12,
      "efforts": 450.0,
      "loc": 120,
      "commit_churn": 25
    }
  ]
}

Team & Knowledge

Engineering Eras

Detects temporal development phases (eras) for a module or the full repository. Eras are derived deterministically from Git signals — no AI is involved. Each era spans a contiguous period with a stable, recognisable pattern.

  • URL: /v1/analysis/eras

  • Method: POST

Request Body:

{
  "module_name": "db",
  "start_date": "2022-01-01T00:00:00",
  "end_date": "2024-01-01T00:00:00",
  "min_duration_months": 2,
  "cp_threshold": 0.30
}

All fields except start_date and end_date are optional. cp_threshold controls sensitivity: lower values detect more era boundaries.

Response:

{
  "module": "db",
  "items": [
    {
      "era_type": "knowledge_concentration",
      "label": "Ownership Concentration Era",
      "start": "2023-04-01T00:00:00",
      "end": "2024-01-01T00:00:00",
      "duration_months": 9,
      "signals": {
        "commits_norm": 0.45,
        "complexity_delta": 0.08,
        "contributor_norm": 0.12,
        "silo_ratio": 0.87
      }
    }
  ]
}

Era types: rapid_growth, stabilization, knowledge_concentration, refactoring, neglect, transition, unknown.

Signal semantics:

  • commits_norm — relative commit activity (0 = lowest month in range, 1 = highest)

  • complexity_delta — signed complexity change per bucket (positive = growing)

  • contributor_norm — relative team size (0 = fewest contributors, 1 = most)

  • silo_ratio — fraction of files in this bucket where one author holds ≥ 80 % of commits (0–1)

Code Ownership (Files)

Returns the number of distinct authors per file and identifies the main contributor.

  • URL: /v1/analysis/contributors/files

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "module_name": "optional_module_name"
}

Code Ownership (Modules)

Returns ownership statistics aggregated by module.

  • URL: /v1/analysis/contributors/modules

  • Method: POST

  • Request Body: Same as Code Ownership (Files).

Response:

{
  "items": [
    {
      "module_name": "src/api/",
      "author_count": 8,
      "main_contributor": "Jane Smith"
    }
  ]
}

Knowledge Silos (Files)

Returns all files classified as a knowledge silo — files where a single developer accounts for at least silo_threshold (default 80 %) of all commits. Results are ordered by ownership percentage descending.

  • URL: /v1/analysis/silos/files

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "module_name": "optional_module_name",
  "silo_threshold": 0.80,
  "min_commits": 5
}
Request Parameters

Parameter

Required

Description

start_date

No

ISO 8601 timestamp. Only commits on or after this date are considered.

end_date

No

ISO 8601 timestamp. Only commits on or before this date are considered.

module_name

No

Restrict analysis to a specific component name.

silo_threshold

No

Fractional ownership threshold (0.5–1.0). A file is a silo when the top contributor meets or exceeds this value. Default: 0.80.

min_commits

No

Minimum total commits a file must have to be included. Filters out rarely touched files. Default: 5.

Response:

{
  "items": [
    {
      "file_path": "src/core/engine.py",
      "component_name": "core",
      "silo_developer": "alice",
      "ownership_pct": 94.3,
      "total_commits": 87,
      "risk": "high"
    }
  ]
}
Response Fields

Field

Description

file_path

Path to the silo file.

component_name

The architectural component this file belongs to (null if unassigned).

silo_developer

The developer who holds sole knowledge of this file.

ownership_pct

Percentage of commits attributed to the silo developer (0–100).

total_commits

Total number of commits to this file within the filtered time window.

risk

Risk classification: low (80–89 %), medium (90–94 %), high (95–99 %), critical (100 %).

Knowledge Silos (Modules)

Returns the silo density for each component — the fraction of files within the module that are knowledge silos — and identifies which developer is responsible for the most silos in that module. Results are ordered by silo ratio descending.

  • URL: /v1/analysis/silos/modules

  • Method: POST

  • Request Body: Same as Knowledge Silos (Files).

Response:

{
  "items": [
    {
      "component_name": "core",
      "total_files": 24,
      "silo_files": 9,
      "silo_ratio": 0.375,
      "dominant_silo_developer": "alice",
      "risk": "medium",
      "risk_score": 3.75
    }
  ]
}
Response Fields

Field

Description

component_name

Name of the architectural component.

total_files

Total number of distinct files active in the module within the time window.

silo_files

Number of files in the module that are classified as silos.

silo_ratio

Fraction of files that are silos (silo_files / total_files).

dominant_silo_developer

The developer responsible for the highest number of silos within this module.

risk

Risk derived from silo_ratio: low (< 25 %), medium (25–49 %), high (50–74 %), critical (≥ 75 %).

risk_score

Numeric risk score on a 0–10 scale (silo_ratio × 10, rounded to 2 decimal places). Used by the Knowledge Risk screen to rank modules and size the risk bar.

Knowledge Silos (Developers)

Returns the silo footprint of each developer — how many files and modules they are the sole knowledge holder of. Results are ordered by silo file count descending.

  • URL: /v1/analysis/silos/developers

  • Method: POST

  • Request Body: Same as Knowledge Silos (Files).

Response:

{
  "items": [
    {
      "developer": "alice",
      "silo_file_count": 14,
      "silo_module_count": 3,
      "avg_ownership_pct": 91.7,
      "risk": "high"
    }
  ]
}
Response Fields

Field

Description

developer

Developer name.

silo_file_count

Number of files for which this developer is the sole knowledge holder.

silo_module_count

Number of distinct components containing at least one of their silo files.

avg_ownership_pct

Average ownership percentage across all their silo files.

risk

Risk derived from silo_file_count: low (1–2), medium (3–9), high (10–19), critical (≥ 20).

Module Ownership by Teams

Shows how much of each module is owned by different teams (Team-centric view).

  • URL: /v1/analysis/alignment/modules

  • Method: POST

Request Body:

{
  "start_date": "2023-01-01T00:00:00",
  "end_date": "2023-12-31T23:59:59",
  "component_name": "optional_module_name"
}

Response:

{
  "items": [
    {
      "team_name": "Frontend Team",
      "module_name_1": "UI Components",
      "ratio_1": 0.85,
      "module_name_2": "Icons",
      "ratio_2": 0.10,
      "module_name_3": "Tests",
      "ratio_3": 0.05,
      "health_status": "healthy"
    }
  ]
}

Top Team Contributors

Shows the top 3 contributing teams for each module (Module-centric view).

  • URL: /v1/analysis/alignment/teams

  • Method: POST

  • Request Body: Same as Module Ownership by Teams.

Response:

{
  "items": [
    {
      "component_name": "src/core/",
      "team_name_1": "Core Team",
      "ratio_1": 0.75,
      "team_name_2": "DevOps",
      "ratio_2": 0.20,
      "team_name_3": "Unassigned/Others",
      "ratio_3": 0.05,
      "health_status": "monopoly"
    }
  ]
}

Team Ownership Drift Timeline

Returns team ownership ratios per module per time bucket, enabling visualisation of how team responsibility shifted over time (Conway’s Law drift). Only modules with a meaningful ownership change (≥10% shift in the leading team’s ratio across buckets) are included.

  • URL: /v1/analysis/alignment/drift

  • Method: POST

Request Body:

Field

Type

Description

start_date

datetime (optional)

Start of the analysis window. Defaults to two years ago.

end_date

datetime (optional)

End of the analysis window. Defaults to today.

bucket_months

integer (default: 3)

Bucket size in months. Use 3 for quarterly, 1 for monthly.

module_name

string (optional)

Filter to a single module name.

Response Fields:

Field

Description

buckets

List of ISO date strings (YYYY-MM-DD) representing bucket start dates.

modules

List of module objects with meaningful ownership drift (see below).

modules[].module_name

Module name (component name).

modules[].health_status

Latest bucket health status: monopoly (>90% one team), unassigned_heavy (Unassigned/Others >30%), fragmented (top-2 teams cover <50%), healthy.

modules[].series

One entry per bucket (aligned to buckets). Each entry has a bucket (ISO date) and teams list of { team, ratio } slices sorted by ratio desc. Empty teams list means no commits in that bucket.

Example Response:

{
  "buckets": ["2023-01-01", "2023-04-01", "2023-07-01", "2023-10-01"],
  "modules": [
    {
      "module_name": "MMI_QML",
      "health_status": "fragmented",
      "series": [
        { "bucket": "2023-01-01", "teams": [{"team": "Team C", "ratio": 0.72}, {"team": "Team F", "ratio": 0.21}] },
        { "bucket": "2023-04-01", "teams": [{"team": "Team C", "ratio": 0.61}, {"team": "Team F", "ratio": 0.31}] },
        { "bucket": "2023-07-01", "teams": [{"team": "Team F", "ratio": 0.55}, {"team": "Team C", "ratio": 0.38}] },
        { "bucket": "2023-10-01", "teams": [{"team": "Team F", "ratio": 0.60}, {"team": "Team C", "ratio": 0.33}] }
      ]
    }
  ]
}

Hotspot Concentration

Returns the hotspot severity distribution for a module or the entire codebase as a single aggregated result — not a ranked list.

Structural scores (log1p(churn) × age_days) are normalised within the result set so the metric is comparable across modules of any size and age. The normalisation mirrors the coupling_score approach: the file with the highest score receives 1.0, the lowest receives 0.0. Thresholds are consistent with the critical_hotspot warning type.

  • URL: /v1/analyze/hotspots/concentration

  • Method: POST

Note

Returns zeros for all fields when no file activity exists in the requested window or the requested module does not exist.

Request Body:

Field

Type

Description

module

string (optional)

Filter to a specific module name. Omit for codebase-wide concentration.

start_date

datetime (optional)

Start of the analysis window.

end_date

datetime (optional)

End of the analysis window.

Response: { "items": { ... } }

The response wraps the aggregate object in the standard items envelope:

{
  "items": {
    "total_files": 120,
    "critical_count": 8,
    "high_count": 14,
    "critical_ratio": 6.67,
    "high_ratio": 11.67
  }
}

Fields inside ``items``:

Field

Description

total_files

Total number of files with activity in the requested window.

critical_count

Files whose normalised hotspot score is ≥ 0.9.

high_count

Files whose normalised hotspot score is ≥ 0.7 and < 0.9.

critical_ratio

critical_count / total_files × 100. Returns 0.0 when total_files = 0.

high_ratio

high_count / total_files × 100. Returns 0.0 when total_files = 0.

Contributors Trend

Returns the number of distinct active contributors per time bucket.

Each bucket spans bucket_days days (default 30). The t field marks the bucket start date, formatted identically to other trend endpoints (/analysis/trends/overview, /analyze/module_trend), making it straightforward to overlay contributor activity with complexity or churn sparklines in custom dashboards.

Without module_name, the trend reflects the entire codebase. A declining trend signals growing knowledge concentration risk before silo metrics surface it at file level.

  • URL: /v1/analysis/contributors/trend

  • Method: POST

Request Body:

Field

Type

Description

module_name

string (optional)

Filter to a specific module. Omit for codebase-wide trend.

start_date

datetime (optional)

Start of the time window. Defaults to the repository’s analysis start date.

end_date

datetime (optional)

End of the time window. Defaults to today.

bucket_days

integer (optional, default 30)

Bucket width in days.

Response Fields (per item in items):

Field

Description

t

Bucket start date (ISO 8601 datetime). Buckets are non-overlapping and ordered ascending.

contributor_count

Number of distinct authors who committed to the module (or codebase) within this bucket. Each author is counted once per bucket regardless of commit frequency.

Change Coupling

Returns module pairs ranked by co-change frequency, enriched with team ownership context. Each pair represents two modules that were modified together in the same commits. Cross-team pairs indicate Conway’s Law violations — coordination overhead caused by architectural boundaries that do not align with team boundaries.

Results are pre-sorted: cross-team pairs first, then by total_co_changes descending within each boundary type.

  • URL: /v1/analysis/coupling/modules

  • Method: POST

Note

Requires at least one completed analysis import. Returns an empty items list if coupling data has not been computed yet.

Request Body:

{
  "start_date":    "2024-01-01T00:00:00",
  "end_date":      "2024-12-31T23:59:59",
  "boundary_type": "cross_team"
}
Request Parameters

Parameter

Required

Description

start_date

No

ISO 8601 timestamp. Restricts team ownership calculation to commits within this window. Omit to use all available history.

end_date

No

ISO 8601 timestamp. Upper bound for the ownership window.

boundary_type

No

Filter results by team boundary: cross_team, same_team, or unknown. Omit to return all pairs.

Response:

{
  "items": [
    {
      "module1":              "src_mongo",
      "team1":                "Storage Engine",
      "team1_ownership":      0.46,
      "module2":              "src_third_party",
      "team2":                "Test Infrastructure",
      "team2_ownership":      0.98,
      "coupled_file_pairs":   15,
      "total_co_changes":     21415,
      "boundary_type":        "cross_team",
      "module1_commit_count": 204831,
      "module2_commit_count": 27112,
      "shared_commit_count":  27
    }
  ]
}
Response Fields (each item in items)

Field

Description

module1

Name of the first module in the pair. The module with the lower lexicographic name is always placed in module1.

team1

Primary owning team of module1 as resolved from the team configuration. null if no team assignment exists.

team1_ownership

Fraction (0–1) of commits to module1 attributed to team1 in the configured time window. null if team is unknown.

module2

Name of the second module in the pair.

team2

Primary owning team of module2. null if no team assignment exists.

team2_ownership

Fraction (0–1) of commits to module2 attributed to team2.

coupled_file_pairs

Number of distinct file pairs (one file from each module) that have co-changed at least once. Indicates the breadth of the coupling: a low value suggests an isolated connection; a high value indicates systemic coupling across many files.

total_co_changes

Total file-pair co-change events: Σ (co_change_count per file pair). If a single commit touches N files in module1 and M files in module2, that counts as N × M events. Can be orders of magnitude larger than shared_commit_count.

boundary_type

Team boundary classification: cross_team (modules owned by different teams), same_team, or unknown (team data unavailable for one or both modules).

module1_commit_count

Total distinct commits that touched any file in module1 across all history. Used as the denominator in coupling direction calculations: P(module2 | module1) = shared_commit_count / module1_commit_count.

module2_commit_count

Total distinct commits that touched any file in module2 across all history.

shared_commit_count

Commits that touched at least one file in module1 and at least one file in module2 simultaneously. This is the commit-level coordination count — directly comparable to module1_commit_count and module2_commit_count for direction analysis.

Note

``total_co_changes`` vs ``shared_commit_count`` — these measure different things. shared_commit_count counts commits at the module level (27 in the example above). total_co_changes counts file-pair co-change events, which multiplies with the number of files touched per commit (27 commits × ~790 file pairs per commit ≈ 21,415 events). Use shared_commit_count for direction analysis; use total_co_changes for ranking pairs.

Coupling Partners

Returns all modules that co-change with a given module, ranked by co-change frequency. Provides an asymmetric, partner-centric view: instead of symmetric pairs, each result item describes one partner relative to the queried module.

The coupling_score is normalised within the result set — the strongest partner always receives a score of 1.0, making relative comparisons meaningful regardless of absolute co-change volume.

  • URL: /v1/analysis/coupling/partners

  • Method: POST

Note

Returns an empty items list if no coupling data exists or the given module has no known co-change partners.

Request Body:

Field

Type

Description

module_name

string (required)

The module for which coupling partners are queried.

start_date

datetime (optional)

Restrict team ownership calculation to commits on or after this date.

end_date

datetime (optional)

Restrict team ownership calculation to commits on or before this date.

boundary_type

string (optional)

Filter by cross_team, same_team, or unknown. Omit to return all.

Response Fields (per item in items):

Field

Description

partner_module

Name of the co-changing partner module.

team

Primary owning team of the partner module. null if no team data is available.

team_ownership

Fraction (0–1) of churn in the partner module attributed to team. null if no team data.

coupled_file_pairs

Number of distinct file pairs (one from each module) that have co-changed at least once.

total_co_changes

Total co-change events between this module and the partner. Used for absolute ranking.

coupling_score

Normalised coupling strength (0.0–1.0). The partner with the highest total_co_changes receives 1.0; all others are scaled relative to it. Enables meaningful comparison across modules with different activity levels.

boundary_type

Team boundary classification relative to the queried module: cross_team, same_team, or unknown (team data unavailable for one or both modules).

Team Co-Change Matrix

Aggregates module-level coupling data into a team × team co-change matrix. Each cell represents a unique team pair and the total number of co-change events across all module pairs that cross that team boundary. Useful for building a heatmap of inter-team coordination overhead. Returns an empty list if no coupling data or no team configuration is present.

  • URL: /v1/analysis/coupling/team-matrix

  • Method: POST

Request body (JSON):

Parameter

Type

Description

start_date

datetime (optional)

Start of the analysis window. Defaults to the beginning of recorded history.

end_date

datetime (optional)

End of the analysis window. Defaults to the latest recorded commit.

Response body:

{
  "items": [
    {
      "team1": "team-alpha",
      "team2": "team-beta",
      "co_changes": 234,
      "module_pair_count": 12
    }
  ]
}

Response fields (each object in items):

Field

Description

team1

First team in the pair, alphabetically ≤ team2 (canonical ordering ensures each pair appears once).

team2

Second team in the pair, alphabetically ≥ team1.

co_changes

Total co-change events summed across all module pairs owned by this team pair.

module_pair_count

Number of distinct module pairs that contributed to this co-change count.


Dashboard KPIs

Lightweight aggregate endpoints that power the four KPI cards, the three sparkline panels, and the warnings list on the overview dashboard. All computation happens in the backend; the frontend receives pre-calculated values and renders them directly.

Project Summary

Returns the four headline metrics for the current period together with their trend percentages compared to an explicit baseline period. Powers all four KPI cards.

  • URL: /v1/analysis/summary

  • Method: POST

Request Body:

{
  "start_date":          "2024-01-01T00:00:00",
  "end_date":            "2024-12-31T23:59:59",
  "baseline_start_date": "2023-01-01T00:00:00",
  "baseline_end_date":   "2023-12-31T23:59:59",
  "module_name": null
}
Request Parameters

Parameter

Required

Description

start_date

Yes

Start of the current analysis period.

end_date

Yes

End of the current analysis period.

baseline_start_date

Yes

Start of the baseline period used for trend calculation.

baseline_end_date

Yes

End of the baseline period used for trend calculation.

module_name

No

Restrict analysis to a specific component.

Response:

{
  "items": [
    {
      "total_commits":            1808,
      "total_commits_trend_pct":  12.5,
      "avg_file_age_days":         47,
      "avg_file_age_trend_pct":   -5.3,
      "avg_complexity":            23.4,
      "avg_complexity_trend_pct":  3.1,
      "silo_ratio_pct":            18.2,
      "silo_ratio_trend_pct":      1.4
    }
  ]
}
Response Fields

Field

Description

total_commits

Total commit count in the current period.

total_commits_trend_pct

Signed percentage change vs. baseline (positive = more commits).

avg_file_age_days

Average file age in days across all files in the current period.

avg_file_age_trend_pct

Signed percentage change in average file age vs. baseline.

avg_complexity

Average cognitive complexity across all files.

avg_complexity_trend_pct

Signed percentage change in average complexity vs. baseline (positive = worse).

silo_ratio_pct

Percentage of files where a single developer owns ≥ 80 % of commits.

silo_ratio_trend_pct

Signed percentage change in silo ratio vs. baseline (positive = more silos).

Warnings

Returns the top-N warnings ranked by severity then normalised risk score. All warning types are derived exclusively from Git data — no external integrations required. Powers the warnings list on the overview dashboard.

  • URL: /v1/analysis/warnings

  • Method: POST

Request Body:

{
  "start_date":  "2024-01-01T00:00:00",
  "end_date":    "2024-12-31T23:59:59",
  "module_name": null,
  "limit":       10
}
Request Parameters

Parameter

Required

Description

start_date

Yes

Start of the analysis window.

end_date

Yes

End of the analysis window.

module_name

No

Restrict analysis to a specific component.

limit

No

Maximum number of warnings to return. Default: 10.

Response:

{
  "items": [
    {
      "module_name":  "PaymentService",
      "reason":       "critical_hotspot",
      "reason_label": "Critical Hotspot",
      "severity":     "critical",
      "metric_value": 94.0,
      "metric_unit":  "normalized_score"
    }
  ]
}
Warning Reason Codes

reason

reason_label

metric_unit

Description

critical_hotspot

Critical Hotspot

normalized_score

Relative risk score 0–100 (hotspot_score / max_hotspot_score × 100). Critical ≥ 90, high ≥ 70. Score is relative to the worst module in the selected period, not an absolute threshold.

silo_risk

Knowledge Silo

ownership_pct

File dominated by a single developer. Critical ≥ 95 %, high ≥ 80 %.

complexity_spike

Complexity Spike

trend_indicator

Rapid complexity growth. Critical > 4.0×, high > 3.0×.

churn_outlier

Churn Outlier

lines_changed

Absolute churn far above project average. Critical > 5× avg, high > 3× avg.

legacy_reactivated

Legacy Reactivated

days

File dormant > 365 days that is now being heavily modified (churn > 2× avg). Always high.

Results are ordered by severity (critical before high) then by normalised risk score descending.

Commit Count KPI

Returns the total commit count together with a growth percentage for use as a KPI indicator.

  • URL: /v1/analyze/commits/count

  • Method: POST

Request Body:

{
  "start_date":        "2024-01-01T00:00:00",
  "end_date":          "2024-12-31T23:59:59",
  "module_name":       null,
  "trend_window_days": 30
}

Response:

{
  "items": {
    "total_commits": 1808,
    "growth_pct": 12.5
  }
}
Response Fields

Field

Description

total_commits

Total commit count within the requested period.

growth_pct

Signed percentage change vs. the same window shifted back by trend_window_days (positive = more commits).

Complexity Average KPI

Returns the project-wide average cognitive complexity and its growth trend. Files with zero cognitive complexity (e.g. non-code assets) are excluded.

  • URL: /v1/analysis/complexity/avg

  • Method: POST

Request Body:

{
  "start_date":        "2024-01-01T00:00:00",
  "end_date":          "2024-12-31T23:59:59",
  "module_name":       null,
  "trend_window_days": 30
}

Response:

{
  "items": {
    "avg_cognitive": 23.4,
    "growth_pct": 3.1
  }
}
Response Fields

Field

Description

avg_cognitive

Average cognitive complexity across all files (latest value per file as of end_date).

growth_pct

Signed percentage change vs. the window shifted back by trend_window_days (positive = complexity increased).

Silo Count KPI

Returns the total number of silo files and its growth trend. Consistent with the other silo endpoints — uses the same threshold and noise filters.

  • URL: /v1/analysis/silos/count

  • Method: POST

Request Body:

{
  "start_date":        "2024-01-01T00:00:00",
  "end_date":          "2024-12-31T23:59:59",
  "module_name":       null,
  "silo_threshold":    0.80,
  "min_commits":       5,
  "trend_window_days": 30
}

All parameters are optional. Defaults: silo_threshold = 0.80, min_commits = 5, trend_window_days = 30.

Response:

{
  "items": {
    "silo_count": 14,
    "growth_pct": 7.7
  }
}
Response Fields

Field

Description

silo_count

Number of silo files in the requested period.

growth_pct

Signed percentage change vs. the window shifted back by trend_window_days (positive = more silos).


Configuration

Get Modules

Returns a list of all configured architectural components/modules.

  • URL: /v1/config/modules

  • Method: GET

Response:

{
  "items": [
    {
      "component_name": "src_core",
      "display_name": "Core"
    }
  ]
}
Response Fields

Field

Description

component_name

Internal component identifier as defined in config.yaml.

display_name

Human-readable label shown in the UI.

Runtime Context

Returns UI-facing runtime flags set by the server configuration. Clients fetch this once at startup to adapt their behaviour (e.g. hide author names in anonymised deployments, or enable demo-mode restrictions).

Note

This endpoint does not carry the /v1 prefix and is served outside the versioned API namespace.

  • URL: /api/context

  • Method: GET

Response:

{
  "anonymized": false,
  "demo_mode": false
}
Response Fields

Field

Description

anonymized

When true, author names are replaced with anonymised identifiers in all responses. Controlled by the context.anonymized flag in the server configuration.

demo_mode

When true, the instance is running in read-only demo mode. Write operations and certain configuration endpoints are disabled.

Average File Age KPI

Returns the project-wide average file age and its growth trend.

  • URL: /v1/analyze/age/avg

  • Method: POST

Request Body:

{
  "start_date": "2024-01-01T00:00:00",
  "end_date": "2024-12-31T23:59:59",
  "module_name": null,
  "trend_window_days": 30
}

Response:

{
  "items": {
    "avg_file_age_days": 47.5,
    "growth_pct": -5.3
  }
}
Response Fields

Field

Description

avg_file_age_days

Average file age in days across all files in the current period.

growth_pct

Signed percentage change vs. the baseline window shifted back by trend_window_days.


Get Analysis Start Date

Returns the configured start date for the current analysis session.

  • URL: /v1/config/analysis-since

  • Method: GET

Response:

{
  "items": {
    "analysis_since": "2020-01-01T00:00:00"
  }
}

API Info

Returns metadata about the currently running analysis session, including database paths.

  • URL: /info

  • Method: GET

Note

This endpoint does not carry the /v1 prefix — it is served at the root path.

Response:

{
  "analysis_database": "/path/to/analysis.duckdb",
  "config_database": "/path/to/config.duckdb",
  "debug": false
}

Architecture Review Briefing

Synthesises knowledge silo, owner inactivity, and cross-team coupling signals into a prioritised list of modules with recommended interview questions for sociotechnical architecture reviews. Based on the principle: “The data surfaces the questions, not the answers.”

Supports Markdown output via the Accept: text/markdown request header.

  • URL: /api/v1/analysis/review/briefing

  • Method: POST

Request Body:

{
  "start_date": "2024-01-01T00:00:00",
  "end_date":   "2024-12-31T23:59:59",
  "lang":       "de"
}
Request Parameters

Parameter

Required

Description

start_date

No

Start of the analysis window. Default: 90 days before end_date.

end_date

No

End of the analysis window. Default: today.

lang

No

Language for question and context strings. Supported: de (default), en.

Response (JSON):

{
  "items": [
    {
      "module":             "src/auth",
      "priority":           "critical",
      "signals": [
        {
          "category": "knowledge_silo",
          "severity": "critical",
          "context":  "12 von 14 Dateien mit Einzelpersonen-Wissen (87.0% Commit-Anteil)"
        },
        {
          "category": "owner_inactive",
          "severity": "high",
          "context":  "Letzter bekannter Hauptverantwortlicher (Alice) ist seit 102 Tagen inaktiv"
        }
      ],
      "suggested_question": "Was passiert mit src/auth, wenn Alice das Team verlässt?"
    }
  ]
}
Response Fields

Field

Description

module

Component/module name.

priority

Highest severity across all detected signals: critical or high.

signals

All signals detected for this module, sorted by severity descending.

signals[].category

Signal type: knowledge_silo, owner_inactive, cross_team_coupling.

signals[].severity

critical or high.

signals[].context

Human-readable context string with interpolated metric values.

suggested_question

Recommended interview question derived from the highest-severity signal.

Markdown output:

When the Accept: text/markdown header is set, the endpoint returns a formatted Markdown document instead of JSON — suitable for export to Confluence, Notion, or direct use in review preparation documents.

Signal Categories

Category

Severity

Trigger condition

knowledge_silo

critical / high

Module silo ratio ≥ 75 % (critical) or ≥ 50 % (high): the majority of files are owned by a single developer.

owner_inactive

high

The dominant owner has not committed to this module in > 90 days.

cross_team_coupling

critical / high

Module appears in cross-team coupling pairs. Critical when co-changes are in the top 20 % of all cross-team pairs.

Health Check

Returns the current health status of the API, database connection, and license. Intended for use by container orchestration systems (Docker, Kubernetes) and monitoring dashboards.

  • URL: /api/health

  • Method: GET

Note

This endpoint is always reachable, even when the license has expired. Use it to inspect license status without triggering HTTP 402.

Response fields:

Field

Description

status

"healthy" or "unhealthy".

database

"connected" when the DuckDB connection is available.

version

Calyntro version string (from Git tag or src/.version).

license.customer

Customer name from the license file.

license.type

"trial" or "full".

license.status

"active" or "expired".

license.expires_at

(trial only) Expiry date in YYYY-MM-DD format.

license.days_remaining

(trial only) Days until expiry. 0 when expired.

license.maintenance_until

(full only) End of maintenance period in YYYY-MM-DD format.

license.maintenance_days_remaining

(full only) Days until maintenance expires.

Response — trial license (healthy):

{
  "status": "healthy",
  "database": "connected",
  "version": "1.13.0",
  "license": {
    "customer": "ACME Corp",
    "type": "trial",
    "expires_at": "2026-08-21",
    "days_remaining": 29,
    "status": "active"
  }
}

Response — full license (healthy):

{
  "status": "healthy",
  "database": "connected",
  "version": "1.13.0",
  "license": {
    "customer": "ACME Corp",
    "type": "full",
    "maintenance_until": "2027-07-22",
    "maintenance_days_remaining": 364,
    "status": "active"
  }
}

Response (unhealthy, HTTP 503):

{
  "status": "unhealthy",
  "reason": "<error message>"
}

See Licensing for full documentation on license types, file placement, and renewal.