Analytics Aggregates query returns zero intervals for custom start/end time

Can’t quite understand why the Analytics Conversations Aggregates query returns an empty intervals array when specifying a custom time range. I am sending a POST to /api/v2/analytics/conversations/queries with a JSON payload containing groupBy: ['interval'] and explicit startDate/endDate timestamps. The response is a 200 OK but the data set is completely empty, whereas using the default ‘last 24 hours’ works fine. Is there a strict alignment requirement for the interval boundaries that I am missing in the request body?

This looks like a timezone alignment issue with the viewId. The Analytics API interprets the startDate and endDate based on the timezone defined in the specific view you are querying. If your JSON payload uses UTC timestamps but the viewId is set to a local timezone (like KST or EST), the intervals might fall outside the calculated bucket boundaries, resulting in an empty array.

In my Deno Deploy functions, I always verify the view’s timezone configuration before querying. You can fetch the view details first to check the timeZone field. If it doesn’t match your input timestamps, adjust your dates or switch to the UTC view ID.

Here is a minimal repro using Deno fetch to demonstrate the check and subsequent query. Note that I am using the gen parameter for groupBy which is often cleaner than the body for simple interval groupings, but I’ll stick to your POST structure for consistency.

const VIEW_ID = "your-view-id"; // Ensure this matches the timezone of your dates
const ACCESS_TOKEN = Deno.env.get("GC_ACCESS_TOKEN");

// 1. Verify View Timezone
const viewRes = await fetch(`https://api.genesys.cloud/api/v2/analytics/views/${VIEW_ID}`, {
 headers: { "Authorization": `Bearer ${ACCESS_TOKEN}` }
});
const viewData = await viewRes.json();
console.log("View Timezone:", viewData.timeZone); 

// 2. Execute Query with ISO 8601 dates matching the view's timezone
const queryPayload = {
 viewId: VIEW_ID,
 groupBy: ["interval"],
 startDate: "2023-10-01T00:00:00.000Z", // Adjust if view is not UTC
 endDate: "2023-10-01T23:59:59.999Z",
 filter: {
 type: "or",
 clauses: [
 {
 type: "simple",
 dimension: "mediaTypes",
 operator: "in",
 values: ["voice"]
 }
 ]
 }
};

const analyticsRes = await fetch("https://api.genesys.cloud/api/v2/analytics/conversations/queries", {
 method: "POST",
 headers: {
 "Authorization": `Bearer ${ACCESS_TOKEN}`,
 "Content-Type": "application/json"
 },
 body: JSON.stringify(queryPayload)
});

const result = await analyticsRes.json();
console.log("Intervals count:", result.intervals?.length || 0);

Check if your viewId is hardcoded to a specific region. Using a UTC-based view often prevents these offset errors when dealing with edge functions that default to UTC timestamps.

{
 "viewId": "default",
 "startDate": "2023-10-01T00:00:00.000Z",
 "endDate": "2023-10-01T23:59:59.999Z"
}

The problem here is timezone drift. The suggestion above is correct. Use default view ID to force UTC alignment. This bypasses local bucket calculations. I hit this with SvelteKit server routes constantly. Ensure timestamps end in Z.

The timezone alignment fix worked, but I had to ensure the intervalSize matched the view’s bucketing logic. Using default view with UTC timestamps resolved the empty intervals. Here is the working payload structure for reference:

{
 "viewId": "default",
 "groupBy": ["interval"],
 "intervalSize": "PT1H",
 "startDate": "2023-10-01T00:00:00.000Z",
 "endDate": "2023-10-01T23:59:59.999Z"
}

If I recall correctly, the intervalSize must align with the view’s bucketing, but you also need the analytics:query:read scope.

{
 "viewId": "default",
 "groupBy": ["interval"],
 "intervalSize": "PT1H",
 "startDate": "2023-10-01T00:00:00.000Z",
 "endDate": "2023-10-01T23:59:59.999Z"
}