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

# Nymble Commerce Products API — Catalog & Pricing Reference

> REST API reference for Nymble Commerce product catalog endpoints — list, search, create, update, activate, deactivate, and manage product pricing.

The Products API lets you manage your B2B product catalog — create products, update pricing tiers, activate or deactivate items, and search across your catalog. All endpoints require a valid Bearer token. The `OrganizationId` is read automatically from your JWT claims.

***

## List products

Retrieve a paginated list of products in your catalog. Prices are resolved against the `PriceTier`, `CurrencyCode`, and `CustomerNumber` encoded in your token.

```http theme={null}
GET https://api.achievemomentum.com/api/products
```

### Query parameters

<ParamField query="pageNumber" default="1" type="integer">
  The page of results to return.
</ParamField>

<ParamField query="pageSize" default="25" type="integer">
  Number of products per page.
</ParamField>

<ParamField query="sortOn" default="Sku" type="string">
  Field to sort on. Common values: `Sku`, `Name`, `Price`.
</ParamField>

<ParamField query="sortDirection" default="asc" type="string">
  Sort direction. Accepts `asc` or `desc`.
</ParamField>

<ParamField query="filters" type="array">
  Optional array of filter objects. Each filter specifies a `field`, `operator`, and `value`. Supported operators: `startswith`, `contains`, `notcontains`, `endswith`, `equals`, `notequals`.
</ParamField>

### Response

Returns a paginated result containing an array of [product objects](#the-product-object).

### Example

```bash theme={null}
curl -X GET "https://api.achievemomentum.com/api/products?pageNumber=1&pageSize=25" \
  -H "Authorization: Bearer {token}"
```

```json theme={null}
{
  "data": [
    {
      "productId": "prod_a1b2c3d4",
      "organizationId": "org_4e9b7f22",
      "sku": "WIDGET-BLU-L",
      "name": "Blue Widget — Large",
      "description": "Heavy-duty blue widget, large format.",
      "category": "Widgets",
      "price": 24.99,
      "priceFormatted": "$24.99",
      "currencyCode": "USD",
      "prices": [
        { "tier": "Wholesale", "price": 18.50, "priceFormatted": "$18.50", "atQuantity": 1 },
        { "tier": "Wholesale", "price": 16.00, "priceFormatted": "$16.00", "atQuantity": 50 },
        { "tier": "Retail",    "price": 24.99, "priceFormatted": "$24.99", "atQuantity": 1 }
      ],
      "quantityOnHand": 240,
      "minimumOrderQuantity": 1,
      "quantityIncrement": 1,
      "weight": 1.2,
      "weightUnit": "lb",
      "dimensions": "10x8x4",
      "dimensionsUnit": "in",
      "upc": "012345678905",
      "active": true,
      "externalId": "ERP-SKU-00421",
      "createdAt": "2024-01-15T09:00:00Z",
      "updatedAt": "2024-05-20T14:32:00Z"
    }
  ],
  "totalRecords": 380,
  "currentPage": 1,
  "totalPages": 16
}
```

***

## Search products

Search your catalog by keyword. Nymble Commerce matches on SKU, name, description, and UPC. Results are paginated and respect the same price-tier resolution as the list endpoint.

```http theme={null}
GET https://api.achievemomentum.com/api/products/search
```

### Query parameters

<ParamField query="searchTerm" type="string" required>
  The keyword or phrase to search for.
</ParamField>

<ParamField query="pageNumber" default="1" type="integer">
  The page of results to return.
</ParamField>

<ParamField query="pageSize" default="50" type="integer">
  Number of products per page.
</ParamField>

### Response

Returns a paginated result containing an array of [product objects](#the-product-object) that match the search term.

### Example

```bash theme={null}
curl -X GET "https://api.achievemomentum.com/api/products/search?searchTerm=blue+widget&pageNumber=1&pageSize=25" \
  -H "Authorization: Bearer {token}"
```

```json theme={null}
{
  "data": [
    {
      "productId": "prod_a1b2c3d4",
      "sku": "WIDGET-BLU-L",
      "name": "Blue Widget — Large",
      "price": 24.99,
      "priceFormatted": "$24.99",
      "active": true
    }
  ],
  "totalRecords": 3,
  "currentPage": 1,
  "totalPages": 1
}
```

***

## Get a product

Retrieve a single product by its SKU.

```http theme={null}
GET https://api.achievemomentum.com/api/products/{sku}
```

### Path parameters

<ParamField path="sku" type="string" required>
  The product's stock-keeping unit (SKU).
</ParamField>

### Response

Returns a single [product object](#the-product-object).

### Example

```bash theme={null}
curl -X GET "https://api.achievemomentum.com/api/products/WIDGET-BLU-L" \
  -H "Authorization: Bearer {token}"
```

```json theme={null}
{
  "productId": "prod_a1b2c3d4",
  "organizationId": "org_4e9b7f22",
  "sku": "WIDGET-BLU-L",
  "name": "Blue Widget — Large",
  "description": "Heavy-duty blue widget, large format.",
  "category": "Widgets",
  "price": 24.99,
  "priceFormatted": "$24.99",
  "currencyCode": "USD",
  "prices": [
    { "tier": "Wholesale", "price": 18.50, "priceFormatted": "$18.50", "atQuantity": 1 }
  ],
  "quantityOnHand": 240,
  "minimumOrderQuantity": 1,
  "quantityIncrement": 1,
  "active": true,
  "externalId": "ERP-SKU-00421",
  "createdAt": "2024-01-15T09:00:00Z",
  "updatedAt": "2024-05-20T14:32:00Z"
}
```

***

## Create a product

Create a new product in your catalog. Use `PUT /api/products` to upsert by SKU — if a product with the given SKU already exists, this call updates it.

```http theme={null}
PUT https://api.achievemomentum.com/api/products
```

### Body parameters

<ParamField body="sku" type="string" required>
  The product's unique stock-keeping unit. Used as the primary identifier for upsert operations.
</ParamField>

<ParamField body="name" type="string">
  Display name for the product.
</ParamField>

<ParamField body="description" type="string">
  Full product description.
</ParamField>

<ParamField body="category" type="string">
  Category name to assign this product to.
</ParamField>

<ParamField body="price" type="number">
  Default base price for this product.
</ParamField>

<ParamField body="prices" type="array">
  Array of price-tier entries. Each entry sets a price for a given tier and optional quantity break.

  ```json theme={null}
  [
    { "tier": "Wholesale", "price": 18.50, "atQuantity": 1 },
    { "tier": "Wholesale", "price": 16.00, "atQuantity": 50 },
    { "tier": "Retail",    "price": 24.99, "atQuantity": 1 }
  ]
  ```
</ParamField>

<ParamField body="quantityOnHand" type="integer">
  Current inventory quantity.
</ParamField>

<ParamField body="minimumOrderQuantity" type="integer">
  Minimum number of units a customer must order.
</ParamField>

<ParamField body="quantityIncrement" type="integer">
  Units must be ordered in multiples of this value.
</ParamField>

<ParamField body="weight" type="number">
  Product weight.
</ParamField>

<ParamField body="weightUnit" type="string">
  Unit for weight, e.g. `lb` or `kg`.
</ParamField>

<ParamField body="dimensions" type="string">
  Product dimensions as a string, e.g. `"10x8x4"`.
</ParamField>

<ParamField body="dimensionsUnit" type="string">
  Unit for dimensions, e.g. `in` or `cm`.
</ParamField>

<ParamField body="upc" type="string">
  Universal Product Code.
</ParamField>

<ParamField body="active" default="true" type="boolean">
  Whether the product is active and visible in the catalog.
</ParamField>

<ParamField body="images" type="array">
  Array of image name strings to associate with this product. Image names must match images already uploaded via the [Images API](/api-reference/images).
</ParamField>

<ParamField body="externalId" type="string">
  Your system's identifier for this product. Used for idempotent imports — re-submitting a product with the same `externalId` updates the existing record rather than creating a duplicate.
</ParamField>

<ParamField body="productAttributes" type="object">
  A free-form dictionary of custom key-value attributes for this product, e.g. `{ "color": "blue", "material": "steel" }`.
</ParamField>

### Response

Returns the created or updated [product object](#the-product-object).

### Example

```bash theme={null}
curl -X PUT "https://api.achievemomentum.com/api/products" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "sku": "WIDGET-BLU-L",
    "name": "Blue Widget — Large",
    "description": "Heavy-duty blue widget, large format.",
    "category": "Widgets",
    "price": 24.99,
    "prices": [
      { "tier": "Wholesale", "price": 18.50, "atQuantity": 1 },
      { "tier": "Wholesale", "price": 16.00, "atQuantity": 50 },
      { "tier": "Retail",    "price": 24.99, "atQuantity": 1 }
    ],
    "quantityOnHand": 240,
    "minimumOrderQuantity": 1,
    "quantityIncrement": 1,
    "weight": 1.2,
    "weightUnit": "lb",
    "dimensions": "10x8x4",
    "dimensionsUnit": "in",
    "upc": "012345678905",
    "active": true,
    "externalId": "ERP-SKU-00421",
    "productAttributes": { "color": "blue", "material": "steel" }
  }'
```

***

## Update product prices

Replace all price-tier entries for one or more products in a single call. This endpoint is designed for bulk price updates — for example, syncing a new price list from your ERP.

```http theme={null}
PUT https://api.achievemomentum.com/api/products/prices
```

### Body parameters

<ParamField body="productUpdates" type="array" required>
  Array of product price update objects. Each entry is matched by `sku` and its prices are fully replaced.

  ```json theme={null}
  [
    {
      "sku": "WIDGET-BLU-L",
      "prices": [
        { "tier": "Wholesale", "price": 17.00, "atQuantity": 1 },
        { "tier": "Retail",    "price": 25.99, "atQuantity": 1 }
      ]
    }
  ]
  ```

  Each object contains:

  | Field                 | Type    | Description                                                           |
  | --------------------- | ------- | --------------------------------------------------------------------- |
  | `sku`                 | string  | The product SKU to update.                                            |
  | `prices[].tier`       | string  | The price tier name, e.g. `Wholesale` or `Retail`.                    |
  | `prices[].price`      | number  | The price for this tier.                                              |
  | `prices[].atQuantity` | integer | The minimum quantity at which this price applies (for volume breaks). |
</ParamField>

### Example

```bash theme={null}
curl -X PUT "https://api.achievemomentum.com/api/products/prices" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "productUpdates": [
      {
        "sku": "WIDGET-BLU-L",
        "prices": [
          { "tier": "Wholesale", "price": 17.00, "atQuantity": 1 },
          { "tier": "Wholesale", "price": 14.50, "atQuantity": 100 },
          { "tier": "Retail",    "price": 25.99, "atQuantity": 1 }
        ]
      },
      {
        "sku": "WIDGET-RED-M",
        "prices": [
          { "tier": "Wholesale", "price": 15.00, "atQuantity": 1 },
          { "tier": "Retail",    "price": 22.99, "atQuantity": 1 }
        ]
      }
    ]
  }'
```

<Tip>
  Pass multiple objects in `productUpdates` to update prices for many products in one request. Each entry is matched by `sku` and its prices are fully replaced.
</Tip>

***

## The product object

<ResponseField name="productId" type="string">
  Nymble Commerce's internal unique identifier for the product.
</ResponseField>

<ResponseField name="organizationId" type="string">
  The organization this product belongs to.
</ResponseField>

<ResponseField name="sku" type="string">
  The product's stock-keeping unit.
</ResponseField>

<ResponseField name="name" type="string">
  Display name.
</ResponseField>

<ResponseField name="description" type="string">
  Full product description.
</ResponseField>

<ResponseField name="category" type="string">
  The category name assigned to this product.
</ResponseField>

<ResponseField name="price" type="number">
  The resolved base price for the requesting token's price tier and currency.
</ResponseField>

<ResponseField name="priceFormatted" type="string">
  Human-readable formatted price, e.g. `"$24.99"`.
</ResponseField>

<ResponseField name="currencyCode" type="string">
  ISO 4217 currency code, e.g. `USD`.
</ResponseField>

<ResponseField name="prices" type="array">
  All price-tier entries for this product.

  <Expandable title="prices[]">
    <ResponseField name="tier" type="string">
      Price tier name.
    </ResponseField>

    <ResponseField name="price" type="number">
      Price for this tier.
    </ResponseField>

    <ResponseField name="priceFormatted" type="string">
      Formatted price string.
    </ResponseField>

    <ResponseField name="atQuantity" type="integer">
      Minimum order quantity for this price to apply.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="quantityOnHand" type="integer">
  Current inventory quantity.
</ResponseField>

<ResponseField name="minimumOrderQuantity" type="integer">
  Minimum units per order.
</ResponseField>

<ResponseField name="quantityIncrement" type="integer">
  Order quantity step size.
</ResponseField>

<ResponseField name="weight" type="number">
  Product weight.
</ResponseField>

<ResponseField name="weightUnit" type="string">
  Unit for weight, e.g. `lb`.
</ResponseField>

<ResponseField name="dimensions" type="string">
  Dimensions string, e.g. `"10x8x4"`.
</ResponseField>

<ResponseField name="dimensionsUnit" type="string">
  Unit for dimensions, e.g. `in`.
</ResponseField>

<ResponseField name="upc" type="string">
  Universal Product Code.
</ResponseField>

<ResponseField name="active" type="boolean">
  Whether the product is active in the catalog.
</ResponseField>

<ResponseField name="images" type="array">
  Array of image objects associated with this product.
</ResponseField>

<ResponseField name="productAttributes" type="object">
  Custom key-value attribute dictionary.
</ResponseField>

<ResponseField name="externalId" type="string">
  Your system's identifier for this product.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 timestamp of when the product was created.
</ResponseField>

<ResponseField name="updatedAt" type="string">
  ISO 8601 timestamp of the most recent update.
</ResponseField>
