NinjaOne Automation with n8n Track/Connecting n8n to NinjaOne
NinjaOne Automation with n8n Track
Module 1 of 6

Connecting n8n to NinjaOne

OAuth2 setup, API applications, credential configuration, and undocumented API gotchas.

14 min read

What You'll Learn

  • Understand why n8n fills the automation gaps that NinjaOne cannot handle natively
  • Create two types of API applications in NinjaOne: client_credentials (read-only) vs authorization_code (full access)
  • Configure a Generic OAuth2 API credential in n8n with the correct authentication method and scopes
  • Make your first successful API call to NinjaOne from an n8n workflow
  • Avoid the undocumented API gotchas that waste hours of debugging time

Why Automate NinjaOne with n8n

NinjaOne is a powerful RMM platform, but it has significant gaps when it comes to automation. There are no native scheduled or recurring tickets. You cannot create a monthly patching ticket that auto-populates with your current device inventory. There is no built-in way to generate custom reports beyond the canned options. Cross-platform integrations (NinjaOne to Slack, NinjaOne to Jira, NinjaOne to Power BI) do not exist out of the box.

This is where n8n comes in. n8n is an open-source workflow automation platform that can connect to any API, including NinjaOne's REST API. With n8n, you can:

  • Create scheduled tickets that run on any cadence (weekly, monthly, quarterly, annually) with dynamic content pulled from the NinjaOne API
  • Build custom reporting pipelines that extract device data, transform it into CSV/Excel, push it to SharePoint, and feed Power BI dashboards
  • Set up smart alerting that consolidates 50 individual "device offline" emails into a single daily digest sent to Slack or Teams
  • Automate onboarding/offboarding workflows that create checklists, assign tickets, and update multiple systems simultaneously

What makes this combination unique: No one else has documented how to build these integrations. If you search "NinjaOne scheduled tickets" or "NinjaOne recurring tickets," you will find nothing useful. MSPs and IT teams are building these solutions in isolation, reinventing the wheel each time. This playbook gives you production-tested patterns you can deploy immediately.

Prerequisites: A self-hosted or cloud-hosted n8n instance (see the n8n Administration playbook for setup), and admin access to your NinjaOne portal.

Quick Test: Check Your NinjaOne API Access

Step 1: Log into your NinjaOne admin portal.

Step 2: Navigate to Administration > Apps > API.

Step 3: If you do not see this menu, your account may not have the required permissions. You need Organization Administrator or a custom role with API application management rights.

Step 4: Verify this access before proceeding to the credential setup steps.

NinjaOne API Applications

NinjaOne supports two OAuth2 grant types, and choosing the wrong one is the most common mistake people make. Each grant type has different capabilities and limitations.

Creating an API Application:

  1. Go to Administration > Apps > API in NinjaOne
  2. Click "Add" to create a new application
  3. Give it a descriptive name (e.g., "n8n Automation" or "n8n Ticketing")
  4. Select the appropriate grant type (see below)
  5. Configure the redirect URI if using Authorization Code flow
  6. Save and copy the Client ID and Client Secret immediately

Grant Type Comparison:

FeatureClient CredentialsAuthorization Code
Auth flowMachine-to-machine, no user loginUser must authorize via browser
Token refreshRequest new token each timeRefresh token for auto-renewal
Read devicesYesYes
Read organizationsYesYes
Create ticketsNo (returns 403)Yes
Create/update ticketsNoYes
Run scriptsYesYes
Best forRead-only monitoring, reportingFull automation including ticketing

Critical distinction: client_credentials cannot create tickets. The NinjaOne API returns a 403 Forbidden error with no explanation. This is not documented anywhere in their API docs. If your automation needs to create, update, or assign tickets, you must use the authorization_code grant type.

Authorization Code flow requires a Redirect URI. When setting up the API application, enter your n8n instance's OAuth2 callback URL:

https://<your-n8n-domain>/rest/oauth2-credential/callback

For example: https://n8n.yourdomain.com/rest/oauth2-credential/callback

Scopes: Request these scopes for full access:

  • monitoring - read device data, alerts, activities
  • management - manage organizations, policies, devices
  • control - run scripts, reboot devices
  • offline_access - enables refresh tokens for long-lived access

Client Credentials Cannot Create Tickets

This is the single biggest gotcha with the NinjaOne API. If you set up a client_credentials application and try to POST to /v2/ticketing/ticket, you will get a 403 Forbidden error. NinjaOne does not document this limitation. You must use authorization_code grant type for any ticket operations.

Setting Up the OAuth2 Credential in n8n

n8n's Generic OAuth2 API credential handles the entire OAuth2 flow, including automatic token refresh. Here is how to set it up for NinjaOne.

Step 1: Create the credential in n8n

  1. Go to Credentials > Add Credential > Search for "Generic OAuth2 API"
  2. Select "Predefined Credential Type" and choose "OAuth2 API"

Step 2: Configure the OAuth2 settings

Fill in the following fields:

FieldValue
Grant TypeAuthorization Code
Authorization URLhttps://app.ninjarmm.com/ws/oauth/authorize
Access Token URLhttps://app.ninjarmm.com/ws/oauth/token
Client IDYour NinjaOne API application Client ID
Client SecretYour NinjaOne API application Client Secret
Scopemonitoring management control offline_access
AuthenticationBody (not Header)

Step 3: Connect the credential

Click "Sign in with Generic OAuth2 API" (or "Connect my account"). This opens a NinjaOne authorization page in your browser. Log in with your NinjaOne admin account, review the requested permissions, check "Remember my decision," and click Authorize.

Once authorized, n8n stores the access token and refresh token. The offline_access scope ensures n8n can automatically refresh the token when it expires (every 3600 seconds / 1 hour) without requiring you to re-authorize.

Why Body authentication, not Header: NinjaOne's token endpoint expects client_id and client_secret in the POST body as form parameters. If you select "Header" authentication, n8n sends them as a Base64-encoded Authorization header, which NinjaOne silently rejects. This is another undocumented behavior. Always use Body.

Test Token Refresh

After connecting the credential, wait 1 hour (or manually expire the token by editing it in n8n) and run a test workflow. If the credential auto-refreshes and the API call succeeds, your OAuth2 setup is correct. If it fails, check that your scope includes "offline_access" and that authentication is set to "Body."

Your First API Call

With the OAuth2 credential connected, let us make a simple API call to verify everything works.

Workflow: List all organizations

  1. Add a Manual Trigger node

  2. Add an HTTP Request node

  3. Configure the HTTP Request:

    • Method: GET
    • URL: https://app.ninjarmm.com/api/v2/organizations
    • Authentication: Predefined Credential Type > OAuth2 API
    • Credential: Select your NinjaOne OAuth2 credential
    • Send Query Parameters: Add pageSize = 100
  4. Click "Test step" and verify you get a JSON response with your organizations

Expected response structure:

[
  {
    "id": 1,
    "name": "Your Organization",
    "description": "",
    "nodeApprovalMode": "AUTOMATIC"
  },
  {
    "id": 2,
    "name": "Client Organization",
    "description": "Managed client",
    "nodeApprovalMode": "AUTOMATIC"
  }
]

Key endpoints you will use throughout this playbook:

EndpointMethodDescription
/api/v2/organizationsGETList all organizations
/api/v2/devicesGETList all devices (supports filters)
/api/v2/devices-detailedGETDevices with full details (OS, status, etc.)
/api/v2/organization/{id}/devicesGETDevices for a specific organization
/api/v2/ticketing/ticketPOSTCreate a new ticket
/api/v2/ticketing/ticket/{id}GETGet ticket details
/api/v2/queries/devicesGETAdvanced device queries

Pagination: Most NinjaOne API endpoints return paginated results. Use the pageSize query parameter (max 1000) to control how many results per page. For endpoints that support cursor-based pagination, check the response for a cursor field and pass it as a query parameter in subsequent requests.

Build Your First NinjaOne Workflow

Create a workflow with Manual Trigger > HTTP Request (GET /api/v2/organizations). Run it and verify you see your organizations in the output. Then change the URL to /api/v2/devices and add pageSize=10 as a query parameter. You should see your managed devices. This confirms your OAuth2 credential is working correctly.

API Gotchas That Will Waste Your Time

The NinjaOne API has several undocumented behaviors that will cost you hours of debugging if you are not aware of them. These are hard-won lessons from production use.

1. htmlBody vs body (Ticket Creation)

When creating a ticket via POST /api/v2/ticketing/ticket, the request body includes a description object. This object accepts two fields: body and htmlBody.

{
  "clientId": 2,
  "subject": "Monthly Patching",
  "description": {
    "body": "This is plain text",
    "htmlBody": "<h3>This is HTML</h3><p>With formatting</p>"
  }
}

The catch: if you include htmlBody, the body field is silently ignored. NinjaOne displays the HTML version in the ticket UI. If you only provide body, NinjaOne uses that as plain text. There is no error or warning when both are provided - it just picks htmlBody and discards body.

Best practice: Always use htmlBody for ticket descriptions. NinjaOne's ticket viewer renders HTML, so you get proper formatting with headers, lists, tables, and bold text. Use <h3>, <ul>, <li>, <strong>, and <table> tags for structured ticket content.

2. client_credentials Cannot Create Tickets

As covered earlier, the client_credentials grant type returns 403 Forbidden when trying to create tickets. The error response gives no indication that the grant type is the issue. You must use authorization_code.

3. DELETE Returns 405 for Tickets

The NinjaOne API does not support deleting tickets via the API. A DELETE request to /api/v2/ticketing/ticket/{id} returns 405 Method Not Allowed. You can close tickets by updating their status, but you cannot delete them programmatically.

4. Device Endpoint Variations

  • /api/v2/devices returns a minimal device list (ID, system name, organization)
  • /api/v2/devices-detailed returns full details including OS version, last contact time, and IP addresses
  • /api/v2/organization/{orgId}/devices returns devices for a specific organization
  • /api/v2/queries/devices supports advanced filtering with query parameters

Use devices-detailed when you need OS version or online/offline status. The basic devices endpoint does not include these fields.

5. Ticket Form and User IDs

When creating tickets, you can assign them using assignedAppUserId and specify a ticket form with ticketFormId. These IDs are not the same as the user's email or the form's display name. You need to look them up via the API:

  • Users: GET /api/v2/users returns all NinjaOne users with their IDs
  • Ticket Forms: GET /api/v2/ticketing/ticket-form returns available forms with IDs

Hardcode these IDs in your workflows after looking them up once, or query them dynamically if your team changes frequently.

The htmlBody Trap

If your tickets are showing up with blank descriptions, check whether you are using "body" instead of "htmlBody" in the description object. The NinjaOne API silently ignores the plain text body when htmlBody is present, and will also silently ignore body in some contexts. Always use htmlBody with HTML-formatted content.

Core Insights

  • NinjaOne has no native scheduled tickets, custom reporting, or cross-platform integrations - n8n fills all three gaps
  • Use authorization_code grant type, not client_credentials, if your automation needs to create or update tickets
  • Set the OAuth2 credential authentication to "Body" in n8n - NinjaOne silently rejects Header authentication
  • Include "offline_access" in your scopes to enable automatic token refresh without manual re-authorization
  • Always use htmlBody (not body) in ticket descriptions - NinjaOne silently ignores the plain text field when HTML is present
  • The NinjaOne API does not support deleting tickets (DELETE returns 405) - you can only close them by updating status