3.6 KiB
Notes
SDP v3 API gotchas
Docs: https://www.manageengine.com/products/service-desk/sdpod-v3-api/getting-started/search-criteria.html
- Condition names have spaces:
greater than,is not,lesser than.greater_thanisn't valid, and SDP silently ignored the entire search criteria because of it, returning every ticket (124,050). If a query'stotal_countis huge, suspect the criteria first. - Paging:
row_countis at most 100. Usestart_index, and stop whenlist_info.has_more_rowsis false. Ask forget_total_count: trueon the first page.getAllRequestsdedupes by ID and stops at 20 pages or when the total is unreachable. - Multiple values: use a
values: [...]array, and join criteria withlogical_operator: 'AND'(seeallOf()intickets.js). - "Technician is empty": written as
{ field: 'technician', condition: 'is' }with no value. This isn't documented, since the docs only show the "is not" form, but it's verified to work. - Field names that work in filters:
site.name,group.name,technician.name,status.name,last_updated_time. - Group names: the ManageEngine UI shows groups as "Customer Support « KVCC", but the API name is plain "Customer Support".
- Sign-in scope:
SDPOnDemand.requests.READis enough for everything so far. - Token lifetime: Zoho access tokens last about an hour. The device flow only returns a
refresh_tokenbecause the device-code request asks foraccess_type: offline. Renew it withPOST accounts.zoho.com/oauth/v2/token,grant_type=refresh_token. - Zoho errors come back as HTTP 200: a rejected refresh token returns
{ "error": "invalid_code" }with status 200, so check foraccess_tokenrather than relying on axios throwing. The device-token poll works the same way (authorization_pending).
Decisions
-
2026-10-15: MIT license. Copyright Skylar Grant.
-
2026-10-15: OpenWeatherMap for weather. The free tier covers current weather and the 5-day forecast, and results are cached for 10 minutes. The National Weather Service API was the alternative (free, no key), but it needs three calls per lookup.
-
2026-10-15: Unassigned counter uses its own status exclusions (
UNASSIGNED_EXCLUDED_STATUSES) to match the ManageEngine view. The debug list is kept but hidden (SHOW_UNASSIGNED_LISTinindex.html). -
2026-10-15: Multi-region approach: one service token plus region config, not per-user Zoho tokens. A user's own token could see all 124k tickets, so it wouldn't separate regions, and per-user polling multiplies API traffic. See
ROADMAP.md. -
2026-10-15: Admin key until real sign-in.
ADMIN_KEYin.env, sent asX-Admin-Key, guards/api/connectand/api/check. With no key set, only loopback requests are admin. Loopback isn't trusted once a key is set, because behind a reverse proxy every request is loopback. Non-admins never see the device code; otherwise anyone could approve the board with their own Zoho account. -
2026-10-15: Token saved to a JSON file (
data/token.json, mode 600, written atomically), not SQLite yet. Move it into the database in phase 2 if one exists by then. Renewal failures with a 400 or a Zohoerrordrop the token and delete the file; network errors keep it and retry on the next check.
Known issues
- The status table scrolls sideways once there are more statuses than fit, because the page is capped at 1,320px. Consider widening the page or narrowing the sidebar.
- All statuses not in
STATUS_NAMEScount as open, including "Need Information" and "On Hold". This is intentional for now; revisit when regions get their own config.