---
title: "Creates a product"
method: POST
path: "/v2/billing/products"
tags: ["Billing"]
---

# Creates a product

`POST /v2/billing/products`

## Request

- Base URL: `https://app.ninjarmm.com` (the document declares no server; this is the origin it was published from)
- URL: `https://app.ninjarmm.com/v2/billing/products`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `sessionKey`
- TypeScript: <https://skmtc.dev/ninjarmm/apis/ninjaone-public-api-2-0/docs/v2/billing/products/post.ts> (a function with typed inputs; its response is checked against the schema)

Creates a new product in the catalog.

The content field structure varies by quantity type and must include all required fields for that type:
- **Required for all types**: price, cost, taxable, billing
- **MANUAL**: quantity, productIds
- **DEVICE_COUNTS**: anyRole, groupIds, allGroups, nodeRoles (optional), productIds
- **END_USER_COUNTS**: anyRole, endUserRoles (optional), matchAllRoles, productIds
- **BACKUP_STORAGE_COUNTS**: anyRole, groupIds, allGroups, nodeRoles (optional), isStorageIncludedPerDevice, includedStorage, productIds
- **TIME_ENTRIES**: autoRoundTimeEntries, laborCodes, userRoles, onSiteMultiplier, offHoursMultiplier, remoteMultiplier, normalHoursMultiplier, scheduleTypeOffHours, scheduleTypeNormalHours, locationTypeOnSite, locationTypeRemote, includeTime, includedTimeAmountUnlimited, includedHours, unusedCarryOverUnlimited, carryOverLimit, productIds

The productUserRole field controls which technicians can use this product.

## Request body `*/*`

- object: Representation of a ninja billing Product request.
  - `name` string, required: Name of the product.
  - `description` string, required: Description of the product.
  - `quantityType` 'MANUAL' | 'DEVICE_COUNTS' | 'TIME_ENTRIES' | 'END_USER_COUNTS' | 'BACKUP_STORAGE_COUNTS' | 'SOFTWARE_LICENSE', required: Quantity type of the product.
  - `accountId` integer, required: Account ID associated with the product.
  - `group` boolean, required: Whether the product should be grouped.
  - `productUserRole` object, nullable, required: Representation of a ninja billing product user role request.
    - `allowAllTechnicians` boolean, required: Whether all technicians are allowed to access this product or specific roles will be specified.
    - `userRoles` integer[], required: Set of user role IDs that can access this product. Only used when allowAllTechnicians is false.
  - `integrationSettings` object: If 3rd party integration is enabled, the settings needed to export invoices with this product.
  - `content` object, required: Additional content/configuration for the product. Structure varies by quantity type.
  - `taxId` integer: Tax ID assigned to the product. If null, the product will use the agreement's tax.
  - `inheritTaxFromAgreement` boolean: Whether this product inherits its tax configuration from the agreement.

## Response `201`

Product successfully created

- object: Detailed representation of a ninja billing Product response.
  - `id` integer: Unique identifier of the product.
  - `name` string: Name of the product.
  - `description` string: Description of the product.
  - `quantityType` 'MANUAL' | 'DEVICE_COUNTS' | 'TIME_ENTRIES' | 'END_USER_COUNTS' | 'BACKUP_STORAGE_COUNTS' | 'SOFTWARE_LICENSE': Quantity type of the product.
  - `content` object: Additional content/configuration for the product. Structure varies by quantity type.
  - `integrationSettings` object: If 3rd party integration is enabled, the settings for exporting invoices with this product.
  - `createTime` number, double: Timestamp when the product was created.
  - `updateTime` number, double: Timestamp when the product was last updated.
  - `productUserRole` object: Representation of a ninja billing product user role response.
    - `allowAllTechnicians` boolean: Whether all technicians are allowed to access this product.
    - `userRoles` object[]: Set of user roles that can access this product. Empty when allowAllTechnicians is true.
      - `id` integer: Unique identifier of the user role.
      - `name` string: Name of the user role.
  - `accountId` integer: Account ID associated with the product.
  - `group` boolean: Whether the product is a group product.
  - `taxId` integer, nullable: Tax ID associated with the product. Null if no specific tax is set.
  - `inheritTaxFromAgreement` boolean: Whether the product inherits tax from the agreement.
  - `active` boolean: Indicates if the product is active.

## Other responses

- `400`: Bad Request - Validation error
- `403`: Forbidden - Insufficient permissions
- `409`: Conflict - Product name already exists

## Changes

- **2026-07-26** `753f26d46650`: 4 info
  - added the new optional request property `inheritTaxFromAgreement`
  - added the new optional request property `taxId`
  - added the optional property `inheritTaxFromAgreement` to the response with the `201` status
  - added the optional property `taxId` to the response with the `201` status
- **2026-07-12** `dec5d4ed264e`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/ninjarmm/apis/ninjaone-public-api-2-0/changes/v2/billing/products/post.md)

---

[API](https://skmtc.dev/ninjarmm/apis/ninjaone-public-api-2-0.md) - [All operations](https://skmtc.dev/ninjarmm/apis/ninjaone-public-api-2-0/llms.txt) - [OpenAPI document](https://skmtc.dev/ninjarmm/apis/ninjaone-public-api-2-0/revisions/5ce571d1bb71?raw)
