Skip to main content
Baobyte AML Suite
Documentation contents

API reference

Metrics

10 operations in this area of the contract. Every one declares the permission it requires.

Contract version 0.2.0All areas

Operations

GET/v1/metrics/alerts/false-positive-rate

The alert false-positive rate over a window

Required permission: analytics.metric.readgetFalsePositiveRate

BRD §13's headline alert KPI, and the number ADR-0017 says an MLRO manages by.

`rate` is null whenever either component was suppressed, or when nothing closed in the window. Publishing "3%" against a visible denominator of 100 republishes the numerator that was suppressed for a reason, and one division is not a defence. "0% false positives" and "nothing was closed" are opposite reports of the same fact, so the second is an absent rate rather than a zero.

`breakdown` carries every closing disposition rather than only the numerator: an MLRO managing false positives needs to see what the other closures were.

Show parameters and responses

Parameters

NameInTypeDescription
fromrequiredquerystringStart of the half-open window, inclusive. Required and never defaulted: a metric whose period was chosen by the server is a number nobody can reproduce, and two identical requests a minute apart would return different figures with no visible reason.
torequiredquerystringEnd of the window, EXCLUSIVE. Half-open because a closed interval double-counts the boundary instant whenever two periods are compared — which is what a trend chart does by design. Must be after `from`.
rule_keyquerystringNarrows to one rule. This is the parameter that makes suppression necessary rather than tidy: it is the knob that narrows a population until a count names somebody.

Responses

  • 200The rate, its components and the coverage of the stream behind itMetricRate
  • 400—
  • 403—
GET/v1/metrics/cases/ageing

Ageing bands for cases still open

Required permission: analytics.metric.readgetCaseAgeing

BRD §8.8's ageing tile, computed in the database over every open case rather than in the browser over a bounded page of them. The dashboard previously derived this from `?limit=100`: at a microfinance bank that is wasteful, at a tier-1 bank the tile describes the first hundred rows and looks exactly as confident as a correct one.

Show parameters and responses

Parameters

NameInTypeDescription
as_ofquerystringThe instant the question is asked about. Defaults to now. Supplying it is how a board pack reproduces last month's figure rather than recomputing a different one.
priorityqueryp1 | p2 | p3 | p4—

Responses

  • 200One cell per ageing bandMetricDistribution
  • 400—
  • 403—
GET/v1/metrics/coverage

Which metric streams are being published, and the live review-queue count

Required permission: analytics.metric.readgetMetricCoverage

What a dashboard should render before it renders a single tile: per stream, whether anybody publishes it and when they last did. A stream that stopped being published a fortnight ago must not read as a quiet fortnight, and a stream nobody has ever published must name the module that owes it.

`review_queue.pending_screening_hits` is the one live count on this surface and is deliberately NOT an analytics metric. It is a count of work in progress rather than a KPI over a period, screening already owns it, and routing it through a published fact would add publication lag to a number whose entire value is being current (ADR-0027).

Show parameters and responses

Responses

  • 200Coverage per stream, plus the review-queue badgeobject
  • 403—
GET/v1/metrics/executive

Current active-book risk exposure plus filing trend and deadline status

Required permission: analytics.metric.readgetExecutiveAnalytics

BRD §8.8-05..10's aggregate executive surface. Risk is the complete CURRENT active customer book at `risk_as_of`; the filing window does not filter customers by their relationship start and is not presented as historical risk. `historical_risk_available` remains false until an append-only/SCD risk source exists.

Sector is derived from the legal party's shipped industry vocabulary or the natural party's bounded occupation risk codes. Unknown/free-text values collapse to `other`, and geography admits only a two-letter code or `UNKNOWN`, so a suppressed cell label cannot itself contain a customer's name. Counts below five are replaced by null inside SQL and complementary cells are withheld in the service. Projection coverage compares analytics' active rows with onboarding's authoritative active-customer control total; matrices are withheld when those differ. Every successful read is appended to the tenant audit chain.

Show parameters and responses

Parameters

NameInTypeDescription
fromrequiredquerystringStart of the half-open window, inclusive. Required and never defaulted: a metric whose period was chosen by the server is a number nobody can reproduce, and two identical requests a minute apart would return different figures with no visible reason.
torequiredquerystringEnd of the window, EXCLUSIVE. Half-open because a closed interval double-counts the boundary instant whenever two periods are compared — which is what a trend chart does by design. Must be after `from`.
grainqueryday | week | month | quarter | year—
dimensionsquerystring[]One to three unique current-risk dimensions. Defaults to all three.

Responses

  • 200Disclosure-controlled executive aggregate; no customer records or identifiers.ExecutiveAnalytics
  • 400—
  • 403—
GET/v1/metrics/executive/export

Export the exact executive aggregate as JSON or CSV

Required permission: analytics.executive.exportexportExecutiveAnalytics

Computes one ExecutiveAnalytics object and serialises that same object once; the CSV path does not issue a second query. Content-Disposition names the artifact, Digest and X-Content-SHA256 identify its exact bytes, and the query plus digest are appended to the tenant's audit chain before any bytes leave the process.

Show parameters and responses

Parameters

NameInTypeDescription
fromrequiredquerystringStart of the half-open window, inclusive. Required and never defaulted: a metric whose period was chosen by the server is a number nobody can reproduce, and two identical requests a minute apart would return different figures with no visible reason.
torequiredquerystringEnd of the window, EXCLUSIVE. Half-open because a closed interval double-counts the boundary instant whenever two periods are compared — which is what a trend chart does by design. Must be after `from`.
grainqueryday | week | month | quarter | year—
dimensionsquerystring[]—
formatrequiredqueryjson | csv—

Responses

  • 200The exact aggregate artifact bytes.string
  • 400—
  • 403—
GET/v1/metrics/filings/deadlines

Regulatory deadline tracking

Required permission: analytics.metric.readgetFilingDeadlines

Reporting creates deadlines from governed reporting.deadlines configuration, publishes each current state, sweeps breached items and marks submitted filings met. A tenant for which the stream has never been published still returns UNAVAILABLE, never a confident zero; `coverage.reason` names reporting and freshness remains visible.

Configured intervals retain their compliance-validation provenance rather than being presented here as hard-coded statutory claims.

Show parameters and responses

Parameters

NameInTypeDescription
as_ofquerystringThe instant the question is asked about. Defaults to now. Supplying it is how a board pack reproduces last month's figure rather than recomputing a different one.
kindquerySTR | CTR | SCUML | CBN_RETURN | BOARD—

Responses

  • 200One cell per deadline status and horizonMetricDistribution
  • 400—
  • 403—
GET/v1/metrics/filings/volumes

Filing volumes and trend, bucketed by period

Required permission: analytics.metric.readgetFilingVolumes
Show parameters and responses

Parameters

NameInTypeDescription
fromrequiredquerystringStart of the half-open window, inclusive. Required and never defaulted: a metric whose period was chosen by the server is a number nobody can reproduce, and two identical requests a minute apart would return different figures with no visible reason.
torequiredquerystringEnd of the window, EXCLUSIVE. Half-open because a closed interval double-counts the boundary instant whenever two periods are compared — which is what a trend chart does by design. Must be after `from`.
grainqueryday | week | month | quarter | yearThe period bucket. A closed set because it is bound into `date_trunc`: a value outside it would arrive at the caller as a Postgres error through a dashboard.
kindquerySTR | CTR | SCUML | CBN_RETURN | BOARDNarrows to one report kind.

Responses

  • 200One point per period, kind and statusMetricSeries
  • 400—
  • 403—
GET/v1/metrics/screening/ageing

Ageing bands for screening hits still awaiting a decision

Required permission: analytics.metric.readgetScreeningHitAgeing

How long hits have been waiting, which the pending count on the dashboard has never been able to say. Forty hits raised this morning and forty raised five weeks ago are the same tile and are not the same institution, and the second one is what an examiner opens with.

Counts only hits that are still pending. A decided hit has an age, but "how long did we take" and "how long has this been sitting" are different questions, and conflating them is how an ageing chart improves by deciding nothing. The bands are the same ones the case ageing panel uses, so the two can be read side by side without rescaling.

Show parameters and responses

Parameters

NameInTypeDescription
as_ofquerystringThe instant the question is asked about. Defaults to now. Supplying it is how a board pack reproduces last month's figure rather than recomputing a different one.
watchlist_keyquerystringNarrows to one list.

Responses

  • 200One cell per ageing bandMetricDistribution
  • 400—
  • 403—
GET/v1/metrics/screening/false-positive-rate

The screening false-positive rate over a window

Required permission: analytics.metric.readgetScreeningFalsePositiveRate

BRD §8.4-08 asks for configurable match sensitivity balancing false positives against risk. This is the half of that sentence the product could not previously show.

Screening is the highest-volume false-positive generator in the platform — one common surname against a consolidated sanctions list produces hits by the thousand — and until the `screening.outcome` stream existed the only number held about it was a live count of the pending queue. Nothing said how many decided hits were wrong, so a tenant moving `screening.match.threshold` was turning a dial with no gauge attached.

Identical semantics to the alert rate, deliberately: `rate` is null whenever either component was suppressed or nothing was decided in the window, and `breakdown` carries every disposition — `true_positive`, `false_positive` and `suppressed` — because the other decisions are what make the rate interpretable. A hit cleared by a standing suppression is counted as decided at the instant it was raised, since the human decision it rests on was made before the hit existed.

Show parameters and responses

Parameters

NameInTypeDescription
fromrequiredquerystringStart of the half-open window, inclusive. Required and never defaulted: a metric whose period was chosen by the server is a number nobody can reproduce, and two identical requests a minute apart would return different figures with no visible reason.
torequiredquerystringEnd of the window, EXCLUSIVE. Half-open because a closed interval double-counts the boundary instant whenever two periods are compared — which is what a trend chart does by design. Must be after `from`.
watchlist_keyquerystringNarrows to one list. The dimension that makes the number actionable: a rate concentrated in one list is a list problem, the same rate spread evenly is a threshold problem. It is also a filter that narrows a population until a count could name somebody, which is why suppression is inside the query.

Responses

  • 200The rate, its components and the coverage of the stream behind itMetricRate
  • 400—
  • 403—
GET/v1/metrics/sla/breaches

SLA breach counts, split by whether the work is late now or was delivered late

Required permission: analytics.metric.readgetSLABreaches
Show parameters and responses

Parameters

NameInTypeDescription
as_ofquerystringThe instant the question is asked about. Defaults to now. Supplying it is how a board pack reproduces last month's figure rather than recomputing a different one.
streamqueryalert.outcome | case.lifecycle | filing.volume | filing.deadline | screening.outcomeOmit for every stream that carries a deadline.

Responses

  • 200One cell per stream and breach kindMetricDistribution
  • 400—
  • 403—