Zoho Desk exposes several dedicated API endpoints for reading time entries on a ticket — from listing every entry to fetching a single record or a rolled-up summary. Here is how to use each one effectively.
Why this matters
Time tracking in Zoho Desk is essential for billing, SLA reporting, and agent productivity analysis. Whether you need to pull all hours logged against a support ticket, filter by billing type, or display a total time summary in a dashboard, the Desk REST API provides purpose-built endpoints for each scenario. As independent expert support (not official Zoho support), Beam Help walks you through each option below.
Step-by-step
Step 1. Confirm your OAuth scopes.
Before making any time-entry request, verify that your OAuth token includes at minimum Desk.tickets.READ and Desk.tickets.ALL in its scope list. These scopes govern read access to ticket sub-resources, including time entries. [7]
Step 2. List all time entries for a ticket.
To retrieve every time entry logged against a specific ticket, send a GET request to:
GET /api/v1/tickets/{ticketId}/timeEntries
Replace {ticketId} with the numeric ID of the ticket you are querying. An optional p parameter dictionary can be passed to control pagination or filtering. [4]
Example (Python):
entries = desk_client.list_ticket_time_entries(ticketId="123456")
Step 3. Fetch a single time entry by its ID.
When you already know the specific timeEntryId you want to inspect, call the individual record endpoint:
GET /api/v1/tickets/{ticketId}/timeEntries/{timeEntryId}
Both ticketId and timeEntryId are required path parameters. An optional p dict can carry additional query parameters. [3]
Example (Python):
entry = desk_client.get_ticket_time_entry(ticketId="123456", timeEntryId="789")
Step 4. Get a summary (total) of all time logged.
If you only need the aggregated totals rather than individual records — useful for dashboards or billing summaries — use the summary endpoint:
GET /api/v1/tickets/{ticketId}/timeEntries/summary
This returns a rolled-up view of time logged for the ticket rather than a list of individual entries. [5]
Example (Python):
summary = desk_client.get_summation_of_ticket_time(ticketId="123456")
Step 5. Filter time entries by billing type.
To segment time entries based on whether they are billable or non-billable, use the billing-type sub-endpoint:
GET /api/v1/tickets/{ticketId}/timeEntries/billingType
Pass any relevant filter criteria through the p parameter dictionary. [2]
Example (Python):
billable = desk_client.get_ticket_time_entries_by(ticketId="123456", p={"billingType": "Billable"})
Step 6. Update a time entry if corrections are needed.
If a retrieved entry contains incorrect data, you can modify it with a PATCH request to:
PATCH /api/v1/tickets/{ticketId}/timeEntries/{timeEntryId}
Supply the fields to change inside the data dictionary. [6]
Example (Python):
desk_client.update_ticket_time_entry(
ticketId="123456",
timeEntryId="789",
data={"timeSpent": "02:30"}
)
Common pitfalls
- Missing scopes. Requests will return a
401or403ifDesk.tickets.READorDesk.tickets.ALLis absent from the token. Always double-check the scope list during OAuth setup. [7] - Confusing the summary and list endpoints. The
/summarypath returns aggregated totals, not individual rows. Attempting to iterate over it as a list will cause unexpected errors. [5] - Wrong path order. The
/billingTypeand/summarysub-paths must come after/timeEntriesin the URL. Reversing or omitting any segment will result in a 404. [2][5]
What to check
- Confirm the
ticketIdyou are using is valid and belongs to your organisation's Zoho Desk portal before calling any endpoint. [4] - Verify that your OAuth token has not expired and that it carries the correct
Desk.ticketsscopes. [7] - After an update via
PATCH, re-fetch the entry withgettickettime_entryto confirm the changes were applied as expected. [3][6]