Skip to content

API Access (Team / Enterprise)

Everything on this site so far covers the free, self-hosted pipeline: import commit/PR data, then generate a PDF report on demand. Team and Enterprise plans add a REST/JSON API on top of the same database, so your own internal dashboards (Grafana, an internal tool, whatever you already use) can pull these metrics directly and on your own schedule, instead of regenerating and re-reading a PDF.

Like the rest of this pipeline, it's self-hosted: it runs in your own infrastructure, against your own database. Two credentials gate it -- a license key we issue you, and an API key you generate and control yourself (see "Auth" below for the difference). No data leaves your instance to make this work, and there's nothing to sign up for beyond the plan itself.

Endpoints

All endpoints return JSON and accept a required start/end date range, plus optional scoping (see below).

Endpoint What it returns
Author activity Per-author commits, lines added/removed, files changed, churn ratio, and active-days/week (a consistency-of-contribution signal) -- plus PR counts and average commits per PR.
Review health PR/merge counts, cycle time broken into pickup (open → first review) and review (first review → merge) stages with p50/p90 percentiles, per-reviewer load, and a review-load-balance (Gini coefficient) score.
Repo trends Weekly commit/PR volume and churn ratio, per repo.
Contributor concentration Per-repo commit-volume concentration (Gini coefficient + top-contributor share) -- same anonymized shape as review load balance above, applied to commits. A cheap "which repo might warrant a closer look" signal, not a per-person ranking.
Recency skew Per-repo decaying-ownership signal: total historical commits/contributors vs. how many of those contributors are still active in the last 90 days (window_days in the response). 0 means everyone historical is still active; approaching 1 means most have gone quiet. Same cheap-trigger family as contributor concentration.
Team-to-repo activity mismatch Per-team, per-repo coverage-gap signal: for each configured team, discovers its presumed-core repo(s) the same way team scoping does, then reports the gap between roster size and how many roster members are actually active there (lookback_days in the response). Scoped differently from every other endpoint -- see "Scoping" below.
Contributor departure/reassignment impact For each real team-membership change you've recorded (a separate, optional team-events log -- see "Team events" below), checks whether that person stopped contributing to a repo they were actually active on before leaving. The one endpoint that returns a named individual (their email) rather than an anonymized aggregate -- deliberately, since it's about a real personnel event. Scoped differently from every other endpoint -- see "Scoping" below.
Ticket-to-first-commit lead time Hours from a ticket's creation to the earliest commit (any repo) whose message referenced that ticket's key -- a best-effort regex match on the commit message, not a Jira-verified link. Requires the allocation-tracking flow (same one Investment Allocation uses). linked_count/total_tickets shows what fraction of tickets in the period were actually referenced in a commit message at all. Not scoped by repo/org/team -- see "Scoping" below.
Ticket scope mismatch Story points vs. actual lines changed for each ticket that has both, ranked by deviation from the overall median ratio -- there's no universal correct ratio, only whether a ticket is unusual relative to your own team's typical one. Not scoped by repo/org/team -- see "Scoping" below.
Planning signature Per-ticket composite of lead time, post-PR-open commit churn, and change size, each bucketed low/mid/high relative to your own tickets in the period -- only two combinations are named ("high-risk": fast + unreviewed + big; "well-planned": slow + iterated + small), everything else is unlabeled. Needs a linked commit and a linked pull request to be eligible, and at least 9 eligible tickets in the period for the buckets to mean anything. Not scoped by repo/org/team -- see "Scoping" below.
Cycle time The pickup/review/total percentile breakdown as its own endpoint, for dashboards that only need that slice.
Deployment frequency Weekly deployment counts per repo (every git tag counts by default; scope down to a real deploy-tagging convention with a tag-pattern filter, see DORA Metrics).
Lead time for changes p50/p90/avg hours from a commit to its nearest later tag.
Change failure rate Percentage of deployments (tags) linked to a Jira incident via that incident's Fix Version field, exact-matched to the tag name. Requires the optional issue-processor Jira integration -- returns 0/null with jira_configured_repo_count: 0 if it isn't set up, not a misleading 0%.
Mean time to restore (MTTR) p50/p90/avg hours from a linked incident's creation to its resolution. Same issue-processor dependency as change failure rate above; still-open incidents are excluded from the average but reported separately as open_excluded.
AI usage Per-author and org-wide weekly trend of commits with an AI-tool Co-authored-by: trailer (the same convention GitHub itself reads to show a tool's avatar on a commit) -- a lower bound on AI-assisted work, not a precise measurement.
Investment allocation Ticket/story-point distribution, allocation trend, cycle time, and logged time, per Jira-ticket category. Requires issue-processor's separate allocation-tracking flow (independent of the CFR/MTTR one above). Not scoped by repo/org/team at all -- see "Scoping" below.
Author distribution trend Weekly p50/p90 (never a per-author number) of commit count, churn ratio, and active days -- the anonymized, ranking-safe alternative to a per-author leaderboard.
Reviewer distribution trend Weekly p50/p90 of reviews-per-reviewer, same anonymization reasoning as above.
Commits-after-open distribution trend Weekly p50/p90 of avg commits pushed after a PR was opened, per PR.
Executive report On-track/at-risk/off-track status, weekly trend, and a fixed suggestion per configured KPI (8 defaults covering deployment frequency, lead time, change failure rate, MTTR, bug effort share, feature delivery, high-priority bug share, and overdue ratio -- 4 more available opt-in), plus a budget/resource snapshot reusing Investment Allocation's own data. Requires the Enterprise plan specifically -- see "Getting access" below. Not scoped by repo/org/team at all -- see "Scoping" below.

Deployment frequency, lead time, change failure rate, and MTTR are the four canonical DORA metrics -- all four are available here. See DORA Metrics for how deployments are counted.

Scoping

Every endpoint accepts:

  • repo (repeatable) and/or org -- limit to specific repos, same as the free CLI's --repo/--org.
  • team -- limit to a team's repos and (where the data has a real git author identity, like commits and AI usage) filter to that team's own members, not just repos they happen to touch. Requires a team roster to be configured. PR/review data and deployment frequency can't be attributed to a team the same way (a PR author is a vendor-API username, not a git email; a tag isn't authored by anyone), so those stay repo-scoped.

repo/org and team are mutually exclusive.

Investment allocation is one exception -- it accepts none of repo/org/team. Jira tickets have no repo relationship (allocation tracking is purely Jira-side data), so there's nothing to scope by; it always returns one combined view across every tracked Jira project.

Team-to-repo activity mismatch is another exception, in the opposite direction -- it accepts no repo/org at all, and always scans your whole org to discover each configured team's own presumed- core repos. team is still accepted, but only to narrow the returned rows to one team afterward, not to change what gets scanned.

Contributor departure/reassignment impact accepts no scoping params at all -- it evaluates each recorded team-membership change against that specific person's own commit history directly.

Ticket-to-first-commit lead time and ticket scope mismatch also accept no scoping params at all, same reasoning as investment allocation -- ticket data has no repo relationship.

Executive report accepts no scoping params either -- it's deliberately one org-wide view, not a drill-down tool, same as investment allocation above.

Team events

A separate, optional log from the team roster above: email,team, action,date rows (action is added or removed), recording real team-membership changes over time -- your roster (team scoping) is a current-snapshot, this is history. Only used by the contributor departure/reassignment endpoint. Configuring one doesn't require the other.

Example

curl "https://your-instance/v1/author-activity?start=2026-01-01&end=2026-04-01&team=Platform" \
    -H "Authorization: Bearer <your key>"
{
  "commit_activity": [
    {
      "author_email": "alice@example.com",
      "author_name": "Alice Anderson",
      "commits": 47,
      "added": 1704,
      "removed": 340,
      "churn_ratio": 0.17,
      "active_days_per_week": 1.6
    }
  ],
  "meta": {
    "start": "2026-01-01T00:00:00Z",
    "end": "2026-04-01T00:00:00Z",
    "team_scope": {"team": "Platform", "repo_count": 20}
  }
}

Auth

Two separate credentials are involved, easy to conflate since both are just an env var and a header -- don't mix them up:

  • License key (GITULTRA_LICENSE_KEY) -- gates the deployment itself. We issue this to you after you get plan access (see "Getting access" below); it's not something you generate. The service checks it once at startup and refuses to boot without a valid one -- see eng-api's README for details.
  • API key (API_KEY/ENG_API_KEY, sent as Authorization: Bearer <key>) -- authenticates your own dashboards' requests to your already-running instance. You generate this yourself (see below); we never see or store it.

Every request needs Authorization: Bearer <key> using the API key (not the license key). Once you have plan access, there's no separate account/key request step for the API key -- only the license key comes from us.

Manager-scoped endpoints

The endpoints above are org-wide, gated by your one shared API key. These four are different: they're scoped to a single manager's own team(s), and gated by that specific manager proving control of their own email address first -- see "Manager verification flow" below.

Endpoint What it returns
Manager contributor summary Per-contributor commit/PR activity for one team you manage, for one period. Pass person (an email) to narrow to one team member.
Manager period comparison The same team's current period vs. the immediately-preceding period of equal length, side by side -- commit activity and cycle time for both. There's no separate "period B" input; the comparison window is always computed for you.
Manager team trend Weekly commit/PR volume per repo, pre-scoped to one team you manage -- the manager-authenticated equivalent of Repo Trends above.
Manager email-team-report Triggers a fresh, on-demand PDF of one team's report, emailed to your own on-file address -- never any other address, even if the request tried to say otherwise. Defaults to the last 30 days if no dates are given.

These require the team roster CSV's role/managed_teams configuration (see Generating Reports) -- querying a team you don't manage returns a 403, not another team's data, or "no data."

Two-header auth model

Every manager-scoped endpoint needs both headers on every request, not just the API key:

  • Authorization: Bearer <API_KEY> -- the same shared install-wide key every other endpoint on this page requires.
  • X-Manager-Token: <token> -- a second, per-manager credential, obtained via the verification flow below. The API key alone is not sufficient for these four endpoints.

Manager verification flow

  1. POST /v1/manager/request-code with {"email": "<manager's email>"} -- always returns {"status": "sent"}, whether or not that email is actually a manager on file (this is deliberate: it stops someone from mapping out your manager roster by trying different emails and comparing responses). If it is a real manager, a 6-digit code is emailed to that address via your own configured SMTP (SMTP_HOST etc. -- see Scheduling for the same SMTP variables), expiring in 10 minutes. Five wrong guesses locks that code out; request a fresh one to recover.
  2. POST /v1/manager/verify-code with {"email": ..., "code": "123456"} -- returns {"token": "...", "expires_at": "..."} on success. Use that token as X-Manager-Token on every call to the four endpoints above for the next 24 hours; after that, verify again.

Org-level roles (Admin / Executive / Director)

Above team level, three org-wide roles cover the cases the manager flow above doesn't: an executive who wants the big picture with no team drill-down, a director who wants team-level detail across teams they don't personally manage, and an admin who needs full access (including individual-contributor data) for troubleshooting -- an audited, per-person alternative to sharing the flat API key. Verified through the exact same two-step email flow as managers above (POST /v1/manager/request-code / POST /v1/manager/verify-code, same X-Manager-Token header) -- a person just needs a row in org_roles.csv instead of (or in addition to) a manager row in the team roster CSV. See Generating Reports for org_roles.csv's format.

The three roles are not a simple more/less hierarchy -- each has a different shape of access:

Access Admin Executive Director
Org-level reports/metrics Yes Yes Yes
Team-level reports/metrics (any team) Yes No Yes
Individual-contributor metrics Yes No No
Executive Report Yes Yes No
Endpoint Roles What it returns
Org team trend Admin, Executive, Director Same as Manager team trend, but org-wide when team is omitted (Admin/Executive/Director), or for any single team when team is given (Admin/Director only -- Executive gets a 403).
Admin contributor summary Admin only Same as Manager contributor summary, for any team, not just ones you manage.
Admin period comparison Admin only Same as Manager period comparison, for any team.
Admin email-team-report Admin only Same as Manager email-team-report, for any team -- still only ever emailed to your own on-file address.

GET /v1/executive-report (see above) additionally requires an Admin or Executive role once ORG_ROLES_PATH is configured -- on an install that hasn't set that up, it works exactly as before (API key alone).

Updating the roster without a restart

Two admin-only endpoints let an Admin update team_map.csv/ org_roles.csv live, no restart required -- useful for routine roster changes on an otherwise long-running install:

  • POST /v1/admin/team-map
  • POST /v1/admin/org-roles

Both take a real file upload (multipart/form-data, field name file), gated by Authorization: Bearer <API_KEY> and X-Manager-Token from an Admin-role token. Each upload replaces the target file's entire contents (not a patch -- include every row you want kept) and is validated in full before anything is written: a malformed CSV, a non-UTF-8 file, or (for org_roles.csv specifically) an upload that would leave zero admin rows all return a 4xx and change nothing on disk or in memory. A valid upload takes effect immediately, for the very next request.

This requires the target file to live somewhere the eng-api container can actually write to -- see Getting Started (or eng-metrics-suite-pro's docker-compose.yml) for the writable-subdirectory mount these two endpoints need. Hand-editing either CSV directly on disk still works exactly as before and still requires a restart to take effect -- these two endpoints are an additional option, not a replacement.

Generating an API key

Any sufficiently random string works -- a UUID, a password manager's generator, whatever you already reach for. If you don't have a preferred method:

openssl rand -hex 32

or, without openssl:

python3 -c "import secrets; print(secrets.token_hex(32))"

Set the result as ENG_API_KEY in your .env (if you're running the eng-metrics-suite-pro compose bundle) or as the API_KEY environment variable directly (if running the container standalone) -- then send it back as Authorization: Bearer <that value> on every request. Treat it like any other credential: don't commit it, and rotate it (just generate a new one and restart the container) if you suspect it's leaked.

Getting access

Available on Team and Enterprise plans -- see gitultra.com for plan details, or apply for beta access there if you're interested. Once you have access, we issue you a license key (GITULTRA_LICENSE_KEY, valid 90 days, renewed on request) -- set that alongside the API key you generate yourself (see "Auth" above) and you're running.

The executive report endpoint is Enterprise-only -- every other endpoint on this page works on the Team plan. If your license doesn't cover it, that one endpoint returns a 403 (everything else keeps working); ask us for a reissue if you upgrade.

Want to query these same metrics conversationally, from Claude Desktop or Claude Code, instead of calling the API yourself? See AI Agent Access.