The Freshdesk Tickets API
Almost every Freshdesk integration is a Freshdesk API tickets integration. Five endpoints do the work, and two behave differently from how you'd guess.
The five Freshdesk API tickets calls that cover most work
Everything hangs off /api/v2/tickets.
include=conversations returns the thread as well.Around those sit the conversation endpoints for adding a note or a reply, the time entry endpoints, and GET /api/v2/ticket_fields for discovering what the ticket object actually contains in your account.
Listing, and its deliberately narrow filters
The list endpoint takes a small, fixed set of filter parameters. Requester, company, updated since, and a few named canned filters such as new and my open or watching. That's roughly it.
It isn't a query language and it's not meant to be. The most useful of them by a distance is updated_since, because it is the basis of every incremental sync anyone builds. You store the timestamp of your last successful run, pass it next time, and process what changed.
One caution on that pattern. Use the timestamp the API reports rather than your own server clock, and overlap the window by a minute or two. Clock skew and in-flight updates otherwise produce a small, persistent set of records you never pick up, and it's the kind of gap that goes unnoticed for months.
Ordering and page size are controllable within limits. Combine updated_since with ascending order by update time and you get a stable crawl, which is the thing you want when the queue is changing underneath you.
Filtering properly with search
When you need "open tickets in the billing group with priority above medium created this week", you want the ticket search endpoint, not the list endpoint.
It takes a query parameter containing a quoted expression over ticket attributes, combined with AND and OR. Custom fields are queryable by their machine name. The whole query string needs URL encoding, and forgetting that produces an unhelpful validation error rather than a clear one.
Its limits are much tighter than the list endpoint. The page size is smaller and the total number of pages you can walk is capped, which in practice means a search returns a few hundred results and then stops. Check the current numbers in the reference.
So the working pattern for anything large is: narrow with search to identify a working set, or slice by date and page the list endpoint. Do not try to enumerate a year of tickets through search. It will look like it works on your test account with two hundred tickets and fail on the real one.
Viewing a ticket and its conversation
A plain single-ticket call gives you fields and metadata, not the thread. Add include=conversations and you get the messages.
Two details worth knowing before you build a viewer or an export.
Conversations distinguish public replies from private notes with a flag. If you are pushing ticket content anywhere a customer might see it, filter on that flag, and filter it server side in your code rather than trusting a template to get it right. Leaking internal notes is the classic support integration incident.
Long threads paginate separately. A ticket with a hundred messages does not hand you all hundred in the ticket response, so there's a dedicated conversations endpoint for walking them. Handle it, or your export will quietly truncate exactly the tickets that matter most.
Attachment metadata comes back with URLs. Those URLs are typically time limited, so download during the same run rather than storing the link and fetching it next week.
Updating without clobbering
Updates are PUT and they are partial. Send {"priority": 3} and only the priority changes.
That is the behaviour you want, and it means you should never do the read-modify-write dance of pulling the full object, editing one key and posting it all back. Between your read and your write an agent may have typed something, and you would overwrite it.
Some things are not update-able through the ticket object. Adding a message to the conversation is a separate call to the reply or note endpoint, not a field on the ticket. Merging tickets is not exposed as a ticket attribute either. And status transitions can be blocked by validation rules in your account, so treat a 400 on an update as a business rule and read the field-level error rather than retrying.
Discover fields before you map them. Call /api/v2/ticket_fields at startup and build your mapping from the machine names it returns. Hardcoding a custom field name from a screenshot is the single most common cause of an integration that works in staging and 400s in production.
Frequently asked questions
How do you list, filter and update tickets?
Freshdesk API list tickets returns a page with narrow built-in filters. To Freshdesk API filter tickets properly you use the search endpoint with a query string. A Freshdesk API update ticket call is a PUT of only the fields you're changing, and the Freshdesk ticket fields API tells you what those fields are called.
How do I filter tickets by status in the Freshdesk API?
Use the search endpoint with a query such as status:2 rather than the list endpoint, which only offers a small fixed set of filters. Status values are integers, with 2 for Open.
How many tickets can I retrieve per request?
List endpoints commonly allow up to 100 per page, and search is smaller with a capped page depth. Verify against the current API reference, since the numbers differ per endpoint.
How do I get the conversation on a ticket?
Request the single ticket with include=conversations, and use the dedicated conversations endpoint for long threads, which paginate separately from the ticket itself.
Does updating a ticket overwrite the fields I don't send?
No. Updates are partial, so only the attributes present in your payload change. That's why you should never send the whole object back.
Can I merge tickets through the API?
Merging isn't a plain ticket attribute you can set. Check the current reference for what is exposed, and expect the interface to be the fully supported path for it.
The merge problem, solved
If your reason for scripting the tickets API is duplicates, Ticket Merger already detects and merges them on Freshdesk and Zendesk without any code.
Start free trial14-day free trial. No credit card required.