--- name: freshservice description: Work with Freshservice ITSM from chat — view, create, update, reply to, and triage tickets; look up and update assets/CMDB; find agents, requesters, groups, and departments; and manage changes, problems, and releases. Use whenever the user mentions Freshservice, a ticket/incident/service request, an asset or CI, or a change/problem/release in their service desk. --- # Freshservice Interact with a Freshservice instance through its REST API v2 using the helper script `scripts/fs.py`, which handles auth, base URL, query encoding, and pagination. ## Setup (first run only) The helper needs credentials. Check whether they exist: ```bash python3 scripts/fs.py check ``` If it reports missing credentials, ask the user for their Freshservice **domain** (subdomain like `acme`, or full host) and **API key** (found in Freshservice → profile picture → *Profile settings* → API key). Then write: ```bash mkdir -p ~/.freshservice cat > ~/.freshservice/credentials <<'EOF' FRESHSERVICE_DOMAIN=acme FRESHSERVICE_API_KEY=PASTE_KEY_HERE EOF chmod 600 ~/.freshservice/credentials ``` Re-run `check` to confirm. (Environment variables `FRESHSERVICE_DOMAIN` / `FRESHSERVICE_API_KEY` override the file if set.) ## How to call the API One command does everything: ```bash python3 scripts/fs.py request [--param KEY=VALUE ...] [--data ''] ``` - `/api/v2` is added to PATH automatically. - `--param query=...` and `--param filter=...` are auto-wrapped in the double quotes the API requires — pass the expression unquoted. - Output is pretty JSON with `status`, `data`, and `next_page` when more pages exist. ### Common operations ```bash # Tickets python3 scripts/fs.py request GET /tickets --param per_page=10 --param order_by=updated_at --param order_type=desc python3 scripts/fs.py request GET /tickets/filter --param 'query=status:2 AND priority:3' python3 scripts/fs.py request GET /tickets/123 --param include=conversations,requester python3 scripts/fs.py request POST /tickets --data '{"subject":"Laptop won'\''t boot","description":"...","email":"user@co.com","priority":2,"status":2}' python3 scripts/fs.py request PUT /tickets/123 --data '{"status":4}' # resolve python3 scripts/fs.py request POST /tickets/123/reply --data '{"body":"Working on it."}' python3 scripts/fs.py request POST /tickets/123/notes --data '{"body":"Internal note","private":true}' # Assets / CMDB python3 scripts/fs.py request GET /assets --param 'filter=name:'\''MacBook'\''' python3 scripts/fs.py request GET /assets/45 --param include=type_fields # People python3 scripts/fs.py request GET /requesters --param email=user@co.com python3 scripts/fs.py request GET /agents --param email=agent@co.com python3 scripts/fs.py request GET /groups python3 scripts/fs.py request GET /departments # Change / Problem / Release python3 scripts/fs.py request GET /changes/filter --param 'query=status:1' python3 scripts/fs.py request GET /problems python3 scripts/fs.py request GET /releases ``` For endpoints, field names, status/priority codes, and filter-query syntax, read `reference.md`. ## Guidance - **Confirm before writing.** Before creating/updating tickets/changes or posting a public `reply` (the requester is emailed), show the user what you'll send and get a yes — unless they've clearly already authorized it. - Resolve people to ids first: look up a requester by email before assigning. - Translate codes for the user (e.g. show "Open / High", not "status 2, priority 3"). - On a 4xx error, read the `error` body — it names the offending field — and fix the request rather than retrying verbatim. - Paginate when `next_page` appears and the user wants the full set.