Skip to content

Wfm ​

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

Workforce management: the per-interval coverage of a day (forecast from the CDR, agents required by Erlang C against the tenant's service target, agents planned in R11 shifts). A derived read; nothing is persisted.

Endpoints ​

MethodPathSummary
GET/v1/wfm/coverageForecast, required and planned agents per 30-minute interval of one day

Forecast, required and planned agents per 30-minute interval of one day ​

http
GET /v1/wfm/coverage

Tenant-management surface (dd_ or ddu_; an agent ddw_ is 403). A derived read (ADR #241): nothing is stored and every call recomputes from the append-only streams.

Forecast. The same weekday of the previous 4 weeks (only days that have already ended), averaged per 30-minute interval of the UTC day. An inbound attempt is an ORIGINAL call_attempts row (corrects_id IS NULL) stamped direction=inbound that was not later corrected to not_placed; what is counted is what was OFFERED. AHT is (conversation + wrap_up) / answered; wrap_up comes from the closed agent_state_intervals of the seats, so for a seat that also dials out it is an upper bound. With fewer than 2 reference days or fewer than 30 offered calls, source is estimate (a flat 6 calls per interval, AHT 300 s: a placeholder, not a prediction) instead of history.

Required agents. Erlang C against the tenant's service target. The target is born absent and absent is inert: without it target and every interval's staffing carry {inert: <reason>} and coverage is null. Passing BOTH threshold_ms and target_percent simulates a target for this response only (never persisted; simulated: true). The search is capped at 5000 agents; a target not reached before the cap says reachable: false, and so does a 100 % target (the model only approaches it asymptotically).

Planned agents. Full-time equivalents of the interval from the R11 planned shifts (paused shifts excluded; one agent's overlapping shifts count once). coverage.gap is planned minus required.

Parameters

NameInTypeRequiredDescription
datequerystring (date)yesUTC calendar day, YYYY-MM-DD, within 366 days of today.
threshold_msqueryintegernoSimulated wait threshold in ms (at most one day). Only valid together with target_percent.
target_percentqueryintegernoSimulated target, percent of answered calls within threshold_ms. Only valid together with threshold_ms.

Responses

200 ​

The 48 intervals of the day.

FieldTypeRequiredDescription
datestring (date)yes
interval_minutes30yes
sourcehistory · estimateyeshistory when the window reached the sample floor; estimate is the flat default.
simulatedbooleanyesTrue when the target is the one in the query, not the tenant's.
historyobjectyes
history.reference_daysarray of string (date)yesThe past days (same weekday) the forecast was averaged over.
history.offered_sampleintegeryes
history.min_reference_daysintegeryes
history.min_sample_callsintegeryes
targetobject | WfmInertyes
intervalsarray of WfmCoverageIntervalyes
intervals[].startstring (date-time)yes
intervals[].endstring (date-time)yes
intervals[].forecastobjectyes
intervals[].forecast.volumenumberyesExpected offered calls in the interval.
intervals[].forecast.aht_msintegeryes
intervals[].forecast.aht_sourceslot · pooled · estimateyesslot from this interval's own history; pooled the window-wide AHT; estimate the default.
intervals[].staffingobject | WfmInertyes
intervals[].scheduled_agentsnumberyesFull-time equivalents planned in the interval (R11 shifts).
intervals[].coverageobject,nullyesNull when the target is inert.
intervals[].coverage.gapnumberyesPlanned minus required; negative is a shortfall.
intervals[].coverage.rationumber,nullyesPlanned / required; null when nothing is required.

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"
  }
}

429 — ApiKeyRateLimited ​

This API key is over its request quota, or the tenant's keys together are over the tenant ceiling (core#2503) (code rate_limited). The request was not processed. Wait Retry-After seconds and retry; a refusal is not counted against the budget, so that wait is always enough. Bounded per API key and, above the keys, per tenant (api_tenant_requests_per_minute): a sibling key is unaffected until the tenant's keys together reach that ceiling. The quota applies to every operation reachable with a dd_ key, so the operations that name a more specific 429 (call control, dispositions, SMS, …) can ALSO answer this one with its X-RateLimit-* headers.

json
{
  "error": {
    "code": "rate_limited",
    "message": "API key request quota exceeded; retry after the interval in Retry-After"
  }
}

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