# Getting Started

Welcome to Trust Enterprises our self-hosted APIs are the bedrock for your tokenized ecosystem. Begin with ease and nurture your community on a platform that's as straightforward as it is robust.

Trust Enterprises is sponsored and maintained by [DOVU](https://dovu.earth/en/) to help that any project benefits from faster launches and our support building on Hedera Hashgraph.

## The introductory video course 🤩

Wanna grab a coffee and want to chill out for 30 minutes with me and step through the entire process of deploying a Trust Enterprises API client and interaction with a fresh Laravel app, [follow this link](https://docs.trust.enterprises/intro-video-course/introduction-of-the-trust-enterprises-project) 🚀

## The Goal

Your starting point, an API to connect your software (SaaS) to the world of tokens, consensus using Hedera Hashgraph, at the lowest time cost, while owning the deployment, keeping control of the private keys and without any additional microservice overhead.

{% hint style="info" %}
This serverless client for hedera hashgraph is released on mainnet, there are issues and tasks we are currently working on, if you find anything that doesn't seem right [raise an issue.](https://github.com/trustenterprises/hedera-serverless-consensus/issues)
{% endhint %}

You can find out about the current [beta release](https://github.com/trustenterprises/hedera-serverless-consensus/projects/1) and [mainnet progress](https://github.com/trustenterprises/hedera-serverless-consensus/projects/2) with the project by in our [Github projects](https://github.com/trustenterprises/hedera-serverless-consensus/projects).

## What to expect

These are the steps you'll need to follow to start using your hedera hashgraph REST API.

* [Register an account on the hedera portal](https://portal.hedera.com/register) and generate your testnet or previewnet credentials.
* Use the [deploy button from the project](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Ftrustenterprises%2Fhedera-serverless-api\&env=HEDERA_ACCOUNT_ID,HEDERA_PRIVATE_KEY,API_SECRET_KEY,HEDERA_NETWORK\&envDescription=Enter%20your%20account%20id%20and%20private%20key%20from%20the%20hedera%20portal.%20The%20API%20secret%20is%20your%20authentication%20key%20to%20communicate%20with%20your%20API%2C%20create%20a%20secure%20string%20of%20at%20least%2010%20characters.\&envLink=https%3A%2F%2Fdocs.trust.enterprises%2Fdeployment%2Fenvironment-variables\&redirect-url=https%3A%2F%2Fdocs.trust.enterprises%2Frest-api%2Foverview) to start the deploy flow with Vercel.
* Start sending requests to your own API, upon successful deployment.

{% hint style="info" %}
We will offer a trial sandbox environment on testnet for those to experiment with the features in the API.
{% endhint %}

In addition, you may update your secrets in your newly generated Github repository in order to use the inbuilt [Github Actions CI flow](https://app.gitbook.com/@flyinggazelle/s/serverless-hedera/deployment/github-actions).

Otherwise, you can follow the mini introductory video course below:


# Introduction of the Trust Enterprises project \[2:16]

This is the first video in the series and focuses on the "Why" of Trust Enterprises.

{% embed url="<https://www.youtube.com/watch?v=_FNbAy66T38&list=PL68gBULBlEmfqmGRQeeaqOLuHbx45XUD9&index=1>" %}


# Deployment of your first Serverless client \[6:29]

This second video focuses on how to deploy your first Serverless Trust Enterprise Client.

{% embed url="<https://www.youtube.com/watch?v=fHIq77o4q58&list=PL68gBULBlEmfqmGRQeeaqOLuHbx45XUD9&index=2>" %}


# Using Postman with the Trust Enterprises API \[6:33]

This third video focuses on basic interaction of your client with Postman.

{% embed url="<https://www.youtube.com/watch?v=95IQwOsVLwU&list=PL68gBULBlEmfqmGRQeeaqOLuHbx45XUD9&index=3>" %}


# Installation of the Trust Enterprises Laravel package \[7:51]

This fourth video focuses on the installation of the Trust Enterprises laravel package

{% embed url="<https://www.youtube.com/watch?v=7SJBqt5qrg0&list=PL68gBULBlEmfqmGRQeeaqOLuHbx45XUD9&index=4>" %}


# Basic interaction with your client with Laravel. \[10:28]

This is the fifth video of the basic introduction, this one focuses on how simple it is to use Laravel with the serverless Trust Enterprise client.

{% embed url="<https://www.youtube.com/watch?v=nNy24dtkaS8&list=PL68gBULBlEmfqmGRQeeaqOLuHbx45XUD9&index=5>" %}


# Vercel

Vercel is a platform for easily deploying static websites and serverless functions.

## Background

The project is a NextJS app, with a custom REST API framework to allow for flexible testing. It is effectively a wrapper for the NodeJS SDK focused on consensus and trust.

{% hint style="danger" %}
You should only use Vercel, especially on the free tier, if you are expecting a low about of traffic or are creating a proof of concept.

Our recommended paid platform for production deployments, that can scale and is easy to use is **Digital Ocean App Platform**
{% endhint %}

## Start the deployment with Vercel

You can start the deployment by[ clicking this link](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Ftrustenterprises%2Fhedera-serverless-api\&env=HEDERA_ACCOUNT_ID,HEDERA_PRIVATE_KEY,API_SECRET_KEY,HEDERA_NETWORK\&envDescription=Enter%20your%20account%20id%20and%20private%20key%20from%20the%20hedera%20portal.%20The%20API%20secret%20is%20your%20authentication%20key%20to%20communicate%20with%20your%20API%2C%20create%20a%20secure%20string%20of%20at%20least%2010%20characters.\&envLink=https%3A%2F%2Fdocs.trust.enterprises%2Fdeployment%2Fenvironment-variables\&redirect-url=https%3A%2F%2Fdocs.trust.enterprises%2Frest-api%2Foverview), this will redirect you to vercel and use the github project as a template it will also inject the various required environment variables in order to successfully deploy.

## Requirements

In order to successfully deploy the application you need to add 3 environment variables. These variables **HEDERA\_ACCOUNT\_ID** and **HEDERA\_PRIVATE\_KEY** can be found in your hedera account [after registration](https://portal.hedera.com/register).

The **HEDERA\_NETWORK** describes the network you are targeting you can select **mainnet**, **previewnet** or **testnet**.

The **API\_SECRET\_KEY** is what you generate to interact with your REST client, keep this secret private and only share it with individuals that need to interact with it, it needs to be act least 10 characters long.

Consider generating it through a password manager like [1Password](https://1password.com) or [Lastpass](https://www.lastpass.com/). Alternatively you could use the [keychain access app in OSX ](https://en.wikipedia.org/wiki/Keychain_%28software%29)to generate a suitable password.

![The import project view with the request environment variables listed.](/files/-MFzD0vi9aXOkXm32qQS)


# Environment Variables

There are a number of environment variables you can change, these act as your config.

## Required&#x20;

As noted in the previous section these are the required environment variables required to successfully deploy.

* **HEDERA\_NETWORK**
* **HEDERA\_ACCOUNT\_ID**
* **HEDERA\_PRIVATE\_KEY**
* **API\_SECRET\_KEY**
* **ENCRYPTION\_KEY**

The **HEDERA\_ENVIRONMENT** is case-insensitive but when lower cased it must map to either, **testnet**, **previewnet** or **mainnet**.

{% hint style="info" %}
If there is an invalid value the client will automatically throw the error.

> *Network from environment 'x' could not match for any hedera network.* Change your 'HEDERA\_NETWORK' environment variable to either: "testnet', 'previewnet' or 'mainnet'

Your scheduled test suite will also expose this configuration issue.
{% endhint %}

The variables **HEDERA\_ACCOUNT\_ID** and **HEDERA\_PRIVATE\_KEY** can be found in your hedera account [after registration](https://portal.hedera.com/register).&#x20;

The **API\_SECRET\_KEY** is securely generated by you and it acts as your authentication key into your REST API.&#x20;

The **ENCRYPTION\_KEY** is a 32 length string acts as your secret for doing any kind of permissioned action in your app while ensuring that private keys don't touch your primary application for storage purposes. For testing you may generate a key with any key generator like [this from GCS](https://cloud.google.com/network-connectivity/docs/vpn/how-to/generating-pre-shared-key), however for production it is recommended that you generate it locally.

Conceptually you may generate custodial Hedera accounts on behalf of your users then assign tokens, there is a balance between non-custodial ([Hashconnect](https://www.hashpack.app/hashconnect)) and custodial solutions dependent on:

* Your experience with Blockchain, Hedera, or DLT technology
* The needs of your users, is there dollar value connected to tokens or accounts
* Whether your use of Hedera is primarily for logging and provenence&#x20;
* Stage of application development, do you need something that is quick to market to test for user feedback?

## Optional Variables

These variables are completely optional and aren't required but they unlock additional capacity for validating an installation of a client, webhook functionality, and security.

* **API\_URL**
* **WEBHOOK\_URL**&#x20;
* **HIDE\_STATUS**
* **NFT\_STORAGE\_TOKEN**
* **MIRROR\_NODE\_URL**

If you want to use our NFT flow functionality for the complete management of NFT over an API for the creation, minting, metadata generation, and advanced transfer feature you need both the **NFT\_STORAGE\_TOKEN** and **MIRROR\_NODE\_URL** set.

[Follow this walkthrough ](https://docs.filebase.com/api-documentation/ipfs-pinning-service-api)to get your **NFT\_STORAGE\_TOKEN** from Filebase.

The **API\_URL** variable is exclusively used by Github Actions to automatically check the status of a deployment, this isn't required to be part of the vercel deployment.

The **WEBHOOK\_URL** variable provides a method for all timestamped consensus responses to be sent to your server, allowing you to set up an asynchronous flow for broadcasting messages and not having to wait for consensus timestamps.&#x20;

{% hint style="info" %}
Using an asynchronous consensus flow enables new messages to be broadcast to hedera via your client in the 150-200ms range instead of waiting for the full 3-5 seconds for response finality when processed linearly.
{% endhint %}

The **HIDE\_STATUS** variable provides the ability to hide the publicly available status screen that describes the state of your deployment, by default this status screen will be displayed.

![Information of the current status of the deployment.](/files/-MFzIQ6ZegZbzSWSzGPg)


# Github Actions

This is an optional step, using GitHub actions provides a continuous integration mechanism for automating the validity of your client and your environment variables.

## Why you should add this CI flow

Consider this process as an automated CI flow for verifying the stablity of your client against your configuration scheduled on a daily basis.

The benefit of setting up the github action flow is that it will check the lint and basic tests for the app.

As before add your esstiential environment variables to your Github&#x20;

* **HEDERA\_NETWORK**
* **HEDERA\_ACCOUNT\_ID**
* **HEDERA\_PRIVATE\_KEY**
* **API\_SECRET\_KEY**

You can update your secrets from your Github repository from **Settings -> Secrets**.

![Update your secrets before re-running your action](/files/-MFzabvnmyLzQr5FY6MW)

If a job fails and you wish to re-run the job you can re-run all jobs from the **Actions** tab.

![](/files/-MFzbNlQ7nMzzUIKMGgV)

## Validating the live client is working as expected

When combined with the **APP\_URL** with the live **API\_SECRET\_KEY** the tests will check basic **free** routes of the client, this includes the end points for status and account balance.

{% hint style="info" %}
If you are developing against previewnet or testnet it is possible that your account id will change in the hedera portal if testnet is reset in a fresh state in cases of extended downtime.
{% endhint %}

Ensure that these environment variables are added as secrets as before.

The scheduled CI Github action will run everyday and check that the external client has a valid configuration.

{% hint style="info" %}
This will provide insight to whether configuration needs to be updated on your deployments, if the request to **/api/account/balance** fails with a status code **502**, it is likey that your **HEDERA\_ACCOUNT\_ID** on Vercel will need to be updated and the app redeployed.
{% endhint %}


# Overview

The REST API provides a number of resources to manage assets, create marketplaces, consume to check the status of your account, update topics and send messages for generate timestamp consensus.

## Postman Documentation&#x20;

If you live and die by your love of Postman for API development, we provide a collection with examples that you can start using now. You'll need to create a new environment with fields for **domain** and **api\_key.**

[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/416758-2c026d8f-795d-48c7-8554-4bbc17f797ad?action=collection%2Ffork\&collection-url=entityId%3D416758-2c026d8f-795d-48c7-8554-4bbc17f797ad%26entityType%3Dcollection#?env%5BTrust%20Enterprises%5D=W3sia2V5IjoiZG9tYWluIiwidmFsdWUiOiJodHRwczovL2hlZGVyYS1zZXJ2ZXJsZXNzLWNvbnNlbnN1cy52ZXJjZWwuYXBwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJhcGlfc2VjcmV0X2tleSIsInZhbHVlIjoiMTIzNDU2NzhhYmMiLCJlbmFibGVkIjp0cnVlfV0=)

## **The Routes**

In all routes swap out the ***hedera-serverless-consensus.vercel.app*** for your URL.

## Build a token marketplace

A permissioned marketplace at your fingertips, link your users to tokens that you sell, without them having to touch or have any blockchain experience. &#x20;

### Create a token&#x20;

A token can be created to be linked to a frontend of a marketplace or online shopfront.

{% content-ref url="/pages/KmifRnjglB0QOJzacCoS" %}
[Create a token](/rest-api/tokens/create-a-token)
{% endcontent-ref %}

### Create an account for a user

Every user is required to have an account in tokens to be sent.

{% content-ref url="/pages/bUgCPKJArTJL1K99ssWg" %}
[Accounts](/rest-api/accounts)
{% endcontent-ref %}

### Bequest a token to a user

Transfer a token that has been purchased to a user, the bequest feature manages all token associations by default so all you need to do is use this endpoint when ready, like verifying a payment.

{% content-ref url="/pages/Eie2aZTrFF0REPxgKiPn" %}
[Bequesting a token](/rest-api/tokens/bequesting-a-token)
{% endcontent-ref %}

## Confirm your deployment

### **Deployment Status**

Want to check the status of your client use **/api/status** remember to update **HIDE\_STATUS** in your environment to **FALSE** if you want to hide this behaviour.

{% content-ref url="/pages/-MFswxZKyq0S1a3LVq1g" %}
[Status](/rest-api/status)
{% endcontent-ref %}

### Account Balance

Fetch the current account balance connected to the deployment, useful for checking that the configuration of the deployed service is valid.

{% content-ref url="/pages/-MFsxUnTR0b1n3WCrfth" %}
[Balance](/rest-api/balance)
{% endcontent-ref %}

## Manage topics and timestamped messages

Topics and messages allow you to add "trusted" proof that an event has happened.

### Managing Topics

Create, update and get the info for a topic that you use to send your consensus messages to.

{% content-ref url="/pages/-MFsyVrZ4z8sLzgqmgAf" %}
[Topics](/rest-api/topics)
{% endcontent-ref %}

### **Sending Consensus Messages**

Send a message to that you wish to get a trusted consensus timestamp for, you may provide an option for whether the message should be asynchronous or wait for finality to be reached.

{% content-ref url="/pages/-MFsyHfhgKQ1KMV3j-\_s" %}
[Consensus Messages](/rest-api/consensus-messages)
{% endcontent-ref %}

##


# Inscriptions

This functionality implements the HCS-20 standard, and evolves with it over time. It provides all the alpha features expected including deploying, minting, burning, and transfer.

> It is inspired by the BRC-20 protocol on Ordinals and has extended the functionality to auditable points in addition to introducing inscriptions on Hedera / Hashinals.

{% hint style="warning" %}
This feature is considered to be in an **Alpha** state, and that any code may change at anytime. We may additionally update this documentation to reflect the updated standards for dealing with this meta-protocol.

But due to the low-cost nature of HCS there is lower overhead to rectify issues.

Use at your own risk but have fun.
{% endhint %}

On **mainnet e**very inscription call may provide a custom topic for private usage but it will always default to the public topic of [0.0.4350190](https://hashscan.io/mainnet/topic/0.0.4350190).

These are the calls as follows:

### Deploy an Inscription

{% content-ref url="/pages/PdKgBGWYaO8bYGztXMmN" %}
[Deploy an Inscription](/rest-api/inscriptions/deploy-an-inscription)
{% endcontent-ref %}

### Mint an Inscription

{% content-ref url="/pages/9M79xAYIuepfa52pufQH" %}
[Mint an Inscription](/rest-api/inscriptions/mint-an-inscription)
{% endcontent-ref %}

### Burn an Inscription

{% content-ref url="/pages/xeeK5KZEaB2GFZ2u6b4H" %}
[Burn an Inscription](/rest-api/inscriptions/burn-an-inscription)
{% endcontent-ref %}

### Transfer an Inscription

{% content-ref url="/pages/F29QK9AtqoDNlZX9wca2" %}
[Transfer an Inscription](/rest-api/inscriptions/transfer-an-inscription)
{% endcontent-ref %}


# Deploy an Inscription

Deploy an Inscription with a name, ticker, max, limit, metadata, and memo.

### Deployment HCS-20 Structure

This is the stucture that is used to send to the topic, this payload has been humanised to be more understandable.

```
{
  "p": "hcs-20",
  "op": "deploy",
  "name": "point_name",
  "tick": "unique_point_identifier",
  "max": "max_supply",
  "lim": "optional_limit_of_mint_per_transaction",
  "metadata": "optional_metadata",
  "m": "optional_memo"
}
```

### Overview

There are 3 required fields needed to deploy an inscription:

* name
* ticker
* max (supply)

These are the optional fields you can use:

* topic\_id (your private application for controlling all points or inscriptions)
* limit (the amount of points or inscription amount that can be sent in one tx)
* metadata (any HIP412 compliant data, can be used for NFT/Art)
* memo (an additional memo at the deployment level)

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/inscription/deploy`

Deploy an Inscription

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                     | Type   | Description                            |
| ---------------------------------------- | ------ | -------------------------------------- |
| ticker<mark style="color:red;">\*</mark> |        | Unique ticker of the inscription       |
| name<mark style="color:red;">\*</mark>   | String | Name of the inscription                |
| max<mark style="color:red;">\*</mark>    | Int    | Supply of the inscription              |
| topic\_id                                | String | your private topic for limiting access |
| limit                                    | Int    |                                        |
| metadata                                 | String |                                        |
| memo                                     | String |                                        |
|                                          |        |                                        |

{% tabs %}
{% tab title="200: OK Inscription Deployed" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing params in body" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Mint an Inscription

Mint an Inscription with an amount, ticker, and to address.

### Mint HCS-20 Structure

This is the stucture that is used to send to the topic, this payload has been humanised to be more understandable.

```
{
  "p": "hcs-20",
  "op": "mint",
  "tick": "unique_point_identifier",
  "amt": "number_of_points",
  "to": "recipient_hedera_address",
  "m": "optional_memo"
}
```

### Overview

There are 2 required fields needed to mint an inscription:

* to
* amount

These are the optional fields you can use:

* topic\_id (your private application for controlling all points or inscriptions)
* memo (an additional memo at the deployment level)

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/inscription/{ticker}/mint`

Mint an Inscription

#### Query Parameters

| Name                                     | Type   | Description                      |
| ---------------------------------------- | ------ | -------------------------------- |
| ticker<mark style="color:red;">\*</mark> | String | Unique ticker of the inscription |

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                     | Type   | Description                            |
| ---------------------------------------- | ------ | -------------------------------------- |
| amount<mark style="color:red;">\*</mark> | Int    | amount to mint in one transaction      |
| topic\_id                                | String | your private topic for limiting access |
| memo                                     | String |                                        |

{% tabs %}
{% tab title="200: OK Inscription Minted" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing params in body" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Burn an Inscription

Burn an Inscription with an amount, ticker, and from address.

### Burn HCS-20 Structure

This is the stucture that is used to send to the topic, this payload has been humanised to be more understandable.

```
{
  "p": "hcs-20",
  "op": "burn",
  "tick": "unique_point_identifier",
  "amt": "number_of_points",
  "from": "recipient_hedera_address",
  "m": "optional_memo"
}
```

### Overview

There are 2 required fields needed to burn an inscription:

* from
* amount

These are the optional fields you can use:

* topic\_id (your private application for controlling all points or inscriptions)
* memo (an additional memo at the deployment level)

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/inscription/{ticker}/burn`

Mint an Inscription

#### Query Parameters

| Name                                     | Type   | Description                      |
| ---------------------------------------- | ------ | -------------------------------- |
| ticker<mark style="color:red;">\*</mark> | String | Unique ticker of the inscription |

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                     | Type   | Description                            |
| ---------------------------------------- | ------ | -------------------------------------- |
| amount<mark style="color:red;">\*</mark> | Int    | amount to mint in one transaction      |
| topic\_id                                | String | your private topic for limiting access |
| memo                                     | String |                                        |
| from                                     | String | from address to burn                   |

{% tabs %}
{% tab title="200: OK Inscription Minted" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing params in body" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Transfer an Inscription

Transfer an Inscription with an amount, ticker, and from/to addresses.

### Transfer HCS-20 Structure

This is the stucture that is used to send to the topic, this payload has been humanised to be more understandable.

```
{
  "p": "hcs-20",
  "op": "transfer",
  "tick": "unique_point_identifier",
  "amt": "number_of_points",
  "from": "sender_hedera_address",
  "to": "recipient_hedera_address",
  "m": "optional_memo"
}
```

### Overview

There are 2 required fields needed to deploy an inscription:

* to
* from
* amount

These are the optional fields you can use:

* topic\_id (your private application for controlling all points or inscriptions)
* memo (an additional memo at the deployment level)

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/inscription/{ticker}/transfer`

Mint an Inscription

#### Query Parameters

| Name                                     | Type   | Description                      |
| ---------------------------------------- | ------ | -------------------------------- |
| ticker<mark style="color:red;">\*</mark> | String | Unique ticker of the inscription |

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                     | Type   | Description                            |
| ---------------------------------------- | ------ | -------------------------------------- |
| amount<mark style="color:red;">\*</mark> | Int    | amount to mint in one transaction      |
| topic\_id                                | String | your private topic for limiting access |
| memo                                     | String |                                        |
| to                                       | String | receiver address                       |
| from                                     | String | origination address                    |

{% tabs %}
{% tab title="200: OK Inscription Minted" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing params in body" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# NFT Ecosystem

Understand our process for building NFTs ecosystems completely through our API endpoints, from creation, minting, metadata creation, to advanced transfer features.

We built out this feature on the API to answer one question...

### What if you could build your entire NFT ecosystem through an API?

Naturally, that would be really cool, we're not going to handle full blown image or media uploads by default, this is handled through [the tools provided by nft.storage](https://nft.storage/docs/quickstart/#uploading-files--directories-via-the-nftup-application), or [using NFTup](https://nft.storage/docs/quickstart/#uploading-files--directories-via-the-nftup-application) for directories.

But with that said, V2 of the API provided these additional features:

* NFT creation, with automatic royalty fees of 5%
* Simple NFT minting with batch built-in
* Metadata generation with strict validation based on the [HIP412 specification](https://hips.hedera.com/hip/hip-412)
* Mirrornode compatibility, with retryable logic, in case [nodes have throttled](https://docs.hedera.com/guides/mirrornet/hedera-mirror-node)
* NFT token transfers
* **Exclusive** NFT pass claiming functionality, for ensuring that community members that own a pass can always claim their project tokens with no off-chain storage requirements

All this of course as a simple REST API developer tool for any developer, at any skill level.

For interrogating NFT data during development we recommend using [Gomint's NFT explorer](https://gomint.me/explore/NFT/?tokenId=0.0.732556\&network=mainnet) or [Hashscan](https://hashscan.io/#/) before viewing assets in [Hashpack](https://www.hashpack.app/).

## Understanding the basic flow

Below is the flow to take to start creating NFTs through the API, we will go into more details in the corresponding pages:

{% hint style="warning" %}
Note, that by using these tools for creating NFTs, we will add **5%** to the current royalty structure for secondary sales we will receive.

As a developer or project owner, you may fork our repositories and remove this additional royalty, however, you probably will **not** receive any support from the team and it will make Matt sad...

Our royalty accounts are as follows:

\
Testnet: 0.0.34319163

Mainnet: 0.0.1119570
{% endhint %}

### Create an NFT

An NFT can be created, before minting, to be viewable on hashgraph ledger.

{% content-ref url="/pages/mkTJuGoKNp9VWmTFjc8U" %}
[Create an NFT Collection](/rest-api/nft-ecosystem/create-an-nft-collection)
{% endcontent-ref %}

### Generate Metadata

Metadata is what we refer to a structure [that conforms to HIP412](https://hips.hedera.com/hip/hip-412), to ensure that it is processable for down-stream clients such as wallets like [Hashpack](https://www.hashpack.app/). Upon successful validation you will be provided a **CID** as a unique reference to an IPFS pin for minting NFTs.

{% content-ref url="/pages/85cHL5x5sp0hYHS5BLpq" %}
[Generate Metadata](/rest-api/nft-ecosystem/generate-metadata)
{% endcontent-ref %}

{% hint style="info" %}
Based on feedback we might add metadata helpers for dealing with the output from mass images uploads through the tools provided through NFT storage.
{% endhint %}

### Mint an NFT

Minting a token with an amount and a CID, see above, you may also **batch mint 10** at a time if the CID you have used is the same

{% content-ref url="/pages/2tH97gMR3OWQV4ZC1WTE" %}
[Mint an NFT](/rest-api/nft-ecosystem/mint-an-nft)
{% endcontent-ref %}

### Transfer an NFT to an account

Lastly, you may transfer NFTs to an expected account, this is an attempted transfer and will check. If the treasury can send the NFT and will provide an additional general error if an account hasn't been associated with a given token.

{% content-ref url="/pages/HSKx6KRfy3zMNVAzphLv" %}
[Transfer an NFT](/rest-api/nft-ecosystem/transfer-an-nft)
{% endcontent-ref %}

### Claimable NFTs through Gated NFT passes

This is **our exclusive functionality** that enables projects to create NFT passes for their community and then automatically assign child tokens to their pool of NFT passes, through a fair claiming flow.

{% content-ref url="/pages/9A3YlbtSd07bebZQZtFk" %}
[Claiming NFTs through Passes](/rest-api/nft-ecosystem/claiming-nfts-through-passes)
{% endcontent-ref %}

## Postman Documentation&#x20;

As before see the documentation in your local postman

[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/416758-2c026d8f-795d-48c7-8554-4bbc17f797ad?action=collection%2Ffork\&collection-url=entityId%3D416758-2c026d8f-795d-48c7-8554-4bbc17f797ad%26entityType%3Dcollection#?env%5BTrust%20Enterprises%5D=W3sia2V5IjoiZG9tYWluIiwidmFsdWUiOiJodHRwczovL2hlZGVyYS1zZXJ2ZXJsZXNzLWNvbnNlbnN1cy52ZXJjZWwuYXBwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJhcGlfc2VjcmV0X2tleSIsInZhbHVlIjoiMTIzNDU2NzhhYmMiLCJlbmFibGVkIjp0cnVlfV0=)


# Create an NFT Collection

Create an NFT Collection with a name, symbol, supply, and basic default royalties.

{% hint style="warning" %}
Note, that by using these tools for creating NFTs, we will add **5%** to the current royalty structure for secondary sales we will receive.

As a developer or project owner, you may fork our repositories and remove this additional royalty, however, you probably will **not** receive any support from the team and it will make Matt sad...

Our royalty accounts are as follows:

\
Testnet: 0.0.34319163

Mainnet: 0.0.1119570
{% endhint %}

### Overview

There are 3 required fields needed to create an NFT:

* symbol
* collection\_name
* supply

In addition, **royalties of 5.25% are automatically added, these may be turned off.** After all, we don't live in a web2 world anymore. For future secondary sales, you will receive 5% and this tooling treasury will receive **0.25% or 5% of the current royal structure.**

These are the optional fields you can use:

* allow\_custom\_fees (to disable royalties)
* royalty\_account\_id (the account that will receive royalties, defaults to the Treasury API account)
* royalty\_fee (set as 0.05, or 5%, by default)
* fallback\_fee (default set as 0, for simpler internal transfers)
* enable\_unsafe\_keys (**CONSIDERED DANGEROUS:** set the admin, freeze, and wipe keys)

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/nft`

Create an NFT collection

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                     | Type    | Description                                                                     |
| ---------------------------------------- | ------- | ------------------------------------------------------------------------------- |
| symbol<mark style="color:red;">\*</mark> |         | Symbol of the NFT collection                                                    |
| name<mark style="color:red;">\*</mark>   | String  | Name of the NFT collection                                                      |
| supply<mark style="color:red;">\*</mark> | Int     | Supply of the NFT collection                                                    |
| allow\_custom\_fees                      | boolean | default true, enable custom/royalty fees                                        |
| royalty\_account\_id                     | String  | Hedera account id to send royalties to                                          |
| royalty\_fee                             | decimal | Royalty percentage as a decimal for secondary sales                             |
| fallback\_fee                            | decimal | HBAR fallback for non-treasury transfers                                        |
| enable\_unsafe\_keys                     | boolean | **Considered Dangerous, if true, stops an NFT collection from being immutable** |

{% tabs %}
{% tab title="200: OK NFT collection created" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing params in body" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Generate Metadata

Helping you to generate and pin HIP412 compliant metadata for your minted NFTs in your collection inside of IPFS through NFT storage.

### Overview&#x20;

Metadata is what we refer to as a structure [that conforms to HIP412](https://hips.hedera.com/hip/hip-412), to ensure that it is processable for down-stream clients such as wallets like [Hashpack](https://www.hashpack.app/). Upon successful validation, you will be provided a **CID** as a unique reference to an IPFS pin for minting NFTs.

You should handle the media uploads by default, this is handled through the[ tools provided by filebase](https://filebase.com/), or [using NFTup](https://nft.storage/docs/quickstart/#uploading-files--directories-via-the-nftup-application) for directories.&#x20;

Below is an example of valid metadata, but the validation has been handcrafted in the API to strictly handle many variations of HIP412, based on spec and examples.

If your JSON structure does **not comply with the rules of the aforementioned HIP a status of 422** will be returned with a detailed error response on the issue.

![Basic metadata to generate CID](/files/HM5MG8YxnRNz6uz1yikI)

### Environment Variables

Remember, for complete management of NFT over an API for the creation, minting, metadata generation, and advanced transfer feature you need both the **NFT\_STORAGE\_TOKEN** and **MIRROR\_NODE\_URL** set.

{% content-ref url="/pages/-MFt0JwWQ92EtUIar8y9" %}
[Environment Variables](/deployment/environment-variables)
{% endcontent-ref %}

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/nft/metadata`

Generate the metadata based on a valid structure

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                 | Type | Description                     |
| ------------------------------------ | ---- | ------------------------------- |
| {}<mark style="color:red;">\*</mark> | json | Compliant HIP412 JSON structure |

{% tabs %}
{% tab title="200: OK Returns a CID" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity JSON structure does not comply with HIP412" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Mint an NFT

After receiving your Metadata CID you may mint an NFT, based on your collection,

### Overview&#x20;

Minting an NFT to a collection is simple, only a **CID** from IPFS is required, however you may also batch your mints in sets of 10 if they use the same CID.

<mark style="color:blue;">`GET`</mark> `https://hedera-serverless-consensus.vercel.app/api/nft/:token_id/mint`

Mint an NFT to a collection, you may only mint in batches of 10, up to the limit of the collection.

#### Path Parameters

| Name                                        | Type   | Description                     |
| ------------------------------------------- | ------ | ------------------------------- |
| token\_id<mark style="color:red;">\*</mark> | String | token\_id of the nft collection |

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                  | Type   | Description                                                 |
| ------------------------------------- | ------ | ----------------------------------------------------------- |
| cid<mark style="color:red;">\*</mark> | String | IPFS CID that has been generated through the metadata route |
| amount                                | int    | Default to 1, maximum batch mint of 10.                     |

{% tabs %}
{% tab title="200: OK Token has been minted into collection" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing CID from body" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Transfer an NFT

Attempt a transfer of your NFT, from your treasury, to any account on Hedera

### Overview

This is the simplest of transfer methods the API can process, a couple of things will happen:

* We'll check that the Treasury owns and can send your NFT to an account
* We'll attempt to send the NFT to an account, if it fails then a error will query to whether an account has associated with said NFT id.

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/nft/transfer`

Transfer a specific NFT that the treasury owns to an account.&#x20;

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                             | Type   | Description                       |
| ------------------------------------------------ | ------ | --------------------------------- |
| token\_id<mark style="color:red;">\*</mark>      | String | Hedera token id to send           |
| receiver\_id<mark style="color:red;">\*</mark>   | String | Hedera account to send the NFT to |
| serial\_number<mark style="color:red;">\*</mark> | String | Serial number of the NFT to send  |

{% tabs %}
{% tab title="200: OK NFT sent to account, you may check a mirrornode/explorer after 5- 10 seconds." %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing params or required treasury state for transfer" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Claiming NFTs through Passes

\[pounding on the desk] This is it! I'm telling you this is it! - Jeremy Irons (Margin Call)

### Overview

This feature extends the current Hedera capability by adding the concept of relationships between NFTs, a NFT pass can be a parent, while child NFTs can be linked for distribution to any holder. While the ledger automatically keeps state with no off-chain storage.

Or as a user story...

> As a project with an NFT pass, I want to be able to generate future NFTs that my community may be able to claim.

Or for an art project...

> As an artist I want to have an NFT pass to build a community with so I can reward my pass owners with future peridoic drops.

### How it works

There is a fair bit of logic to make this work, we rely on Mirrornodes to read currently minted NFTs and respective holders.

* Check that an account owns an NFT, or many.
* Check that the minted and supply of the child NFT matches the parent NFT pass.
* Check that a child NFT has been fully pre-minted.
* Check that the child NFT serial is held by treasury
* Attempt to send, or receive a generic association failure error.

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/nft/claim`

Enable an account to claim an NFT through a pass they own.

#### Headers

| Name                                        | Type   | Description                                                       |
| ------------------------------------------- | ------ | ----------------------------------------------------------------- |
| x-api-key<mark style="color:red;">\*</mark> | String | The **API\_SECRET\_KEY** from the client's environment variables. |

#### Request Body

| Name                                                   | Type   | Description                       |
| ------------------------------------------------------ | ------ | --------------------------------- |
| token\_id<mark style="color:red;">\*</mark>            | String | Hedera token id to send           |
| receiver\_id<mark style="color:red;">\*</mark>         | String | Hedera account to send the NFT to |
| serial\_number<mark style="color:red;">\*</mark>       | String | Serial number of the NFT to send  |
| nft\_pass\_token\_id<mark style="color:red;">\*</mark> | String | Hedera token id of pass to send   |

{% tabs %}
{% tab title="200: OK NFT sent to account, you may check a mirrornode/explorer after 5- 10 seconds." %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Missing params, NFT or required treasury state for transfer" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Header Auth Missing/invalid" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Accounts

Create a hedera account for a user, this will provide you will the capability to send tokens to a user.

## Create new account

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/account/create/`

This endpoint allows you to create a user, you can then link the response **accountId** to an actor you have in your system.

You'll also receive an **encryptedKey** and **publicKey**, that you should store in your database.

The **encryptedKey** can be decrypted with your **API\_SECRET\_KEY.**

#### Headers

| Name                                             | Type   | Description                                                        |
| ------------------------------------------------ | ------ | ------------------------------------------------------------------ |
| Authentication<mark style="color:red;">\*</mark> | string | The **API\_SECRET\_KEY** from th e client's environment variables. |

{% tabs %}
{% tab title="200 New account to link to a user" %}

```
{
    "data": {
        "accountId": "0.0.2838629",
        "encryptedKey": "4cc0ccd5446023a2:4e584643658b020a8b2fbfeceb293e00fdaf6cb41bdc3438379e6f6acbc4efeb516320e82b1d9102594f975f4b6ef8444f960017611035598297defb26b19b08a34e8f366639ee72bb265567b7f585597fd459eedfa8c1c6e40e68f439efff9a18f2ccd71cee260ea0f125c4aad730e2",
        "publicKey": "302a300506032b6570032100cebb39dbfc486ec10e6c415233f12572e2abd3d1ac3687308f1953deaef92643"
    }
}
```

{% endtab %}
{% endtabs %}


# Tokens

Manage tokens through minting and sending to your users.

### Understanding Tokens

On Hedera tokens are managed through SDKs, this API wraps the NodeJS SDK and allows any developer or individual exploring nocode applications a simple entry point to get started.

{% hint style="info" %}
Currently the API is opinionated with sane defaults to make everything super simple, but feel free to extend and modify the API code to meet whatever needs you require for your usecase.
{% endhint %}

We are just focused on minting and sending/bequesting of tokens to a user, in a permissioned setting. Imagine a scenerio where your users don't have experience with blockchain but you need a UX that is as friendly as possible for everyone.

For the developers out there I recommend digging into the API code and changing the behaviour as you see fit, the architecture and testing suite of the API is strong and delivers an incredible foundational layer.

{% hint style="info" %}
[Release 2.2.0](https://github.com/trustenterprises/hedera-serverless-api/releases/tag/2.2.0) finally adds support for explicitly setting external token decimals instead of relying on defaults 😅
{% endhint %}

### Minting Tokens

A token can be created to be linked to a frontend of a marketplace or online shopfront.

{% content-ref url="/pages/KmifRnjglB0QOJzacCoS" %}
[Create a token](/rest-api/tokens/create-a-token)
{% endcontent-ref %}

### Bequesting/Sending Tokens

Transfer a token that has been purchased to a user, the bequest feature manages all token associations by default so all you need to do is use this endpoint when ready, like verifying a payment.

{% content-ref url="/pages/Eie2aZTrFF0REPxgKiPn" %}
[Bequesting a token](/rest-api/tokens/bequesting-a-token)
{% endcontent-ref %}


# Create a token

Create a token with a name, symbol, supply, and memo.

## Create new token

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/token`

This endpoint allows you to create a token with a name, symbol, supply, and memo.&#x20;

The memo is an important feature to allow linking but not exclusive to: Hedera Topic IDs (dynamic NFTs), decentralised identity (DIDs), or IPFS (dStorage) images/files.

#### Headers

| Name                                             | Type   | Description                                                        |
| ------------------------------------------------ | ------ | ------------------------------------------------------------------ |
| Authentication<mark style="color:red;">\*</mark> | string | The **API\_SECRET\_KEY** from th e client's environment variables. |

#### Request Body

| Name                                     | Type   | Description                                                                            |
| ---------------------------------------- | ------ | -------------------------------------------------------------------------------------- |
| symbol<mark style="color:red;">\*</mark> | String | Symbol of the token                                                                    |
| name<mark style="color:red;">\*</mark>   | String | Name of the token                                                                      |
| supply<mark style="color:red;">\*</mark> | Number | Number of tokens to mint, whole.                                                       |
| memo                                     | String | Attached memo to a token, for linking to external content or for dynamic NFT purposes. |
| decimals                                 | int    | decimals of the token, if not present will default to 6.                               |

{% tabs %}
{% tab title="200 New token that has been minted, capability to send to send to accounts." %}

```
{
    "data": {
        "name": "Matt token",
        "symbol": "MATT",
        "memo": "abc",
        "reference": "basic.fungible",
        "supply": "100",
        "supplyWithDecimals": "100000000",
        "tokenId": "0.0.2839273"
    }
}
```

{% endtab %}
{% endtabs %}


# Bequesting a token

Send a token to an account that you have previously generated. This feature allows you to create decentralised experiences with onchain proof where a user requires no prior blockchain experience.

{% hint style="warning" %}
This feature is in beta and there will be unexpected side effects if the body parameters aren't used.
{% endhint %}

## Send/bequest a token to an account

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/token/bequest`

This endpoint allows you to send a token to user as a permissioned function, provide the encrypted keys and ids of the receiver and token.

#### Headers

| Name                                             | Type   | Description                                                        |
| ------------------------------------------------ | ------ | ------------------------------------------------------------------ |
| Authentication<mark style="color:red;">\*</mark> | string | The **API\_SECRET\_KEY** from th e client's environment variables. |

#### Request Body

| Name                                                       | Type   | Description                          |
| ---------------------------------------------------------- | ------ | ------------------------------------ |
| encrypted\_receiver\_key<mark style="color:red;">\*</mark> | String | Encrypted private key of receiver    |
| token\_id<mark style="color:red;">\*</mark>                | String | ID of token to send                  |
| receiver\_id<mark style="color:red;">\*</mark>             | String | Account id of receiving account      |
| amount<mark style="color:red;">\*</mark>                   | Number | amount of tokens to send             |
| decimals                                                   | Number | Explicitly set decimals of the token |

{% tabs %}
{% tab title="200 Token sent to user" %}

```
{
    "data": {
        "amount": "1",
        "receiver_id": "0.0.2120537",
        "transaction_id": "0.0.1156@1634128052.72220023"
    }
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Encrypted key too short" %}

```javascript
{
    "errors": [
        "\"encrypted_receiver_key\" length must be 241 characters long"
    ]
}
```

{% endtab %}
{% endtabs %}


# Token Holdings and Balance

There are a couple of requests you can use to check the balance of a given token for a given account or you can check if an account has a number of different tokens.

{% hint style="warning" %}
Remember, for a given call to check the account holdings or an individual balance you need to be aware whether an account ID is valid for a given environment. As an example, the amount of accounts on testnet far exceeds that of mainnet, thus you may receive errors if you try to pass an incorrect accounts into different environments.
{% endhint %}

This returns back to Balance for a given token that belongs to a given account, you can use this as an alternative to balance lookups on mirror nodes, if balance requests are critical.

## Get Token Balance

<mark style="color:blue;">`GET`</mark> `https://hedera-serverless-consensus.vercel.app/api/account/:id/:token_id`

This endpoint allows you to get the token balance of a given account for a particular environment.

#### Path Parameters

| Name                                        | Type   | Description                |
| ------------------------------------------- | ------ | -------------------------- |
| <mark style="color:red;">\*</mark>          | String | account id in 0.0.x format |
| token\_id<mark style="color:red;">\*</mark> | String | token id in 0.0.x format   |

#### Query Parameters

| Name     | Type   | Description                         |
| -------- | ------ | ----------------------------------- |
| decimals | Number | Set the number of expected decimals |

{% tabs %}
{% tab title="200 Account balance response" %}

```
{
    "data": {
        "balance": "10000"
    }
}
```

{% endtab %}

{% tab title="401 Will ask to include a api-key, if invalid will return with "Unable to validate with the supplied 'x-api-key'"" %}

```
{
    "reason": "Please set \"x-api-key\" in your header"
}
```

{% endtab %}

{% tab title="500: Internal Server Error Known issue: Account ID is not valid" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

Perhaps you just want to know whether an account holds particular tokens, this could be helpful if you are a building service that requires one or many tokens (like NFTs) to be held to unlock access to particular feature of your service.

## Get Account Holdings

<mark style="color:blue;">`GET`</mark> `https://hedera-serverless-consensus.vercel.app/api/account/:id/holdings/:token_ids`

This endpoint allows you to know if a given account holds many different tokens or NFTS.

#### Path Parameters

| Name                                         | Type   | Description                          |
| -------------------------------------------- | ------ | ------------------------------------ |
| <mark style="color:red;">\*</mark>           | String | account id in 0.0.x format           |
| token\_ids<mark style="color:red;">\*</mark> | String | token id in 0.0.x,0.0.y,0.0.z format |

{% tabs %}
{% tab title="200 Account balance response" %}

```
{
    "data": {
        "balance": "10000"
    }
}
```

{% endtab %}

{% tab title="401 Will ask to include a api-key, if invalid will return with "Unable to validate with the supplied 'x-api-key'"" %}

```
{
    "reason": "Please set \"x-api-key\" in your header"
}
```

{% endtab %}

{% tab title="500: Internal Server Error Known issue: Account ID is not valid" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Topics

Manage topics for sending consensus messages to the client. You may create, update and read the information of a given topic.

## Topic routes

There are 3 routes that help to manage a given topic before sending consensus messages. The focus is that if you have a particular group of users or a particular app that you wish to have a separate topic to keep track of messages you can do so with different topics.

{% hint style="info" %}
Please note that currently the creation of new topics automatically set the admin key to be the public key of the account of the deployed client. This means that a topic may only be updated by that account, the memo can only be changed.
{% endhint %}

All routes required authentication through the **x-api-key** and a escaped JSON value can be injected into the memo to hold more information about the topic.

### Get topic info

Get the topic information using a supplied **topic\_id.**

{% content-ref url="/pages/-MFsyufjbKHattJT2q1R" %}
[Get topic info](/rest-api/topics/get-topic-info)
{% endcontent-ref %}

### Create new topic

Create a topic with 2 optional values, the **memo** or the **enable\_private\_submit\_key** which stops any other account to successfully sent a consensus message to the topic.

{% content-ref url="/pages/-MFsy\_ir6oZ2Xhl0a5yD" %}
[Creating a new topic](/rest-api/topics/creating-a-new-topic)
{% endcontent-ref %}

### Update a current topic

Update the memo of a given topic by providing a **memo** property to the body.

{% content-ref url="/pages/-MFsyii8WyB4WroP84He" %}
[Updating a topic](/rest-api/topics/updating-a-topic)
{% endcontent-ref %}


# Get topic info

Get the information for a given topic.

## Get topic information

<mark style="color:blue;">`GET`</mark> `https://hedera-serverless-consensus.vercel.app/api/consensus/topic/:id`

Get detailed topic information.  There is currently a development effort in checking that a topic exists before attempting to fetch a receipt.<br>

#### Path Parameters

| Name | Type   | Description         |
| ---- | ------ | ------------------- |
| id   | string | The id of the topic |

#### Headers

| Name      | Type   | Description                                                        |
| --------- | ------ | ------------------------------------------------------------------ |
| x-api-key | string | The value set as **API\_SECRET\_KEY** in the client's environment. |

{% tabs %}
{% tab title="200 Topic information received" %}

```
{
    "data": {
        "topicMemo": "topic memo information",
        "runningHash": {
           ...
        },
        "sequenceNumber": 0,
        "expirationTime": {
            "seconds": 1606715551,
            "nanos": 990716007
        },
        "adminKey": {
           ...
        },
        "submitKey": {
           ...
        },
        "autoRenewPeriod": 7890000,
        "autoRenewAccount": null
    }

```

{% endtab %}
{% endtabs %}


# Creating a new topic

Create a topic that automatically has a admin key set, only allowing for the serverless client to update them. You can a topic completely private for writes and updates and sending messages.

## Create new topic

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/consensus/topic/:id`

This endpoint will create a new topic that can be used to send messages to for a consensus timestamp. As this is an authenticated endpoint, **401** errors will be shown on incorrect authentication keys.

#### Query Parameters

| Name                         | Type    | Description                                                                                 |
| ---------------------------- | ------- | ------------------------------------------------------------------------------------------- |
| memo                         | string  | A memo that will be added to the topic, this can also be an escaped JSON string.            |
| enable\_private\_submit\_key | boolean | Make sure that consensus messages can only be sent from the account that created the topic. |

#### Headers

| Name      | Type   | Description                                                      |
| --------- | ------ | ---------------------------------------------------------------- |
| x-api-key | string | The **API\_SECRET\_KEY** that is set in the clients environment. |

{% tabs %}
{% tab title="200 Topic created with a memo." %}

```
{
    "data": {
        "memo": "topic memo information",
        "topic": "0.0.16091"
    }
}
```

{% endtab %}

{% tab title="422 This occurs if any of the variables are invalid for the API to process" %}

```
{
    "errors": [
        "\"enable_private_submit_key\" must be a boolean"
    ]
}
```

{% endtab %}
{% endtabs %}


# Updating a topic

Update a topic with a different memo that is more suitable for your use case.

## Update a topic

<mark style="color:orange;">`PUT`</mark> `https://hedera-serverless-consensus.vercel.app/api/consensus/topic/:id`

This endpoint allows you to update the memo of the topic, only from the original creator of the topic.

#### Path Parameters

| Name | Type   | Description          |
| ---- | ------ | -------------------- |
| id   | string | The id of the topic. |

#### Query Parameters

| Name | Type   | Description                                       |
| ---- | ------ | ------------------------------------------------- |
| memo | string | The memo that you want to update the topic id to. |

#### Headers

| Name           | Type   | Description                                                      |
| -------------- | ------ | ---------------------------------------------------------------- |
| Authentication | string | The **API\_SECRET\_KEY** from the  client environment variables. |

{% tabs %}
{% tab title="200 Cake successfully retrieved." %}

```
{
    "data": {
        "memo": "Updated memo",
        "topic_id": "16091",
        "accountId": {
            "shard": 0,
            "realm": 0,
            "account": 1156
        },
        "validStart": {
            "seconds": 1598827049,
            "nanos": 719000000
        }
    }
}
```

{% endtab %}
{% endtabs %}


# Consensus Messages

Send a consensus message to hedera through your API with the option of using webhooks for waiting synchronously for finality.

## Create new consensus message

<mark style="color:green;">`POST`</mark> `https://hedera-serverless-consensus.vercel.app/api/consensus/message/`

This endpoint allows you to send a message to a topic id, you may simply broadcast the message, or wait for consensus to be reached using **allow\_synchronous\_consensus.** \
\
If you are using testnet or mainnet environments there will be a **explorer\_url** property linking to an external hashgraph explorer for the given transaction.

#### Query Parameters

| Name                          | Type    | Description                                                                                    |
| ----------------------------- | ------- | ---------------------------------------------------------------------------------------------- |
| reference                     | string  | A reference to an internal app idenitier so that after the response it will be easier to link. |
| allow\_synchronous\_consensus | boolean | Wait for consensus to be finished to finality before receiving a response.                     |
| topic\_id                     | string  | The id of the topic you want to sent the message to.                                           |
| message                       | string  | The string message that is sent to received a consensus response.                              |

#### Headers

| Name           | Type   | Description                                                        |
| -------------- | ------ | ------------------------------------------------------------------ |
| Authentication | string | The **API\_SECRET\_KEY** from th e client's environment variables. |

{% tabs %}
{% tab title="200 New message sent to a topic, using a topic\_id and message." %}

```
{
    "data": {
        "reference": "my reference",
        "topic_id": "16091",
        "transaction_id": "0.0.1156@1598828456.197000000",
        "explorer_url": "https://ledger-testnet.hashlog.io/tx/0.0.1156@1598828456.197000000",
        "consensus_timestamp": {
            "seconds": 1598828466,
            "nanos": 501124002
        }
    }
```

{% endtab %}
{% endtabs %}

**WARNING**: if you have a **WEBHOOK\_URL** set in your client it is recommended that you **do not set** the **allow\_synchronous\_consensus** to false due to the implications of the NodeJS event loop with AWS Lambda.


# Balance

Get the current account balance of the client

## Get Account Balance

<mark style="color:blue;">`GET`</mark> `https://hedera-serverless-consensus.vercel.app/api/account/balance`

This endpoint allows you to get the account balance of the client

#### Headers

| Name      | Type   | Description                                                    |
| --------- | ------ | -------------------------------------------------------------- |
| x-api-key | string | The value set as API\_SECRET\_KEY in the client's environment. |

{% tabs %}
{% tab title="200 Account balance response" %}

```
{
    "data": {
        "balance": "10000"
    }
}
```

{% endtab %}

{% tab title="401 Will ask to include a api-key, if invalid will return with "Unable to validate with the supplied 'x-api-key'"" %}

```
{
    "reason": "Please set \"x-api-key\" in your header"
}
```

{% endtab %}
{% endtabs %}


# Status

Get the current status of the deployed client

## Get Status

<mark style="color:blue;">`GET`</mark> `https://hedera-serverless-consensus.vercel.app/api/status`

This endpoint allows you to get the current status of the client, this information can be hidden by setting **HIDE\_STATUS** in your environment variables.\
\
**Note:** The **authenticationKey** could return as false if it is shorter then 10 characters.

{% tabs %}
{% tab title="200 The current status of the deployed client." %}

```
{
    "message": "Your environment status for your client",
    "environment_status": {
        "hederaAccountId": true,
        "hederaPrivateKey": true,
        "authenticationKey": true
    },
    "meta": {
        "hint": "Hide this status endpoint by setting \"HIDE_STATUS=TRUE\" in your environment"
    }
}
```

{% endtab %}
{% endtabs %}


# Webhooks

Using webhooks provides a mechanism to be sent consensus responses from your client without having to wait for consensus. Currently in development.

## Using webhooks in the deployment

In your Vercel deployment set **WEBHOOK\_URL** to the **POST** route that you wish to send all messages and redeploy your API.

{% hint style="info" %}
Make sure that your **POST** route **\*\*responds with the status code of** 200.\*\*
{% endhint %}

## Proving the source of messages

The concern of webhooks combined with trust is proving that the message came from the correct source.

In the request there will be a header including an **x-signature** this will be a **HMAC hash** of the body and the **API\_SECRET\_KEY** using the SHA256 algorithm.

To trust the source of the message you'll need to match the signature by creating a hash of the body and **API\_SECRET\_KEY** in your server and comparing.

{% hint style="info" %}
Without verifying the signature at this step you cannot be sure that the message you received is valid. Otherwise anyone that knew your webhook route could fake a consensus response.
{% endhint %}

## Example Webhook implementation

We provide an example webhook implementation that you can copy for your needs, this is found in the [postman documentation](https://www.getpostman.com/collections/e61a0c42e7d572890996) and the[ implemented handler is on github](https://github.com/trustenterprises/hedera-serverless-consensus/blob/master/app/handler/exampleWebhookHandler.js) for inspiration.

The route of the webhook for the project is **/api/webhook.**

To conform your webhook to our standards and testing mechanism the behaviour is as follows.

* The webhook will only respond to a **POST** request
* The webhook requires a **x-signature** in its header, this is a **HMAC SHA256** signature.
* The webhook is a valid signature of the entire payload body.

If the incorrect HTTP method is used to request the webhook the status code will be **405 (Method Not Allowed).**

If the **x-signature** cannot be verified with the payload a status code **400 (Bad Request)** will be returned.


# Overview

Automatically capture the consensus trust timestamps in your local database, automatically using the webhook flow. Manage any trust process.

[This Laravel package](https://github.com/trustenterprises/laravel-hashgraph) allows SaaS builders to integrate with distributed ledger technology, Hedera Hashgraph, at minimal effort and cost.

It is effectively **proof of anything** packaged up, for free, and with no overhead.

There are 2 methods to configure this package.

If you are just getting started with Trust Enterprises and you will use Laravel, [we recommend that you use this link](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Ftrustenterprises%2Fhedera-serverless-api\&env=HEDERA_ACCOUNT_ID,HEDERA_PRIVATE_KEY,API_SECRET_KEY,HEDERA_NETWORK,WEBHOOK_URL\&envDescription=Enter%20your%20account%20id%20and%20private%20key%20from%20the%20hedera%20portal.%20The%20API%20secret%20is%20your%20authentication%20key%20to%20communicate%20with%20your%20API%2C%20create%20a%20secure%20string%20of%20at%20least%2010%20characters.\&envLink=https%3A%2F%2Fdocs.trust.enterprises%2Fdeployment%2Fenvironment-variables\&redirect-url=https%3A%2F%2Fdocs.trust.enterprises%2Frest-api%2Foverview), which includes the **WEBHOOK\_URL** configuration when initially creating your client.

Alternatively, adding the **WEBHOOK\_URL** as a new environment variable in your project settings. You will have to **redeploy your client for the changes to take effect.**

> If you are testing locally use ngrok or localhost.run to create a tunnel to your local app.

![](/files/-MJWz59tfKf5agybq1Az)

### A brief overview

A Laravel client library to automate adding webhooks, feeding the trust responses into your database automatically.

1. A fluent PHP API that communicates with the REST API.
2. Inbuilt database consensus table migrations that contain the bare bones of tables you need to have a stored log.&#x20;
3. The webhook flow will automatically store and validate all incoming consensus timestamp responses.
4. Custom events on insert events so that you may easily add additional logic if required.

## \*\*\*\*


# Installation

How to install and migrate the database.

## Installation:

The Laravel Package is hosted on [Packagist](https://packagist.org/packages/trustenterprises/hashgraph). Install as below.

```
composer require trustenterprises/hashgraph
```

### Requirements

* PHP 7.4
* Laravel 7.\*

This package will have releases that will support Laravel 5.8.\* projects, the version of Guzzle needed to be lowered to meet these requirements.

## Database migration

Run these commands in your terminal to publish and migrate your new tables.

```
php artisan vendor:publish --provider="Trustenterprises\LaravelHashgraph\LaravelHashgraphServiceProvider" --tag="migrations"
php artisan migrate
```

## Configuration

Publish your config file with this command.

```
php artisan vendor:publish --provider="Trustenterprises\LaravelHashgraph\LaravelHashgraphServiceProvider" --tag="config"
```

## Adding your Environment Variables

Update these environment variables in your **.env** file with your client URL and secret key.

* HASHGRAPH\_NODE\_URL
* HASHGRAPH\_SECRET\_KEY

Don't forget to reset your server to update the config.

## Updating the webhook route

By default the callback webhook route in the app ends with **/hashgraph** this can be changed by updating the **HASHGRAPH\_WEBHOOK\_ROUTE** in your Laravel App.


# Interacting with your client

How to get started with the laravel package.

## Recording a trust event

Events can only be recorded using a single private key, this is the default behaviour. This means that you and your users can Trust that the messages will only come from you, the owner of the hedera private key.&#x20;

If a **Topic** doesn't exist in your database one will be created before the consensus message is dispatched.

### Imports

```
use Trustenterprises\LaravelHashgraph\LaravelHashgraph;
use Trustenterprises\LaravelHashgraph\Models\ConsensusMessage;
```

### Code

The Consensus Message takes a **String** if you wish to use an object convert it first using **json\_encode.** We suggest that this code should be run in a Job as it uses the synchronous&#x20;

```
$message = new ConsensusMessage('This is an event you wish to store');
$message->setReference('an-internal-model-id'); // optional

LaravelHashgraph::withTopic('Trust Enterprises')->sendMessage($message);
```

## Extending behaviour with event listenters

There are 2 events that can be listened to:

* ConsensusMessageWasReceived&#x20;
* TopicWasCreated

Have a look at the [Laravel offical docs for events](https://laravel.com/docs/8.x/events) for creating your own listenters for events.

�


# Create a Marketplace

The backbone for a permissioned marketplace for you to mint tokens, create accounts, and to send  to your users after purchase.

## Overview

Understand that decentralisation is hard, many people don't have experience to use blockchain applications to use apps like [Metamask](https://metamask.io/) and others. The role of this API and client is for you to build&#x20;

{% hint style="warning" %}
I'm going to assume that you know Laravel, creating of tables to link users to generated accounts. As we move forward there will be updates but for now this will be simple.
{% endhint %}

## Creating an account

Create and connect a hedera account to a user you have in your system, I would suggest either adding a new field on your **users** table or creating a new **hedera\_accounts** table for a one-to-many relationship.

In this case I am using a simple approach that a user can only have one hedera account, thus three new fields have been added to a user migration.

* encrypted\_key
* public\_key
* hedera\_id

### Imports

```
use Trustenterprises\LaravelHashgraph\LaravelHashgraph;
use Trustenterprises\LaravelHashgraph\Models\AccountCreateResponse;
```

### Code

```
$account = LaravelHashgraph::createAccount(); // Returns AccountCreateResponse

// Get the Authorised user from a controller.
$user = \Auth::user();

// Update the fields of the user.
$user->encrypted_id = $account->getEncryptedKey();
$user->public_key = $account->getPublicKey();
$user->hedera_id = $account->getAccountId();

// Persist to storage.
$user->save();
```

## Creating a token

Create a token that can be sent to a user's account after an event or a purchase.

{% hint style="info" %}
Recommend that you create a new table to hold the details of a minted token. Use the returned **tokenId** at the primary key.
{% endhint %}

### Imports

```
use Trustenterprises\LaravelHashgraph\LaravelHashgraph;
use Trustenterprises\LaravelHashgraph\Models\FungibleTokenResponse;
use Trustenterprises\LaravelHashgraph\Models\FungibleToken;
```

### Code

```
// The base token object.
$fungible_token = new FungibleToken('MATT', 'MATTHEW', 10, 'This is a memo');

// The response from hedera, via the API
$token = LaravelHashgraph::mintFungibleToken($fungible_token);

// Store this id against the details of the above object.
$token->getTokenId();
```

## Bequesting a token

Bequesting or sending a token to an account that has been generated, and linked to a user in your local database. This bypasses hedera's default association behaviour.

This is the magic element that provides a **permissioned marketplace**, the ability to send tokens of any asset to a user from any event.&#x20;

### Imports

```
use Trustenterprises\LaravelHashgraph\LaravelHashgraph;
use Trustenterprises\LaravelHashgraph\Models\BequestToken;
use Trustenterprises\LaravelHashgraph\Models\BequestTokenResponse;
```

### Code

```
// Assume the user and token from the previous steps.
$token_id = $token->getTokenId();

$encrypted_key = $user->encrypted_key;
$public_key = $user->public_key;
$hedera_id = $user->hedera_id;

$amount = 1;

// The object to bequest tokens to an account
$bequest = new BequestToken($encrypted_key, $token_id, $hedera_id, $amount);

// The response from hedera, to send tokens
$response = LaravelHashgraph::bequestToken($bequest);

// This transaction id can be tracked on a hedera explorer such as dragonglass.
$response->getTransactionId();

```


# Manage your Inscription Flow

The Laravel client provides the programmatic ability to manage the entire lifecycle of inscriptions, for deployments, minting, burning, and transferring.

This provides inscription capibility for PHP, you can view the tests where appropriate but the features mirror the inscription API for:

* deploying
* minting
* burning
* transferring

Every response through the Inscription methods will return a **InscriptionResponse** object that includes the raw inscription data and related consensus message ids for storage.

{% hint style="warning" %}
This feature is considered to be in an **Alpha** state, and that any code may change at anytime. We may additionally update this documentation to reflect the updated standards for dealing with this meta-protocol.

Have fun!
{% endhint %}

These examples consider a **private topic as a points system on testnet.** If you don't set the private topic on mainnet it will default to the default HCS-20 topic

## Deploying an Inscription

### Imports

```
use Trustenterprises\LaravelHashgraph\LaravelHashgraph;
use Trustenterprises\LaravelHashgraph\Models\Inscriptions\BurnInscription;
use Trustenterprises\LaravelHashgraph\Models\Inscriptions\DeployInscription;
use Trustenterprises\LaravelHashgraph\Models\Inscriptions\MintInscription;
use Trustenterprises\LaravelHashgraph\Models\Inscriptions\TransferInscription;
```

### Code

```
$deploy = new DeployInscription('TICK1', 'Ticker', 300);
$deploy->setPrivateTopic("7459744");

$minted = LaravelHashgraph::deployInscription($deploy);

```

## Mint an Inscription

### Code

```
$mint = new MintInscription('TICK1', '0.0.1', 1);
$mint->setPrivateTopic("7459744");

$minted = LaravelHashgraph::mintInscription($mint);
```

## Burn an Inscription

### Code

```
$burn = new BurnInscription('TICK1', '0.0.1', 1);
$burn->setPrivateTopic("7459744");

$minted = LaravelHashgraph::burnInscription($burn);
```

## Transfer an Inscription

### Code

```
$transfer = new TransferInscription('TICK1', '0.0.1', '0.0.2', 1);
$transfer->setPrivateTopic("7459744");

$minted = LaravelHashgraph::transferInscription($transfer);
```


# Checking account balances and sending tokens

In this flow, we are going to describe the process of checking an account balance and sending tokens to a hedera id. There are a number of applications of this including systems for access tokens and

## Overview

This process of sending tokens to an external account isn't permissioned, that is any hedera wallet can register with a system, and you can use these actions.

{% hint style="warning" %}
Under Hedera's APIs, sending of tokens requires an association of a given token, at this time we are focused on using the [Venly Wallet (Widget)](https://docs.venly.io/widget/) which provides 25 free associations for tokens per wallet.
{% endhint %}

## Check a token balance

Check a hedera token balance for any account, this focused on HTS tokens such that if you need to check the balance for access to a service or to gauge an account share of a staking pool.

{% hint style="info" %}
&#x20;Infrastructure testing needs to be conducted for high-volume account balance requests.
{% endhint %}

### Imports

```
use Trustenterprises\LaravelHashgraph\LaravelHashgraph;
use Trustenterprises\LaravelHashgraph\Models\AccountTokenBalanceResponse;
```

### Code

```
$account_id = '0.0.15657776'; // A venly-created account on testnet
$token_id = '0.0.15657534'; // Token already created

$token_balance = LaravelHashgraph::getTokenBalance($account_id, $token_id);

// Token value in whole numbers, ignoring the "decimals places" of a created token.
$token_balance->getAmount(); 
```

## Send a token to an account

Send a token to a hedera account, expects a SendToken object to be created at the payload. The response will tell you if the transfer succeeded or not, if the latter an error can be used.

This assumes that the token you are sending has been created with the mint token methods of the API/client and has custody over them.

{% hint style="info" %}
This method waits for the finality of the transfer transaction, thus you will receive an error that a transfer has failed that will describe the issue, if an originator account does not have enough balance to make the transfer or if there is an association error.

Expect the response to be between 2-3 seconds, jobs should be used.
{% endhint %}

### Imports

```
use Trustenterprises\LaravelHashgraph\LaravelHashgraph;
use Trustenterprises\LaravelHashgraph\Models\SendToken;
use Trustenterprises\LaravelHashgraph\Models\SendTokenResponse;
```

### Code

```
// Pre-generated Venly wallet (testnet) (maxes out at 25 assocs)
$account_id = '0.0.15657776'; // A venly-created account on testnet
$token_id = '0.0.15657534'; // Token already created
$amount = 0.000001;

$send_token = new SendToken($token_id, $account_id, $amount);
$token_sent = LaravelHashgraph::sendToken($send_token);

if ($token_sent->hasTransferSucceeded()) {
    // Continue action.
} else {
    $token_sent->getError();
}
```


# Local Development


# Architecture Rationale

The internal structure we used to build the API and why.

The architecture is more or less custom as the API layer on a NextJS app is very thin, it focuses on using simple **handlers** for processing API requests.

All API requests hit the `pages/api` directory, are processed by a defined set of middleware, then if successfully forwarded to a given handler.

You can consider `app/handlers` to effectively be invokable single function controllers.

The validation for a given handler is expected to be tightly coupled to the code, as it is simpler to test a handler in isolation.

As the Hedera Hashgraph costs a small amount of real money, we have created a mock that is injected into the handlers during the basic set of tests to prove additional logic for the API query and body parameters.

All other items that validate and inject into a handler do so at the API route layer. We use a `process` function to chain a list of middleware, authentication validation, and context injection before hitting in the handler. Providing a higher degree of flexible testability.

Due to the constraints of Vercel only providing a maximum of 12 unique routes for a free account, this can be slightly overcome through leveraging a routing to handler approach.

The topic handler `pages/api/consensus/topic/[id].js` provides additional insight into how to wrap a single route to manage a given resource consisting of different handlers.

Thank you to [James Wrightson](https://github.com/guerrillacontra) for your insight on handling injecting additional functionality as **context** for a given handler.


# Contributing Guidelines

Contributions are **welcome** and will be fully **credited**.

Please read and understand the contribution guide before creating an issue or pull request.

### Etiquette

This project is open source, and as such, the maintainers give their free time to build and maintain the source code held within. They make the code freely available in the hope that it will be of use to other developers. It would be extremely unfair for them to suffer abuse or anger for their hard work.

Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the world that developers are civilized and selfless people.

It's the duty of the maintainer to ensure that all submissions to the project are of sufficient quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.

### Viability

When requesting or submitting new features, first consider whether it might be useful to others. Open source projects are used by many developers, who may have entirely different needs to your own. Think about whether or not your feature is likely to be used by other users of the project.

### Procedure

Before filing an issue:

* Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
* Check to make sure your feature suggestion isn't already present within the project.
* Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
* Check the pull requests tab to ensure that the feature isn't already in progress.

Before submitting a pull request:

* Check the codebase to ensure that your feature doesn't already exist.
* Check the pull requests to ensure that another person hasn't already submitted the feature or fix.

### Requirements

If the project maintainer has any additional requirements, you will find them listed here.

* **Add tests!** - Your patch won't be accepted if it doesn't have tests.
* **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
* **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
* **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
* **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.

**Happy coding**!


# Changelog

See the various releases and changelogs for the projects below:

* [Hedera Serverless Consensus REST API](https://github.com/trustenterprises/hedera-serverless-consensus/releases)
* [Laravel Hashgraph](https://github.com/trustenterprises/laravel-hashgraph/blob/master/CHANGELOG.md%29)


