Appearance
Wfm
Generated from
DialerDigital/corecommit0fc18008b3c8— specopenapi/dialer-v1.yamlv0.134.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.
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
| Method | Path | Summary |
|---|---|---|
GET | /v1/wfm/coverage | Forecast, 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/coverageTenant-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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
date | query | string (date) | yes | UTC calendar day, YYYY-MM-DD, within 366 days of today. |
threshold_ms | query | integer | no | Simulated wait threshold in ms (at most one day). Only valid together with target_percent. |
target_percent | query | integer | no | Simulated target, percent of answered calls within threshold_ms. Only valid together with threshold_ms. |
Responses
200
The 48 intervals of the day.
| Field | Type | Required | Description |
|---|---|---|---|
date | string (date) | yes | |
interval_minutes | 30 | yes | |
source | history · estimate | yes | history when the window reached the sample floor; estimate is the flat default. |
simulated | boolean | yes | True when the target is the one in the query, not the tenant's. |
history | object | yes | |
history.reference_days | array of string (date) | yes | The past days (same weekday) the forecast was averaged over. |
history.offered_sample | integer | yes | |
history.min_reference_days | integer | yes | |
history.min_sample_calls | integer | yes | |
target | object | WfmInert | yes | |
intervals | array of WfmCoverageInterval | yes | |
intervals[].start | string (date-time) | yes | |
intervals[].end | string (date-time) | yes | |
intervals[].forecast | object | yes | |
intervals[].forecast.volume | number | yes | Expected offered calls in the interval. |
intervals[].forecast.aht_ms | integer | yes | |
intervals[].forecast.aht_source | slot · pooled · estimate | yes | slot from this interval's own history; pooled the window-wide AHT; estimate the default. |
intervals[].staffing | object | WfmInert | yes | |
intervals[].scheduled_agents | number | yes | Full-time equivalents planned in the interval (R11 shifts). |
intervals[].coverage | object,null | yes | Null when the target is inert. |
intervals[].coverage.gap | number | yes | Planned minus required; negative is a shortfall. |
intervals[].coverage.ratio | number,null | yes | Planned / 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"
}
}