Skip to main content

Dashboard Heatmap

Returns call distribution by day-of-week and hour-of-day to identify optimal calling times. Queries the raw calls table since hourly granularity is not available in the pre-aggregated table. Returns a sparse heatmap (only time slots with data) and the top 5 best-performing time slots.

Endpoint

PropertyValue
Function Namedashboard-heatmap
HTTP MethodGET
AuthenticationSupabase JWT (Bearer token)

Request

Headers

Authorization: Bearer <supabase_jwt_token>
Content-Type: application/json

Query Parameters

ParameterTypeRequiredDefaultDescription
periodstringNo30d7d, 30d, or 90d only (no today or custom)
metricstringNocallscalls, connected, or meetings_booked
campaign_idstring (UUID)No--Filter to a specific campaign
client_idstring (UUID)No--Filter to a specific client

Response

Success (200)

{
"period": { "start_date": "2026-01-18", "end_date": "2026-02-16" },
"metric": "calls",
"heatmap": [
{ "day": 0, "hour": 9, "total_calls": 5, "connected_calls": 3, "meetings_booked": 0 },
{ "day": 0, "hour": 10, "total_calls": 8, "connected_calls": 4, "meetings_booked": 1 },
{ "day": 1, "hour": 9, "total_calls": 12, "connected_calls": 7, "meetings_booked": 2 }
// ... entries only for day/hour combos that had calls
],
"best_times": [
{ "day": 2, "hour": 10, "metric_value": 15, "label": "Tuesday 10:00" },
{ "day": 3, "hour": 14, "metric_value": 12, "label": "Wednesday 14:00" },
{ "day": 1, "hour": 11, "metric_value": 11, "label": "Monday 11:00" },
{ "day": 4, "hour": 9, "metric_value": 10, "label": "Thursday 09:00" },
{ "day": 2, "hour": 15, "metric_value": 9, "label": "Tuesday 15:00" }
]
}

Day Number Mapping

DayLabel
0Sunday
1Monday
2Tuesday
3Wednesday
4Thursday
5Friday
6Saturday
note

Hours are in UTC. Convert to the user's timezone on the frontend before rendering.

Error Responses

StatusCondition
401Missing or invalid authorization header
403User exists but has no agency_id
405HTTP method is not GET
500Failed to query calls table

Behavior

  • Authenticates the user via Supabase JWT and resolves their agency_id.
  • Only accepts 7d, 30d, or 90d periods. Other values return an error.
  • Queries the raw calls table for ended calls within the date range.
  • Extracts UTC day-of-week and hour from created_at for each call.
  • Builds a heatmap by counting total_calls, connected_calls (calls where joined_at is set and end_reason is not unjoined), and meetings_booked (from analysis.sdr.meeting_booked).
  • Sorts heatmap by day then hour. Identifies the top 5 time slots based on the requested metric.
  • Uses the idx_calls_agency_created index for efficient querying.

Database Tables

TableOperationDescription
usersReadFetches user profile to determine agency_id
callsReadRaw call records, queried for hourly distribution

External APIs

None.