NinjaOne Device Glance
An optional, strictly read-only integration with NinjaOne RMM: when a client starts a chat, AVA tries to identify their machine and shows the engineer a "device at a glance" card right in the chat's context panel — no tab-switching to the RMM console mid-conversation.
Off by default. With the NinjaOne variables unset, the feature is completely dormant: no Device section renders anywhere, and no NinjaOne network calls are ever made. Engineer and client behavior is byte-identical to a build without the feature.
What the engineer sees
A read-only card in the client-context panel of an active chat:
- Identity header — device name, make/model, organization
- Stat tiles — online/offline status, last boot, disk free, pending/failed OS patches, antivirus state, public/private IPs, OS/system info, last logged-on user
- Alerts strip — recent NinjaOne alerts for the device
- Confidence chip — how sure the match is (a device is only shown when the resolution pipeline has real evidence; it never guesses)
- "Open in NinjaOne" — a deep link to the device's page in your NinjaOne console
Telemetry values (disk, patches, AV, alerts) reflect NinjaOne's own last-check-in data for the device — not a live poll triggered by the chat.
In the engineer console, the chat's Intake card also shows a one-line device summary, and the /device command jumps straight to the card (see engineer-console.md).
The read-only guarantee
This integration is designed so that it cannot modify anything in your RMM, as a matter of credential scope rather than convention:
- The NinjaOne API client you create is scoped to Monitoring only — the credential itself cannot run scripts, reboot devices, or trigger any action.
- AVA's NinjaOne client exposes GET requests exclusively — there is no code path that issues a write to NinjaOne. (The one POST under the hood is the OAuth2 token exchange itself, which is a POST by spec.)
- No remote-session launch, no device actions — the "Open in NinjaOne" link is a console URL and requires the engineer to already be signed in to NinjaOne in their browser.
The only write the feature can perform anywhere is the optional AutoTask ticket enrichment (to your own AT ticket, never to NinjaOne), and that is gated behind its own default-off switch — see below.
How device resolution works (two independent layers)
Layer 1 — AutoTask-only baseline (no NinjaOne credentials needed). If your AutoTask instance already syncs NinjaOne data onto Configuration Items (the NinjaRMM-RemoteUrl / -BackgroundUrl / -Antivirus / -PrivateIpAddress / -DeviceUID UDFs, as the standard NinjaOne↔AutoTask sync populates), AVA matches the chat's AutoTask company + reported hostname to a Configuration Item and shows those UDF facts plus a deep link parsed from the remote-URL UDF — even with all NINJAONE_* variables unset.
Layer 2 — live NinjaOne API (optional). With the three credentials set, AVA additionally queries the NinjaOne API for live device telemetry, and can fall back to a hostname/user search when no Configuration Item matched.
Matching is identity-gated and never-guess: hints have to line up with the chat's company before a device is shown.
Step 1 — Create the API client (NinjaOne admin)
- In NinjaOne: Administration → Apps → API → Client App IDs → Add.
- Platform: API Services (machine-to-machine).
- Scope: Monitoring only — do not grant
managementor any write scope. This is the least-privilege line the whole feature is built on. - Grant type: Client Credentials. No redirect URI (server-to-server, not interactive OAuth).
- Copy the generated Client ID and Client Secret.
Step 2 — Set the enable variables
The feature is all-or-nothing: all three must be set together.
| Variable | Required to enable | Effect |
|---|---|---|
NINJAONE_BASE_URL | Yes | Your region's API base URL (table below). Trailing slash optional. |
NINJAONE_CLIENT_ID | Yes | The Client App ID from Step 1 |
NINJAONE_CLIENT_SECRET | Yes | The Client App secret. Quote it in the env file — it is read via the same raw-file mechanism as the AutoTask secret, so $ and other special characters are safe. |
NINJAONE_TIMEOUT_MS | Optional (default 15000) | Per-request timeout for NinjaOne API calls |
Region base URLs
Use the same data-center region your NinjaOne console login URL shows:
| Region | NINJAONE_BASE_URL |
|---|---|
| Americas (default/US) | https://app.ninjarmm.com |
| Americas 2 | https://us2.ninjarmm.com |
| Canada | https://ca.ninjarmm.com |
| Europe | https://eu.ninjarmm.com |
| Oceania | https://oc.ninjarmm.com |
Step 3 — Systray URL hints (recommended)
AVA resolves "which machine is this?" most reliably when the client reaches the chat page via a link carrying systray-substituted hints. NinjaOne systray custom URL items support ${HOSTNAME} / $USERNAME / ${DOMAIN} placeholders, substituted at click time. In your NinjaOne branding/systray policy, point the chat link at:
https://chat.example.com/?host=${HOSTNAME}&user=$USERNAME&domain=${DOMAIN}
AVA captures these once on page load, forwards them with the chat-start request, and stores them on the session as display and lookup hints only — never an authorization signal (they are client-reported, exactly like a browser user agent). The hints are also stripped from the visible URL after capture.
Omitting the query string entirely still works: the resolution pipeline falls back to a user/email-based search (when the API layer is enabled) or shows a "no managed device matched" empty state.
Step 4 — Validate
npx tsx scripts/test-ninjaone.ts [hostname]Confirms configuration presence, exercises the real OAuth2 client-credentials token exchange, lists organizations and a few devices, and — with a hostname argument — runs the same hostname search the device-resolution pipeline uses.
Optional: AutoTask ticket enrichment (NINJAONE_ENRICH_TICKETS)
NINJAONE_ENRICH_TICKETS)Independently of the device card, AVA can write the resolved device onto the chat's AutoTask ticket: attaching the matched Configuration Item (configurationItemID) and, when available, the NinjaRMM-DeviceUID ticket UDF. This is best-effort, only fires on high-confidence matches, and never overwrites a pre-existing CI or UDF value already on the ticket.
| Variable | Default | Effect |
|---|---|---|
NINJAONE_ENRICH_TICKETS | false (off) | Sole enable switch for AT ticket writes. Anything other than the exact string true means disabled — no AT enrichment calls at all. The read-only device card is unaffected either way. |
⚠️ Do not enable this until you have run the UDF merge pre-flight against your own AutoTask instance. The enrichment PATCHes the ticket's
userDefinedFieldsarray, and correctness depends on your AutoTask instance merging that array (updating the named UDF, leaving others untouched) rather than replacing it wholesale. This behavior should be verified per instance, on a throwaway ticket, before any production ticket is touched.
UDF merge pre-flight (one-time, ~10 minutes)
-
Create a scrap ticket in your AutoTask instance — any test company, any title clearly marked as a test. You'll delete it afterwards.
-
Seed two different UDFs on that ticket with recognizable values (via the AutoTask UI or API) — for example a text UDF set to
KEEP-MEand a second UDF set toWILL-PATCH. -
PATCH exactly one of them via the REST API, sending a
userDefinedFieldsarray that contains only the one UDF you're changing:curl -X PATCH "$AUTOTASK_API_ZONE_URL/Tickets" \ -H "Content-Type: application/json" \ -H "UserName: $AUTOTASK_API_USER" \ -H "Secret: $AUTOTASK_API_SECRET" \ -H "ApiIntegrationcode: $AUTOTASK_API_INTEGRATION_CODE" \ -d '{"id": <scrap-ticket-id>, "userDefinedFields": [{"name": "<patched-udf-name>", "value": "PATCHED"}]}' -
Re-read the ticket and verify both outcomes: the patched UDF now says
PATCHED, and the other UDF still saysKEEP-ME. A plain filter query returns UDFs by default — do not add anIncludeFieldskey (some instances reject it). -
Both survived? Your instance merges. Delete the scrap ticket and set
NINJAONE_ENRICH_TICKETS=true. The seeded UDF was blanked? Your instance replaces the array — leave enrichment off (the device card still works fully without it).
Honest limitations
- The "Open in NinjaOne" deep link requires an existing NinjaOne console session in the engineer's browser — it is not a standalone remote-session launcher.
- No device actions of any kind — no remote session, no reboot, no scripts. This is a read-only glance by design.
- Systray hints are client-reported — useful for lookup, never trusted for identity or authorization.
- Telemetry reflects NinjaOne's last check-in, not a chat-triggered real-time poll.
Next steps
configuration.md— full variable reference.autotask-setup.md— the AutoTask integration the enrichment writes into.
Updated 15 days ago