> For the complete documentation index, see [llms.txt](https://umber.gitbook.io/umber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://umber.gitbook.io/umber/api-reference-v2/virtual-assets/version-deployment.md).

# Version Deployment API

Deploying moves a [version](/umber/api-reference-v2/virtual-assets/versions.md) onto the Live/Offline state machine described in [Deployment States](/umber/concepts/deployment-states.md), plus the separate Default pointer that model describes — for one asset, one target platform, one environment (a "channel"). This reference covers the two write endpoints that drive that machine (deploy, which also covers promoting to Default, and undeploy), plus reading back what's currently deployed to an environment.

{% hint style="info" %}
This is a low-level HTTP reference. For the dashboard equivalent, see [Managing Deployments](/umber/guides/managing-deployments.md). For the state model itself — Live, Offline, Default, and how they interact — read [Deployment States](/umber/concepts/deployment-states.md) first; this reference assumes you're already familiar with it.
{% endhint %}

## Base URL and authentication

```
https://api.umbercloud.io/api/v2/{domainId}/va/{assetId}
```

Both endpoints below hang off the parent virtual asset (`{assetId}`) — see the exact paths in each section. Authenticate with the same `apikey` header as the [Virtual Assets API](/umber/api-reference-v2/virtual-assets.md#base-url-and-authentication).

{% hint style="warning" %}
Neither endpoint on this page enforces `createdBy`/`updatedBy` the way create/update endpoints elsewhere in this API do. On the very first deploy for a channel, a missing `createdBy` fails as a generic `500` rather than a clean `400`. Always send it.
{% endhint %}

## Deploy a version

`POST /api/v2/{domainId}/va/{assetId}/versions/{versionId}/deploy?targetPlatformId={platformId}`

This one endpoint does three different things depending on whether the version is already deployed to this environment, and what `intent` you send:

| Situation                               | `intent`                 | What happens                                                                                                       |
| --------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| Not deployed to this environment yet    | `LIVE` or `OFFLINE` only | First deploy. **`DEFAULT` is rejected here** — you can't promote straight to Default without deploying Live first. |
| Already deployed, not currently Default | `LIVE`                   | Re-publish — moves this version to Live in this environment.                                                       |
| Already deployed, not currently Default | `OFFLINE`                | Takes this version offline in this environment.                                                                    |
| Already deployed and Live               | `DEFAULT`                | Promotes this version to be the channel's Default — see [Promoting to Default](#promoting-to-default).             |

`createdBy` is required for the first deploy of a channel. Every state change on an already-deployed version — Live, Offline, or Default — reads `updatedBy` instead; send both if you're not sure which case you'll hit.

### Deploy Live (first time)

{% tabs %}
{% tab title="JSON" %}

```json
{ "envId": "prod", "intent": "LIVE", "createdBy": "dev@acme-games.com" }
```

{% endtab %}

{% tab title="cURL" %}

```bash
curl -X POST "https://api.umbercloud.io/api/v2/acme-games/va/hero-skin-01/versions/AND3/deploy?targetPlatformId=android" \
  -H "apikey: $ASSET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "envId": "prod", "intent": "LIVE", "createdBy": "dev@acme-games.com" }'
```

{% endtab %}
{% endtabs %}

`201 Created`

```json
{
  "assetVersion": {
    "version": 3,
    "assetType": "0001",
    "versionId": "AND3",
    "versionName": "Hero Skin 01 v3",
    "envId": "prod",
    "fallback": false,
    "lock": false,
    "state": "LIVE",
    "createdBy": "dev@acme-games.com",
    "updatedBy": "dev@acme-games.com",
    "createdAt": "2026-09-07T12:00:00.000Z",
    "updatedAt": "2026-09-07T12:00:00.000Z",
    "active": true,
    "secured": true,
    "size": "2.35MB",
    "targetPlatform": "android",
    "uploadStatus": "Committed"
  },
  "message": "Deployment has been completed."
}
```

`state` always comes back already settled — `"LIVE"`, not a transient "processing" value — by the time this response is sent (see the note in [Deployment States](/umber/concepts/deployment-states.md)). Every branch below uses this same `{ assetVersion, message }` envelope; only `state` (and which fields apply) changes.

### Re-publish Live / Offline

Same request shape and URL — only difference is you're now sending `updatedBy` instead of `createdBy`, since the deployment record already exists:

{% tabs %}
{% tab title="JSON" %}

```json
{ "envId": "prod", "intent": "OFFLINE", "updatedBy": "dev@acme-games.com" }
```

{% endtab %}

{% tab title="cURL" %}

```bash
curl -X POST "https://api.umbercloud.io/api/v2/acme-games/va/hero-skin-01/versions/AND3/deploy?targetPlatformId=android" \
  -H "apikey: $ASSET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "envId": "prod", "intent": "OFFLINE", "updatedBy": "dev@acme-games.com" }'
```

{% endtab %}
{% endtabs %}

`201 Created` — same shape as above, `"state": "OFFLINE"`.

A version that's currently Default can't be moved to Live or Offline directly — promote a different version to Default first, which demotes this one automatically.

### Promoting to Default

There are two shapes of this request, depending on whether anything is already Default on this channel.

**Nothing is Default yet** — the version must already be Live:

{% tabs %}
{% tab title="JSON" %}

```json
{ "envId": "prod", "intent": "DEFAULT", "updatedBy": "dev@acme-games.com" }
```

{% endtab %}

{% tab title="cURL" %}

```bash
curl -X POST "https://api.umbercloud.io/api/v2/acme-games/va/hero-skin-01/versions/AND1/deploy?targetPlatformId=android" \
  -H "apikey: $ASSET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "envId": "prod", "intent": "DEFAULT", "updatedBy": "dev@acme-games.com" }'
```

{% endtab %}
{% endtabs %}

`201 Created`

```json
{
  "assetVersion": {
    "version": 1,
    "assetType": "0001",
    "versionId": "AND1",
    "versionName": "Hero Skin 01 v1",
    "envId": "prod",
    "fallback": false,
    "lock": false,
    "state": "DEFAULT",
    "createdBy": "dev@acme-games.com",
    "updatedBy": "dev@acme-games.com",
    "createdAt": "2026-08-01T09:00:00.000Z",
    "updatedAt": "2026-09-07T12:05:00.000Z",
    "active": true,
    "secured": true,
    "size": "2.10MB",
    "targetPlatform": "android",
    "uploadStatus": "Committed"
  },
  "message": "Deployment has been completed."
}
```

**Promoting over an existing Default** — add `currentVersionId` (the version currently Default on this channel) and `currentAssetIntent: "LIVE"` (what to demote it to):

{% tabs %}
{% tab title="JSON" %}

```json
{
  "envId": "prod",
  "intent": "DEFAULT",
  "currentVersionId": "AND1",
  "currentAssetIntent": "LIVE",
  "updatedBy": "dev@acme-games.com"
}
```

{% endtab %}

{% tab title="cURL" %}

```bash
curl -X POST "https://api.umbercloud.io/api/v2/acme-games/va/hero-skin-01/versions/AND3/deploy?targetPlatformId=android" \
  -H "apikey: $ASSET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "envId": "prod",
    "intent": "DEFAULT",
    "currentVersionId": "AND1",
    "currentAssetIntent": "LIVE",
    "updatedBy": "dev@acme-games.com"
  }'
```

{% endtab %}
{% endtabs %}

`201 Created` — same shape as above, describing the **newly-promoted** version only (`AND3`, now `DEFAULT`). The previous Default (`AND1`) is demoted to Live in the same request, but its updated record isn't part of this response — fetch it separately (`GET .../versions/AND1`) if you need to confirm it.

{% hint style="warning" %}
Send exactly `"LIVE"` for `currentAssetIntent` — it's the only value this demotion path maps to a real state today. Anything else demotes to no state at all and fails on the next write.
{% endhint %}

### Errors

Every error is a small JSON body, same shape as [the Virtual Assets API](/umber/api-reference-v2/virtual-assets.md#errors).

| Status | Meaning                                                                                                                                                                                                                                                                                                     |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid/unrecognized `intent` on a re-publish; the version is currently Default (revert it first); already in the target state; an Offline version can't be promoted to Default; promoting a first Default while one already exists; demoting a version that isn't actually Default.                        |
| `404`  | `assetId`/`envId`/`targetPlatformId` not found; the version doesn't exist or isn't active for this platform; `intent` missing or invalid on the first deploy for a channel (only `LIVE`/`OFFLINE` are valid there); nothing deployed yet to re-publish; the old Default version wasn't found when demoting. |
| `409`  | The Default pointer was moved by another request between your read and write — retry with a fresh `currentVersionId`.                                                                                                                                                                                       |
| `500`  | `createdBy`/`updatedBy` missing; the channel is already mid-deployment; any other unexpected failure.                                                                                                                                                                                                       |

## List deployed URLs for an environment

`GET /api/v2/{domainId}/va/{assetId}/asset-urls?envId={envId}`

After deploying, this is how you see what's actually Live (or Offline) for this asset in that environment — the same [asset-urls endpoint](/umber/api-reference-v2/virtual-assets.md#list-an-assets-deployed-urls) documented on the Virtual Assets API, filtered down to one environment. It's not scoped to a single version — every version currently deployed to `envId` comes back, across all target platforms; pick your `versionId` out of the results.

```bash
curl "https://api.umbercloud.io/api/v2/acme-games/va/hero-skin-01/asset-urls?envId=prod" \
  -H "apikey: $ASSET_API_KEY"
```

`200 OK` — the [pagination envelope](/umber/api-reference-v2/virtual-assets.md#pagination); each result:

```json
{
  "assetId": "hero-skin-01",
  "version": 3,
  "versionId": "AND3",
  "versionName": "Hero Skin 01 v3",
  "targetPlatform": "android",
  "assetType": "0001",
  "secured": true,
  "state": "LIVE",
  "envId": "prod",
  "downloadUrl": "https://adn.umbercloud.io/acme-games/hero-skin-01/prod/android"
}
```

`downloadUrl` is omitted for a version in the `OFFLINE` state. Add `targetPlatform` as a further filter if you only care about one platform.

### Narrowing to one version

`GET /api/v2/{domainId}/va/{assetId}/versions/{versionId}/asset-urls?envId={envId}`

Same endpoint family and response shape as above, pre-filtered to just this `versionId` — useful when you already know which version you care about. It's still the pagination envelope, not a flat single object, even though it typically resolves to zero or one result.

```bash
curl "https://api.umbercloud.io/api/v2/acme-games/va/hero-skin-01/versions/AND3/asset-urls?envId=prod" \
  -H "apikey: $ASSET_API_KEY"
```

`200 OK`

```json
{
  "totalResults": 1,
  "pageNumber": 1,
  "pageSize": 50,
  "results": [
    {
      "assetId": "hero-skin-01",
      "version": 3,
      "versionId": "AND3",
      "versionName": "Hero Skin 01 v3",
      "targetPlatform": "android",
      "assetType": "0001",
      "secured": true,
      "state": "LIVE",
      "envId": "prod",
      "downloadUrl": "https://adn.umbercloud.io/acme-games/hero-skin-01/prod/android"
    }
  ]
}
```

## Undeploy

`POST /api/v2/{domainId}/va/{assetId}/undeploy`

Removes deployment records for one or more target platforms from one environment in a single call — there's no per-version undeploy; it's scoped to (asset, environment, platform) and clears every version deployed under that combination.

{% tabs %}
{% tab title="JSON" %}

```json
{ "envId": "prod", "targetPlatforms": ["android", "ios"] }
```

{% endtab %}

{% tab title="cURL" %}

```bash
curl -X POST "https://api.umbercloud.io/api/v2/acme-games/va/hero-skin-01/undeploy" \
  -H "apikey: $ASSET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "envId": "prod", "targetPlatforms": ["android", "ios"] }'
```

{% endtab %}
{% endtabs %}

`200 OK`

```json
{
  "message": "Asset Container undeployed successfully.",
  "totalUndeployedVersions": 2
}
```

`totalUndeployedVersions` is a delete count across every deployment record matched (all versions × all requested platforms in that one environment), not a count of distinct asset versions.

### Errors

| Status | Meaning                                                                                                                                                   |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `404`  | `assetId`/`envId` not found; `targetPlatforms` missing, empty, or contains an unknown platform code.                                                      |
| `500`  | Unexpected failure. A `500` from this specific endpoint may not carry the usual problem+json error body — treat any non-2xx response from it defensively. |

{% hint style="info" %}
See [Deployment States](/umber/concepts/deployment-states.md) for what Live, Offline and Default mean, and [Managing Deployments](/umber/guides/managing-deployments.md) for the equivalent dashboard actions (Deploy Here, Take Offline, Set Live, Set Default, Revert).
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://umber.gitbook.io/umber/api-reference-v2/virtual-assets/version-deployment.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
