Summary
Onboard a new SDK method getIncidentsTimeline on both MaestroProcesses and Cases services, backed by the existing IncidentsByTimeWindow Insights API. Follow the same pattern as getInstanceStatusTimeline and extend the shared TimelineOptions type to expose the process-level filters the backend already supports — for both methods.
Motivation
The current SDK has no way to retrieve incident counts over time. getIncidents(processKey, folderKey) returns full incident records for a single process, and getInstanceStatusTimeline returns instance status counts over time — neither answers "how many incidents happened per hour/day/week?"
This is the timeline chart data shape (e.g., "Incidents over the last 30 days") that drives monitoring dashboards.
Backend API
Endpoint: POST /AgenticInstanceStatus/IncidentsByTimeWindow
Insights-monitoring controller: AgenticInstanceStatusController.GetIncidentsByTimeWindow
SQL: AgenticOrchestrationQuery.IncidentsByTimeWindowQuery
Request
Response
Why expose on both MaestroProcesses and Cases?
The backend already accepts an isCaseManagement flag and uses it to filter PROCESSRUNS.CASEINSTANCEID IS NOT NULL/NULL — same pattern as TopProcessesByRunCount, TopProcessesByDuration, InstanceStatusByDate. So this method can be cleanly type-pure on both services:
MaestroProcesses.getIncidentsTimeline(...) → sends isCaseManagement: false
Cases.getIncidentsTimeline(...) → sends isCaseManagement: true
SDK design
Method signature
Match getInstanceStatusTimeline exactly for symmetry:
```ts
getIncidentsTimeline(
startTime: Date,
endTime: Date,
options?: TimelineOptions,
): Promise<IncidentTimelinePoint[]>;
```
Response type (new)
/**
* Incident count within a specific time bucket.
*/
export interface IncidentTimelinePoint {
/** Start of the time bucket (ISO timestamp) */
startTime: string;
/** End of the time bucket (ISO timestamp) */
endTime: string;
/** Number of incidents in this bucket */
count: number;
}
Note: endTime is technically derivable from startTime + groupBy, but the backend returns it explicitly to handle DST / timezone edge cases cleanly. We pass it through.
Extend TimelineOptions (shared with getInstanceStatusTimeline)
Both backend endpoints (InstanceStatusByDate and IncidentsByTimeWindow) accept the identical filter set, but the SDK's TimelineOptions currently only exposes groupBy. Extend it once so both methods benefit:
```ts
export interface TimelineOptions {
/**
- How to group data points on the time axis.
- @default TimeInterval.Day
*/
groupBy?: TimeInterval;
/** Filter by package ID */
packageId?: string;
/** Filter by package version */
version?: string;
/** Filter by process key */
processKey?: string;
/** Filter by a list of process keys (allowlist) */
processKeys?: string[];
}
```
Wiring this through fetchInstanceStatusTimeline (and the new fetchIncidentsTimeline) is straightforward — they just pass these fields into commonParams.
Service-level model
- New file:
src/models/maestro/incidents-timeline.types.ts (or co-locate in insights.types.ts next to InstanceStatusTimelineResponse)
- Add
getIncidentsTimeline to both MaestroProcessesServiceModel and CasesServiceModel
- Implement in
src/services/maestro/insights.ts as fetchIncidentsTimeline(), mirroring the existing fetchInstanceStatusTimeline()
- Both
processes.ts and cases.ts services delegate to it, supplying isCaseManagement
Endpoint constant
Add to src/utils/constants/endpoints/maestro.ts:
```ts
INCIDENTS_BY_TIME_WINDOW: \${INSIGHTS_RTM_BASE}/agenticInstanceStatus/IncidentsByTimeWindow,
```
Notable design decisions
- No
timezoneOffset exposed (initially) — matches getInstanceStatusTimeline precedent. Can be added later under TimelineOptions for both methods if demanded.
- Pass through
endTime in the response — backend includes it, costs little, avoids DST math on the consumer side.
@track('MaestroProcesses.GetIncidentsTimeline') and @track('Cases.GetIncidentsTimeline') on the public methods.
- Integration test for both services in
tests/integration/shared/maestro/.
- Unit tests in
tests/unit/services/maestro/processes/ and tests/unit/services/maestro/cases/.
- Update
docs/oauth-scopes.md with the new method's scopes.
Out of scope
topInstancesSummary onboarding (deferred — see internal notes; needs backend isCaseManagement filter first).
- Adding
timezoneOffset to TimelineOptions — defer until there's a concrete consumer need.
References
- Insights-monitoring controller:
RealtimeMonitoring/RealTimeDashboards/src/Controllers/AgenticInstanceStatusController.cs (lines 909–957)
- SQL:
RealtimeMonitoring/RealTimeDashboards/src/DataAccessor/Queries/AgenticOrchestrationQuery.ProcessAndInstances.cs (IncidentsByTimeWindowQuery, lines 479+)
- Existing precedent:
getInstanceStatusTimeline on both services
Summary
Onboard a new SDK method
getIncidentsTimelineon bothMaestroProcessesandCasesservices, backed by the existingIncidentsByTimeWindowInsights API. Follow the same pattern asgetInstanceStatusTimelineand extend the sharedTimelineOptionstype to expose the process-level filters the backend already supports — for both methods.Motivation
The current SDK has no way to retrieve incident counts over time.
getIncidents(processKey, folderKey)returns full incident records for a single process, andgetInstanceStatusTimelinereturns instance status counts over time — neither answers "how many incidents happened per hour/day/week?"This is the timeline chart data shape (e.g., "Incidents over the last 30 days") that drives monitoring dashboards.
Backend API
Endpoint:
POST /AgenticInstanceStatus/IncidentsByTimeWindowInsights-monitoring controller:
AgenticInstanceStatusController.GetIncidentsByTimeWindowSQL:
AgenticOrchestrationQuery.IncidentsByTimeWindowQueryRequest
{ "commonParams": { "startTime": <epoch ms>, "endTime": <epoch ms>, "packageId": "...", // optional filter "version": "...", // optional filter "processKey": "...", // optional filter "processKeys": ["..."], // optional allowlist filter "isCaseManagement": false // true for Cases, false for MaestroProcesses }, "timeSliceUnit": "HOUR" | "DAY" | "WEEK", "timezoneOffset": <minutes from UTC, optional> }Response
{ "dataPoints": [ { "count": 0, "startTime": "2026-04-27T00:00:00", "endTime": "2026-05-04T00:00:00" }, { "count": 26, "startTime": "2026-05-04T00:00:00", "endTime": "2026-05-11T00:00:00" }, { "count": 129, "startTime": "2026-05-11T00:00:00", "endTime": "2026-05-18T00:00:00" } // … all buckets in range, zero-padded ] }Why expose on both
MaestroProcessesandCases?The backend already accepts an
isCaseManagementflag and uses it to filterPROCESSRUNS.CASEINSTANCEID IS NOT NULL/NULL— same pattern asTopProcessesByRunCount,TopProcessesByDuration,InstanceStatusByDate. So this method can be cleanly type-pure on both services:MaestroProcesses.getIncidentsTimeline(...)→ sendsisCaseManagement: falseCases.getIncidentsTimeline(...)→ sendsisCaseManagement: trueSDK design
Method signature
Match
getInstanceStatusTimelineexactly for symmetry:```ts
getIncidentsTimeline(
startTime: Date,
endTime: Date,
options?: TimelineOptions,
): Promise<IncidentTimelinePoint[]>;
```
Response type (new)
Note:
endTimeis technically derivable fromstartTime + groupBy, but the backend returns it explicitly to handle DST / timezone edge cases cleanly. We pass it through.Extend
TimelineOptions(shared withgetInstanceStatusTimeline)Both backend endpoints (
InstanceStatusByDateandIncidentsByTimeWindow) accept the identical filter set, but the SDK'sTimelineOptionscurrently only exposesgroupBy. Extend it once so both methods benefit:```ts
export interface TimelineOptions {
/**
*/
groupBy?: TimeInterval;
/** Filter by package ID */
packageId?: string;
/** Filter by package version */
version?: string;
/** Filter by process key */
processKey?: string;
/** Filter by a list of process keys (allowlist) */
processKeys?: string[];
}
```
Wiring this through
fetchInstanceStatusTimeline(and the newfetchIncidentsTimeline) is straightforward — they just pass these fields intocommonParams.Service-level model
src/models/maestro/incidents-timeline.types.ts(or co-locate ininsights.types.tsnext toInstanceStatusTimelineResponse)getIncidentsTimelineto bothMaestroProcessesServiceModelandCasesServiceModelsrc/services/maestro/insights.tsasfetchIncidentsTimeline(), mirroring the existingfetchInstanceStatusTimeline()processes.tsandcases.tsservices delegate to it, supplyingisCaseManagementEndpoint constant
Add to
src/utils/constants/endpoints/maestro.ts:```ts
INCIDENTS_BY_TIME_WINDOW:
\${INSIGHTS_RTM_BASE}/agenticInstanceStatus/IncidentsByTimeWindow,```
Notable design decisions
timezoneOffsetexposed (initially) — matchesgetInstanceStatusTimelineprecedent. Can be added later underTimelineOptionsfor both methods if demanded.endTimein the response — backend includes it, costs little, avoids DST math on the consumer side.@track('MaestroProcesses.GetIncidentsTimeline')and@track('Cases.GetIncidentsTimeline')on the public methods.tests/integration/shared/maestro/.tests/unit/services/maestro/processes/andtests/unit/services/maestro/cases/.docs/oauth-scopes.mdwith the new method's scopes.Out of scope
topInstancesSummaryonboarding (deferred — see internal notes; needs backendisCaseManagementfilter first).timezoneOffsettoTimelineOptions— defer until there's a concrete consumer need.References
RealtimeMonitoring/RealTimeDashboards/src/Controllers/AgenticInstanceStatusController.cs(lines 909–957)RealtimeMonitoring/RealTimeDashboards/src/DataAccessor/Queries/AgenticOrchestrationQuery.ProcessAndInstances.cs(IncidentsByTimeWindowQuery, lines 479+)getInstanceStatusTimelineon both services