feat: allow querying reporting events via the API (#12832)

This commit is contained in:
Shivam Mishra 2025-11-13 12:46:55 +05:30 committed by GitHub
parent f455e7994e
commit 4f09c2203c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 1373 additions and 5 deletions

View File

@ -35,4 +35,21 @@ class ReportingEvent < ApplicationRecord
belongs_to :user, optional: true
belongs_to :inbox, optional: true
belongs_to :conversation, optional: true
# Scopes for filtering
scope :filter_by_date_range, lambda { |range|
where(created_at: range) if range.present?
}
scope :filter_by_inbox_id, lambda { |inbox_id|
where(inbox_id: inbox_id) if inbox_id.present?
}
scope :filter_by_user_id, lambda { |user_id|
where(user_id: user_id) if user_id.present?
}
scope :filter_by_name, lambda { |name|
where(name: name) if name.present?
}
end

View File

@ -141,6 +141,7 @@ Rails.application.routes.draw do
post :custom_attributes
get :attachments
get :inbox_assistant
get :reporting_events if ChatwootApp.enterprise?
end
end
@ -186,6 +187,7 @@ Rails.application.routes.draw do
get :download
end
end
resources :reporting_events, only: [:index] if ChatwootApp.enterprise?
resources :custom_attribute_definitions, only: [:index, :show, :create, :update, :destroy]
resources :custom_filters, only: [:index, :show, :create, :update, :destroy]
resources :inboxes, only: [:index, :show, :create, :update, :destroy] do

View File

@ -0,0 +1,30 @@
class Api::V1::Accounts::ReportingEventsController < Api::V1::Accounts::EnterpriseAccountsController
include DateRangeHelper
RESULTS_PER_PAGE = 25
before_action :check_admin_authorization?
before_action :set_reporting_events, only: [:index]
before_action :set_current_page, only: [:index]
def index
@reporting_events = @reporting_events.page(@current_page).per(RESULTS_PER_PAGE)
@total_count = @reporting_events.total_count
end
private
def set_reporting_events
@reporting_events = Current.account.reporting_events
.includes(:conversation, :user, :inbox)
.filter_by_date_range(range)
.filter_by_inbox_id(params[:inbox_id])
.filter_by_user_id(params[:user_id])
.filter_by_name(params[:name])
.order(created_at: :desc)
end
def set_current_page
@current_page = (params[:page] || 1).to_i
end
end

View File

@ -11,6 +11,10 @@ module Enterprise::Api::V1::Accounts::ConversationsController
end
end
def reporting_events
@reporting_events = @conversation.reporting_events.order(created_at: :asc)
end
def permitted_update_params
super.merge(params.permit(:sla_policy_id))
end

View File

@ -0,0 +1,3 @@
json.array! @reporting_events do |reporting_event|
json.partial! 'api/v1/models/reporting_event', formats: [:json], reporting_event: reporting_event
end

View File

@ -0,0 +1,11 @@
json.payload do
json.array! @reporting_events do |reporting_event|
json.partial! 'api/v1/models/reporting_event', formats: [:json], reporting_event: reporting_event
end
end
json.meta do
json.count @total_count
json.current_page @current_page
json.total_pages @reporting_events.total_pages
end

View File

@ -0,0 +1,12 @@
json.id reporting_event.id
json.name reporting_event.name
json.value reporting_event.value
json.value_in_business_hours reporting_event.value_in_business_hours
json.event_start_time reporting_event.event_start_time
json.event_end_time reporting_event.event_end_time
json.account_id reporting_event.account_id
json.inbox_id reporting_event.inbox_id
json.user_id reporting_event.user_id
json.conversation_id reporting_event.conversation_id
json.created_at reporting_event.created_at
json.updated_at reporting_event.updated_at

View File

@ -102,4 +102,146 @@ RSpec.describe 'Conversations API', type: :request do
end
end
end
describe 'GET /api/v1/accounts/{account.id}/conversations/:id/reporting_events' do
let(:conversation) { create(:conversation, account: account) }
let(:inbox) { conversation.inbox }
let(:agent) { administrator }
before do
# Create reporting events for this conversation
@event1 = create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: agent,
name: 'first_response',
value: 120,
created_at: 3.hours.ago)
@event2 = create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: agent,
name: 'reply_time',
value: 45,
created_at: 2.hours.ago)
@event3 = create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: agent,
name: 'resolution',
value: 300,
created_at: 1.hour.ago)
# Create an event for a different conversation (should not be included)
other_conversation = create(:conversation, account: account)
create(:reporting_event,
account: account,
conversation: other_conversation,
inbox: other_conversation.inbox,
user: agent,
name: 'other_conversation_event',
value: 60)
end
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
as: :json
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user with conversation access' do
it 'returns all reporting events for the conversation' do
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
headers: administrator.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
# Should return array directly (no pagination)
expect(json_response).to be_an(Array)
expect(json_response.size).to eq(3)
# Check they are sorted by created_at asc (oldest first)
expect(json_response.first['name']).to eq('first_response')
expect(json_response.last['name']).to eq('resolution')
# Verify it doesn't include events from other conversations
event_names = json_response.map { |e| e['name'] }
expect(event_names).not_to include('other_conversation_event')
end
it 'returns empty array when conversation has no reporting events' do
conversation_without_events = create(:conversation, account: account)
get "/api/v1/accounts/#{account.id}/conversations/#{conversation_without_events.display_id}/reporting_events",
headers: administrator.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response).to be_an(Array)
expect(json_response).to be_empty
end
end
context 'when agent has limited access' do
let(:limited_agent) { create(:user, account: account, role: :agent) }
it 'returns unauthorized for unassigned conversation without permission' do
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
headers: limited_agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
it 'returns reporting events when agent is assigned to the conversation' do
conversation.update!(assignee: limited_agent)
# Also create inbox member for the agent
create(:inbox_member, user: limited_agent, inbox: conversation.inbox)
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
headers: limited_agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response).to be_an(Array)
expect(json_response.size).to eq(3)
end
end
context 'when agent has team access' do
let(:team_agent) { create(:user, account: account, role: :agent) }
let(:team) { create(:team, account: account) }
before do
create(:team_member, team: team, user: team_agent)
conversation.update!(team: team)
end
it 'allows accessing conversation reporting events via team membership' do
get "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/reporting_events",
headers: team_agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response).to be_an(Array)
expect(json_response.size).to eq(3)
end
end
end
end

View File

@ -0,0 +1,217 @@
require 'rails_helper'
RSpec.describe 'Enterprise Reporting Events API', type: :request do
let!(:account) { create(:account) }
let!(:admin) { create(:user, account: account, role: :administrator) }
let!(:agent) { create(:user, account: account, role: :agent) }
let!(:inbox) { create(:inbox, account: account) }
let!(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: agent) }
describe 'GET /api/v1/accounts/{account.id}/reporting_events' do
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/reporting_events",
as: :json
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated normal agent user' do
it 'returns unauthorized' do
get "/api/v1/accounts/#{account.id}/reporting_events",
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated admin user' do
before do
create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: agent,
name: 'first_response',
value: 120,
created_at: 3.days.ago)
create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: agent,
name: 'resolution',
value: 300,
created_at: 2.days.ago)
create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: agent,
name: 'reply_time',
value: 45,
created_at: 1.day.ago)
end
it 'fetches reporting events with pagination' do
get "/api/v1/accounts/#{account.id}/reporting_events",
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
# Check structure and pagination
expect(json_response).to have_key('payload')
expect(json_response).to have_key('meta')
expect(json_response['meta']['count']).to eq(3)
# Check events are sorted by created_at desc (newest first)
events = json_response['payload']
expect(events.size).to eq(3)
expect(events.first['name']).to eq('reply_time')
expect(events.last['name']).to eq('first_response')
end
it 'filters reporting events by date range using since and until' do
get "/api/v1/accounts/#{account.id}/reporting_events",
params: { since: 2.5.days.ago.to_time.to_i.to_s, until: 1.5.days.ago.to_time.to_i.to_s },
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response['meta']['count']).to eq(1)
expect(json_response['payload'].first['name']).to eq('resolution')
end
it 'filters reporting events by inbox_id' do
other_inbox = create(:inbox, account: account)
other_conversation = create(:conversation, account: account, inbox: other_inbox)
create(:reporting_event,
account: account,
conversation: other_conversation,
inbox: other_inbox,
user: agent,
name: 'other_inbox_event')
get "/api/v1/accounts/#{account.id}/reporting_events",
params: { inbox_id: inbox.id },
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response['meta']['count']).to eq(3)
expect(json_response['payload'].map { |e| e['name'] }).not_to include('other_inbox_event')
end
it 'filters reporting events by user_id (agent)' do
other_agent = create(:user, account: account, role: :agent)
create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: other_agent,
name: 'other_agent_event')
get "/api/v1/accounts/#{account.id}/reporting_events",
params: { user_id: agent.id },
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response['meta']['count']).to eq(3)
expect(json_response['payload'].map { |e| e['name'] }).not_to include('other_agent_event')
end
it 'filters reporting events by name' do
get "/api/v1/accounts/#{account.id}/reporting_events",
params: { name: 'first_response' },
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response['meta']['count']).to eq(1)
expect(json_response['payload'].first['name']).to eq('first_response')
end
it 'supports combining multiple filters' do
# Create more test data
other_conversation = create(:conversation, account: account, inbox: inbox, assignee: agent)
create(:reporting_event,
account: account,
conversation: other_conversation,
inbox: inbox,
user: agent,
name: 'first_response',
value: 90,
created_at: 2.days.ago)
get "/api/v1/accounts/#{account.id}/reporting_events",
params: {
inbox_id: inbox.id,
user_id: agent.id,
name: 'first_response',
since: 4.days.ago.to_time.to_i.to_s,
until: Time.zone.now.to_time.to_i.to_s
},
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response['meta']['count']).to eq(2)
expect(json_response['payload'].map { |e| e['name'] }).to all(eq('first_response'))
end
context 'with pagination' do
before do
# Create more events to test pagination
30.times do |i|
create(:reporting_event,
account: account,
conversation: conversation,
inbox: inbox,
user: agent,
name: "event_#{i}",
created_at: i.hours.ago)
end
end
it 'returns 25 events per page by default' do
get "/api/v1/accounts/#{account.id}/reporting_events",
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response['payload'].size).to eq(25)
expect(json_response['meta']['count']).to eq(33) # 30 + 3 original events
expect(json_response['meta']['current_page']).to eq(1)
end
it 'supports page navigation' do
get "/api/v1/accounts/#{account.id}/reporting_events",
params: { page: 2 },
headers: admin.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response['payload'].size).to eq(8) # Remaining events
expect(json_response['meta']['current_page']).to eq(2)
end
end
end
end
end

View File

@ -1,11 +1,13 @@
FactoryBot.define do
factory :reporting_event do
name { 'MyString' }
name { 'first_response' }
value { 1.5 }
value_in_business_hours { 1 }
account_id { 1 }
inbox_id { 1 }
user_id { 1 }
conversation_id { 1 }
account
inbox { association :inbox, account: account }
user { association :user, account: account }
conversation { association :conversation, account: account, inbox: inbox }
event_start_time { 2.hours.ago }
event_end_time { 1.hour.ago }
end
end

View File

@ -248,3 +248,9 @@ contact_conversations_response:
$ref: ./resource/contact_conversations_response.yml
contactable_inboxes_response:
$ref: ./resource/contactable_inboxes_response.yml
reporting_event:
$ref: ./resource/reporting_event.yml
reporting_event_meta:
$ref: ./resource/reporting_event_meta.yml
reporting_events_list_response:
$ref: ./resource/reporting_events_list_response.yml

View File

@ -0,0 +1,47 @@
type: object
properties:
id:
type: number
description: ID of the reporting event
name:
type: string
description: Name of the event (e.g., first_response, resolution, reply_time)
value:
type: number
format: double
description: Value of the metric in seconds
value_in_business_hours:
type: number
format: double
description: Value of the metric in seconds, calculated only for business hours
event_start_time:
type: string
format: date-time
description: The timestamp when the event started
event_end_time:
type: string
format: date-time
description: The timestamp when the event ended
account_id:
type: number
description: ID of the account
conversation_id:
type: number
nullable: true
description: ID of the conversation
inbox_id:
type: number
nullable: true
description: ID of the inbox
user_id:
type: number
nullable: true
description: ID of the user/agent
created_at:
type: string
format: date-time
description: The timestamp when the reporting event was created
updated_at:
type: string
format: date-time
description: The timestamp when the reporting event was last updated

View File

@ -0,0 +1,11 @@
type: object
properties:
count:
type: integer
description: Total number of reporting events
current_page:
type: integer
description: Current page number
total_pages:
type: integer
description: Total number of pages

View File

@ -0,0 +1,10 @@
type: object
properties:
meta:
$ref: '#/components/schemas/reporting_event_meta'
description: Metadata about the reporting events list response
payload:
type: array
items:
$ref: '#/components/schemas/reporting_event'
description: List of reporting events

View File

@ -0,0 +1,29 @@
tags:
- Conversations
operationId: get-conversation-reporting-events
summary: Conversation Reporting Events
security:
- userApiKey: []
description: Get reporting events for a specific conversation. This endpoint returns events such as first response time, resolution time, and other metrics for the conversation, sorted by creation time in ascending order.
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/reporting_event'
description: Array of reporting events for the conversation
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/bad_request_error'
'404':
description: Conversation not found
content:
application/json:
schema:
$ref: '#/components/schemas/bad_request_error'

View File

@ -0,0 +1,47 @@
tags:
- Reports
operationId: get-account-reporting-events
summary: Account Reporting Events
security:
- userApiKey: []
description: Get paginated reporting events for the account. This endpoint returns reporting events such as first response time, resolution time, and other metrics. Only administrators can access this endpoint. Results are paginated with 25 items per page.
parameters:
- $ref: '#/components/parameters/page'
- in: query
name: since
schema:
type: string
description: The timestamp from where events should start (Unix timestamp in seconds)
- in: query
name: until
schema:
type: string
description: The timestamp from where events should stop (Unix timestamp in seconds)
- in: query
name: inbox_id
schema:
type: number
description: Filter events by inbox ID
- in: query
name: user_id
schema:
type: number
description: Filter events by user/agent ID
- in: query
name: name
schema:
type: string
description: Filter events by event name (e.g., first_response, resolution, reply_time)
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/reporting_events_list_response'
'403':
description: Access denied - Only administrators can access this endpoint
content:
application/json:
schema:
$ref: '#/components/schemas/bad_request_error'

View File

@ -389,6 +389,15 @@
post:
$ref: ./application/conversation/labels/create.yml
# Conversation Reporting Events
/api/v1/accounts/{account_id}/conversations/{conversation_id}/reporting_events:
parameters:
- $ref: '#/components/parameters/account_id'
- $ref: '#/components/parameters/conversation_id'
get:
$ref: ./application/conversation/reporting_events.yml
# Inboxes
/api/v1/accounts/{account_id}/inboxes:
$ref: ./application/inboxes/index.yml
@ -535,6 +544,13 @@
### Reports
# Account Reporting Events
/api/v1/accounts/{account_id}/reporting_events:
parameters:
- $ref: '#/components/parameters/account_id'
get:
$ref: ./application/reporting_events/index.yml
# List
/api/v2/accounts/{account_id}/reports:
parameters:

View File

@ -5140,6 +5140,65 @@
}
}
},
"/api/v1/accounts/{account_id}/conversations/{conversation_id}/reporting_events": {
"parameters": [
{
"$ref": "#/components/parameters/account_id"
},
{
"$ref": "#/components/parameters/conversation_id"
}
],
"get": {
"tags": [
"Conversations"
],
"operationId": "get-conversation-reporting-events",
"summary": "Conversation Reporting Events",
"security": [
{
"userApiKey": []
}
],
"description": "Get reporting events for a specific conversation. This endpoint returns events such as first response time, resolution time, and other metrics for the conversation, sorted by creation time in ascending order.",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/reporting_event"
},
"description": "Array of reporting events for the conversation"
}
}
}
},
"403": {
"description": "Access denied",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/bad_request_error"
}
}
}
},
"404": {
"description": "Conversation not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/bad_request_error"
}
}
}
}
}
}
},
"/api/v1/accounts/{account_id}/inboxes": {
"get": {
"tags": [
@ -7311,6 +7370,93 @@
}
}
},
"/api/v1/accounts/{account_id}/reporting_events": {
"parameters": [
{
"$ref": "#/components/parameters/account_id"
}
],
"get": {
"tags": [
"Reports"
],
"operationId": "get-account-reporting-events",
"summary": "Account Reporting Events",
"security": [
{
"userApiKey": []
}
],
"description": "Get paginated reporting events for the account. This endpoint returns reporting events such as first response time, resolution time, and other metrics. Only administrators can access this endpoint. Results are paginated with 25 items per page.",
"parameters": [
{
"$ref": "#/components/parameters/page"
},
{
"in": "query",
"name": "since",
"schema": {
"type": "string"
},
"description": "The timestamp from where events should start (Unix timestamp in seconds)"
},
{
"in": "query",
"name": "until",
"schema": {
"type": "string"
},
"description": "The timestamp from where events should stop (Unix timestamp in seconds)"
},
{
"in": "query",
"name": "inbox_id",
"schema": {
"type": "number"
},
"description": "Filter events by inbox ID"
},
{
"in": "query",
"name": "user_id",
"schema": {
"type": "number"
},
"description": "Filter events by user/agent ID"
},
{
"in": "query",
"name": "name",
"schema": {
"type": "string"
},
"description": "Filter events by event name (e.g., first_response, resolution, reply_time)"
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/reporting_events_list_response"
}
}
}
},
"403": {
"description": "Access denied - Only administrators can access this endpoint",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/bad_request_error"
}
}
}
}
}
}
},
"/api/v2/accounts/{account_id}/reports": {
"parameters": [
{
@ -12066,6 +12212,100 @@
"description": "List of contactable inboxes for the contact"
}
}
},
"reporting_event": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "ID of the reporting event"
},
"name": {
"type": "string",
"description": "Name of the event (e.g., first_response, resolution, reply_time)"
},
"value": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds"
},
"value_in_business_hours": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds, calculated only for business hours"
},
"event_start_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event started"
},
"event_end_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event ended"
},
"account_id": {
"type": "number",
"description": "ID of the account"
},
"conversation_id": {
"type": "number",
"nullable": true,
"description": "ID of the conversation"
},
"inbox_id": {
"type": "number",
"nullable": true,
"description": "ID of the inbox"
},
"user_id": {
"type": "number",
"nullable": true,
"description": "ID of the user/agent"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was created"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was last updated"
}
}
},
"reporting_event_meta": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"description": "Total number of reporting events"
},
"current_page": {
"type": "integer",
"description": "Current page number"
},
"total_pages": {
"type": "integer",
"description": "Total number of pages"
}
}
},
"reporting_events_list_response": {
"type": "object",
"properties": {
"meta": {
"$ref": "#/components/schemas/reporting_event_meta"
},
"payload": {
"type": "array",
"items": {
"$ref": "#/components/schemas/reporting_event"
},
"description": "List of reporting events"
}
}
}
},
"parameters": {

View File

@ -3683,6 +3683,65 @@
}
}
},
"/api/v1/accounts/{account_id}/conversations/{conversation_id}/reporting_events": {
"parameters": [
{
"$ref": "#/components/parameters/account_id"
},
{
"$ref": "#/components/parameters/conversation_id"
}
],
"get": {
"tags": [
"Conversations"
],
"operationId": "get-conversation-reporting-events",
"summary": "Conversation Reporting Events",
"security": [
{
"userApiKey": []
}
],
"description": "Get reporting events for a specific conversation. This endpoint returns events such as first response time, resolution time, and other metrics for the conversation, sorted by creation time in ascending order.",
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/reporting_event"
},
"description": "Array of reporting events for the conversation"
}
}
}
},
"403": {
"description": "Access denied",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/bad_request_error"
}
}
}
},
"404": {
"description": "Conversation not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/bad_request_error"
}
}
}
}
}
}
},
"/api/v1/accounts/{account_id}/inboxes": {
"get": {
"tags": [
@ -5854,6 +5913,93 @@
}
}
},
"/api/v1/accounts/{account_id}/reporting_events": {
"parameters": [
{
"$ref": "#/components/parameters/account_id"
}
],
"get": {
"tags": [
"Reports"
],
"operationId": "get-account-reporting-events",
"summary": "Account Reporting Events",
"security": [
{
"userApiKey": []
}
],
"description": "Get paginated reporting events for the account. This endpoint returns reporting events such as first response time, resolution time, and other metrics. Only administrators can access this endpoint. Results are paginated with 25 items per page.",
"parameters": [
{
"$ref": "#/components/parameters/page"
},
{
"in": "query",
"name": "since",
"schema": {
"type": "string"
},
"description": "The timestamp from where events should start (Unix timestamp in seconds)"
},
{
"in": "query",
"name": "until",
"schema": {
"type": "string"
},
"description": "The timestamp from where events should stop (Unix timestamp in seconds)"
},
{
"in": "query",
"name": "inbox_id",
"schema": {
"type": "number"
},
"description": "Filter events by inbox ID"
},
{
"in": "query",
"name": "user_id",
"schema": {
"type": "number"
},
"description": "Filter events by user/agent ID"
},
{
"in": "query",
"name": "name",
"schema": {
"type": "string"
},
"description": "Filter events by event name (e.g., first_response, resolution, reply_time)"
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/reporting_events_list_response"
}
}
}
},
"403": {
"description": "Access denied - Only administrators can access this endpoint",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/bad_request_error"
}
}
}
}
}
}
},
"/api/v2/accounts/{account_id}/reports": {
"parameters": [
{
@ -10573,6 +10719,100 @@
"description": "List of contactable inboxes for the contact"
}
}
},
"reporting_event": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "ID of the reporting event"
},
"name": {
"type": "string",
"description": "Name of the event (e.g., first_response, resolution, reply_time)"
},
"value": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds"
},
"value_in_business_hours": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds, calculated only for business hours"
},
"event_start_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event started"
},
"event_end_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event ended"
},
"account_id": {
"type": "number",
"description": "ID of the account"
},
"conversation_id": {
"type": "number",
"nullable": true,
"description": "ID of the conversation"
},
"inbox_id": {
"type": "number",
"nullable": true,
"description": "ID of the inbox"
},
"user_id": {
"type": "number",
"nullable": true,
"description": "ID of the user/agent"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was created"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was last updated"
}
}
},
"reporting_event_meta": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"description": "Total number of reporting events"
},
"current_page": {
"type": "integer",
"description": "Current page number"
},
"total_pages": {
"type": "integer",
"description": "Total number of pages"
}
}
},
"reporting_events_list_response": {
"type": "object",
"properties": {
"meta": {
"$ref": "#/components/schemas/reporting_event_meta"
},
"payload": {
"type": "array",
"items": {
"$ref": "#/components/schemas/reporting_event"
},
"description": "List of reporting events"
}
}
}
},
"parameters": {

View File

@ -5019,6 +5019,100 @@
"description": "List of contactable inboxes for the contact"
}
}
},
"reporting_event": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "ID of the reporting event"
},
"name": {
"type": "string",
"description": "Name of the event (e.g., first_response, resolution, reply_time)"
},
"value": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds"
},
"value_in_business_hours": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds, calculated only for business hours"
},
"event_start_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event started"
},
"event_end_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event ended"
},
"account_id": {
"type": "number",
"description": "ID of the account"
},
"conversation_id": {
"type": "number",
"nullable": true,
"description": "ID of the conversation"
},
"inbox_id": {
"type": "number",
"nullable": true,
"description": "ID of the inbox"
},
"user_id": {
"type": "number",
"nullable": true,
"description": "ID of the user/agent"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was created"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was last updated"
}
}
},
"reporting_event_meta": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"description": "Total number of reporting events"
},
"current_page": {
"type": "integer",
"description": "Current page number"
},
"total_pages": {
"type": "integer",
"description": "Total number of pages"
}
}
},
"reporting_events_list_response": {
"type": "object",
"properties": {
"meta": {
"$ref": "#/components/schemas/reporting_event_meta"
},
"payload": {
"type": "array",
"items": {
"$ref": "#/components/schemas/reporting_event"
},
"description": "List of reporting events"
}
}
}
},
"parameters": {

View File

@ -4434,6 +4434,100 @@
"description": "List of contactable inboxes for the contact"
}
}
},
"reporting_event": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "ID of the reporting event"
},
"name": {
"type": "string",
"description": "Name of the event (e.g., first_response, resolution, reply_time)"
},
"value": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds"
},
"value_in_business_hours": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds, calculated only for business hours"
},
"event_start_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event started"
},
"event_end_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event ended"
},
"account_id": {
"type": "number",
"description": "ID of the account"
},
"conversation_id": {
"type": "number",
"nullable": true,
"description": "ID of the conversation"
},
"inbox_id": {
"type": "number",
"nullable": true,
"description": "ID of the inbox"
},
"user_id": {
"type": "number",
"nullable": true,
"description": "ID of the user/agent"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was created"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was last updated"
}
}
},
"reporting_event_meta": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"description": "Total number of reporting events"
},
"current_page": {
"type": "integer",
"description": "Current page number"
},
"total_pages": {
"type": "integer",
"description": "Total number of pages"
}
}
},
"reporting_events_list_response": {
"type": "object",
"properties": {
"meta": {
"$ref": "#/components/schemas/reporting_event_meta"
},
"payload": {
"type": "array",
"items": {
"$ref": "#/components/schemas/reporting_event"
},
"description": "List of reporting events"
}
}
}
},
"parameters": {

View File

@ -5195,6 +5195,100 @@
"description": "List of contactable inboxes for the contact"
}
}
},
"reporting_event": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "ID of the reporting event"
},
"name": {
"type": "string",
"description": "Name of the event (e.g., first_response, resolution, reply_time)"
},
"value": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds"
},
"value_in_business_hours": {
"type": "number",
"format": "double",
"description": "Value of the metric in seconds, calculated only for business hours"
},
"event_start_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event started"
},
"event_end_time": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the event ended"
},
"account_id": {
"type": "number",
"description": "ID of the account"
},
"conversation_id": {
"type": "number",
"nullable": true,
"description": "ID of the conversation"
},
"inbox_id": {
"type": "number",
"nullable": true,
"description": "ID of the inbox"
},
"user_id": {
"type": "number",
"nullable": true,
"description": "ID of the user/agent"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was created"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the reporting event was last updated"
}
}
},
"reporting_event_meta": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"description": "Total number of reporting events"
},
"current_page": {
"type": "integer",
"description": "Current page number"
},
"total_pages": {
"type": "integer",
"description": "Total number of pages"
}
}
},
"reporting_events_list_response": {
"type": "object",
"properties": {
"meta": {
"$ref": "#/components/schemas/reporting_event_meta"
},
"payload": {
"type": "array",
"items": {
"$ref": "#/components/schemas/reporting_event"
},
"description": "List of reporting events"
}
}
}
},
"parameters": {