Avium Platform
Audience Leadership · Product · Eng Status Current
Avium
See the work. Plan the capacity. Catch the risk.
AI delivery intelligence + Visibility, Capacity, and Risk management across every project.
Ask anything about your work — capacity, flow, risk, and when you'll really ship. Get answers grounded in your own Jira data — or any work management tool — and act on them with one click back to your tool (two-way write-back live for Jira, Azure DevOps and Asana).
Version
v2.4.0
Visibility
Who's working on what — across every project
Capacity
Whether your team can take on more work
Risk
Where delivery is at risk before it happens
How Your Data Flows
From source to insight — what Avium does with the data you give it
01 Ingest
02 Process & Transform
03 Deliver
01 Ingest
📊
Excel Import
Spreadsheet ingest
  • File upload (.xlsx, .csv)
  • Column-to-field mapping wizard
  • Avium Files — org document storage (R2): folders, preview lightbox, downloads, per-plan quota
  • Field alias recognition
  • Collision detection vs Jira data
  • Preview before commit
  • Explicit re-upload mode: refresh (merge) or full replace (reconcile-to-match; absent items soft-archived, restorable)
  • Post-import delta report: progressed / slipped / new / restored / archived (Team+)
🔗
Jira Import
API-driven sync
  • OAuth + API token auth
  • Project & sprint wizard
  • Native statuses pass through 1:1 (never remapped)
  • Cursor-paginated JQL sync
  • Issue links → ticket dependencies
  • Parent / sub-task links resolved
  • Protected (erm_created skipped)
Excel · .xlsx
Jira · REST API
02 Process & Transform
Avium Platform
Unified data plane · processing engine · governance
Core
Import Mapping Layer
Ingests the full Jira field set — promotes the Agile/planning fields to typed columns, captures the long tail in rawFields (JSONB) · resolves custom-field IDs per instance · resolves phases · tags dataSource. If a plan's ticket limit is ever reached, any un-imported work is disclosed honestly — the exact skipped count surfaces on the Dashboard, Reports, the daily briefing, and the API (meta.coverageComplete), never hidden as if the import were complete. Per-source freshness is disclosed the same way: each connected source (Jira, Azure DevOps, Asana) carries its last successful-sync age, so a stale, silently-failed, or never-synced source is surfaced (Dashboard, Reports, briefing, and the API meta.sources) rather than pooled into one green "on track" number. Custom capacity fields (planned effort, story points, release) are never guessed at: the Data & Fields page (/admin/fields; RULE 24, lib/dataRequirements.ts) is a thin source-switched orchestrator (FieldMappingPage.tsx) over two views that share the same underlying discovery/proposal/confirm machinery. For JIRA orgs (phase 1) it opens on the v5 signal-first view, "Required fields to get Avium Signals" (SignalFieldsView.tsxGET /admin/field-mapping/requirements, lib/signalRequirements.ts, Brian's drawing, hi-fi-approved 2026-07-17): a framing box states the live count computed off the Signal registry ("Avium ships N Signals — only the M decisions below need you"), and one block per real decision — Estimated effort per work item, Story points, Releases/milestones — each led by the Signals it unlocks, showing Avium's own detected native-field proposal ("Import detected field = Original estimate") with a Yes/No, or a searchable dropdown of alternatives. Time actually spent and Blocked render as plain "read automatically" rows, not decisions; Blocked additionally keeps its own real opt-in for a custom flag field, and a confirmed Blocked mapping now actually projects into detection (new JiraTicket.flaggedMapped column, re-run on every sync and every confirm/removal, detection reads flagged OR flaggedMapped — previously this control saved a mapping nothing read, a silent no-op). The three pop-ups Brian kept carry over unchanged: the epic-rollup question (does the epic's own estimate already cover its children?), the three-step release flow (field → date source → preview), and the decline acknowledgment naming the exact Signals a decline darkens before it takes effect. For non-JIRA sources (a spreadsheet today; Azure DevOps and Asana keep this page unchanged until their own pass, Law 4) the page opens on the untouched receipt/question/kept view (ReceiptMapperView.tsx, AVM-284, lib/fieldDiscovery.ts + lib/fieldReceipt.ts), not an interview. It opens on a walkable RECEIPT of every native concept Avium already reads without asking — Original Estimate, Remaining Estimate, the dated Work log, the Time Spent rollup, Story Points, Linked issues (dependency blocking), the impediment flag, and Sprints & Fix Versions — each row stating its coverage (the shared 300-ticket sample, or a real-time full-scope count where the concept demands it), real sample values, and, where a real filter exists, a "See the rows →" link straight into /pipeline scoped to the exact tickets behind it (never an invented route). A question appears only where one genuinely exists: a REQUIRED concept Avium can't resolve on its own (today: the estimated-effort field, story points) renders an amber "Needs an answer" card with a coverage-ranked candidate rail, evidence (sample values), a full-registry name/id search, and "We don't use this" as a reversible decline — one that carries real weight when it does: declining a concept with darkensSignals opens an acknowledgment modal naming the exact Signals going dark, drawn from the coverage matrix server-side (never hand-maintained copy), before the decline takes effect. An ENRICHMENT concept already covered by a native feed — today, Blocked/impediment, since Jira's own flag and issue links already power blocker detection — asks quietly as an optional extra with no amber badge and no acknowledgment: nothing goes dark either way. A source with a structural gap (Excel and Asana carry no change history) shows a one-time, plain-language acknowledgment of exactly which history-driven Signals can't fire on that source, collapsing to a quiet reopenable line once acknowledged. A dashed "We kept your other N fields" box lists the org's remaining custom fields, verbatim from the discovery scan. An org with more than one connected source (Jira and a spreadsheet in v1) gets a Source selector rendered by the orchestrator above either view, so the receipt (or the v5 blocks), the questions, and every coverage count scope to ONE source at a time — never a blended count across sources. The underlying capability-contract computation (GET /api/capability-contract, readable by every role, RULE 16; changing it stays admin-only) still drives the post-sync banner and the Dashboard's provenance strip the same way it always has — both views now consume it internally to decide which questions are still open, rather than surfacing it as four visual cards. File import writes each row's own columns into rawFields just like the Jira path, so a spreadsheet's real column headers surface in the receipt and question cards with evidence, mappable exactly like a Jira custom field; lib/excelFieldBridge.ts reconciles the file-import wizard's mapping with this page's requirement vocabulary so a column mapped on either surface closes the matching question on the other, never disagreeing. Resolution precedence is explicit and never silent: the org's CONFIRMED mapping (lib/confirmedFields.ts) outranks the instance's own field metadata. Story points carry NO further fallback beyond that (Brian's decision, 2026-07-16, AVM-289 — "Don't assume — ask"): an instance whose custom-field id Avium can't resolve any other way stays honestly dark rather than guessing the historical customfield_10016 default, which a differently-numbered instance could silently get wrong. (Sprint and Epic Link keep their own disclosed last-resort defaults — AVM-289's scope was story points only.) A confirmed story-points mapping resolves at the very next sync AND backfills immediately, so the numbers move the moment an admin answers, not at some unknowable future sync. A confirmed planned-effort mapping projects into DepartmentAllocation (lib/mappedEffort.ts, source='mapping', re-run on every sync) so it flows into capacity, velocity and utilization exactly like a hand-entered allocation — hand-entered rows are never touched. The mapper proposes, never polices, for VALUE-shape doubts (RULE 24): a field whose sample values look off (Fibonacci-looking hours, >100 "points") warns loudly on its candidate chip via shapeWarning and goes through on the admin's own call, because there the customer may genuinely know something Avium doesn't. A STRUCTURAL type mismatch is a different class and is REFUSED, not warned (Brian, 2026-07-17, Data & Fields v5 — reverses the prior "loud warning, never a refused drop" rule after the Issue-Type-proposed-as-releases incident): typeGate in lib/dataRequirements.ts is the one authority, enforced in three places — discovery's candidate lists, the mapping page's dropdown, and POST /field-mapping/confirm, which answers 422 if a structurally impossible field (a user field as releases, an option field as hours) is forced through anyway. An UNKNOWN type (no registry row, uninferrable samples — a sparse Excel column) still passes with a warning: the gate blocks known incompatibility, never missing metadata. Splitting an estimate across roles ("Dev Est" → Engineering, "QA Est" → QA) is no longer part of this page's main flow — the old per-field "whose time is this?" attribution interview is deferred; a link is shown for that case but the dedicated per-role flow isn't built yet, and every requirement here confirms as a single owner in the meantime. Release is itself a mapped concept (lib/mappedReleases.ts): any option, text, or label field can name an org's releases — each distinct value projects into a FixVersion row (source 'mapping') with its items linked, feeding the release filter, the milestone forecast, and the delivery-date signals on the org's own vocabulary — confirmed through a three-step flow (field picker with evidence → an explicit date-source step → a dry-run preview of exactly what confirming would create), ported behavior-for-behavior into the rebuilt page. The release date is the org's own answer, never Avium's guess: the latest date among an item's own confirmed date field (recomputed on every sync), a date typed directly in Avium (never overwritten by sync, never written back to the source), or honestly none — grouping and the filter still work, the date-risk signals stay off and say why. A ticket already linked by the source tool's native fixVersions is never re-linked, and confirming the standard fixVersions field simply hands authority back to native ingest. Above the ticket level, the Effort Rollup Engine (lib/effortRollup.ts) answers a different question — how much effort sits under a given epic/feature/story, at any depth: an item's OWN effort and its ROLLED-UP effort (the sum of every descendant's own effort) are two facts that coexist and ADD, never persisted, always derived at read time (RULE 26) — and lib/sourceLink.ts gives every contributing item a link straight back to its own row in Jira, Azure DevOps or Asana, so a rolled-up total is never a bare claim: it decomposes, click by click, to the customer's own tickets. The dedicated Rollup page (/rollup, client pages/RollupPage.tsx) puts this engine on its own top-level surface: GET /api/rollup/tree (lib/rollupTreeService.ts → computeRollupTree(), optional ?rootId= to scope one subtree) walks a parent's full Epic→Story→Sub-task tree and returns three rolled columns per row — Logged (Σ TimeLog.hours), Committed (Σ DepartmentAllocation.plannedHours), and Estimated (the item's own estimate; hours or, in points mode, story points, with the hours columns dropped rather than fabricated) — each carrying per-column coverage ("6 of 8 items" / "not planned") and a click-through walk to its exact contributing tickets. It's an app endpoint, not a /v1 shape — the frozen GET /v1/work-items/:id/effort-rollup single-item walk below is unaffected.
excel_import jira_import
Work Management Core
The engine — what Avium actually does
Engine
Workload Board
Sprint Planning
Resource Capacity
Time Tracking
Phase Pipeline
Velocity & Throughput
Allocation Planning
Effort Rollup
Dashboards & KPIs
Signals Engine (Team+)
AI Layer (Business+)
Export Mapping Layer
Translates the internal schema back into Jira fields & Excel columns · write-back eligibility · plan gating
jira_modified erm_created jira_import
Excel · .xlsx
Jira · REST API
03 Deliver
📤
Excel Export
Round-trip ready
  • Combined workbook (single export)
  • Individual CSV per entity table
  • Headers match import wizard
  • Filtered scopes (project, sprint, dept)
  • Time logs · resources · allocations
↗️
Jira Write-back
Sync to source of truth
  • Field updates (summary, points, priority)
  • Status changes via Jira transitions
  • Sprint & fix version assignment
  • Review & push: preview every staged change by kind, resolve conflicts inline, commit in one audited step
  • erm_created & excel_import skipped
🔌
Avium API · Webhooks
Risk → your systems (Enterprise)
  • signal · blocker · briefing · lever events
  • HMAC-SHA256 signed, grounded payloads
  • Exponential-backoff retry + replay
  • SSRF-validated · per-endpoint limits
  • Lands in Teams / ServiceNow / PagerDuty — no new login
Auto-sync · Real-time · Automations
The event-driven integration layer
  • Scheduled auto-sync per source — OFF by default, admin-armed
  • Real-time inbound webhooks: verified “doorbell” triggers Avium’s own incremental sync — payloads never ingested
  • Per-source verification: Jira capability token · Azure basic auth · Asana handshake HMAC
  • Avium Automations: event + scheduled rules → email or webhook (Enterprise)
  • Per-rule immediate vs daily-digest delivery + per-recipient hourly cap
The Avium Signals Engine
The engine is Avium's proprietary core — domain-specific rules that produce every insight card. Your data, your rules, runs without an LLM API key. ~80% of the Insights page works on the engine alone. AI sits on top as a narrative layer; the engine is the moat.
Signals Engine · Layer 1
Team+
  • Milestone Risk — Monte-Carlo on-time forecast against the org's chosen planning milestone (sprint end · release date · custom date field), not sprints only; the drilldown triages EVERY driver ranked by impact on the date (count × date-relevance), each with its lever. A regime (recoverable / lost / ended) drives an honest call: at 0% the move becomes "set a date you can hit" (re-baseline), not "protect the date"; a passed milestone offers refresh-or-roll-forward, never "re-plan a finished sprint"
  • Kanban Flow Health Catch — the peer engine for continuous-flow teams with no date (Organization.deliveryMode = sprint | kanban, auto-inferred from the milestone or pinned in Settings, with a per-team override (Team.deliveryMode, precedence team → org → auto) so a continuous-flow team inside a sprint org gets the flow lens scoped to its own work; the two engines coexist, one surfaced at a time). Grounded in the Kanban Guide v2025.5 / Vacanti: the four flow metrics (WIP · Throughput · Work Item Age · Cycle Time), a Service Level Expectation — shown to users as the Delivery Time Target (plain-language label; "SLE" reads as jargon, so every user-facing surface says "Delivery Time Target" while the data identifiers keep sle*) — auto-derived as the 85th percentile of the org's own cycle-time distribution (or an admin-pinned target via Organization.flowSleTargetDays) — the deadline-less "on time", a Monte-Carlo flow forecast on real throughput ("how many by date D / when will the open work clear", 50/85/95) reusing the sprint simulator, and risk signals — throughput run-rate falling, WIP backing up (arrival > departure — now also checked against the top of the throughput Projected Delivery Band, the flow-native peer of the velocity projection built from the same velocityForecastService.ts bootstrap over perWeek history, so "WIP is backing up" also names when intake is arriving above the pace the team's own history supports), work-item age past the SLE (the flagship leading indicator, with a per-item nudge lever), and configurable per-column WIP-limit breaches (WipLimit table, admin-set per status). The flow drill also renders a Cumulative Flow Diagram (lib/cfd.ts · GET /intelligence/cfd) — the canonical stacked-area picture where the vertical arrival→done gap is WIP, grounded in the CFD literature (definitions research-locked, cited to Kanban University / Vacanti / the CFD canon — never to the Kanban Guide, which defines only the four metrics). Plugs into the same compute→derive→emit→score→drill spine and Avium Priority Score (date-impact scaled by the flow verdict, not a forecast) (server/src/lib/flowEngine.ts · deliveryMode.ts)
  • Completion Model 1.0 See + Catch — one canonical completion timestamp (JiraTicket.completedAt = when the item last entered a done-stage status) behind every time-based metric (Throughput, Cycle/Lead Time, CFD, flow forecasts). Three-rung evidence hierarchy: witnessed (Jira changelog transitions — with a truncation guard that pages long histories; ADO state-transition history ingested from the work-item updates API (AVM-166 — giving Azure orgs the same Cycle/Lead Time, CFD, and flow-efficiency anchors as Jira) plus system-stamped ClosedDate/StateChangeDate; Asana completed_at; board moves inside Avium, which also record a TicketTransition so Avium-native teams get cycle time) → declared (a completion-date column in a file import) → unknown-and-disclosed (excluded from windowed metrics with the count shown on the surface — never approximated from an edit date, an assumed window, or a diff between imports). Reopens clear the timestamp; re-completion re-stamps it. Every value carries provenance (completedAtSource: witnessed · declared · asserted): AVM-167 adds the audited "correct the record" endpoint (PATCH /tickets/:id/completion, Avium-owned + done-stage only) so a human can assert a known date — audit-logged old→new, marked "set by hand" in the UI, and never confusable with recorded history (docs/completion-model-1.0-spec.md · lib/completionModel.ts)
  • Over-Allocation — anyone committed above 105% of capacity
  • Rebalance — spare capacity in the SAME department as the over-allocated person
  • Velocity Drift — last sprint < 65% of period peak (cliff) or 12% trend swing, plus a future (not-yet-started) sprint already committed above its scope's Projected Delivery Band — a closed-form bootstrap of that scope's own visible velocity history (empirical percentiles; low = the pace cleared ~85% of the time, high = cleared ~15% of the time), gated honestly (no band under 2 closed sprints; a coarse min–max range with the median suppressed under 5), computed only on unfiltered org views. Both drivers stay investigate-only — no one-click fix (server/src/lib/velocityForecastService.ts, AVM-172)
  • Blocked / Stale — flagged tickets OR no activity for X days (per phase)
  • Blocker Aging Catch — blocked / dependency detection is otherwise memoryless, so it can't see how long a block has lasted. A first-class Blocker table persists every live blocker (flagged · stuck-in-review · stale · dependency), stamped firstDetectedAt on the daily snapshot loop; the engine then emits a blocker-aging Avium Signal the moment a blocker passes the threshold (3d, admin-tunable), grounded against the live signal so a cleared block never ages. It rides the existing Unblock / Clear levers — no new lever — and other surfaces read the same rows via GET /intelligence/blockers with server-computed ageDays (server/src/lib/blockerEngine.ts)
  • Data Quality — weighted penalty for missing assignee / estimate / sprint / due date
  • Lead Time Configurable — days from your chosen start phase to Done · P50/P75/P90 percentiles · any user picks the start phase
  • Time in Status Configurable — per-phase dwell (median, P75, P90) + currently-stuck list · stuck threshold configurable · bottleneck detection
  • Dwell / Stuck-in-phase — Insight card emits the moment ANY ticket dwells past the threshold · clicks open a drill-in modal listing every stuck ticket
  • Reopen Rate Configurable — % of resolved tickets that bounced back from Done · quality + acceptance-criteria signal · drives the next sprint's QA priorities
  • Sprint Scope-Change Configurable — per-sprint added / removed tickets after the sprint started, each tagged with its current status so you can tell a still-open commitment from one that snuck in but already shipped · planning-discipline signal most tools don't surface
  • Sprint Creep — Insight card emits on ANY mid-sprint addition to the active sprint · drill-in lists every added ticket with author + timestamp
  • Flow Efficiency Configurable — active-phase time / total lifecycle · Lean staple · industry typical 15-25% · also a Dashboard headline KPI
  • Hand-off Cost Configurable — assignee-change count per ticket · high counts predict slower cycle time + reopens
  • Delivery Knowledge Graph Knowledge Graph — people · work · sprints · epics · dependencies · signals as one React Flow graph, the visual twin of the briefing (Web ⇄ Risk Path), linked to The Brief (hover a finding → its subgraph lights up) with a temporal replay scrubber; each signal node is coloured by its Avium Priority severity (critical = danger-red + halo, warning = amber) and carries its Avium Priority Score on the node itself, and the side panel's resting state is a "Signals by priority" rail ranking every risk-path signal by its Avium Priority Score (critical first, grounded "How it's calculated" per row, click → isolate that path), with off-path signals (velocity, data quality) surfaced as a "+N in The Brief" link — severity colours the whole node, never an invented per-item split; the sprint node surfaces the Monte-Carlo on-time forecast (probability, P85 finish date, on-track/at-risk/off-track verdict, items likely to spill past the deadline) — the same forecast the briefing stands on, now grounded on the evidence map (payload.sprint.forecast), and the leader-summary reason chips carry their per-reason Priority Score; the same endpoint serves a ticket-context mode (?ticketId) — the graph scoped to that ticket's own sprint and trimmed server-side to its ego-graph (owner · blockers · epic · attached signals), embedded as the "In Context" section at the bottom of every ticket detail modal; every ticket key listed in the Reports cards is clickable and opens that same modal (resolved via GET /tickets/by-key/:key — report payloads carry keys, not DB ids), and the loop closes on the graph itself: selecting a work-item node offers "Open the ticket card" (double-click does it directly); and a Focus drawer scopes the graph (and The Brief — they share one Focus via the filter store) to a non-time-bound "family tree": ?parentIds switches the engine into a parent-anchored mode (buildParentGraph) that resolves the full descendant subtree under the chosen parents across all sprints — bypassing the sprint-anchored intelligence path entirely so The Brief's engine is untouched — grounds blocked/flagged risk straight from the rows and rolls it up per parent (the red/amber badge on each epic node), with project/sprint/release as optional narrowers (scope the family tree to one or more projects from any source) and a server-searched, source-agnostic parent picker (GET /intelligence/parents, labelled by the source's native issue type — Jira Epic, Azure Feature/Epic, Asana Project) that scales past thousands without truncating
  • Workflow Sankey Configurable — process-mining over real status transitions · backward moves tinted amber · noise floor configurable · the flagship Phase 5 visualization
  • Unassigned Work — open active-sprint items with no owner · drill assigns each to spare capacity on the spot (closed loop)
  • Ping-Pong Anti-Pattern Configurable — tickets bouncing A↔B between two statuses · org's signature bottleneck pair surfaced · emits an Insight card on ANY cycle
  • Avium Agents — Action Items (the lever) Catch — each actionable Signal is derived into a persisted, grounded ActionItem lever (Rebalance · Unblock · Clear · Assign for sprint capacity, plus the Kanban flow levers Nudge — an in-progress item aging past the SLE, grounded in signal:wip-aging — and Reflow — a column over its WIP limit, grounded in signal:wip-limit; both flow signals live in NON_GRAPH_SIGNAL_IDS so they ground a lever but never hit the Knowledge-Graph / REASON lookup), deduped by fingerprint and carrying its source dataSource for per-source apply routing; the Brief's "Do today" strip records accept/dismiss (PATCH /intelligence/action-items/:id, audit-logged) and opens each lever's drill focused on its own target (the lever's targetId threads through as the drill's scope — a per-ticket "Clear" pins that ticket, never the generic aggregate list); the CTA is honest per kind — real-apply levers (Rebalance · Assign) route Accept into the "Apply the move" mutation, investigate-only levers (Unblock · Clear · Nudge) say "Review & nudge" and open the ticket-focused list where the Nudge email lives, the column-level Reflow lever says "Review the column" and opens the WIP-limit view, never a fake apply (client/src/lib/leverDrill.ts). Once a move is applied, Notify the team drafts the announcement to recipients derived from the move — the affected people, their team, and the team's lead (Team.leadResourceId, set on Departments & Teams, so the accountable owner isn't blindsided) — with a "+ Add person" escape hatch for anyone else; transactional, no opt-out. Sync reconciles levers idempotently (create / refresh / expire) and never resurrects a user-resolved one (server/src/lib/actionItems.ts · leverConfig.ts)
  • Planning Milestone + Re-baseline Plan — admins choose what date the engine plans against in Settings (Organization.planningMilestoneType); release teams forecast off trailing-week throughput when there's no sprint history, and date-less Kanban teams switch to the Kanban Flow Health engine entirely (above), so the risk surface works for every non-Scrum team. A lost milestone records an Avium-internal re-baselined date (MilestoneBaseline; never written back to the source) that the Brief echoes and Notify-the-team communicates (server/src/lib/targetDeadline.ts · milestoneForecast.ts · milestoneRegime.ts)
AI Layer · Layer 2
Requires Anthropic key
  • Business+ AI Briefing — sprint narrative at top of Insights
  • Business+ Sprint Risk Forecast — likelihood + drivers + recommendations
  • Business+ Data-Quality Fixes — plain-English fix suggestions
  • Business+ Sprint Review Draft — first-draft retro from sprint data
  • Business+ Ask Avium — ask anything in plain English; an agentic loop calls read-only tools over your own data and answers, grounded (every number fetched, never invented)
  • Business+ Reports Narrative — AI summary on the Reports tab
  • Team+ Import Mapping — Claude proposes the field for every column (import wizard)
  • Team+ Document → Stories — Claude extracts action items from an uploaded .docx/.txt/.md into a structured template (Due dates · Requirements · Action items · Milestones · Open questions · Notes); the user reviews numbered Story recommendations — Summary + sectioned Description, editable per section — then each becomes an Avium Story (heuristic bullet parser on Free). Global intake: the header's "+ Add data" menu and an app-wide drag-and-drop target open it as a modal on any page
Layer 3 — UI Routing + Closed Loop: the drill-in modal, panel-per-signal mapping, and "Open in full view" destinations live in the client — and every drill carries its Apply: rebalance, scope trim (Monte-Carlo-ranked deferrals), assign unowned work, return mid-sprint adds, nudge a blocked assignee, fix data-quality fields. Applies ride the normal ticket update (Avium-only, joins the jira_modified / azure_modified push queue, audit-logged); the nudge is a one-per-ticket-per-day email. Nothing auto-pushes to a source tool.
🔌
The Avium Enterprise API Enterprise · /v1 · read-only
The engine isn't trapped behind human login. Buy the engine, keep your own workflow: an enterprise's portal, Teams channel, or warehouse reads Avium's risk signals, levers, blockers, the 7am briefing, work items, and capacity through a scoped server-to-server key — zero net-new logins. The app and the API are two surfaces over one lib/ engine: every /v1 handler is a thin caller of the same service the app uses, so improving detection once improves both. Curated, versioned, frozen shapes — never a raw model — so once you integrate, the contract never changes under you (versioning is a one-way door; /v2 would parallel-run, never mutate /v1).
Read endpoints · /v1
See · Catch · Plan
  • GET /v1/signals — the Avium Priority-scored risk ledger, with the transparent factor breakdown
  • GET /v1/action-items — the recommended moves (levers), read-only
  • GET /v1/blockers — blocker history + server-computed aging
  • GET /v1/briefing — the 7am briefing as structured JSON (the headless answer + the one move), ?lens=team|leaders
  • GET /v1/work-items — a compact, source-agnostic work model (cursor-paginated, ?updatedSince for incremental sync); its effort field is always the item's OWN effort, never a rollup
  • GET /v1/work-items/:id/effort-rollup — the audit-trail walk (RULE 26): decomposes one item's effort into own + descendants = total, with every contributing item linked back to its own row in Jira / Azure DevOps / Asana
  • GET /v1/capacity — committed-vs-capacity, unit-aware (hours OR points)
  • GET /v1/teams · /people · /departments · /sprints · /projects · /releases — the reference / dimension lookups (one read:reference scope) that let a caller discover the ids every other endpoint filters by
  • GET /v1/forecast — the Monte-Carlo sprint on-time forecast (percentiles + histogram), with /scope-trim and /what-if levers, plus /velocity — the per-scope velocity history, its Projected Delivery Band (?windowSprints, 2–12), and future-sprint over-commitment verdicts (same read:forecast scope)
  • GET /v1/reports — throughput, overdue, WIP-aging, and cycle-time aggregates
  • GET /v1/flow — Kanban flow analytics (WIP, cycle time, SLE, breach forecast, WIP limits)
  • GET /v1/graph — the Knowledge Graph (people, work, sprints, epics, dependencies, signals as nodes + edges), with /graph/parents for the family-tree id lookup
Contract & trust
Frozen
  • One self-describing envelopeapiVersion · resource · generatedAt · unit · meta · data; every number carries its unit, window, and definition
  • Scoped keys — one read scope per resource (read:signalsread:capacity, plus read:reference for the dimension lookups the Plan/See analytics reads read:forecast · read:reports · read:flow, and read:graph for the Knowledge Graph); a missing scope is 403 insufficient_scope. Write scopes are separate and higher-privilege (earned, not assumed): write:action-items + write:work-items, each Enterprise-only and behind an off-by-default flag
  • OpenAPI 3.1 + live docsGET /v1/openapi.json and a readable reference at /v1/docs, served by the API so they never drift from the running contract; a CI contract test fails the build if a /v1 shape changes
  • No silent caps — work-items pages explicitly (meta.pageInfo with hasMore + nextCursor); the full set is always reachable
Roadmap: Phase 0 (the gating build) = the ApiKey model, dual-mode (key or login) auth, and the auto-injecting tenant-isolation guard. Phase 1 (here) = the read-only core. Phase 2 = outbound webhooks (the risk arrives in Teams/ServiceNow, untouched by a human). Phase 3 = act-via-API (write-back to the customer's tracker). Phase 4 = bulk / warehouse export. Avium stays the system of intelligence, not a system of record — it never pushes its own tickets into a customer's tracker.