The Watchbillby LatticeDDI

Open a NinjaOne ticket for an outage

Updated October 12, 2026

Short answer

Save a NinjaOne client id, secret, organization id, and ticket form id. A confirmed outage opens a ticket. Recovery comments. Does not close it or run a script.

How The Watchbill helps

  • A check runs about once a minute.
  • Email goes out when a check is down and when it recovers.
  • Each client can have a status page that stays private until you publish it.

Start free

This guide is what to paste for NinjaOne, which permission the app needs, and what a confirmed outage writes.

On Pro or Business, open the client, then Alerting, then Remote monitoring, and choose NinjaOne. Paste the organization id, https://app.ninjaone.com or another allowed host, the client id, the client secret, and the ticket form id. Device id and status id are optional. Confirm one ticket before you enable more clients.

Leave the checkbox off until the values are right, then turn on send when a confirmed outage opens or closes. A single failed minute does not send. The write is a ticket. Recovery adds a comment on that same ticket. It does not close the ticket, and it does not run a script.

What you create in NinjaOne

Auth is OAuth 2.0 client credentials. You create the API Services app in your own NinjaOne tenant. The Watchbill does not hold a NinjaOne partner credential. The token request is POST {origin}/ws/oauth/token with grant_type=client_credentials, client_id, and client_secret. The sample response has access_token, expires_in (3600 in the sample), and token_type Bearer. scope is optional and defaults to the scopes on the app. This request omits scope, so the token receives the app's configured scopes.

The OAuth token article, last updated 19 August 2026 on that page, lists three scopes. Monitoring is read-only access to monitoring data and organization structure. Management allows modification of device and organization information, including creating organizations, adding devices, running scripts, and others. Control activates remote access via the API. That page does not name a separate ticketing scope. Give the app Management, because that is the documented write scope. Do not enable Control for this connection. This path does not use remote access and does not run scripts.

The OpenAPI file's top-level security lists monitoring, management, and control together, and the ticketing operations do not replace that list. Whether creating a ticket specifically requires Management, and whether Control is required because it appears in that shared list, was not confirmed by a live call. That part is unverified.

The same reference is linked from eu.ninjarmm.com and oc.ninjarmm.com. The form accepts app.ninjaone.com and hosts ending in .ninjaone.com or .ninjarmm.com. Other hosts are rejected. A full list of regional hostnames was not copied from a single NinjaOne page.

What gets posted

A confirmed outage calls POST /v2/ticketing/ticket. The OpenAPI summary is "Create ticket". Required fields are clientId (the organization id), ticketFormId, status, and subject. The subject is [Watchbill] Down: plus the check name, cut at 200 characters. The description includes the check URL, the status URL, and the outage start time. description.public is required and defaults to true in the schema, so the request sends true. Whether that shows the ticket to an end user is unverified.

The ticket form id is required. GET /v2/ticketing/ticket-form lists form ids. This path does not call that read. You paste the id. Status is optional. A blank status sends 1000, the string default on the create-ticket schema. GET /v2/ticketing/statuses returns statusId. Whether 1000 is a particular display name is unverified.

If you save a device id, the body includes it as nodeId, and the description includes the URL from GET /v2/device/{id}/dashboard-url with redirect=false. The schema says the link expires. The exact lifetime is the expires value on the response, not a number copied here. Leave the device id blank and the ticket still opens, without that link.

The create response includes an integer id. That id is stored for the outage. Recovery calls POST /v2/ticketing/ticket/{ticketId}/comment. The comment is multipart/form-data. The OpenAPI file does not set an encoding content type for the comment object. The request sends one part named comment as application/json, with public true and a text body that includes the check URL, the status URL, the start time, and the dashboard link when a device id is set. Whether that part encoding is what the server accepts is unverified.

PUT /v2/ticketing/ticket/{ticketId} can change ticket fields, including status. This path does not call it. Recovery does not close the ticket and does not change its status. POST /v2/device/{id}/script/run and POST /v2/knowledgebase/articles are in the OpenAPI. This path does not call either. Script, command, job, reboot, and patch paths are refused before the request is sent.

Limits that were on the page

A numeric rate limit was not in the OpenAPI file, the client-credentials article, or the OAuth token article. That limit is unverified. HTTP 429 is retried. Retry-After is honored when it is a delay in seconds or an HTTP date. A 401 or other ordinary client error is a bad credential and is not retried as a rate limit. Five terminal failures turn the connection off.

The organization id, ticket form id, device id, and status id have to be digits in the int32 range. A name will not be accepted in those fields. The access id and secret are stored encrypted. Leave them blank on a later save to keep the secret you already stored. The two-factor field is for ConnectWise Automate. Leave it blank for NinjaOne. Agent id is for Kaseya. Leave it blank for NinjaOne.

Turn it on for one client

The checkbox is off until you check it. Saving the ids without the checkbox stores the connection and does not send. Each client has its own connection. There is no account-wide NinjaOne switch. A confirmed outage is the only trigger: both regions agreed the check was down, or both agreed it recovered. A maintenance window stays quiet on this path the same way other alert channels stay quiet.

If the ticket never appears, confirm the host, the organization id, the ticket form id, and that the app includes Management. Rotate a leaked secret in NinjaOne and paste the new secret here. The old secret is replaced.

What the screen shows

Before a row is saved, the line says Off. After you save with the checkbox clear, it still says Off, and it names NinjaOne. With the checkbox on, it says On. After failed attempts it says Off after failed attempts and shows the count. Remove deletes that client's connection, including the stored secret. It does not delete the ticket already opened in NinjaOne, and it does not close that ticket.

A second open for the same outage does not open a second ticket. Recovery comments on the stored ticket id. If that id was never stored, recovery does not open a ticket in its place.

Keep the client id and secret in the NinjaOne app you control. A leaked secret should be rotated there, then pasted here. Leaving the secret boxes blank on the next save keeps the secret already stored, so a rotation has to type the new secret. The organization id is not a secret. It is the number in the organization field.

How The Watchbill helps

On Pro and Business, a NinjaOne connection can open one ticket when a confirmed outage opens and comment on it when the check recovers. It stays off until that client turns it on. It can include a device id and that device's dashboard link. It does not close the ticket and it does not run scripts. Ticket email to a PSA is a separate card, in ticket email.

Sources

Checked 12 Oct 2026.

  1. NinjaOne Public API 2.0 OpenAPI
  2. NinjaOne, Client Credentials Flow
  3. NinjaOne, API OAuth Token Configuration

Related guides