Files
freshservice-claude/reference.md
spencerm 5ded947b73 Document include=assets as the way to see a ticket's associated assets
The /tickets/{id}/associated-assets path 404s on this instance; assets come
back embedded via GET /tickets/{id}?include=assets. Spell out the full include
list on get_ticket and in the skill reference so consumers don't hunt for a
nonexistent endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 15:37:16 -06:00

5.6 KiB
Raw Permalink Blame History

Freshservice API v2 reference

Base URL: https://<domain>.freshservice.com/api/v2. Auth is HTTP Basic with the API key as username (handled by scripts/fs.py). Full docs: https://api.freshservice.com

Codes

Ticket status (defaults): 2 Open · 3 Pending · 4 Resolved · 5 Closed Ticket priority: 1 Low · 2 Medium · 3 High · 4 Urgent

⚠️ Instances often define custom statuses beyond the 4 defaults (e.g. "Working", "Scheduled", "Waiting Vendor Support"). Resolved and Closed are always ids 4 and 5; every other status is "open". To list them all, read the status field choices: GET /ticket_form_fields → field where name == "status"choices[]. So "all my tickets that aren't resolved/closed" must enumerate every non-4/5 status, not just (status:2 OR status:3). Recipe: agent_id:<id> AND (status:2 OR status:3 OR status:6 OR status:7 OR ...) using all open ids from the status field. Ticket source: 1 Email · 2 Portal · 3 Phone · 4 Chat · 5 Feedback widget · 6 Yammer · 7 AWS CloudWatch · 8 PagerDuty · 9 Walkup · 10 Slack

Status/priority for changes use their own workflow codes; list a few existing records to infer them, or read the ticket-fields / change-fields endpoints.

Endpoints

Resource List Create View Update Delete
Tickets GET /tickets POST /tickets GET /tickets/{id} PUT /tickets/{id} DELETE /tickets/{id}
Ticket filter GET /tickets/filter?query="..."
Conversations GET /tickets/{id}/conversations reply: POST /tickets/{id}/reply; note: POST /tickets/{id}/notes PUT /conversations/{id} DELETE /conversations/{id}
Assets GET /assets POST /assets GET /assets/{display_id} PUT /assets/{display_id} DELETE /assets/{display_id}
Agents GET /agents POST /agents GET /agents/{id} PUT /agents/{id}
Requesters GET /requesters POST /requesters GET /requesters/{id} PUT /requesters/{id}
Groups GET /groups POST /groups GET /groups/{id} PUT /groups/{id} DELETE /groups/{id}
Departments GET /departments POST /departments GET /departments/{id} PUT /departments/{id} DELETE /departments/{id}
Changes GET /changes (+ /changes/filter) POST /changes GET /changes/{id} PUT /changes/{id} DELETE /changes/{id}
Problems GET /problems POST /problems GET /problems/{id} PUT /problems/{id} DELETE /problems/{id}
Releases GET /releases POST /releases GET /releases/{id} PUT /releases/{id} DELETE /releases/{id}
Current agent GET /agents/me

Other useful endpoints reachable the same way: /solutions/categories, /solutions/folders, /solutions/articles, /products, /vendors, /ticket_fields, /tickets/{id}/time_entries, /canned_responses.

Ticket fields (create/update)

subject, description (HTML ok), email or requester_id, priority, status, source, group_id, responder_id (assigned agent), type (e.g. "Incident", "Service Request"), tags (array), category, sub_category, custom_fields (object), due_by, fr_due_by.

Provide either email or requester_id. For a public reply the requester is emailed; a note with "private": true is internal-only.

Filter (query) syntax — /tickets/filter and /changes/filter

  • Format: field:value, combined with AND / OR.
  • Strings single-quoted: tag:'vip'. Numbers/dates bare or quoted.
  • Operators on dates/numbers: >, <, e.g. created_at:>'2026-01-01'.
  • Filterable ticket fields include: status, priority, agent_id, group_id, requester_id, type, source, tag, created_at, updated_at, due_by, plus custom fields by name.
  • The whole expression must be URL-double-quoted; scripts/fs.py does this when you pass --param query=... / --param filter=....

Two common gotchas:

  • Assignee is agent_id (numeric), not an email. Resolve an email to an id first: GET /agents?email=person@co.com → read id, then filter on it.
  • No "not" operator for status. "Open / unresolved / not closed" must be enumerated: (status:2 OR status:3). Parenthesize the OR group when AND-ing it.

Examples:

  • status:2 AND priority:3
  • agent_id:0 AND status:2 — unassigned open tickets
  • agent_id:21000816864 AND (status:2 OR status:3) — assigned to an agent, still open
  • type:'Incident' AND created_at:>'2026-06-01'

Multi-workspace accounts: /tickets/filter searches one workspace by default. Pass --param workspace_id=<id> to target another (an agent's workspace_ids lists which ones they're in).

Listing vs. filtering

  • GET /tickets supports filter presets (new_and_my_open, watching, spam, deleted), updated_since, order_by, order_type, page, per_page (max 100), and include (conversations, requester, stats).
  • GET /tickets/{id}?include=assets is the only way to see a ticket's associated CMDB assets — they come back embedded in the ticket object. There is no /tickets/{id}/associated-assets endpoint (it 404s). Other single-ticket includes: conversations, requester, requested_for, stats, problem, tags, related_tickets.
  • GET /tickets/filter?query="..." is for ad-hoc field queries (also 100/page).

Pagination & rate limits

  • 30 results/page default, 100 max via per_page. scripts/fs.py surfaces next_page when a next-page Link header is present.
  • Per-plan minute limits (100500/min). Responses include rate_limit_remaining.