# Request Signed URL for Upload/Download Files

<mark style="color:green;">`POST`</mark> `<base_url>/port/api/v1/commerce/signedUrls`

Please replace `<base_url>` as explained [here](https://docs.startrail.io/readme/url-per-environment).&#x20;

### Precaution

#### File Size

{% hint style="danger" %}
Our system currently only support file sizes with a maximum limit of strictly less than 2GB, or in other words:

```
    filesize < 2^31 
```

This essentially implies that any user interaction with our API involving data transfer would necessitate adherence to this requirement. Manifestly, if a file size exceeds the defined threshold of 2GB, it may possibly impede the operation of the application.
{% endhint %}

#### File Name

{% hint style="danger" %}
File name

1. should not contain space.
2. should contain the file extension, including but not limited to `.jpg`, `.png`, `.pdf`, etc.
3. use a unique name for each file. Filename is unique per`issuer-address` otherwise it will fail.

   This is to avoid modification of files that are already used in SRR.\
   However given the upgrade to the IPFS protocol, there is no need to be concerned for the filename in terms of its look. The filename is not going to exist in the minted SRR since it is going to be converted to IPFS and the filename will be replaced with `cid` that is a function of the file's content and not file's name.

\*In order to make the file names unique anyway, you can prefix/suffix the name with a unique number such as `Date.now()` .

\*\*Given the underlying usage of IPFS, there is no need to be worried about duplicated contents. Since if two files with different name but same content will eventually be replaced with the same `ipfs` url.
{% endhint %}

#### Headers

| Name                                               | Type   | Description                        |
| -------------------------------------------------- | ------ | ---------------------------------- |
| commerce-api-key<mark style="color:red;">\*</mark> | string | Commerce API Key.                  |
| issuer-address<mark style="color:red;">\*</mark>   | string | Contract Address of API Key owner. |

#### Request Body

| Name                                                    | Type                    | Description                                                                                                                                                                                                                                                                     |
| ------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| action<mark style="color:red;">\*</mark>                | string (write and read) | <p>Field to specify the action of the Signed URL. Value</p><p><code>write</code></p><p>to request upload signed URL, and</p><p><code>read</code></p><p>to request download signed URL.</p>                                                                                      |
| payload<mark style="color:red;">\*</mark>               | array                   | Array of signed URL request.                                                                                                                                                                                                                                                    |
| payload\[\*].filename<mark style="color:red;">\*</mark> | string                  | <p>The filename must meet the constraints mentioned <a href="#file-name">above</a>. </p><p>If the client needs to delete an existing file, please contact Startbahn.</p>                                                                                                        |
| payload\[\*].category<mark style="color:red;">\*</mark> | string                  | <p>Please refer to <a href="https://help.port.startrail.io/hc/en-us/articles/7720691967767-What-is-an-Artwork-File-">this page</a> to understand the difference among the categories.</p><p>Use <code>non\_attachment\_file</code> to upload thumbnails and contract terms.</p> |

{% tabs %}
{% tab title="201: Created " %}
The API responds with 201 when the signed URL is created. The validity of the signed URL is **15 minutes** after it is created.

The client’s back-end needs to consider its upload speed. If the files that need to be uploaded are many, client’s back-end may consider splitting the signed URL request to ensure that all of the files are uploaded.

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

| Body Attribute           | Description                                                                                                                                                                                                                                                                                                                                                                | Format |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| results                  | results of the request                                                                                                                                                                                                                                                                                                                                                     | Array  |
| results\[\*].filename    | Name of the file, same as one in the request                                                                                                                                                                                                                                                                                                                               | string |
| results\[\*].contentType | `Content-Type` that was chosen and set for the file. You need to set the same value in `Content-Type` header when uploading or downloading the file with the signed URL. Otherwise, you will get an error about signature mismatch.                                                                                                                                        | string |
| results\[\*].url         | The signed URL that client can use to perform action such as upload or download. NOTE: This URL is only valid for 15 minutes and should not be saved. Please check the [reference below](https://app.gitbook.com/o/cuPeonZRfwePJTvFEU44/s/Ou6aN3RW264zdJsOQMJ2/issue-transfer-api/issue-and-transfer-srr-nft/api-endpoint-signed-url-for-upload-download-files#reference). | string |
| results\[\*].finalUrl    | The URL that client should save and use when calling issue endpoint. Check below for details                                                                                                                                                                                                                                                                               | string |

#### Usage of Final URL

| category                                     | Usage                                                                                                                              | example                                                                                                                               |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| artwork                                      | On issue endpoint, use it for `payload.attachmentFiles[*].url`                                                                     | <https://static-files-stg.startrail.startbahn.jp/srr-images/0xf1B51E02804A7AF4Eb4c2f57dc9a05510A513C17/221208_royalty-01-001.jpg>     |
| certificate, installation, for\_authenticity | On issue endpoint, use it for `payload.attachmentFiles[*].url`                                                                     | <https://storage.googleapis.com/artwork-staging-images/srr-images/luw-address-1/certificate.tif>                                      |
| non\_attachment\_file                        | use it for the field in metadata on the `image`, `payload[*].metadata.thumbnailURL` or `payload[*].metadata.contractTerms.fileURL` | <https://storage.googleapis.com/artwork-staging-images/srr-images/0xf1B51E02804A7AF4Eb4c2f57dc9a05510A513C17/Contract_Terms_test.pdf> |
| {% endtab %}                                 |                                                                                                                                    |                                                                                                                                       |

{% tab title="Example" %}

```javascript
{
  "results": [
    // Example result for non_attachment_file and artwork category
    {
      "filename": "artwork.jpg",
      "contentType": "image/jpeg",
      "url": "https://storage.googleapis.com/bucket/directory/luw-address/artwork.jpg?signature=xyz",
      "finalUrl": "https://static-files.startrail.io/directory/luw-address/artwork.jpg"
    },
    // Example for other categories
    {
      "filename": "certificate.jpg",
      "contentType": "image/jpeg",
      "url": "https://storage.googleapis.com/bucket/directory/luw-address/certificate.jpg?signature=xyz",
      "finalUrl": "https://storage.googleapis.com/bucket/directory/luw-address/certificate.jpg"
    }
  ]
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="400: Bad Request " %}
The API responds with 400 if the request body is invalid.

```javascript
// If the payload is incorrect
{
  "statusCode": 400,
  "message": [
    "payload.0.category must be one of the following values: certificate,for_authenticity,artwork,installation,non_attachment_file"
  ]
}
```

{% endtab %}

{% tab title="500: Internal Server Error " %}
The API responds with 5xx if there is an issue between the network and also storage provider, currently it is Google Cloud Storage.

```
// If the network is error or unknown error. Startbahn side needs to check.
{
  "statusCode": 502,
  "message": "Bad Gateway"
}
```

{% endtab %}
{% endtabs %}

## Swagger Endpoint (Test Environment)

[Swagger to test](https://api-stg.startrail.startbahn.jp/port/api#/public/CommerceController_bulkGenerateSignedUrls).

## Required Permissions

Check [parent page](https://docs.startrail.io/issue-transfer-api/issue-and-transfer-srr-nft).

## Request Body Example

### Signed URL for upload

```json
// Example for thumbnail
{
  "payload": [
    {
      "filename": "thumbnail.jpg",
      "category": "non_attachment_file"
    }
  ],
  "action": "write"
}

// Example for contract terms
{
  "payload": [
    {
      "filename": "contract.pdf",
      "category": "non_attachment_file"
    }
  ],
  "action": "write"
}

// Example for other categories
{
  "payload": [
    {
      "filename": "certificate.pdf",
      "category": "certificate"
    }
  ],
  "action": "write"
}
```

### Signed URL for Download

```json
{
  "payload": [
    {
      "filename": "certificate.pdf",
      "category": "certificate"
    }
  ],
  "action": "read"
}
```

## Code Example

Check [parent page](https://docs.startrail.io/issue-transfer-api/issue-and-transfer-srr-nft).

## Reference

<https://cloud.google.com/storage/docs/access-control/signed-urls>


---

# Agent Instructions: 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:

```
GET https://docs.startrail.io/issue-transfer-api/issue-and-transfer-srr-nft/request-signed-url-for-upload-download-files.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
