
## Restore asset

URL: https://docs.atlan.com/product/capabilities/build-apps/sdks/python/how-tos/asset-crud/restore-asset

> Restore soft-deleted (archived) assets in Atlan using Asset and the Python SDK (pyatlan).

# Asset: restore soft-deleted assets

Use `Asset` in the Atlan Python SDK to programmatically restore soft-deleted assets back to active state.

Restoring an [asset](https://docs.atlan.com/llms/platform/python/build-your-first-metadata-workflow/llms.txt) from an archived (soft-deleted) state back to active uses a similar pattern to the deletion operations.

## By `qualifiedName`

To restore an asset by its `qualifiedName`:

### Java

```java showLineNumbers title="Restore an asset by its qualifiedName"
boolean restored = GlossaryTerm
	.restore(client, "gsNccqJraDZqM6WyGP3ea@FzCMyPR2LxkPFgr8eNGrq"); // (1)
```

1. If an asset with the provided qualifiedName exists and is now active, the operation will return true. If no archived (soft-deleted) version of the asset could be found the operation will return false. Because this operation will restore the asset in Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Python

```python showLineNumbers title="Restore an asset by its qualifiedName"
from pyatlan.client.atlan import AtlanClient
from pyatlan.model.assets import AtlasGlossaryTerm

client = AtlanClient()
restored = client.asset.restore(
 asset_type=AtlasGlossaryTerm,
 qualified_name="gsNccqJraDZqM6WyGP3ea@FzCMyPR2LxkPFgr8eNGrq" # (1)
)
```

1. If an asset with the provided qualified_name exists and is now active, the operation will return true. If no archived (soft-deleted) version of the asset could be found the operation will return false.

### Kotlin

```kotlin showLineNumbers title="Restore an asset by its qualifiedName"
val restored = GlossaryTerm
 .restore("gsNccqJraDZqM6WyGP3ea@FzCMyPR2LxkPFgr8eNGrq") // (1)
```

1. If an asset with the provided qualifiedName exists and is now active, the operation will return true. If no archived (soft-deleted) version of the asset could be found the operation will return false. Because this operation will restore the asset in Atlan, you must [provide it an `AtlanClient`](https://docs.atlan.com/llms/platform/python/set-up-sdk/llms.txt) through which to connect to the tenant.

### Raw REST API

```json showLineNumbers title="POST /api/meta/entity/bulk?replaceClassifications=false&replaceBusinessAttributes=false&overwriteBusinessAttributes=false"
{
 "entities": [ // (1)
 },
 "status": "ACTIVE" // (8)
 }
 ]
}
```

1. All assets must be wrapped in an `entities` array.
2. You must provide the exact type name for the asset (case-sensitive). For a glossary, this is `AtlasBusiness Graph`.
3. You must provide the exact name of the existing asset (case-sensitive).
4. You must provide the exact `qualifiedName` of the existing asset (case-sensitive).

 :::warning[Must exactly match the `qualifiedName` of an existing asset]
If this doesn't exactly match the `qualifiedName` of an existing asset, the API call will instead *create a new asset* rather than restoring an existing one.
 :::
5. For glossary-contained objects (terms and categories), you must also specify the glossary in which they're contained. You do this using the `anchor` attribute.
6. Nested within the `anchor` attribute you must give the `typeName` as exactly `AtlasBusiness Graph`.
7. Nested within the `anchor` attribute you must also give the GUID of the glossary the archived object is contained within.
8. The piece that actually triggers the restore is to change the `status` of the asset. When soft-deleted (archived) the status will be `DELETED`. Therefore, changing this to `ACTIVE` will restore the asset.

## In bulk

To restore a number of assets at the same time, for example after retrieving them via a search:

### Java

```java showLineNumbers title="Restore assets in bulk"
List toRestore = client.assets.select(true) // (1)
 .archived()
 .stream() // (2)
 .limit(50) // (3)
 .collect(Collectors.toList()); // (4)
AssetMutationResponse response = client.assets.restore(toRestore); // (4)
response.getUpdatedAssets(); // (5)
```

1. You would want more to your search criteria than this, but the `true` sent to the `select(true)` will make sure archived (soft-deleted) assets are returned, while the `.archived()` will make sure _only_ archived assets are returned.
2. Run the search to retrieve such results, and page through them automatically.
3. Limit the results to some maximum number, as you will need to limit how many you try to restore at the same time to avoid timeouts or other issues.
4. You can collect up the assets to be restored into a list from the stream.
5. You can then simply pass the results of the search across to the restore operation to re-activate all of them en masse.

 :::warning[The restore will only be run on that _limited_ set of results]
In this example, the restore is only running on the first set of 50 results. To restore _all_ assets that match the search criteria, don't forget to loop over this logic or create your own batching mechanism to process all pages!
 :::
5. You can retrieve the details of the specific assets that were restored from the bulk restore response.

### Python

:::warning[Restoring assets in bulk isn't currently available in the Python SDK, but will be coming soon.]
:::

### Kotlin

```kotlin showLineNumbers title="Restore assets in bulk"
val toRestore = client.assets.select(true) // (1)
 .archived()
 .stream() // (2)
 .limit(50) // (3)
 .collect(Collectors.toList()) // (4)
val response = client.assets.restore(toRestore) // (4)
response.updatedAssets // (5)
```

1. You would want more to your search criteria than this, but the `true` sent to the `select(true)` will make sure archived (soft-deleted) assets are returned, while the `.archived()` will make sure _only_ archived assets are returned.
2. Run the search to retrieve such results, and page through them automatically.
3. Limit the results to some maximum number, as you will need to limit how many you try to restore at the same time to avoid timeouts or other issues.
4. You can collect up the assets to be restored into a list from the stream.
5. You can then simply pass the results of the search across to the restore operation to re-activate all of them en masse.

 :::warning[The restore will only be run on that _limited_ set of results]
In this example, the restore is only running on the first set of 50 results. To restore _all_ assets that match the search criteria, don't forget to loop over this logic or create your own batching mechanism to process all pages!
 :::
5. You can retrieve the details of the specific assets that were restored from the bulk restore response.

### Raw REST API

:::warning[Multiple API calls required]
You will need to first run a search for all assets with a status of `DELETED`. You can then bulk-restore them by placing all of the returned assets into a single API call.
:::
```json showLineNumbers title="POST /api/meta/entity/bulk?replaceClassifications=false&replaceBusinessAttributes=false&overwriteBusinessAttributes=false"
{
 "entities": [ // (1)
 },
 "status": "ACTIVE" // (8)
 },
 {
 "typeName": "AtlasGlossaryTerm",
 "attributes": {
 "name": "Another Example",
 "qualifiedName": "...",
 "anchor": {
 "typeName": "AtlasBusiness Graph",
 "guid": "51a28d46-b700-4c9d-807d-397f25f2b6d6"
 }
 },
 "status": "ACTIVE"
 }
 { ... },
 { ... },
 { ... }
 ]
}
```

1. All assets must be wrapped in an `entities` array.
2. You must provide the exact type name for each asset (case-sensitive).
3. You must provide the exact name of each existing asset (case-sensitive).
4. You must provide the exact `qualifiedName` of each existing asset (case-sensitive).

 :::warning[Must exactly match the `qualifiedName` of an existing asset]
If this doesn't exactly match the `qualifiedName` of an existing asset, the API call will instead *create a new asset* rather than restoring an existing one.
 :::
5. For glossary-contained objects (terms and categories), you must also specify the glossary in which they're contained. You do this using the `anchor` attribute.
6. Nested within the `anchor` attribute you must give the `typeName` as exactly `AtlasBusiness Graph`.
7. Nested within the `anchor` attribute you must also give the GUID of the glossary the archived object is contained within.
8. The piece that actually triggers the restore is to change the `status` of each asset. When soft-deleted (archived) the status will be `DELETED`. Therefore, changing this to `ACTIVE` will restore each asset.

---
