Skip to content

Speaker Services – Analytics

The analytics endpoint returns pre-aggregated verification statistics for the requested time window.
Results are sliced by time bucket (day / week / month / total) and optionally filtered by speaker, embedding model, resolved model, voice print, or sentence-verification model.

Endpoint

GET /api/v1/speaker-services/speaker-verification/analytics/verifications

Required scope: speaker:analytics:read

User view vs Admin view

  • User view – callers who hold only speaker:analytics:read receive statistics scoped to their own verifications. The user_uuid of the authenticated user is applied automatically as a filter; no extra parameter is required or accepted.
  • Admin view – callers who additionally hold speaker:analytics:admin (Admin, Operator, Manager, Supervisor) receive statistics for all users in the tenant. The per-user restriction is lifted entirely.

The endpoint URL and query parameters are identical for both views - the difference is purely driven by the caller's scopes.

Query Parameters

Parameter Type Required Default Description
from ISO 8601 UTC Yes Inclusive start of the analysis period.
to ISO 8601 UTC No now Exclusive end of the analysis period.
granularity enum No DAY Time-bucket size. One of DAY, WEEK, MONTH, TOTAL.
speakerId UUID No Limit statistics to a single speaker.
voicePrintId UUID No Filter by a specific voice print.
embeddingsModel string No Filter by speaker-embeddings model alias (e.g. en-general-v2).
embeddingsResolvedModel string No Filter by resolved (concrete) speaker-embeddings model name.
sentverModel string No Filter by sentence-verification model alias (e.g. en-sentver-v1).
sentverResolvedModel string No Filter by resolved (concrete) sentence-verification model name.

Response

Each bucket and the totals object now expose three independent decision breakdowns:

Field Measures
decisionStats Final combined decision - speaker-embedding + sentence-verification policy applied together.
speakerDecisionStats Speaker-embedding sub-decision only.
sentenceDecisionStats Sentence-verification sub-decision only.

Attribution note

decisionStats reflects the final outcome after all policy factors are applied. When you filter by embeddingsModel or voicePrintId, look at speakerDecisionStats to measure the direct quality of that embedding dimension. When you filter by sentverModel, look at sentenceDecisionStats. Using decisionStats alone as a model-quality metric is misleading because the other sub-system can pull the combined decision in a different direction.

{
  "from": "2025-01-01T00:00:00Z",
  "to": "2025-04-01T00:00:00Z",
  "granularity": "MONTH",
  "filters": {
    "speakerId": null,
    "embeddingsModel": null,
    "embeddingsResolvedModel": null,
    "voicePrintId": null,
    "sentverModel": null,
    "sentverResolvedModel": null
  },
  "buckets": [
    {
      "periodStart": "2025-01-01T00:00:00Z",
      "periodEnd":   "2025-02-01T00:00:00Z",
      "processingStats": {
        "total":       1240,
        "completed":   1190,
        "failed":        50,
        "successRate": 0.9597,
        "errorRate":   0.0403
      },
      "decisionStats": {
        "totalDecided": 1190,
        "accept":        870,
        "review":        180,
        "reject":        140,
        "acceptRate":  0.7311,
        "reviewRate":  0.1513,
        "rejectRate":  0.1176
      },
      "speakerDecisionStats": {
        "totalDecided": 1190,
        "accept":        920,
        "review":        150,
        "reject":        120,
        "acceptRate":  0.7731,
        "reviewRate":  0.1261,
        "rejectRate":  0.1008
      },
      "sentenceDecisionStats": {
        "totalDecided": 1190,
        "accept":        940,
        "review":        130,
        "reject":        120,
        "acceptRate":  0.7899,
        "reviewRate":  0.1092,
        "rejectRate":  0.1008
      }
    }
  ],
  "totals": {
    "periodStart": "2025-01-01T00:00:00Z",
    "periodEnd":   "2025-04-01T00:00:00Z",
    "processingStats": { "total": 3620, "completed": 3480, "failed": 140, "successRate": 0.9614, "errorRate": 0.0386 },
    "decisionStats":   { "totalDecided": 3480, "accept": 2534, "review": 526, "reject": 420, "acceptRate": 0.7282, "reviewRate": 0.1511, "rejectRate": 0.1207 },
    "speakerDecisionStats": { "totalDecided": 3480, "accept": 2680, "review": 450, "reject": 350, "acceptRate": 0.7701, "reviewRate": 0.1293, "rejectRate": 0.1006 },
    "sentenceDecisionStats": { "totalDecided": 3480, "accept": 2730, "review": 410, "reject": 340, "acceptRate": 0.7845, "reviewRate": 0.1178, "rejectRate": 0.0977 }
  },
  "cachedAt":      "2025-05-11T22:40:00Z",
  "cacheExpiresAt":"2025-05-11T23:40:00Z"
}

processingStats fields

Field Description
total Total verification attempts in the bucket.
completed Verifications with status COMPLETED.
failed Verifications with status FAILED.
successRate completed / total. null when total = 0.
errorRate failed / total. null when total = 0.

decisionStats / speakerDecisionStats / sentenceDecisionStats fields

All three decision stat objects share the same shape:

Field Description
totalDecided Verifications that produced a decision (accept + review + reject).
accept Number of ACCEPT decisions.
review Number of REVIEW decisions.
reject Number of REJECT decisions.
acceptRate accept / totalDecided. null when totalDecided = 0.
reviewRate review / totalDecided. null when totalDecided = 0.
rejectRate reject / totalDecided. null when totalDecided = 0.

Freshness fields

Field Description
cachedAt UTC timestamp when the current cached result was computed.
cacheExpiresAt UTC timestamp when the cached result will be considered stale.

Caching Behaviour

Responses include cachedAt and cacheExpiresAt fields. Historical queries (where to is entirely in the past) are cached longer than live queries. Use Cache-Control headers for client-side caching.

Window type Condition HTTP Cache-Control
Historical to is entirely in the past max-age=3600, stale-while-revalidate=300
Live / open to overlaps now (or is omitted) max-age=60, stale-while-revalidate=30

Granularity Reference

Value Bucket size periodEnd derivation
DAY 1 calendar day (UTC midnight boundaries) periodStart + 1 day
WEEK 1 week starting Monday UTC periodStart + 7 days
MONTH 1 calendar month UTC periodStart + 1 month
TOTAL Single bucket spanning the full requested period to (request boundary)

Example Requests

Monthly breakdown for the first quarter, all speakers

GET /api/v1/speaker-services/speaker-verification/analytics/verifications
    ?from=2025-01-01T00:00:00Z
    &to=2025-04-01T00:00:00Z
    &granularity=MONTH

Last 7 days, per-day, for one speaker

GET /api/v1/speaker-services/speaker-verification/analytics/verifications
    ?from=2025-05-05T00:00:00Z
    &granularity=DAY
    &speakerId=<uuid>

Last 30 days totals, filtered by speaker-embedding model alias

GET /api/v1/speaker-services/speaker-verification/analytics/verifications
    ?from=2025-04-11T00:00:00Z
    &granularity=TOTAL
    &embeddingsModel=en-general-v2

Filter by sentence-verification model alias

GET /api/v1/speaker-services/speaker-verification/analytics/verifications
    ?from=2025-04-11T00:00:00Z
    &granularity=TOTAL
    &sentverModel=en-sentver-v1

Filter by both speaker-embedding and sentence-verification model

GET /api/v1/speaker-services/speaker-verification/analytics/verifications
    ?from=2025-01-01T00:00:00Z
    &embeddingsModel=en-general-v2
    &sentverModel=en-sentver-v1
    &granularity=MONTH

Filter by both embeddings model alias and resolved concrete model

GET /api/v1/speaker-services/speaker-verification/analytics/verifications
    ?from=2025-01-01T00:00:00Z
    &embeddingsModel=en-general-v2
    &embeddingsResolvedModel=en-general-v2-2025Q1
    &granularity=MONTH