Skip to main content

Guide: How to set up a credentials issuer

This article details the steps to set up a Credentials Issuer, create your credentials schema, and issue the first credentials.


Firstly, you will need to install Docker via the provided link. Running the app with Docker allows for minimal installation and a quick setup. Then, you will need to clone the repository or download it manually.

git clone -b v1.0.0

After cloning the repository, you should do the following:

  1. Generate an Ethereum keypair for the Issuer Node. It will be used to sign state transitions on the Rarimo chain.


    Currently, there is no network fee for the state transition transactions. To prevent network abuse, we maintain an allowlist of identity issuers. Contact us in Discord and provide the corresponding Ethereum address to get added to the allowlist.

  2. In the folder you've cloned rename .env-api.example to .env-api, .env-ui.example to .env-ui and .env-issuer.example to .env-issuer.

    • .env-api is used to configure the api-ui. This file allows the user to configure the basic auth of the api-ui, the server URL, and others.
    • .env-ui is used to configure the api-ui. This file allows the user to configure the basic auth of the Issuer UI, the server URL, and others.
    • .env-issuer is used to configure the api-issuer. It contains the needed configuration to start the node, such as the infrastructure configuration (postgres/redis/vault), the blockchain variables to be able to publish the state, the Basic Auth variables, and other variables.
  3. In the .env-issuer file, you need to set the variable ISSUER_ETHEREUM_URL to a Rarimo RPC endpoint.

  1. Run sudo make build in the cloned folder
  2. Run sudo make private_key=YOUR_ETHEREUM_PRIVATE_KEY run-all with the issuer's private key.
  3. Check that localhost:3001 (Issuer API) and localhost:3002 (Issuer UI) are available.

How to create credential schemas

If you need to create your own Credentials Schemas (some of the schemas can be found here) you can use either Polygon ID Schema Builder (recommended option) or you can write it by yourself and import it, using Issuer UI API.

Creating a schema with Polygon ID Schema Builder

To create the schema using Polygon ID Builder, follow these steps:

  1. Enter the title, type, version, and description of your schema
  2. Define the attributes. Let's add the date of birth and the full name for this example.
  3. After clicking on Add button, a new attribute will appear, and you need to change its name, title, type, and description and set the checkbox, whether it is required or not
  4. You can also set additional restrictions by clicking on the Advanced button
  5. After you've finished, you can copy it from the right window or download it by pressing on the Download JSON button below the properties
  6. Publish it somewhere (e.g., on GitHub or IPFS) and paste the link into url field at the Import JSON schema in the Issuer UI API. You should also copy the type, title, description, and version from the posted schema

Issuing credentials

Once the issuer is ready, we can issue our first credentials.

Using the issuer UI

  1. The Issuer is also an identity, so we need to create one. To do that, open localhost:3001 and select Create Identity in the left sidebar.
  2. Fill in the method, blockchain, and network fields. The method field is required. We will use the method iden3 without specifying blockchain and network. We will also create an identity for the user so we can issue credentials to him.
  3. We can issue our first claim after creating both identities (or receiving the user's identity from him). To do that, press the Create Claim button and paste the Issuer identifier (our first generated ID) and user's ID in the id field below:
  4. We can check our claim using the Get Claim endpoint:
  5. The last thing we need to do is publish the state of our issuer on-chain
  6. Now, we can send to the user MTP of Claim inclusion in the tree, using Get Claim MTP

Issuing via API

API documentation can be found in apy.yaml.

Follow these steps:

  1. Let's issue credentials to the previously created identity:

    • the authorization field is Base64 encoded username and password
    • we will change the id (receiver's did), birthday and expiration fields
    curl -X POST "http://localhost:3002/v1/credentials" \
    -H "accept: application/json"\
    -H "authorization: Basic dXNlci1hcGk6cGFzc3dvcmQtYXBp"\
    -H "content-type: application/json" \
    -d '{
    "credentialSchema": "",
    "type": "KYCAgeCredential",
    "birthday": 20000101,
    "documentType": 2
    "expiration": "2023-10-27T10:56:42.618Z",
    "signatureProof": true,
    "mtProof": true }'

    The response would be the credentials ID:

    "id": "b326c436-6f58-11ee-8dab-0242ac120007"
  2. After credentials are issued, we can publish our issuer's identity state on-chain:

    curl -X POST "http://localhost:3002/v1/state/publish" \
    -H "accept: application/json"\
    -H "authorization: Basic dXNlci1hcGk6cGFzc3dvcmQtYXBp"

    The response would be the new state, new tree roots and the txID:

    "claimsTreeRoot": "c8d09a3e4fc89ce6407ac96ea6e007b68cdd2e853b945c5f9baf70af3faf0510",
    "revocationTreeRoot": "0000000000000000000000000000000000000000000000000000000000000000",
    "rootOfRoots": "2c2db5c1ef764b48ca0cdf186208f7de940114b1c42061a89d3851beeb956c28",
    "state": "6f511e29380a28bb47cbc628ae6b20a1df2169c3cfec46fef07bc5c7ab3e6819",
    "txID": "0xbde3732071c9947d43a46175e47b6604b924e273ce86898f76ff621b6e48691b"
  3. Finally, we can make a request to the Issuer API and check that credentials exist in the tree and also receive the MTP of existence:

     curl -X GET "http://localhost:3001/v1/claims/b326c436-6f58-11ee-8dab-0242ac120007/mtp" \
    -H "accept: application/json"

    The response would be the information about the issuer and MTP (of existence in our case):

    "issuer": {
    "claimTreeRoot": "c8d09a3e4fc89ce6407ac96ea6e007b68cdd2e853b945c5f9baf70af3faf0510",
    "revocationTreeRoot": "0000000000000000000000000000000000000000000000000000000000000000",
    "rootOfRoots": "2c2db5c1ef764b48ca0cdf186208f7de940114b1c42061a89d3851beeb956c28",
    "state": "6f511e29380a28bb47cbc628ae6b20a1df2169c3cfec46fef07bc5c7ab3e6819"
    "mtp": {
    "existence": true,
    "siblings": [