> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nexudus.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Product

> Create a new Product record.

A **Product** represents an item that can be sold to customers. Products can be sold via contracts (`ContractProduct` entity), added to bookings (`BookingProduct` entity), or purchased directly (`CoworkerProduct` entity).

Products support both one-off sales and recurring charges. Recurring charges can be set to daily, weekly, monthly, or yearly frequencies, or charged every time a contract is invoiced. For invoice-linked recurring charges, prefer using `ContractProduct` to associate the sale directly with a specific contract rather than relying on the customer's `MainContract`.

Use `AvailableAs` to control whether a product can be sold as a one-off purchase, a recurring charge, or both. The `SystemProductType` field categorises the product (e.g. day pass, credit bundle, booking product, stationery, or other).

Products can optionally track stock levels, be restricted to specific pricing plans (tariffs), and be limited to members or contacts only.

## Authentication

<Note>
  This endpoint requires OAuth2 authentication. Include a valid bearer token in the `Authorization` header.
  The authenticated user must be a full unrestricted administrator or have the **`Product-Create`** role.
</Note>

## Enums

<Accordion title="eProductType — SystemProductType values">
  | Value | Name            |
  | ----- | --------------- |
  | 0     | None            |
  | 1     | DayPass         |
  | 2     | CreditBundle    |
  | 3     | Stationery      |
  | 4     | BookingFeature  |
  | 5     | BookingProducts |
  | 99    | Other           |
</Accordion>

<Accordion title="eRecurrentProductOptions — AvailableAs values">
  | Value | Name              |
  | ----- | ----------------- |
  | 0     | None              |
  | 1     | RecurrentOrOneOff |
  | 2     | OnlyRecurrent     |
  | 3     | OnlyOneOff        |
</Accordion>

## Request Body

### Required Fields

<ParamField body="BusinessId" type="integer" required>
  Business Id.
</ParamField>

<ParamField body="Name" type="string" required>
  Product name.
</ParamField>

<ParamField body="SystemProductType" type="integer" required>
  Category of the product: DayPass, CreditBundle, Stationery, BookingFeature, BookingProducts, or Other.
</ParamField>

<ParamField body="Description" type="string" required>
  Product description.
</ParamField>

<ParamField body="DisplayOrder" type="integer" required>
  Display order. Defaults to `0`.
</ParamField>

<ParamField body="Price" type="number" required>
  Product price.
</ParamField>

<ParamField body="CurrencyId" type="integer" required>
  Currency Id.
</ParamField>

<ParamField body="AvailableAs" type="integer" required>
  Controls whether the product can be sold as a one-off purchase, a recurring charge, or both (RecurrentOrOneOff, OnlyRecurrent, OnlyOneOff).
</ParamField>

### Optional Fields

<ParamField body="InvoiceLineDisplayAs" type="string">
  Custom text shown on the invoice line instead of the product name.
</ParamField>

<ParamField body="Sku" type="string">
  SKU code.
</ParamField>

<ParamField body="Tags" type="string">
  Tags.
</ParamField>

<ParamField body="Visible" type="boolean">
  Whether the product is visible to customers on the members portal and mobile app. Defaults to `true`.
</ParamField>

<ParamField body="SyncToSquare" type="boolean">
  Sync to Square.
</ParamField>

<ParamField body="TaxRateId" type="integer">
  Tax Rate Id.
</ParamField>

<ParamField body="ReducedTaxRateId" type="integer">
  Reduced Tax Rate Id.
</ParamField>

<ParamField body="ExemptTaxRateId" type="integer">
  Exempt Tax Rate Id.
</ParamField>

<ParamField body="FinancialAccountId" type="integer">
  Financial Account Id.
</ParamField>

<ParamField body="OnlyForContacts" type="boolean">
  Restrict purchase to contacts (customers without an active contract).
</ParamField>

<ParamField body="OnlyForMembers" type="boolean">
  Restrict purchase to customers with an active contract (members).
</ParamField>

<ParamField body="Tariffs" type="integer[]">
  Tariffs.
</ParamField>

<ParamField body="Archived" type="boolean">
  Whether the product is archived. Archived products cannot be sold but existing charges remain active.
</ParamField>

<ParamField body="Starred" type="boolean">
  Mark the product as featured or highlighted.
</ParamField>

<ParamField body="TrackStock" type="boolean">
  Enable stock tracking for this product. When enabled, each sale reduces the stock count.
</ParamField>

<ParamField body="AllowNegativeStock" type="boolean">
  Allow sales to continue even when stock reaches zero.
</ParamField>

<ParamField body="StockAlertLevel" type="integer">
  Stock level at which a low-stock alert is triggered.
</ParamField>

<ParamField body="ApplyProRating" type="boolean">
  Whether to pro-rate the price when the product is added or removed part-way through a billing period.
</ParamField>

<ParamField body="NewImageUrl" type="string">
  New Image Url.
</ParamField>

<ParamField body="ClearImageFile" type="boolean">
  Clear Image File.
</ParamField>

<ParamField body="InvoiceCoworker" type="boolean">
  Whether to invoice the customer directly rather than their company or team.
</ParamField>

<ParamField body="SyncToNexKiosk" type="boolean">
  Sync to NexKiosk.
</ParamField>

<ParamField body="CreateDeliveryWhenPurchased" type="boolean">
  Automatically create a delivery record for the customer when this product is purchased.
</ParamField>

## Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
    "https://spaces.nexudus.com/api/billing/products" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "BusinessId": 0,
      "Name": "",
      "SystemProductType": 0,
      "Description": "",
      "DisplayOrder": 0,
      "Price": 0,
      "CurrencyId": 0,
      "AvailableAs": 0
  }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://spaces.nexudus.com/api/billing/products',
    {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_TOKEN',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        BusinessId: 0,
        Name: '',
        SystemProductType: 0,
        Description: '',
        DisplayOrder: 0,
        Price: 0,
        CurrencyId: 0,
        AvailableAs: 0
      })
    }
  );

  const data = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://spaces.nexudus.com/api/billing/products',
      headers={
          'Authorization': 'Bearer YOUR_TOKEN',
          'Content-Type': 'application/json'
      },
      json={
          'BusinessId': 0,
          'Name': '',
          'SystemProductType': 0,
          'Description': '',
          'DisplayOrder': 0,
          'Price': 0,
          'CurrencyId': 0,
          'AvailableAs': 0
      }
  )

  data = response.json()
  ```
</CodeGroup>

## Response

### 200

<ResponseField name="Status" type="integer">
  HTTP status code. `200` on success.
</ResponseField>

<ResponseField name="Message" type="string">
  A human-readable message confirming the creation.
</ResponseField>

<ResponseField name="Value" type="object">
  Contains the `Id` of the newly created record.
</ResponseField>

<ResponseField name="WasSuccessful" type="boolean">
  `true` if the product was created successfully.
</ResponseField>

<ResponseField name="Errors" type="array">
  `null` on success.
</ResponseField>

```json Example Response theme={null}
{
  "Status": 200,
  "Message": "Product was successfully created.",
  "Value": {
    "Id": 87654321
  },
  "OpenInDialog": false,
  "OpenInWindow": false,
  "RedirectURL": null,
  "JavaScript": null,
  "UpdatedOn": "2025-01-15T10:30:00Z",
  "UpdatedBy": "admin@example.com",
  "Errors": null,
  "WasSuccessful": true
}
```

### 400

<ResponseField name="Message" type="string">
  A summary of the validation error(s), in the format `PropertyName: error message`.
</ResponseField>

<ResponseField name="Value" type="any">
  `null` on validation failure.
</ResponseField>

<ResponseField name="Errors" type="object[]">
  Array of validation errors.

  <Expandable>
    <ResponseField name="AttemptedValue" type="any">
      The value that was submitted for the field, or `null` if missing.
    </ResponseField>

    <ResponseField name="Message" type="string">
      The validation error message.
    </ResponseField>

    <ResponseField name="PropertyName" type="string">
      The name of the property that failed validation.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="WasSuccessful" type="boolean">
  `false` when the request fails validation.
</ResponseField>

```json Example Response theme={null}
{
  "Message": "Name: is a required field",
  "Value": null,
  "Errors": [
    {
      "AttemptedValue": null,
      "Message": "is a required field",
      "PropertyName": "Name"
    }
  ],
  "WasSuccessful": false
}
```
