Skip to content

Insights ​

Generated from DialerDigital/core commit 0fc18008b3c8 — spec openapi/dialer-v1.yaml v0.134.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.

Español

Anomaly evidence of the insights evaluator (core#1983): contact, abandon, cost, gate-block and media-timeout series, each anomaly with its series and threshold. Always on; insights_anomaly_k only tunes the sensitivity.

Endpoints ​

MethodPathSummary
GET/v1/insights/anomaliesAnomalies the evaluator opened, with their evidence
GET/v1/insights/seriesOne metric as hourly buckets with the band the rule uses
POST/v1/insights/anomalies/{id}/ackAcknowledge an anomaly as the calling user

Anomalies the evaluator opened, with their evidence ​

http
GET /v1/insights/anomalies

Every anomaly is its opened row: the observed value, the baseline it was measured against (baseline_mean, baseline_stddev, stddev_floor, baseline_n), the resulting threshold with its k, the bucket sample (sample_n) and the hourly series the dashboard draws. A resolved row that cites it makes state resolved and fills resolution. Newest first; page with cursor.

The acknowledgement is PER PERSON: read is whether the calling user acknowledged the anomaly, and unread=true keeps only the ones the caller has not. A dd_ key has no inbox: read is null and unread=true is 400. Always on: there is no activation flag.

Parameters

NameInTypeRequiredDescription
campaign_idquerystring (uuid)noOnly this campaign's series.
metricquerycontact_rate · abandon_rate · cost_per_contact · gate_block_rate · media_timeout_rateno
statequeryopen · resolvedno
unreadquerybooleannotrue keeps the anomalies the calling user has not acknowledged (a dashboard login only).
limitqueryintegernoPage size, 50 by default and at most 200.
cursorquerystringnoThe next_cursor of the previous page.

Responses

200 ​

A page of anomalies.

FieldTypeRequiredDescription
anomaliesarray of InsightsAnomalyyes
anomalies[].idstring (uuid)yes
anomalies[].campaign_idstring,null (uuid)yesnull for the whole-tenant series.
anomalies[].metriccontact_rate · abandon_rate · cost_per_contact · gate_block_rate · media_timeout_rateyescontact_rate alerts downwards; every other metric alerts upwards.
anomalies[].gatestring,nullyesOnly gate_block_rate carries a gate.
anomalies[].rulestringyesThe rule that produced it, e.g. zscore.v1.
anomalies[].directionup · downyesThe harmful direction that was crossed.
anomalies[].stateopen · resolvedyes
anomalies[].window_startstring (date-time)yesThe hourly bucket that crossed the threshold (inclusive).
anomalies[].window_endstring (date-time)yesThe same bucket (exclusive).
anomalies[].observednumberyesThe bucket value.
anomalies[].baseline_meannumberyes
anomalies[].baseline_stddevnumberyesSample standard deviation of the baseline buckets.
anomalies[].stddev_floornumberyesThe floor applied to the deviation so a near-constant series does not alert on noise.
anomalies[].thresholdnumberyesbaseline_mean ± k·max(baseline_stddev, stddev_floor) on the harmful side.
anomalies[].knumberyesThe sensitivity in force when it was opened (insights_anomaly_k).
anomalies[].sample_nintegeryesAttempts in the bucket.
anomalies[].baseline_nintegeryesBaseline buckets used.
anomalies[].seriesarray of InsightsSeriesPointyesThe baseline buckets followed by the bucket that crossed, oldest first.
anomalies[].series[].tstring (date-time)yesStart of the hourly bucket.
anomalies[].series[].sampleintegeryes
anomalies[].series[].numeratornumberyes
anomalies[].series[].denominatornumberyes
anomalies[].series[].valuenumber,nullyesnumerator / denominator.
anomalies[].opened_atstring (date-time)yes
anomalies[].resolutionobject,nullyesThe row that closed it; null while open.
anomalies[].resolution.idstring (uuid)yes
anomalies[].resolution.window_startstring (date-time)yes
anomalies[].resolution.window_endstring (date-time)yes
anomalies[].resolution.observednumberyes
anomalies[].resolution.resolved_atstring (date-time)yes
anomalies[].readboolean,nullyesWhether the calling user acknowledged it; null for a dd_ key.
anomalies[].acknowledged_atstring,null (date-time)yes
next_cursorstring,nullyesnull on the last page.

400 — BadRequest ​

Malformed request (shape/type errors, invalid filters, bad timestamps).

json
{
  "error": {
    "code": "bad_request",
    "message": "from must be RFC-3339"
  }
}

401 — Unauthorized ​

Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature). A dashboard session (ddu_) that a newer login of the same person ended answers the code session_superseded instead (tenant flag single_session_enforced), so the screen can say why it was signed out; a logout, an expired or an unknown token stay unauthorized.

json
{
  "error": {
    "code": "unauthorized",
    "message": "invalid or revoked API key"
  }
}

403 — Forbidden ​

The tenant is suspended. A dashboard session (ddu_) of a tenant whose login policy (ADR 227) is in mode enforce answers 403 with the code login_policy_denied on a request from an address or at an hour the policy does not allow — the same body for both; the session is not revoked and a later request inside the policy goes through. A widget token (ddw_) of a seat is held to the same policy on every request (core#2406, flag widget_login_honors_policy). A synthetic (demo) tenant answers 403 with the code synthetic_tenant on every route that would reach a third party — manual dial, external transfer or conference leg, SMS send (core#2251, ADR #280 addendum). No payment changes it.

json
{
  "error": {
    "code": "forbidden",
    "message": "tenant is suspended"
  }
}

One metric as hourly buckets with the band the rule uses ​

http
GET /v1/insights/series

The hourly buckets of metric in [from, to) and, for each, the band mean ± k·max(σ, floor) that zscore.v1 computes from the 7 days before the bucket, the bucket itself excluded: the same arithmetic as the evaluator, so the chart shows why a point did or did not cross. band is null while the bucket has fewer than 24 baseline buckets (min_baseline); a bucket under min_sample attempts is drawn but never evaluated. k is the tenant's insights_anomaly_k.

from and to round down to the hour; to defaults to now and from to 48 hours before it. The window may not exceed 14 days. gate is mandatory for gate_block_rate and is refused for every other metric.

Parameters

NameInTypeRequiredDescription
metricquerycontact_rate · abandon_rate · cost_per_contact · gate_block_rate · media_timeout_rateyes
campaign_idquerystring (uuid)noThe series of this campaign; absent, the whole tenant.
gatequerystringnoThe compliance gate (1 to 64 bytes); only with gate_block_rate.
fromquerystring (date-time)noRFC 3339 lower bound (inclusive), rounded down to the hour.
toquerystring (date-time)noRFC 3339 upper bound (exclusive), rounded down to the hour.

Responses

200 ​

The series.

FieldTypeRequiredDescription
rulestringyes
metriccontact_rate · abandon_rate · cost_per_contact · gate_block_rate · media_timeout_rateyescontact_rate alerts downwards; every other metric alerts upwards.
campaign_idstring,null (uuid)yes
gatestring,nullyes
directionup · downyes
knumberyes
min_sampleintegeryesAttempts a bucket needs to be evaluated.
min_baselineintegeryesBaseline buckets a series needs to be evaluated.
fromstring (date-time)yes
tostring (date-time)yes
bucketsarray of InsightsSeriesBucketyes
buckets[].startstring (date-time)yes
buckets[].sampleintegeryes
buckets[].numeratornumberyes
buckets[].denominatornumberyes
buckets[].valuenumber,nullyes
buckets[].bandInsightsBand | nullyesnull while the bucket has fewer than min_baseline baseline buckets.

400 — BadRequest ​

Malformed request (shape/type errors, invalid filters, bad timestamps).

json
{
  "error": {
    "code": "bad_request",
    "message": "from must be RFC-3339"
  }
}

401 — Unauthorized ​

Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature). A dashboard session (ddu_) that a newer login of the same person ended answers the code session_superseded instead (tenant flag single_session_enforced), so the screen can say why it was signed out; a logout, an expired or an unknown token stay unauthorized.

json
{
  "error": {
    "code": "unauthorized",
    "message": "invalid or revoked API key"
  }
}

403 — Forbidden ​

The tenant is suspended. A dashboard session (ddu_) of a tenant whose login policy (ADR 227) is in mode enforce answers 403 with the code login_policy_denied on a request from an address or at an hour the policy does not allow — the same body for both; the session is not revoked and a later request inside the policy goes through. A widget token (ddw_) of a seat is held to the same policy on every request (core#2406, flag widget_login_honors_policy). A synthetic (demo) tenant answers 403 with the code synthetic_tenant on every route that would reach a third party — manual dial, external transfer or conference leg, SMS send (core#2251, ADR #280 addendum). No payment changes it.

json
{
  "error": {
    "code": "forbidden",
    "message": "tenant is suspended"
  }
}

Acknowledge an anomaly as the calling user ​

http
POST /v1/insights/anomalies/{id}/ack

Writes the calling user's acknowledgement (append-only, one per user and anomaly). Idempotent: acknowledging again answers 200 with the acknowledgement that already exists. Needs a dashboard login: a dd_ key has no inbox and is 403. An id that is not an anomaly of the tenant (another tenant's, a resolution row, an invented one) is 404.

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Responses

200 ​

The acknowledgement.

FieldTypeRequiredDescription
ackobject (InsightsAck)yes
ack.anomaly_idstring (uuid)yes
ack.user_idstring (uuid)yes
ack.acknowledged_atstring (date-time)yes

401 — Unauthorized ​

Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature). A dashboard session (ddu_) that a newer login of the same person ended answers the code session_superseded instead (tenant flag single_session_enforced), so the screen can say why it was signed out; a logout, an expired or an unknown token stay unauthorized.

json
{
  "error": {
    "code": "unauthorized",
    "message": "invalid or revoked API key"
  }
}

403 — Forbidden ​

The tenant is suspended. A dashboard session (ddu_) of a tenant whose login policy (ADR 227) is in mode enforce answers 403 with the code login_policy_denied on a request from an address or at an hour the policy does not allow — the same body for both; the session is not revoked and a later request inside the policy goes through. A widget token (ddw_) of a seat is held to the same policy on every request (core#2406, flag widget_login_honors_policy). A synthetic (demo) tenant answers 403 with the code synthetic_tenant on every route that would reach a third party — manual dial, external transfer or conference leg, SMS send (core#2251, ADR #280 addendum). No payment changes it.

json
{
  "error": {
    "code": "forbidden",
    "message": "tenant is suspended"
  }
}

404 — NotFound ​

Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).

json
{
  "error": {
    "code": "not_found",
    "message": "resource not found for this tenant"
  }
}

Nothing in these docs is legal advice — always confirm compliance posture with your own counsel.