> For the complete documentation index, see [llms.txt](https://docs.insurehero.io/shield-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.insurehero.io/shield-api/policies/risk-item-management/risk-item-asset-management.md).

# Risk Item Asset Management

With the InsureHero Shield API you can upload assets on behalf of your risk items. This creates a repository of assets for each risk item. Each uploaded asset gets a public URL that you can attach to: risk items, claims, events and more.

{% hint style="success" %}
**Good to know**

Attaching assets to entities like claims & events is a 2 step process.

* First assets are uploaded to a private repository. A public URL is returned for each of the uploaded assets.
* Then you create/update an entity with the given URLs.
  {% endhint %}

## Endpoints

<table><thead><tr><th width="113">Method</th><th>Endpoint</th></tr></thead><tbody><tr><td><mark style="color:green;">POST</mark></td><td><a href="#upload-assets-to-a-risk-item"><code>https://app.insurehero.io/api/shield/v1/risk-items/:riskItemId/assets</code></a></td></tr></tbody></table>

All error responses use the `{ "error": string, "details": any }` envelope. See [Error Handling](https://docs.insurehero.io/shield-api/data-dictionary#error-handling) for the general format.

### Upload assets

When needed allow users to upload assets to their private repositories.

## Upload assets to a risk item

<mark style="color:green;">`POST`</mark> `https://app.insurehero.io/api/shield/v1/risk-items/:riskItemId/assets`

When you need to add documents, videos or any other type of asset to backup a claim or attach evidence to a risk item event, you will first need to upload those assets to a risk item.

#### Path Parameters

| Name                                         | Type | Description                 |
| -------------------------------------------- | ---- | --------------------------- |
| riskItemId<mark style="color:red;">\*</mark> | uuid | The id of a given risk item |

#### Headers

| Name                                            | Type   | Description         |
| ----------------------------------------------- | ------ | ------------------- |
| Authorization<mark style="color:red;">\*</mark> | string | Bearer access token |
| Content-Type<mark style="color:red;">\*</mark>  | string | multipart/form-data |

#### Request Body

| Name                                    | Type    | Description                                                                                                                                                                                    |
| --------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| files<mark style="color:red;">\*</mark> | Blob\[] | The list of files to be uploaded. Send each file under the `files` key of the form-data.                                                                                                       |
| name                                    | string  | Form-data field that provides descriptive context for the files being uploaded. It is applied to every file of the request. If you do not provide a name, the file name of each asset is used. |

Each uploaded file is added to the `assets` of the risk item as `{ "url", "name" }`. If the risk item already has an asset with the same `name`, the new one is not added to `assets`, although the file is uploaded and its URL is returned.

{% tabs %}
{% tab title="200: OK Upload finished" %}
Each file is returned with its `success` status and, in case of success, its public URL. The request answers `200` when at least one file was uploaded; files that failed include a `cause`.

```json
{
    "data": {
        "result": "1 / 2 files uploaded successfully.",
        "files": [
            {
                "success": true,
                "url": "https://storage.example.com/riskItems/0ccad1d6-18ee-5c17-a684-9f8fe203d7c1/f2131218-d320-5b45-9d26-29402855d2db/document.pdf",
                "fileName": "document.pdf"
            },
            {
                "success": false,
                "url": null,
                "fileName": "photo.jpg",
                "cause": "The resource already exists"
            }
        ]
    }
}
```

{% endtab %}

{% tab title="400: Bad Request Request contains malformed data" %}

```json
{
    "error": "Request contains malformed data",
    "details": "Missing bearer token"
}
```

{% endtab %}

{% tab title="401: Unauthorized Invalid or expired access token" %}

```json
{
    "error": "Invalid or expired access token",
    "details": "Invalid access token"
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity No files" %}

```json
{
    "error": "Invalid request, use the 'files' key on the form-data files that should be uploaded.",
    "details": null
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity No files were uploaded" %}

```json
{
    "error": "Invalid request, no files were uploaded.",
    "details": {
        "result": "0 / 1 files uploaded successfully.",
        "files": [
            {
                "success": false,
                "url": null,
                "fileName": "document.pdf",
                "cause": "The resource already exists"
            }
        ]
    }
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Risk item not found" %}

```json
{
    "error": "Internal validation failed",
    "details": {
        "code": "PGRST116",
        "details": "The result contains 0 rows",
        "hint": null,
        "message": "Cannot coerce the result to a single JSON object"
    }
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Internal error" %}

```json
{
    "error": "Internal validation failed",
    "details": "Internal error"
}
```

{% endtab %}
{% endtabs %}

When the body is not a valid multipart form-data, the request returns `422` with `"error": "Invalid request, not files to upload."` and `"details": null`. The `Internal error` response means the files were uploaded but could not be added to the risk item.

{% hint style="info" %}
**Keep in mind**

* Files are stored under the risk item and are not overwritten: uploading a file whose name already exists for that risk item fails for that file, and its `cause` explains why.
* The storage may reject a file (for example, because of its size or type). Check `success` and `cause` for each file in the response.
  {% endhint %}
