# Issue & Transfer

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

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

### Precaution

#### Multiple issuance

{% hint style="warning" %}
Feel free to include more than one issuance in a single request via the `payload` array. The minimum number of issue requests is one. Though there is no fixed upper limit for the number of issue requests you can submit at one time, we recommend limiting batches to no more than 250 issue requests for optimal processing.
{% endhint %}

#### issue to issuer

{% hint style="info" %}
If payload\[\*].to is not given, your SRR will be issued to your `luw` address
{% 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                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------------------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| requestId                                                           | string         | <p>A <code>requestId</code> given by the caller, to ensure requests are only processed once. If the <code>requestId</code> is known and processed before, api will not process this call again, and respond with an error. A good practice is using random UUID.</p><p>\*<code>requestId</code> must be unique for a given <code>issuer-address</code>. As a result any duplicate combination of <code>requestId</code> and <code>issuer-address</code> is instantly rejected with no impact on either.</p> |
| payload<mark style="color:red;">\*</mark>                           | array          | Array of issue requests. Further constraints explained [above](#multiple-issuance).                                                                                                                                                                                                                                                                                                                                                                                                                         |
| payload\[\*].externalId<mark style="color:red;">\*</mark>           | string         | An ID to identify the record in your system. We recommend to use UUID, but it can use any string as long it is unique in your system.                                                                                                                                                                                                                                                                                                                                                                       |
| payload\[\*].metadata<mark style="color:red;">\*</mark>             | object         | <p>The metadata to be issued as a complex object. Detailed schema specification can be found <a href="../../metadata-schema/startrail-registry-srr/version-2.2">here</a>.</p><p></p><p>The API accepts versions 2.0 and higher.</p>                                                                                                                                                                                                                                                                         |
| payload\[\*].artistAddress<mark style="color:red;">\*</mark>        | string         | The ethereum address of the artist of the artwork.                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| payload\[\*].isPrimaryIssuer<mark style="color:red;">\*</mark>      | boolean        | If you are the primary issuer of this NFT, set this to true.                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| payload\[\*].lockExternalTransfer<mark style="color:red;">\*</mark> | boolean        | If you want to prevent your NFTs to be transferred on decentralized marketplaces, set this to true.                                                                                                                                                                                                                                                                                                                                                                                                         |
| payload\[\*].to                                                     | string         | <p>Ethereum address target the NFT should be sent to after minting (Issue on Buyer).</p><p>If none is given the NFT will be minted into your LUW by default.</p>                                                                                                                                                                                                                                                                                                                                            |
| payload\[\*].attachmentFiles                                        | Array\<object> | Attachment files that will be included in SRR.                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| payload\[\*].attachmentFiles\[\*].name                              | string         | <p>The name of file.</p><p>This is used for when the file is downloaded or shown. The extension is recommended to be the same as the actual uploaded file.</p>                                                                                                                                                                                                                                                                                                                                              |
| payload\[\*].attachmentFiles\[\*].category                          | 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>Please note that contract terms and thumbnail are NOT attachment files. The URL for contract terms and thumbnail are needed for metadata. (See metadata attribute)</p>                                                                                                                                          |
| payload\[\*].attachmentFiles\[\*].url                               | string         | For the time being, the URL must be under Startbahn's GCS bucket. This can include finalUrl's that is the field in the response of the [singed URL endpoint](https://docs.startrail.io/issue-transfer-api/issue-and-transfer-srr-nft/request-signed-url-for-upload-download-files) or a URL that has already been prepared for the client by Startbahn's team. Any other URL will result to rejecting the request without issuing the SRR                                                                   |
| payload\[\*].collectionAddress                                      | string         | The address of collection that the SRR will belong to. This collection must be owned by the caller `issuer-address`.                                                                                                                                                                                                                                                                                                                                                                                        |

{% tabs %}
{% tab title="201: Created " %}
The API responds with 201. see Response Body results\[\*].status for details of each entry.

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

<table><thead><tr><th>Body Attribute</th><th width="259.66666666666663">Description</th><th>Format</th></tr></thead><tbody><tr><td>results</td><td>results of the request</td><td>Array</td></tr><tr><td>results[*].srr</td><td>Detail of the SRR. Please check example for detailed information.</td><td>object</td></tr><tr><td>results[*].externalId</td><td>ID to identify the SRR. Defined by client when calling.</td><td>string</td></tr><tr><td>results[*].status</td><td><code>waiting_for_mining</code>wait for completion of blockchain mining. The status can be confirmed via <a href="../../subgraph">subgraph</a> or less favorably via <a href="../../get-srr-api/get-srr-by-token-id">this</a> REST endpoint.</td><td>string</td></tr></tbody></table>

{% hint style="info" %}
After a successful issuance, 2 types of JSONs will be returned in *`results[*].srr.metadata`*:

1. *`json`*

   It is converted from the `originalJson`. The object contains some values that are different from those that are written on chain. This json is meant to be easier for consumption on third party applications and it is maintained for backward compatibility. For example if an `ipfs` link exists in the metadata, this json converts it to an `https` link for easier consumption.
2. *`originalJson`*

   It is equal to what is written on chain. So if you want to consume this field, some carings are needed. For example it can contain `ipfs` links like `ipfs://` that requires conversion before a browser can display it.

\* both of the above JSONs may be different from what originally sent in the request payload.
{% endhint %}
{% endtab %}

{% tab title="Example" %}

```json
{
  "results": [
    {
      "status": "waiting_for_mining",
      "srr": {
        "tokenId": "149941159501",
        "collectionContractAddress": "0x552e100d1c368435db99974C658c757E8A6102Dd",
          "collection": {
            "contractAddress": "0x552e100d1c368435db99974C658c757E8A6102Dd",
            "name": "Test",
            "symbol": "TTT"
        },
        "artist": {
          "contractAddress": "0xA6E6a9E20a541680a1D6E1412f5088AefBF58a22",
          "originalName": "artist orignal name",
          "englishName": "artist english name",
          "userType": "artist",
          "createdAt": "2022-04-14T03:15:35.153Z",
          "updatedAt": "2022-04-14T03:15:35.153Z"
        },
        "issuer": {
          "contractAddress": "0xA6E6a9E20a541680a1D6E1412f5088AefBF58a22",
          "originalName": "artist orignal name",
          "englishName": "artist english name",
          "userType": "artist",
          "createdAt": "2022-04-14T03:15:35.153Z",
          "updatedAt": "2022-04-14T03:15:35.153Z"
        },
        "isPrimaryIssuer": true,
        "issuedAt": "2022-04-14T03:15:35.153Z",
        "metadata": { 
          "json": {
            // converted verion of originalJson. It converts some fields from the originalJson
            // for backward compatibility and easier consumption reasons
            //   This JSON may be different from the one sent in the request payload, 
            //   because Startbahn update it to comply with the latest version
          },
          "originalJson": {
            // The JSON that is saved on chain.
            //   This JSON may be different from the one sent in the request payload, 
            //   because Startbahn update it to comply with the latest version
          },
          "digest": "b764ad28dec64764c83089967db4710c94d831c677424d1883....",
        },
        "createdAt": "2022-04-14T03:15:35.153Z",
        "updatedAt": "2022-04-14T03:15:35.153Z"
      },
      "externalId": "c0456840-5bdf-4375-a6ce-106697b7dfb7"
    }
  ]
}
```

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

{% tab title="400: Bad Request " %}
The API responds with 400 if request body invalid or some validation errors that can be instantly detected.&#x20;

```json
// If the metadata is same with another previous SRR
{
  "statusCode": 400,
  "message": {
    "results": [
      {
        "status": "failed",
        "externalId": "c0456840-5bdf-4375-a6ce-106697b7dfb7",
        "message": "DUPLICATE_METADATA"
      }
    ]
  }
}

{
  "statusCode": 400,
  "message": {
    "results": [
      {
        "status": "failed",
        "externalId": "c0456840-5bdf-4375-a6ce-106697b7dfb7",
        "message": "DUPLICATE_CHIP"
      }
    ]
  }
}


{
    "statusCode": 400,
    "message": "Request Content Error: Current request already logged with status successful"
}


{
    "statusCode": 400,
    "message": {
        "results": [
            {
                "status": "failed",
                "externalId": "bulk20122fdredcd2dfve",
                "message": "UNKNOWN_ERROR: external ID: bulk20122fdredcd2dfve."
            }
        ]
    }
}

{
  "statusCode": 400,
  "message": {
    "results": [
      {
        "status": "failed",
        "externalId": "c0456840-5bdf-4375-a6ce-106697b7dfb7",
        "message": "UNKNOWN_ARTIST"
      }
    ]
  }
}

// If metadata with issuer and artist combination is already sent
{
  "statusCode": 400,
  "message": "Request Content Error: Current request already logged with status successful"
}

// DTO validation error
{
    "statusCode": 400,
    "message": [
        "payload.0.metadata is invalid. Check it against the metadata JSON schema. Details:  should have required property 'title' ({\"missingProperty\":\"title\"}).",
        "payload.0.artistAddress must be a valid Ethereum addresses",
        "payload.0.externalId should not be empty",
        "payload.0.externalId must be a string"
    ]
}
```

### Multiple issuance

In case of multiple/bulk issuance as soon as one case failed, the rest of the payload will be definitely failed as well.

#### Example of duplicated metadata

```json
{
    "statusCode": 400,
    "message": {
        "results": [
            {
                "status": "failed",
                "externalId": "anId",
                "message": "DUPLICATE_METADATA"
            },
            {
                "status": "failed",
                "externalId": "anId",
                "message": "SRR_NOT_CREATED: Not created because there is SRR in the same batch that error"
            }
        ]
    }
}
```

#### Example of DTO validation error

```json
{
    "statusCode": 400,
    "message": [
        "payload.1.metadata is invalid. Check it against the metadata JSON schema. Details:  should have required property 'title' ({\"missingProperty\":\"title\"}).",
        "payload.1.artistAddress must be a valid Ethereum addresses",
        "payload.1.externalId should not be empty",
        "payload.1.externalId must be a string"
    ]
}
```

{% endtab %}

{% tab title="500: Internal Server Error " %}
The API responds with 5xx if there are other issues, such as deeper validation errors.

```json
// For example in case of collection ownership issue
{
  "statusCode": 500,
  "message": "STARTRAIL_ERROR: <reason>"
}

// In case there is unknown error. Please contact us.
{
  "statusCode": 500,
  "message": "UNKNOWN_ERROR: external ID: xxxx"
}
```

{% endtab %}
{% endtabs %}

## Swagger Endpoint (Test Environment)

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

## Required Permissions

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

## Request Body Example

```json
{
  "requestId": "0004f572-7769-4b8b-8108-a13a36cd88d4",
  "payload": [
    {
      "externalId": "0004f572-7769-4b8b-8108-a13a36cd88d4",
      "metadata": {
        "$schema": "https://api.startrail.io/api/v1/schema/registry-record-metadata.v2.1.schema.json",
        "$schemaIntegrity": "sha256-15f8e99eb9d4292287282942db2f2de9bbcc4761c555c6f7da23feec010c1221",
        "title": {
          "en": "A title",
          "ja": "タイトル",
          "zh": "一个标题"
        },
        "size": {
          "width": 200,
          "height": 400,
          "depth": 12.4,
          "unit": "pixel",
          "flexibleDescription": {
            "en": "flexibleDescription comes here",
            "ja": "自由だーーー"
          }
        },
        "medium": {
          "en": "Oil on canvas",
          "ja": "キャンバスに油彩",
          "zh": "布面油画"
        },
        "edition": {
          "uniqueness": "unique work",
          "proofType": "ED",
          "number": 1,
          "totalNumber": 3,
          "note": {
            "en": "some extra notes in 1 or more languages"
          }
        },
        "contractTerms": {
          "royaltyRate": 15.7,
          "fileURL": "https://startrail.io/whitepaper/startrail_wp_en_v1.1.pdf"
        },
        "note": {
          "en": "note",
          "zh": "注意"
        },
        "thumbnailURL": "https://storage.googleapis.com/opensea-prod.appspot.com/puffs/3.png",
        "yearOfCreation": {
          "en": "around 2010-2020",
          "ja": "2010年から2020年頃"
        },
        "isDigital": true,
        "name": "some nft name",
        "description": "some nft description",
        "image": "https://storage.googleapis.com/opensea-prod.appspot.com/puffs/3.png",
        "external_url": "https://openseacreatures.io/3"
      },
      "artistAddress": "0x36E9f4C26357FDb14AdF939a12AdBba92a209C01",
      "isPrimaryIssuer": true,
      "lockExternalTransfer": false,
      "to": "0x36E9f4C26357FDb14AdF939a12AdBba92a209C01",
      "collectionAddress": "0xfbF4C1A1eb4258aE0F74807f6c1e854918DC8ed3",
      "attachmentFiles": [
        {
          "name": "image-example.jpg",
          "url": "https://static-files-stg.startrail.startbahn.jp/srr-images/image-example.jpg",
          "category": "artwork"
        },
        {
          "name": "certificate-example.jpg",
          "url": "https://static-files-stg.startrail.startbahn.jp/srr-images/certificate-example.jpg",
          "category": "certificate"
        },
        {
          "name": "for_authenticity.jpg",
          "url": "https://static-files-stg.startrail.startbahn.jp/srr-images/for_authenticity.jpg",
          "category": "for_authenticity"
        },
        {
          "name": "installation.jpg",
          "url": "https://static-files-stg.startrail.startbahn.jp/srr-images/installation.jpg",
          "category": "installation"
        }
      ]
    }
  ]
}
```

## Code Example

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

{% hint style="success" %}
If you have a TAG for a physical artwork please add

*`chipUIDs`* and *startbahnCertICTagUIDs* both at the same time and they both need to contain the same value. The value is an array containing the list of the Chip UIDs. For example

```javascript
"startbahnCertICTagUIDs": [
    "1234567890abcdef"
],
"chipUIDs": [
    "1234567890abcdef"
],
```

{% endhint %}
