> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/dsx-air/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/dsx-air/_mcp/server.

# Marketplace Demos

```python
# Imports (run once)
from typing import Iterator

from air_sdk import AirApi
from air_sdk.endpoints import MarketplaceDemo, MarketplaceDemoTag
from air_sdk.endpoints.simulations import Simulation
```

```python
# Authentication (run once)
api = AirApi.with_ngc_config()
# OR api = AirApi.with_api_key(api_key="...")
# OR api = AirApi.with_device_login(email="...", org_num="...")
#    ^ use in terminal only — not supported in Jupyter notebooks
```

## Create

A marketplace demo is created from an existing **simulation**, which becomes the
template that gets cloned each time someone provisions the demo. By default the latest
`COMPLETE` checkpoint of that simulation is used; pass `checkpoint` to pin a specific
one.

```python
simulation_id = '...'  # replace with an actual simulation ID to use as the template

demo: MarketplaceDemo = api.marketplace_demos.create(
    name='My Marketplace Demo',
    simulation=simulation_id,
    description='A short, catalog-friendly description of the demo.',
    documentation='https://example.com/docs',
    repo='https://github.com/example/repo',
    tags=['networking', 'sonic'],
)
demo.dict()
```

## Get

Retrieve a single marketplace demo by ID. The model exposes several fields worth
calling out:

* `demo` — foreign key to the template `Simulation` (lazily resolved).
* `demo_simulation_state` — state of that template simulation (`DEMO`, `CLONING`,
  `INVALID`).
* `published` / `publicly_published` — whether the demo is published, and whether it is
  published catalog-wide vs. restricted to an allow-list.
* `publish_access_record_id` — the active publish access record, if any.
* `featured` / `order` — control default catalog ordering (see *Featuring & ordering*).
* `provision_count` — how many clones have been provisioned from this demo.

```python
demo_id = '...'  # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)

print(f'{demo.name} ({demo.id})')
print(f'  published={demo.published}  publicly_published={demo.publicly_published}')
print(f'  demo_simulation_state={demo.demo_simulation_state!r}')
print(f'  publish_access_record_id={demo.publish_access_record_id}')
print(f'  featured={demo.featured}  order={demo.order}')
print(f'  provision_count={demo.provision_count}')

# `demo` is a foreign key to the template Simulation (resolved on access).
template: Simulation = demo.demo
print(f'  template simulation: {template.name} ({template.id}) state={template.state}')
```

## List / Filter / Search

`list()` returns an iterator of `MarketplaceDemo` objects (paginated automatically).
Pass query parameters to filter, order, or search. Convert to a `list` to work with all
results at once, or iterate lazily.

```python
# All marketplace demos
demos: Iterator[MarketplaceDemo] = api.marketplace_demos.list()
for demo in demos:
    print(f'{demo.name:40} published={demo.published} state={demo.demo_simulation_state}')

# Filter by creator, tags, and published status
mine = list(
    api.marketplace_demos.list(
        creator='me@example.com',
        tags=['networking'],
        published=True,
    )
)

# Filter by the template simulation state and order the results
demo_state = list(
    api.marketplace_demos.list(demo_simulation_state='DEMO', ordering='order')
)

# Free-text search
search_results = list(api.marketplace_demos.list(search='sonic'))
```

## Update

Update the editable metadata on a demo: `name`, `description`, `documentation`,
`repo`, `tags`, and `icon`. Fields like `creator`, `demo`, and `published` are
read-only. You can update via the model instance or via the endpoint API.

```python
demo_id = '...'  # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)

# Update via the model instance
demo.update(
    description='An updated description.',
    documentation='https://example.com/docs/v2',
    tags=['networking', 'evpn'],
)
print(demo.description, demo.tags)

# Or patch via the endpoint API using the demo's primary key
api.marketplace_demos.patch(demo.id, name='My Renamed Demo')
```

## Provision

Provisioning clones the demo's template simulation into a brand-new `Simulation` that
belongs to you. Each successful provision increments the demo's `provision_count`.

```python
demo_id = '...'  # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)

# Provision via the model instance...
simulation: Simulation = demo.provision()
print(f'Provisioned simulation {simulation.name} ({simulation.id})')

# ...or via the endpoint API using the demo (object or ID)
simulation = api.marketplace_demos.provision(marketplace_demo=demo.id)
```

## Tags

Tags are managed through `api.marketplace_demo_tags`. Each `MarketplaceDemoTag` has an
`is_public` flag indicating whether the tag is visible catalog-wide. A tag also exposes
a `marketplace_demos` property that reverse-lists the demos assigned that tag.

```python
# List all tags and show the is_public flag
tags: Iterator[MarketplaceDemoTag] = api.marketplace_demo_tags.list()
for tag in tags:
    print(f'{tag.name:30} is_public={tag.is_public}')

# Retrieve a single tag by ID
tag_id = '...'  # replace with an actual tag ID
tag: MarketplaceDemoTag = api.marketplace_demo_tags.get(tag_id)

# The `marketplace_demos` property reverse-lists demos assigned this tag
for demo in tag.marketplace_demos.list():
    print(f'  {demo.name} ({demo.id})')
```

## Featuring & Ordering (Privileged)

These management actions require elevated (SRE/ADMIN) privileges.

* `manage(featured=..., order=...)` sets whether a demo is featured and its ordering
  value. Featured demos sort before non-featured ones, and lower `order` values sort
  first. Pass `order=None` to clear a demo's order.
* `tighten_order()` is a collection-level action that re-numbers the populated `order`
  values to be consecutive starting at 1 (e.g. `[1, 5, 20] -> [1, 2, 3]`), preserving
  relative ordering. Demos with `order=None` are left untouched.

```python
demo_id = '...'  # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)

# Feature the demo and place it first
demo.manage(featured=True, order=1)
print(f'featured={demo.featured} order={demo.order}')

# Or via the endpoint API
api.marketplace_demos.manage(marketplace_demo=demo.id, featured=False, order=None)

# Recompact ordering across all demos so `order` values are consecutive from 1
api.marketplace_demos.tighten_order()
```

## Delete

Delete a marketplace demo. This removes the demo entry; it does not delete the
underlying template simulation.

```python
demo_id = '...'  # replace with an actual marketplace demo ID
demo: MarketplaceDemo = api.marketplace_demos.get(demo_id)

# Delete via the model instance...
demo.delete()
assert demo.id is None

# ...or via the endpoint API by ID
api.marketplace_demos.delete('marketplace-demo-id')
```