---
name: "Catalog Api v2"
last_updated: 2026-06-19T03:26:40Z
type: legacy
api_base_url: "https://catalog.roblox.com"
versions: [v2, v1]
endpoints: 24
auth: [cookie]
---

# Catalog Api v2

> **Warning:** Legacy APIs with cookie authentication can incorporate breaking changes without notice. We don't recommend them for production applications.

**Base URL:** `https://catalog.roblox.com`
**Versions:** v2, v1

## V2

### GET `/v2/assets/{assetId}/bundles`

Lists bundles that contain the given asset (hydrated search-detail shape for marketplace).

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `integer (int64)` | Yes | Asset id. |
| `Roblox-Place-Id` | header | `integer (int64)` | Yes | Roblox-Place-Id header. |
| `Roblox-Game-Id` | header | `string` | Yes | Roblox-Game-Id header. |
| `limit` | query | `integer (int32)` | No | The number of results per request. Valid values: `10`, `25`, `50`, `100` |
| `cursor` | query | `string` | No | The paging cursor for the previous or next page. |
| `sortOrder` | query | `string` | No | The order the results are sorted in. Valid values: `Asc`, `Desc` |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]`
- `400`: 1: Invalid assetId 4: Invalid Cursor.
- `403`: 7: User is unauthorized.

**Response fields** (`Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]`)

See [Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]](#roblox-web-webapi-models-apipageresponse-roblox-catalog-api-catalogsearchdetailedresponseitem-) in Models.

**Response example:**
```json
{
  "previousPageCursor": "string",
  "nextPageCursor": "string",
  "data": [
    {
      "id": "...",
      "itemType": "...",
      "assetType": "...",
      "bundleType": "...",
      "isRecolorable": "...",
      "name": "..."
    }
  ]
}
```

**Error handling:** `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v2/assets/{ASSETID}/bundles"
```

### GET `/v2/search/items/details`

Search for catalog items.

This endpoint is for search by item type ids.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `Taxonomy` | query | `string` | No |  |
| `AssetTypeIds` | query | `array` | No |  |
| `BundleTypeIds` | query | `array` | No |  |
| `CategoryFilter` | query | `integer (int32)` | No | Valid values: `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7` |
| `SortAggregation` | query | `integer (int32)` | No | Valid values: `0`, `1`, `2`, `3`, `4`, `5` |
| `SortType` | query | `integer (int32)` | No | Valid values: `0`, `1`, `2`, `3`, `4`, `5` |
| `CreatorType` | query | `integer (int32)` | No | Valid values: `0`, `1`, `2` |
| `CreatorTargetId` | query | `integer (int64)` | No |  |
| `CreatorName` | query | `string` | No |  |
| `MaxPrice` | query | `integer (int32)` | No |  |
| `MinPrice` | query | `integer (int32)` | No |  |
| `Keyword` | query | `string` | No |  |
| `IncludeNotForSale` | query | `boolean` | No |  |
| `TriggeredByTopicDiscovery` | query | `boolean` | No |  |
| `SalesTypeFilter` | query | `integer (int32)` | No | Valid values: `0`, `1`, `2`, `3`, `4` |
| `Topics` | query | `string` | No | The input topics format is split by ",". E.g "topics=cat,hat,red". |
| `limit` | query | `integer (int32)` | No | The number of results per request. Valid values: `10`, `28`, `30`, `60`, `120` |
| `cursor` | query | `string` | No | The paging cursor for the previous or next page. |
| `sortOrder` | query | `string` | No | The order the results are sorted in. Valid values: `Desc` |

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.CatalogSearchPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]`
- `400`: 1: Category subcategory selection not supported. 2: Creator id not found. 3: Creator type not found or cannot search by CreatorTargetId with CreatorType.All 4: Genre not found. 5: Sort combination not supported. 6: Invalid price range. 10: StartRequest is invalid.
- `403`: 7: User is unauthorized. 22: In-experience search is denied for this place or universe.
- `429`: 8: The flood limit has been exceeded. 8: The flood limit has been exceeded.
- `503`: 18: Search request timed out

**Response fields** (`Roblox.Catalog.Api.CatalogSearchPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]`)

See [Roblox.Catalog.Api.CatalogSearchPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]](#roblox-catalog-api-catalogsearchpageresponse-roblox-catalog-api-catalogsearchdetailedresponseitemv2-) in Models.

**Response example:**
```json
{
  "keyword": "string",
  "elasticsearchDebugInfo": {
    "elasticsearchQuery": "string",
    "isFromCache": false,
    "indexName": "string",
    "isTerminatedEarly": false,
    "isForceTerminationEnabledByRequest": false,
    "searchResultDataSource": "string"
  },
  "previousPageCursor": "string",
  "nextPageCursor": "string",
  "data": [
    {
      "bundledItems": "...",
      "taxonomy": "...",
      "itemCreatedUtc": "...",
      "discountInformation": "...",
      "id": "...",
      "itemType": "..."
    }
  ]
}
```

**Error handling:** `429`: Retry with exponential backoff (start at 1s). `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v2/search/items/details"
```

## Models

### Roblox.Catalog.Api.BundleItemDetailModel

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `owned` | `boolean` | No |  |
| `id` | `integer` | No |  |
| `name` | `string` | No |  |
| `type` | `string` | No |  |
| `supportsHeadShapes` | `boolean` | No | Whether the bundle item supports head shapes. |
| `assetType` | `integer` | No | The asset type of the bundle item, if it's an asset. |

### Roblox.Catalog.Api.BundleItemDetailModelV2

The is the beta (non game-engine) version of BundleItemDetailModel for internal consumption on Roblox web and universal-app.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `owned` | `boolean` | No |  |
| `id` | `integer` | No |  |
| `name` | `string` | No |  |
| `type` | `string` | No |  |
| `supportsHeadShapes` | `boolean` | No | Whether the bundle item supports head shapes. |
| `assetType` | `integer` | No | The asset type of the bundle item, if it's an asset. |

### Roblox.Catalog.Api.CatalogSearchDetailedResponseItem

Game-engine version of fully hydrated asset or bundle in catalog marketplace.
Documented here: https://create.roblox.com/docs/reference/engine/classes/AvatarEditorService#SearchCatalog.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `integer` | No | The Item Id. |
| `itemType` | `1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.ItemType item type. ['Asset' = 1, 'Bundle' = 2] |
| `assetType` | `integer enum (85 values)` | No | The Roblox.Platform.Assets.AssetType serialized if item is an asset. Values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92 |
| `bundleType` | `1 \| 2 \| 3 \| 4` | No | The Roblox.Platform.Bundles.Core.BundleType serialized if item is a bundle. |
| `isRecolorable` | `boolean` | No | Gets or sets the property whether a bundle is recolorable or not. Not serialized for asset. |
| `name` | `string` | No | The item name. |
| `description` | `string` | No | The item description. |
| `productId` | `integer` | No | The product id of corresponding item. |
| `bundledItems` | `Roblox.Catalog.Api.BundleItemDetailModel[]` | No | The System.Collections.Generic.IEnumerable`1 contained in the bundle, serialized if item is a bundle. |
| `itemStatus` | `1 \| 2 \| 7 \| 8[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemStatus. |
| `itemRestrictions` | `integer enum (9 values)[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemRestriction. |
| `creatorHasVerifiedBadge` | `boolean` | No | The verified status of a creator. |
| `creatorType` | `0 \| 1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.CreatorType of the item's creator. |
| `creatorTargetId` | `integer` | No | The creator id of the item's creator. |
| `creatorName` | `string` | No | The creator name of the item's creator. |
| `price` | `integer` | No | The item's price. |
| `lowestPrice` | `integer` | No | The item's lowest price, only if the item is resellable and there are resellers. |
| `lowestResalePrice` | `integer` | No | The item's lowest resale price, only if the item is resellable and there are resellers, including current user. |
| `priceStatus` | `string` | No | The localized string item status if the item's price should not be displayed. |
| `unitsAvailableForConsumption` | `integer` | No | The number of items in stock, only if the item is resellable and is limitedEdition. |
| `favoriteCount` | `integer` | No | The number of times the item has been favorited. |
| `offSaleDeadline` | `string` | No | When the item will go off sale, if the item has an off deadline. |
| `collectibleItemId` | `string` | No | The item's collectible item id. It is an UUID if a item is collectible type. Otherwise, it is null. |
| `totalQuantity` | `integer` | No | The collectible or limited-unique item's total quantity of unique instances. |
| `saleLocationType` | `integer enum (8 values)` | No | The sale location type of the item. ['NotApplicable' = 0, 'ShopOnly' = 1, 'MyExperiencesOnly' = 2, 'ShopAndMyExperiences' = 3, 'ExperiencesById' = 4, 'ShopAndAllExperiences' = 5, 'ExperiencesDevApiOnly' = 6, 'ShopAndExperiencesById' = 7] Values: 0, 1, 2, 3, 4, 5, 6, 7 |
| `hasResellers` | `boolean` | No | An indicator if the item has resellers or not (null if not resellable). |
| `isOffSale` | `boolean` | No | An indicator if the item is off sale or not. |
| `quantityLimitPerUser` | `integer` | No | Quantity limit for how many instances a user can buy. |
| `supportsHeadShapes` | `boolean` | No | Whether the item supports head shapes. |
| `timedOptions` | `Roblox.Catalog.Api.TimedOption[]` | No | The timed options for the item. |

### Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2

This is the beta (non game-engine) version of our hydration model representing asset or bundle in marketplace.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `bundledItems` | `Roblox.Catalog.Api.BundleItemDetailModelV2[]` | No | The System.Collections.Generic.IEnumerable`1 contained in the bundle, serialized if item is a bundle. |
| `taxonomy` | `Roblox.Catalog.Api.TaxonomyModel[]` | No | The taxonomy ids and names for this item. |
| `itemCreatedUtc` | `string` | No | The UTC creation date-time of the asset or bundle. |
| `discountInformation` | `Roblox.Catalog.Api.DiscountInformation` | No |  |
| `id` | `integer` | No | The Item Id. |
| `itemType` | `1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.ItemType item type. ['Asset' = 1, 'Bundle' = 2] |
| `assetType` | `integer enum (85 values)` | No | The Roblox.Platform.Assets.AssetType serialized if item is an asset. Values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92 |
| `bundleType` | `1 \| 2 \| 3 \| 4` | No | The Roblox.Platform.Bundles.Core.BundleType serialized if item is a bundle. |
| `isRecolorable` | `boolean` | No | Gets or sets the property whether a bundle is recolorable or not. Not serialized for asset. |
| `name` | `string` | No | The item name. |
| `description` | `string` | No | The item description. |
| `productId` | `integer` | No | The product id of corresponding item. |
| `itemStatus` | `1 \| 2 \| 7 \| 8[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemStatus. |
| `itemRestrictions` | `integer enum (9 values)[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemRestriction. |
| `creatorHasVerifiedBadge` | `boolean` | No | The verified status of a creator. |
| `creatorType` | `0 \| 1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.CreatorType of the item's creator. |
| `creatorTargetId` | `integer` | No | The creator id of the item's creator. |
| `creatorName` | `string` | No | The creator name of the item's creator. |
| `price` | `integer` | No | The item's price. |
| `lowestPrice` | `integer` | No | The item's lowest price, only if the item is resellable and there are resellers. |
| `lowestResalePrice` | `integer` | No | The item's lowest resale price, only if the item is resellable and there are resellers, including current user. |
| `priceStatus` | `string` | No | The localized string item status if the item's price should not be displayed. |
| `unitsAvailableForConsumption` | `integer` | No | The number of items in stock, only if the item is resellable and is limitedEdition. |
| `favoriteCount` | `integer` | No | The number of times the item has been favorited. |
| `offSaleDeadline` | `string` | No | When the item will go off sale, if the item has an off deadline. |
| `collectibleItemId` | `string` | No | The item's collectible item id. It is an UUID if a item is collectible type. Otherwise, it is null. |
| `totalQuantity` | `integer` | No | The collectible or limited-unique item's total quantity of unique instances. |
| `saleLocationType` | `integer enum (8 values)` | No | The sale location type of the item. ['NotApplicable' = 0, 'ShopOnly' = 1, 'MyExperiencesOnly' = 2, 'ShopAndMyExperiences' = 3, 'ExperiencesById' = 4, 'ShopAndAllExperiences' = 5, 'ExperiencesDevApiOnly' = 6, 'ShopAndExperiencesById' = 7] Values: 0, 1, 2, 3, 4, 5, 6, 7 |
| `hasResellers` | `boolean` | No | An indicator if the item has resellers or not (null if not resellable). |
| `isOffSale` | `boolean` | No | An indicator if the item is off sale or not. |
| `quantityLimitPerUser` | `integer` | No | Quantity limit for how many instances a user can buy. |
| `supportsHeadShapes` | `boolean` | No | Whether the item supports head shapes. |
| `timedOptions` | `Roblox.Catalog.Api.TimedOption[]` | No | The timed options for the item. |

### Roblox.Catalog.Api.CatalogSearchPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]

ApiPageResponse for catalog search.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `keyword` | `string` | No | Keyword used for search query. |
| `elasticsearchDebugInfo` | `Roblox.Catalog.Api.ElasticsearchDebugInfo` | No |  |
| `previousPageCursor` | `string` | No |  |
| `nextPageCursor` | `string` | No |  |
| `data` | `Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2[]` | No |  |

### Roblox.Catalog.Api.Discount

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `robuxDiscountAmount` | `integer` | No |  |
| `robuxDiscountPercentage` | `number` | No |  |
| `discountCampaign` | `string` | No |  |
| `localizedDiscountAttribution` | `string` | No |  |

### Roblox.Catalog.Api.DiscountInformation

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `originalPrice` | `integer` | No |  |
| `totalDiscountPercentage` | `number` | No |  |
| `totalDiscountAmount` | `integer` | No |  |
| `discounts` | `Roblox.Catalog.Api.Discount[]` | No |  |

### Roblox.Catalog.Api.ElasticsearchDebugInfo

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `elasticsearchQuery` | `string` | No | Gets or sets the nest query that resulted from the operation. |
| `isFromCache` | `boolean` | No | Gets or sets if the results were returned from cache. |
| `indexName` | `string` | No | Gets or sets the index name. |
| `isTerminatedEarly` | `boolean` | No | Gets or sets if the query was Terminated Early. |
| `isForceTerminationEnabledByRequest` | `boolean` | No | Gets or sets if Force Termination was Enabled in the Request. |
| `searchResultDataSource` | `string` | No | Gets or sets the search result data source. |
| `searchResultRelevanceScore` | `string` | No | Gets or sets the search result relevance score. |
| `searchResultEngagementScore` | `string` | No | Gets or sets the search result engagement score. |

### Roblox.Catalog.Api.TaxonomyModel

public api model coaslescing taxonomy information for a single item.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `taxonomyId` | `string` | No | The id value to pass into taxonomy field in SearchV2 catalog-api. |
| `taxonomyName` | `string` | No | The localized human readable name of the category. |

### Roblox.Catalog.Api.TimedOption

Defines a timed option for a catalog item.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `days` | `integer` | No | The days for the timed option. |
| `price` | `integer` | No | The price for the timed option. |
| `discountInformation` | `Roblox.Catalog.Api.DiscountInformation` | No |  |
| `selected` | `boolean` | No | To indicate if this option is selected by the client. |

### Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `previousPageCursor` | `string` | No |  |
| `nextPageCursor` | `string` | No |  |
| `data` | `Roblox.Catalog.Api.CatalogSearchDetailedResponseItem[]` | No |  |

## V1

### GET `/v1/asset-to-category`

Lists a mapping for assets to category IDs to convert from inventory ID to catalog ID. Creates a mapping to link 'Get More' button in inventory page to the relevant catalog page.

**Responses:**

- `200`: OK → `object`

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/asset-to-category"
```

### GET `/v1/asset-to-subcategory`

Lists a mapping for assets to subcategory IDs to convert from inventory ID to catalog ID. Creates a mapping to link 'Get More' button in inventory page to the relevant catalog page.

**Responses:**

- `200`: OK → `object`

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/asset-to-subcategory"
```

### GET `/v1/assets/{assetId}/bundles`

Lists the bundles a particular asset belongs to. Use the Id of the last bundle in the response to get the next page.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `integer (int64)` | Yes |  |
| `limit` | query | `integer (int32)` | No | The number of results per request. Valid values: `10`, `25`, `50`, `100` |
| `cursor` | query | `string` | No | The paging cursor for the previous or next page. |
| `sortOrder` | query | `string` | No | The order the results are sorted in. Valid values: `Asc`, `Desc` |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.BundleDetailsModel]`
- `400`: 1: Invalid assetId 4: Invalid Cursor.

**Response fields** (`Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.BundleDetailsModel]`)

See [Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.BundleDetailsModel]](#roblox-web-webapi-models-apipageresponse-roblox-catalog-api-bundledetailsmodel-) in Models.

**Response example:**
```json
{
  "previousPageCursor": "string",
  "nextPageCursor": "string",
  "data": [
    {
      "id": "...",
      "name": "...",
      "description": "...",
      "bundleType": "...",
      "isRecolorable": "...",
      "items": "..."
    }
  ]
}
```

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/assets/{ASSETID}/bundles"
```

### GET `/v1/bundles/{bundleId}/details`

Returns details about the given bundleId.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `bundleId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.BundleDetailsModel`
- `400`: 1: Invalid bundle

**Response fields** (`Roblox.Catalog.Api.BundleDetailsModel`)

See [Roblox.Catalog.Api.BundleDetailsModel](#roblox-catalog-api-bundledetailsmodel) in Models.

**Response example:**
```json
{
  "id": 0,
  "name": "string",
  "description": "string",
  "bundleType": "string",
  "isRecolorable": false,
  "items": [
    {
      "owned": "...",
      "id": "...",
      "name": "...",
      "type": "...",
      "supportsHeadShapes": "...",
      "assetType": "..."
    }
  ]
}
```

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/bundles/{BUNDLEID}/details"
```

### GET `/v1/bundles/{bundleId}/recommendations`

Gets recommendations for a given bundle, bundleId of 0 returns randomized bundles
- Accepts both public and authenticated users.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `bundleId` | path | `integer (int64)` | Yes |  |
| `numItems` | query | `integer (int32)` | No | The number of recommended items to return. |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.BundleDetailsModel]`
- `400`: 1: Invalid bundle 2: Error retrieving bundles 3: Error getting bundle recommendations 4: NumItems exceed maximum

**Response fields** (`Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.BundleDetailsModel]`)

See [Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.BundleDetailsModel]](#roblox-web-webapi-models-apiarrayresponse-roblox-catalog-api-bundledetailsmodel-) in Models.

**Response example:**
```json
{
  "data": [
    {
      "id": "...",
      "name": "...",
      "description": "...",
      "bundleType": "...",
      "isRecolorable": "...",
      "items": "..."
    }
  ]
}
```

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/bundles/{BUNDLEID}/recommendations"
```

### GET `/v1/bundles/details`

Returns details about the given bundleIds.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `bundleIds` | query | `array` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.BundleDetailsModel[]`
- `400`: 3: Cannot request so many bundles at once.

**Response fields** (`Roblox.Catalog.Api.BundleDetailsModel[]`)

See [Roblox.Catalog.Api.BundleDetailsModel](#roblox-catalog-api-bundledetailsmodel) in Models.

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/bundles/details?bundleIds={VALUE}"
```

### GET `/v1/categories`

Lists Category Names and their Ids.

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.CategoryModel[]`

**Response fields** (`Roblox.Catalog.Api.CategoryModel[]`)

See [Roblox.Catalog.Api.CategoryModel](#roblox-catalog-api-categorymodel) in Models.

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/categories"
```

### GET `/v1/favorites/assets/{assetId}/count`

Gets the favorite count for the given asset Id.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `integer`
- `400`: 2: Invalid asset Id.

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/assets/{ASSETID}/count"
```

### GET `/v1/favorites/bundles/{bundleId}/count`

Gets the favorite count for the given bundle Id.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `bundleId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `integer`
- `400`: 2: Invalid bundle Id.

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/bundles/{BUNDLEID}/count"
```

### GET `/v1/favorites/users/{userId}/assets/{assetId}/favorite`

Gets the favorite model for the asset and user.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `assetId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.AssetFavoriteModel`
- `400`: 1: Invalid user Id. 2: Invalid asset Id.
- `401`: 0: Authorization has been denied for this request.

**Response fields** (`Roblox.Catalog.Api.AssetFavoriteModel`)

See [Roblox.Catalog.Api.AssetFavoriteModel](#roblox-catalog-api-assetfavoritemodel) in Models.

**Response example:**
```json
{
  "assetId": 0,
  "userId": 0,
  "created": "2024-01-01T00:00:00Z"
}
```

**Error handling:** `401`: Check that your API key/token is valid and not expired. 

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/assets/{ASSETID}/favorite"
```

### POST `/v1/favorites/users/{userId}/assets/{assetId}/favorite`

Create a favorite for an asset by the authenticated user.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `assetId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.ApiEmptyResponseModel`
- `400`: 1: Invalid user Id. 2: Invalid asset Id.
- `401`: 0: Authorization has been denied for this request.
- `403`: 0: Token Validation Failed 6: You are not authorized to perform this action.
- `409`: 3: Asset is already favorited.
- `429`: 5: This action was floodchecked. Please try again later.

**Response fields** (`Roblox.Web.WebAPI.ApiEmptyResponseModel`)

See [Roblox.Web.WebAPI.ApiEmptyResponseModel](#roblox-web-webapi-apiemptyresponsemodel) in Models.

**Error handling:** `429`: Retry with exponential backoff (start at 1s). `401`: Check that your API key/token is valid and not expired. `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -X POST -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/assets/{ASSETID}/favorite"
```

### DELETE `/v1/favorites/users/{userId}/assets/{assetId}/favorite`

Delete a favorite for an asset by the authenticated user.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `assetId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.ApiEmptyResponseModel`
- `400`: 1: Invalid user Id. 2: Invalid asset Id.
- `401`: 0: Authorization has been denied for this request.
- `403`: 0: Token Validation Failed 6: You are not authorized to perform this action.
- `409`: 4: Asset is already not favorited.
- `429`: 5: This action was floodchecked. Please try again later.

**Response fields** (`Roblox.Web.WebAPI.ApiEmptyResponseModel`)

See [Roblox.Web.WebAPI.ApiEmptyResponseModel](#roblox-web-webapi-apiemptyresponsemodel) in Models.

**Error handling:** `429`: Retry with exponential backoff (start at 1s). `401`: Check that your API key/token is valid and not expired. `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -X DELETE -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/assets/{ASSETID}/favorite"
```

### GET `/v1/favorites/users/{userId}/bundles/{bundleId}/favorite`

Gets the favorite model for the bundle and user.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `bundleId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.BundleFavoriteModel`
- `400`: 1: Invalid user Id. 2: Invalid bundle Id.
- `401`: 0: Authorization has been denied for this request.

**Response fields** (`Roblox.Catalog.Api.BundleFavoriteModel`)

See [Roblox.Catalog.Api.BundleFavoriteModel](#roblox-catalog-api-bundlefavoritemodel) in Models.

**Response example:**
```json
{
  "bundleId": 0,
  "userId": 0,
  "created": "2024-01-01T00:00:00Z"
}
```

**Error handling:** `401`: Check that your API key/token is valid and not expired. 

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/bundles/{BUNDLEID}/favorite"
```

### POST `/v1/favorites/users/{userId}/bundles/{bundleId}/favorite`

Create a favorite for the bundle by the authenticated user.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `bundleId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.ApiEmptyResponseModel`
- `400`: 1: Invalid user Id. 2: Invalid bundle Id.
- `401`: 0: Authorization has been denied for this request.
- `403`: 0: Token Validation Failed 6: You are not authorized to perform this action.
- `409`: 3: Bundle is already favorited.
- `429`: 5: This action was floodchecked. Please try again later.

**Response fields** (`Roblox.Web.WebAPI.ApiEmptyResponseModel`)

See [Roblox.Web.WebAPI.ApiEmptyResponseModel](#roblox-web-webapi-apiemptyresponsemodel) in Models.

**Error handling:** `429`: Retry with exponential backoff (start at 1s). `401`: Check that your API key/token is valid and not expired. `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -X POST -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/bundles/{BUNDLEID}/favorite"
```

### DELETE `/v1/favorites/users/{userId}/bundles/{bundleId}/favorite`

Delete favorite for the bundle by the authenticated user.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `bundleId` | path | `integer (int64)` | Yes |  |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.ApiEmptyResponseModel`
- `400`: 1: Invalid user Id. 2: Invalid bundle Id.
- `401`: 0: Authorization has been denied for this request.
- `403`: 0: Token Validation Failed 6: You are not authorized to perform this action.
- `409`: 4: Bundle is already not favorited.
- `429`: 5: This action was floodchecked. Please try again later.

**Response fields** (`Roblox.Web.WebAPI.ApiEmptyResponseModel`)

See [Roblox.Web.WebAPI.ApiEmptyResponseModel](#roblox-web-webapi-apiemptyresponsemodel) in Models.

**Error handling:** `429`: Retry with exponential backoff (start at 1s). `401`: Check that your API key/token is valid and not expired. `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -X DELETE -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/bundles/{BUNDLEID}/favorite"
```

### GET `/v1/favorites/users/{userId}/favorites/{assetTypeId}/assets`

Lists the marketplace assets favorited by a given user with the given assetTypeId.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `assetTypeId` | path | `integer (int32)` | Yes |  |
| `limit` | query | `integer (int32)` | No | The number of results per request. Valid values: `10`, `18`, `24`, `25`, `50`, `100` |
| `cursor` | query | `string` | No | The paging cursor for the previous or next page. |
| `sortOrder` | query | `string` | No | The order the results are sorted in. Valid values: `Asc`, `Desc` |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]`
- `400`: 1: Invalid user Id. 8: Ascending order is not allowed. 11: Invalid asset type id.
- `500`: 99: Internal server error.

**Response fields** (`Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]`)

See [Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]](#roblox-web-webapi-models-apipageresponse-roblox-catalog-api-catalogsearchdetailedresponseitem-) in Models.

**Response example:**
```json
{
  "previousPageCursor": "string",
  "nextPageCursor": "string",
  "data": [
    {
      "id": "...",
      "itemType": "...",
      "assetType": "...",
      "bundleType": "...",
      "isRecolorable": "...",
      "name": "..."
    }
  ]
}
```

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/favorites/{ASSETTYPEID}/assets"
```

### GET `/v1/favorites/users/{userId}/favorites/{subtypeId}/bundles`

Lists the bundles favorited by a given user with the given bundle subtypeId.Switched to EAAS style pagination cursors since July 2024.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `subtypeId` | path | `integer (int32)` | Yes |  |
| `itemsPerPage` | query | `integer (int32)` | No |  |
| `cursor` | query | `string` | No |  |
| `isPrevious` | query | `boolean` | No |  |

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.FavoriteBundlesResponse`
- `400`: 1: Invalid user Id. 3: Cannot request so many bundles at once. 10: Invalid previous pagination request. Please provide a cursor when isPrevious is true
- `401`: 0: Authorization has been denied for this request.
- `403`: 6: You are not authorized to perform this action.
- `500`: 11: Internal server error. Please check if you have provided correct pagination cursor

**Response fields** (`Roblox.Catalog.Api.FavoriteBundlesResponse`)

See [Roblox.Catalog.Api.FavoriteBundlesResponse](#roblox-catalog-api-favoritebundlesresponse) in Models.

**Response example:**
```json
{
  "favorites": [
    {
      "id": "...",
      "name": "...",
      "description": "...",
      "bundleType": "...",
      "isRecolorable": "...",
      "items": "..."
    }
  ],
  "moreFavorites": false,
  "nextCursor": "string",
  "previousCursor": "string"
}
```

**Error handling:** `401`: Check that your API key/token is valid and not expired. `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/favorites/users/{USERID}/favorites/{SUBTYPEID}/bundles"
```

### GET `/v1/subcategories`

Lists Subcategory Names and their Ids.

**Responses:**

- `200`: OK → `object`

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/subcategories"
```

### GET `/v1/users/{userId}/bundles`

Lists the bundles owned by a given user.

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `cursor` | query | `string` | No |  |
| `limit` | query | `integer (int32)` | No |  |
| `sortOrder` | query | `integer (int32)` | No | Valid values: `1`, `2` |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.OwnedBundleModel]`
- `400`: 1: Invalid bundle

**Response fields** (`Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.OwnedBundleModel]`)

See [Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.OwnedBundleModel]](#roblox-web-webapi-models-apipageresponse-roblox-catalog-api-ownedbundlemodel-) in Models.

**Response example:**
```json
{
  "previousPageCursor": "string",
  "nextPageCursor": "string",
  "data": [
    {
      "id": "...",
      "name": "...",
      "bundleType": "...",
      "creator": "..."
    }
  ]
}
```

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/users/{USERID}/bundles"
```

### GET `/v1/users/{userId}/bundles/{bundleType}`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `userId` | path | `integer (int64)` | Yes |  |
| `bundleType` | path | `integer (int32)` | Yes | Valid values: `1`, `2`, `3`, `4` |
| `cursor` | query | `string` | Yes |  |
| `limit` | query | `integer (int32)` | No |  |
| `sortOrder` | query | `integer (int32)` | No | Valid values: `1`, `2` |

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.OwnedBundleModel]`

**Response fields** (`Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.OwnedBundleModel]`)

See [Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.OwnedBundleModel]](#roblox-web-webapi-models-apipageresponse-roblox-catalog-api-ownedbundlemodel-) in Models.

**Response example:**
```json
{
  "previousPageCursor": "string",
  "nextPageCursor": "string",
  "data": [
    {
      "id": "...",
      "name": "...",
      "bundleType": "...",
      "creator": "..."
    }
  ]
}
```

**Example:**
```bash
curl -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/users/{USERID}/bundles/{BUNDLETYPE}?cursor={VALUE}"
```

### POST `/v1/catalog/items/details`

Returns details for one or more catalog items.

There is an item count limit per request. Exceeding this returns 400 Bad Request.

**Request Body:** `application/json` — Type: `Roblox.Catalog.Api.MultigetItemDetailsRequestModel`

See [Roblox.Catalog.Api.MultigetItemDetailsRequestModel](#roblox-catalog-api-multigetitemdetailsrequestmodel) in Models.

**Request example:**
```json
{
  "items": [
    {
      "itemType": "...",
      "id": "..."
    }
  ]
}
```

**Responses:**

- `200`: OK → `Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]`
- `400`: 2: Invalid count
- `403`: 0: Token Validation Failed 7: User is unauthorized.
- `429`: 8: The flood limit has been exceeded.

**Response fields** (`Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]`)

See [Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]](#roblox-web-webapi-models-apiarrayresponse-roblox-catalog-api-catalogsearchdetailedresponseitemv2-) in Models.

**Response example:**
```json
{
  "data": [
    {
      "bundledItems": "...",
      "taxonomy": "...",
      "itemCreatedUtc": "...",
      "discountInformation": "...",
      "id": "...",
      "itemType": "..."
    }
  ]
}
```

**Error handling:** `429`: Retry with exponential backoff (start at 1s). `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -X POST -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/catalog/items/details" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "itemType": "...",
      "id": "..."
    }
  ]
}'
```

### POST `/v1/topic/get-topics`

Get topic given TopicRequestModel.

**Request Body:** `application/json` — Type: `Roblox.Catalog.Api.TopicRequestModel`

See [Roblox.Catalog.Api.TopicRequestModel](#roblox-catalog-api-topicrequestmodel) in Models.

**Request example:**
```json
{
  "items": [
    {
      "TargetId": "...",
      "ItemType": "..."
    }
  ],
  "selectTopics": [
    "string"
  ],
  "inputQuery": "string",
  "maxResult": 0,
  "genderType": 1
}
```

**Responses:**

- `200`: OK → `Roblox.Catalog.Api.TopicResponse`
- `403`: 0: Token Validation Failed

**Response fields** (`Roblox.Catalog.Api.TopicResponse`)

See [Roblox.Catalog.Api.TopicResponse](#roblox-catalog-api-topicresponse) in Models.

**Response example:**
```json
{
  "topics": [
    {
      "displayName": "...",
      "originalTopicName": "..."
    }
  ],
  "error": {
    "Message": "string",
    "Code": 0
  }
}
```

**Error handling:** `403`: Verify your API key has the required scopes listed above. 

**Example:**
```bash
curl -X POST -H "Authorization: Bearer $ROBLOX_ACCESS_TOKEN" \
  "https://catalog.roblox.com/v1/topic/get-topics" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "TargetId": "...",
      "ItemType": "..."
    }
  ],
  "selectTopics": [
    "string"
  ],
  "inputQuery": "string",
  "maxResult": 0,
  "genderType": 1
}'
```

## Models

### Roblox.Catalog.Api.AssetFavoriteModel

A model to represent asset favorites.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `assetId` | `integer` | No | The Id of the asset being favorited. |
| `userId` | `integer` | No | The Id of the user favoriting the asset. |
| `created` | `string` | No | The time at which the user favorited the asset. |

### Roblox.Catalog.Api.BundleCreatorModel

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `integer` | No |  |
| `name` | `string` | No |  |
| `type` | `string` | No |  |
| `hasVerifiedBadge` | `boolean` | No |  |

### Roblox.Catalog.Api.BundleDetailsModel

The hydration model representing a bundle on marketplace. Returned in all bundles controller endpoints.
Bound in the game-engine MarketplaceService.GetProductInfo method.
https://create.roblox.com/docs/reference/engine/classes/MarketplaceService#GetProductInfo.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `integer` | No |  |
| `name` | `string` | No |  |
| `description` | `string` | No |  |
| `bundleType` | `string` | No |  |
| `isRecolorable` | `boolean` | No |  |
| `items` | `Roblox.Catalog.Api.BundleItemDetailModel[]` | No |  |
| `creator` | `Roblox.Catalog.Api.BundleCreatorModel` | No |  |
| `product` | `Roblox.Catalog.Api.BundleProductModel` | No |  |
| `itemRestrictions` | `integer enum (9 values)[]` | No |  |
| `collectibleItemDetail` | `Roblox.Catalog.Api.CollectibleItemDetail` | No |  |
| `discountInformation` | `Roblox.Catalog.Api.DiscountInformation` | No |  |

### Roblox.Catalog.Api.BundleFavoriteModel

A model to represent bundle favorites.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `bundleId` | `integer` | No | The Id of the bundle being favorited. |
| `userId` | `integer` | No | The Id of the user favoriting the bundle. |
| `created` | `string` | No | The time at which the user favorited the bundle. |

### Roblox.Catalog.Api.BundleItemDetailModel

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `owned` | `boolean` | No |  |
| `id` | `integer` | No |  |
| `name` | `string` | No |  |
| `type` | `string` | No |  |
| `supportsHeadShapes` | `boolean` | No | Whether the bundle item supports head shapes. |
| `assetType` | `integer` | No | The asset type of the bundle item, if it's an asset. |

### Roblox.Catalog.Api.BundleItemDetailModelV2

The is the beta (non game-engine) version of BundleItemDetailModel for internal consumption on Roblox web and universal-app.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `owned` | `boolean` | No |  |
| `id` | `integer` | No |  |
| `name` | `string` | No |  |
| `type` | `string` | No |  |
| `supportsHeadShapes` | `boolean` | No | Whether the bundle item supports head shapes. |
| `assetType` | `integer` | No | The asset type of the bundle item, if it's an asset. |

### Roblox.Catalog.Api.BundleProductModel

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `integer` | No |  |
| `type` | `string` | No |  |
| `isPublicDomain` | `boolean` | No |  |
| `isForSale` | `boolean` | No |  |
| `priceInRobux` | `integer` | No |  |
| `isFree` | `boolean` | No |  |
| `noPriceText` | `string` | No |  |
| `premiumPricing` | `Roblox.Catalog.Api.PremiumPricingModel` | No |  |

### Roblox.Catalog.Api.CatalogSearchDetailedResponseItem

Game-engine version of fully hydrated asset or bundle in catalog marketplace.
Documented here: https://create.roblox.com/docs/reference/engine/classes/AvatarEditorService#SearchCatalog.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `integer` | No | The Item Id. |
| `itemType` | `1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.ItemType item type. ['Asset' = 1, 'Bundle' = 2] |
| `assetType` | `integer enum (85 values)` | No | The Roblox.Platform.Assets.AssetType serialized if item is an asset. Values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92 |
| `bundleType` | `1 \| 2 \| 3 \| 4` | No | The Roblox.Platform.Bundles.Core.BundleType serialized if item is a bundle. |
| `isRecolorable` | `boolean` | No | Gets or sets the property whether a bundle is recolorable or not. Not serialized for asset. |
| `name` | `string` | No | The item name. |
| `description` | `string` | No | The item description. |
| `productId` | `integer` | No | The product id of corresponding item. |
| `bundledItems` | `Roblox.Catalog.Api.BundleItemDetailModel[]` | No | The System.Collections.Generic.IEnumerable`1 contained in the bundle, serialized if item is a bundle. |
| `itemStatus` | `1 \| 2 \| 7 \| 8[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemStatus. |
| `itemRestrictions` | `integer enum (9 values)[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemRestriction. |
| `creatorHasVerifiedBadge` | `boolean` | No | The verified status of a creator. |
| `creatorType` | `0 \| 1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.CreatorType of the item's creator. |
| `creatorTargetId` | `integer` | No | The creator id of the item's creator. |
| `creatorName` | `string` | No | The creator name of the item's creator. |
| `price` | `integer` | No | The item's price. |
| `lowestPrice` | `integer` | No | The item's lowest price, only if the item is resellable and there are resellers. |
| `lowestResalePrice` | `integer` | No | The item's lowest resale price, only if the item is resellable and there are resellers, including current user. |
| `priceStatus` | `string` | No | The localized string item status if the item's price should not be displayed. |
| `unitsAvailableForConsumption` | `integer` | No | The number of items in stock, only if the item is resellable and is limitedEdition. |
| `favoriteCount` | `integer` | No | The number of times the item has been favorited. |
| `offSaleDeadline` | `string` | No | When the item will go off sale, if the item has an off deadline. |
| `collectibleItemId` | `string` | No | The item's collectible item id. It is an UUID if a item is collectible type. Otherwise, it is null. |
| `totalQuantity` | `integer` | No | The collectible or limited-unique item's total quantity of unique instances. |
| `saleLocationType` | `integer enum (8 values)` | No | The sale location type of the item. ['NotApplicable' = 0, 'ShopOnly' = 1, 'MyExperiencesOnly' = 2, 'ShopAndMyExperiences' = 3, 'ExperiencesById' = 4, 'ShopAndAllExperiences' = 5, 'ExperiencesDevApiOnly' = 6, 'ShopAndExperiencesById' = 7] Values: 0, 1, 2, 3, 4, 5, 6, 7 |
| `hasResellers` | `boolean` | No | An indicator if the item has resellers or not (null if not resellable). |
| `isOffSale` | `boolean` | No | An indicator if the item is off sale or not. |
| `quantityLimitPerUser` | `integer` | No | Quantity limit for how many instances a user can buy. |
| `supportsHeadShapes` | `boolean` | No | Whether the item supports head shapes. |
| `timedOptions` | `Roblox.Catalog.Api.TimedOption[]` | No | The timed options for the item. |

### Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2

This is the beta (non game-engine) version of our hydration model representing asset or bundle in marketplace.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `bundledItems` | `Roblox.Catalog.Api.BundleItemDetailModelV2[]` | No | The System.Collections.Generic.IEnumerable`1 contained in the bundle, serialized if item is a bundle. |
| `taxonomy` | `Roblox.Catalog.Api.TaxonomyModel[]` | No | The taxonomy ids and names for this item. |
| `itemCreatedUtc` | `string` | No | The UTC creation date-time of the asset or bundle. |
| `discountInformation` | `Roblox.Catalog.Api.DiscountInformation` | No |  |
| `id` | `integer` | No | The Item Id. |
| `itemType` | `1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.ItemType item type. ['Asset' = 1, 'Bundle' = 2] |
| `assetType` | `integer enum (85 values)` | No | The Roblox.Platform.Assets.AssetType serialized if item is an asset. Values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92 |
| `bundleType` | `1 \| 2 \| 3 \| 4` | No | The Roblox.Platform.Bundles.Core.BundleType serialized if item is a bundle. |
| `isRecolorable` | `boolean` | No | Gets or sets the property whether a bundle is recolorable or not. Not serialized for asset. |
| `name` | `string` | No | The item name. |
| `description` | `string` | No | The item description. |
| `productId` | `integer` | No | The product id of corresponding item. |
| `itemStatus` | `1 \| 2 \| 7 \| 8[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemStatus. |
| `itemRestrictions` | `integer enum (9 values)[]` | No | The System.Collections.Generic.IEnumerable`1 if item has Roblox.Catalog.Api.CatalogItemRestriction. |
| `creatorHasVerifiedBadge` | `boolean` | No | The verified status of a creator. |
| `creatorType` | `0 \| 1 \| 2` | No | The Roblox.Catalog.Api.CatalogSearchDetailedResponseItem.CreatorType of the item's creator. |
| `creatorTargetId` | `integer` | No | The creator id of the item's creator. |
| `creatorName` | `string` | No | The creator name of the item's creator. |
| `price` | `integer` | No | The item's price. |
| `lowestPrice` | `integer` | No | The item's lowest price, only if the item is resellable and there are resellers. |
| `lowestResalePrice` | `integer` | No | The item's lowest resale price, only if the item is resellable and there are resellers, including current user. |
| `priceStatus` | `string` | No | The localized string item status if the item's price should not be displayed. |
| `unitsAvailableForConsumption` | `integer` | No | The number of items in stock, only if the item is resellable and is limitedEdition. |
| `favoriteCount` | `integer` | No | The number of times the item has been favorited. |
| `offSaleDeadline` | `string` | No | When the item will go off sale, if the item has an off deadline. |
| `collectibleItemId` | `string` | No | The item's collectible item id. It is an UUID if a item is collectible type. Otherwise, it is null. |
| `totalQuantity` | `integer` | No | The collectible or limited-unique item's total quantity of unique instances. |
| `saleLocationType` | `integer enum (8 values)` | No | The sale location type of the item. ['NotApplicable' = 0, 'ShopOnly' = 1, 'MyExperiencesOnly' = 2, 'ShopAndMyExperiences' = 3, 'ExperiencesById' = 4, 'ShopAndAllExperiences' = 5, 'ExperiencesDevApiOnly' = 6, 'ShopAndExperiencesById' = 7] Values: 0, 1, 2, 3, 4, 5, 6, 7 |
| `hasResellers` | `boolean` | No | An indicator if the item has resellers or not (null if not resellable). |
| `isOffSale` | `boolean` | No | An indicator if the item is off sale or not. |
| `quantityLimitPerUser` | `integer` | No | Quantity limit for how many instances a user can buy. |
| `supportsHeadShapes` | `boolean` | No | Whether the item supports head shapes. |
| `timedOptions` | `Roblox.Catalog.Api.TimedOption[]` | No | The timed options for the item. |

### Roblox.Catalog.Api.CategoryModel

Response model for category.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `category` | `integer enum (14 values)` | No | Category type. Values: 0, 1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 16, 17, 18 |
| `taxonomy` | `string` | No | The associated public facing web_stable_id corresponding to internal taxonomy uuid for this category. |
| `assetTypeIds` | `integer[]` | No | List of AssetTypeIds corresponding to AssetType enum that this category returns. |
| `bundleTypeIds` | `integer[]` | No | List of bundleTypeIds corresponding to BundleType enum that this category returns. |
| `categoryId` | `integer` | No | Category id. |
| `name` | `string` | No | Category name. |
| `orderIndex` | `integer` | No | Category order index. |
| `subcategories` | `Roblox.Catalog.Api.SubcategoryModel[]` | No | Subcategories under this category. |
| `isSearchable` | `boolean` | No | Gets or sets whether the category is searchable in search bar. |

### Roblox.Catalog.Api.CollectibleItemDetail

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `collectibleItemId` | `string` | No |  |
| `collectibleProductId` | `string` | No |  |
| `price` | `integer` | No |  |
| `lowestPrice` | `integer` | No |  |
| `lowestResalePrice` | `integer` | No |  |
| `totalQuantity` | `integer` | No |  |
| `unitsAvailable` | `integer` | No |  |
| `saleLocation` | `Roblox.Catalog.Api.SaleLocation` | No |  |
| `hasResellers` | `boolean` | No |  |
| `saleStatus` | `0 \| 1 \| 2 \| 3 \| 4` | No | ['Invalid' = 0, 'Draft' = 1, 'OffSale' = 2, 'OnSale' = 3, 'PendingSale' = 4] |
| `quantityLimitPerUser` | `integer` | No |  |
| `offSaleDeadline` | `string` | No |  |
| `collectibleItemType` | `0 \| 1 \| 2` | No | The type of collectible item, limited or non-limited for now. ['Invalid' = 0, 'Limited' = 1, 'NonLimited' = 2] |
| `lowestAvailableResaleProductId` | `string` | No |  |
| `lowestAvailableResaleItemInstanceId` | `string` | No |  |
| `resaleRestriction` | `0 \| 1 \| 2` | No | ['Invalid' = 0, 'None' = 1, 'Disabled' = 2] |

### Roblox.Catalog.Api.Discount

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `robuxDiscountAmount` | `integer` | No |  |
| `robuxDiscountPercentage` | `number` | No |  |
| `discountCampaign` | `string` | No |  |
| `localizedDiscountAttribution` | `string` | No |  |

### Roblox.Catalog.Api.DiscountInformation

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `originalPrice` | `integer` | No |  |
| `totalDiscountPercentage` | `number` | No |  |
| `totalDiscountAmount` | `integer` | No |  |
| `discounts` | `Roblox.Catalog.Api.Discount[]` | No |  |

### Roblox.Catalog.Api.FavoriteBundlesResponse

A response containing favorited bundles and whether there are more.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `favorites` | `Roblox.Catalog.Api.BundleDetailsModel[]` | No | Collection of favorited bundles and associated details. |
| `moreFavorites` | `boolean` | No | True if there exists a next page of favorited bundles. |
| `nextCursor` | `string` | No | Pagination cursor for the next page. |
| `previousCursor` | `string` | No | Pagination cursor for the previous page. |

### Roblox.Catalog.Api.MultigetItemDetailsRequestItem

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `itemType` | `1 \| 2` | No | ['Asset' = 1, 'Bundle' = 2] |
| `id` | `integer` | No |  |

### Roblox.Catalog.Api.MultigetItemDetailsRequestModel

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `items` | `Roblox.Catalog.Api.MultigetItemDetailsRequestItem[]` | No | The items to retrieve details for. Each endpoint has an item count limit per request. |

### Roblox.Catalog.Api.OwnedBundleModel

A model to represent owned bundles.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | `integer` | No |  |
| `name` | `string` | No |  |
| `bundleType` | `string` | No |  |
| `creator` | `Roblox.Catalog.Api.BundleCreatorModel` | No |  |

### Roblox.Catalog.Api.PremiumPricingModel

Defines the Premium pricing for a catalog item.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `premiumDiscountPercentage` | `integer` | No | The Premium discount percentage for a catalog item. |
| `premiumPriceInRobux` | `integer` | No | The Premium price for a catalog item. |

### Roblox.Catalog.Api.SaleLocation

SaleLocation information for a collectible item (asset or bundle).

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `saleLocationType` | `integer enum (8 values)` | No | Sale location type related for an item detail. ['NotApplicable' = 0, 'ShopOnly' = 1, 'MyExperiencesOnly' = 2, 'ShopAndMyExperiences' = 3, 'ExperiencesById' = 4, 'ShopAndAllExperiences' = 5, 'ExperiencesDevApiOnly' = 6, 'ShopAndExperiencesById' = 7] Values: 0, 1, 2, 3, 4, 5, 6, 7 |
| `saleLocationTypeId` | `integer` | No |  |
| `universeIds` | `integer[]` | No |  |
| `enabledUniverseIds` | `integer[]` | No |  |

### Roblox.Catalog.Api.SubcategoryModel

Response model for subcategory.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `subcategory` | `integer enum (52 values)` | No | Subcategory type. Values: 0, 1, 2, 3, 4, 5, 9, 10, 12, 13, 14, 15, 19, 20, 21, 22, 23, 24, 25, 26, 27, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67 |
| `taxonomy` | `string` | No | The taxonomy UUID associated with this node. |
| `assetTypeIds` | `integer[]` | No | List of AssetTypeIds corresponding to AssetType enum that this category returns. |
| `bundleTypeIds` | `integer[]` | No | List of bundleTypeIds corresponding to BundleType enum that this category returns. |
| `subcategoryId` | `integer` | No | Subcategory id. |
| `name` | `string` | No | Subcategory name. |
| `shortName` | `string` | No | Subcategory short name. |

### Roblox.Catalog.Api.TaxonomyModel

public api model coaslescing taxonomy information for a single item.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `taxonomyId` | `string` | No | The id value to pass into taxonomy field in SearchV2 catalog-api. |
| `taxonomyName` | `string` | No | The localized human readable name of the category. |

### Roblox.Catalog.Api.TimedOption

Defines a timed option for a catalog item.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `days` | `integer` | No | The days for the timed option. |
| `price` | `integer` | No | The price for the timed option. |
| `discountInformation` | `Roblox.Catalog.Api.DiscountInformation` | No |  |
| `selected` | `boolean` | No | To indicate if this option is selected by the client. |

### Roblox.Catalog.Api.TopicModel

Response model for avatar topics.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `displayName` | `string` | No | The display topic name. |
| `originalTopicName` | `string` | No | The original topic name stored in the table. |

### Roblox.Catalog.Api.TopicRequestModel

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `items` | `Roblox.MarketplaceTopicDiscovery.TopicDiscoveryService.V1Beta1.AvatarItem[]` | No |  |
| `selectTopics` | `string[]` | No |  |
| `inputQuery` | `string` | No |  |
| `maxResult` | `integer` | No | Maximum number of topic results returned from the server. |
| `genderType` | `1 \| 2 \| 3` | No | ['Unknown' = 1, 'Male' = 2, 'Female' = 3] |

### Roblox.Catalog.Api.TopicResponse

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `topics` | `Roblox.Catalog.Api.TopicModel[]` | No |  |
| `error` | `Roblox.MarketplaceTopicDiscovery.TopicDiscoveryService.V1Beta1.Error` | No |  |

### Roblox.MarketplaceTopicDiscovery.TopicDiscoveryService.V1Beta1.AvatarItem

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `TargetId` | `integer` | No |  |
| `ItemType` | `0 \| 1 \| 2` | No | ['Invalid' = 0, 'Asset' = 1, 'Bundle' = 2] |

### Roblox.MarketplaceTopicDiscovery.TopicDiscoveryService.V1Beta1.Error

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `Message` | `string` | No |  |
| `Code` | `integer` | No |  |

### Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.BundleDetailsModel]

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `data` | `Roblox.Catalog.Api.BundleDetailsModel[]` | No |  |

### Roblox.Web.WebAPI.Models.ApiArrayResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2]

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `data` | `Roblox.Catalog.Api.CatalogSearchDetailedResponseItemV2[]` | No |  |

### Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.BundleDetailsModel]

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `previousPageCursor` | `string` | No |  |
| `nextPageCursor` | `string` | No |  |
| `data` | `Roblox.Catalog.Api.BundleDetailsModel[]` | No |  |

### Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.CatalogSearchDetailedResponseItem]

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `previousPageCursor` | `string` | No |  |
| `nextPageCursor` | `string` | No |  |
| `data` | `Roblox.Catalog.Api.CatalogSearchDetailedResponseItem[]` | No |  |

### Roblox.Web.WebAPI.Models.ApiPageResponse[Roblox.Catalog.Api.OwnedBundleModel]

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `previousPageCursor` | `string` | No |  |
| `nextPageCursor` | `string` | No |  |
| `data` | `Roblox.Catalog.Api.OwnedBundleModel[]` | No |  |