Getting started

Covering the basics from authentication to buying and selling an item using the Market-API.

What we cover in this guide

In this guide, we will explain how to authenticate to our API service, create your sub-users, buy an item from the market, and sell an item on the market.

We will walk you through several endpoints to help you get started. We will cover the following topics:

  1. How to authenticate
  2. How to create a sub-user
  3. How to create sub-user's deposit address
  4. Deposit funds to sub-user's address
  5. How to buy an offer
  6. Check status of the fulfillment
  7. How to put an item on sale

Prerequisites

  1. You need a Venly business account, if you don't have one, click here to register in our Developer Portal, or follow our step-by-step guide, Getting Started with Venly.
  2. You need an active trial or paid subscription of the Market-API. You can start a 30-day free trial for the Market-API as shown below.
  3. You need your Client ID and Client Secret which can be obtained from the Portal as shown below.
Starting a trial subscription and obtaining a Client ID and Client Secret

Starting a trial subscription and obtaining a Client ID and Client Secret

📘

All the API calls for this guide run on a sandbox environment. You can test and experiment with API calls without causing any harm to the actual blockchain or data.

There are several ways to run API calls, but for this guide, you can use the API-Reference or Postman to execute the different endpoints.

1. Authenticating

To obtain a bearer token and authorize all API calls, you will need your Client ID and Client Secret. These credentials are necessary for authentication purposes.

📘

Click here to learn how to retrieve a bearer token and authenticate API calls.

Please note that the base path for all Market API endpoints is https://api-sandbox.venly.market

2. Create a Sub-User

Request Endpoint: reference

 POST /users

Request Body:

ParameterDescriptionTypeRequired
typeIndicates the type of user you want to create. For now we allow the type: SUB_USERString
nicknameA nickname to identify your sub-userString
{
  "type": "SUB_USER",
  "nickname": "Moon"
}

Response Body:

📘

Save the result.id from the response body. This is the sub-user's ID.

{
  "success": true,
  "result": {
    "id": "6eb26b77-268d-4772-a788-21b09e099df3",
    "nickname": "Moon via Anonymous",
    "type": "SUB_USER",
    "parentUserId": "cc16bf97-cb64-45d4-8096-b16c20db790c"
  }
}

3. Create a Sub-User's Deposit Address

Request Endpoint: reference

 POST /users/{userId}/deposit-addresses

Request Body:

ParameterDescriptionTypeRequired
chainThe blockchain on which on you want to create a deposit address for your SUB_USERString
{
  "chain": "MATIC"
}

Response Body:

📘

Save the result.address from the response body. This is the sub-user's deposit address, and will be used to transfer some USDC balance in the next step.

{
  "success": true,
  "result": {
    "userId": "6eb26b77-268d-4772-a788-21b09e099df3",
    "chain": "MATIC",
    "address": "0x5d336ee19afabfcb77706760dcf86886b0af1f8c"
  }
}

3. Deposit Funds to sub-users address

You can deposit funds from your Market account. If you don't have one, click here to visit Market and create an account.

Withdraw funds to sub-users deposit address

Withdraw funds to sub-users deposit address

4. Buy an Offer

Request Endpoint: reference

 POST /fulfillments

Request Body:

ParameterDescriptionTypeRequired
typeThe blockchain on which on you want to create a deposit address for your SUB_USERString
offerIdThis is the ID of the offer that is to be purchasedString
userIdThis is the ID of the user who wants to purchase an offerString
wallletAddressThis is the user's wallet addressString
amountThis is the amount of offer that the user want to purchaseInteger
{
  "type": "PURCHASE",
  "offerId": "90f1cce7-ae3f-4d54-a11a-e10dccdd0cce",
  "userId": "6eb26b77-268d-4772-a788-21b09e099df3",
  "walletAddress": "0x722c4b8649d54ae2feb9697b178cb37c955d6b48",
  "amount": 1
}

Response Body:

📘

In the response body, the result.status is QUEUED which means the transaction of the NFT item is still in process. In the next step we will check the fulfillment status again.

{
  "success": true,
  "result": {
    "id": "98a3b3ba-5603-4a2f-a701-a1eaa00cf7fb",
    "type": "PURCHASE",
    "offerId": "90f1cce7-ae3f-4d54-a11a-e10dccdd0cce",
    "amount": 1,
    "status": "QUEUED",
    "creationDate": "2023-10-23T10:43:07.808536659",
    "pricePerItem": 1,
    "buyer": {
      "id": "6eb26b77-268d-4772-a788-21b09e099df3",
      "nickname": "Moon via Anonymous"
    },
    "buyerWalletAddress": "0x722c4b8649d54ae2feb9697b178cb37c955d6b48"
  }
}

5. Check the Status of the Fulfillment

Request Endpoint: reference

 GET /fulfillments/{id}

Response Body:

📘

The result.status has been updated to COMPLETED which means the NFT item has been successfully transferred to the sub-user's wallet. If it shows as PROCESSING that means the transaction is still in progress. So you can try running this endpoint again after some time.

{
  "success": true,
  "result": {
    "id": "98a3b3ba-5603-4a2f-a701-a1eaa00cf7fb",
    "type": "PURCHASE",
    "offerId": "90f1cce7-ae3f-4d54-a11a-e10dccdd0cce",
    "amount": 1,
    "status": "COMPLETED",
    "creationDate": "2023-10-23T10:43:07.808537",
    "pricePerItem": 1,
    "buyer": {
      "id": "6eb26b77-268d-4772-a788-21b09e099df3",
      "nickname": "Moon via Anonymous"
    },
    "buyerWalletAddress": "0x722c4b8649d54ae2feb9697b178cb37c955d6b48"
  }
}

6. Put an Item on Sale

Request Endpoint: reference

 POST /offers

Request Body:

ParameterDescriptionTypeRequired
nftThis object includes the information of the NFT that is being put on saleString
nft.tokenIdThe tokenID of the NFTString
nft.addressThe address of the NFTString
nft.chainThe blockchain of the NFTString
startDateThe start date of your sale offer in ISO 8601 formatString
endDateThe end date of your sale offer in ISO 8601 formatString
typeThe type of offer. In this case it is SALEString
currencyThe currency in which you want to sell your offer. Currently we only support USDCString
sellerIdThe ID of the sellerString
sellerAddressThe wallet address of the seller and where the NFT is currently heldString
visibilityIndicator to put the offer as public or privateString
minimumBidThe minimum bid allowed for the offerInteger
buyNowPriceThe price of your offer if someone wants to instantly buy it without biddingInteger
priceThe actual price of your offerInteger
{
  "nft": {
    "tokenId": "6",
    "address": "0xb00e62813579d22f143dc194a6377433ad1b2032",
    "chain": "MATIC"
  },
  "startDate": "2023-10-24T10:44:03.331Z",
  "endDate": "2023-10-27T10:44:03.331Z",
  "type": "SALE",
  "currency": "USDC",
  "sellerId": "6eb26b77-268d-4772-a788-21b09e099df3",
  "sellerAddress": "0x722c4b8649d54ae2feb9697b178cb37c955d6b48",
  "visibility": "PUBLIC",
  "minimumBid": 1,
  "buyNowPrice": 1.5,
  "price": 1
}

Response Body:

📘

Once created, you will receive an Offer with result.status as NEW.

{
  "success": true,
  "result": {
    "id": "99aa8976-972c-4598-9cce-052947424aa0",
    "nft": {
      "id": "6",
      "address": "0xb00e62813579d22f143dc194a6377433ad1b2032",
      "chain": "MATIC",
      "name": "Heartseeker",
      "description": "The perfect weapon choice when looking to perforate your enemies heart.",
      "imageUrl": "https://cdn.simplehash.com/assets/dd4ce378d8314210e41c093126354b16d0bfaaf20097654611421999a2ab6494.png",
      "imagePreviewUrl": "https://lh3.googleusercontent.com/slNQUIJPzYvsMcg04JvHiRm_Wq8J0bIrehrx28n0avgD9p9s3Xt9_biVa11kZ4DxQfr8h5SzFcIVe5OlNm4tL1vIx4JDwu-WGyo",
      "imageThumbnailUrl": "https://lh3.googleusercontent.com/slNQUIJPzYvsMcg04JvHiRm_Wq8J0bIrehrx28n0avgD9p9s3Xt9_biVa11kZ4DxQfr8h5SzFcIVe5OlNm4tL1vIx4JDwu-WGyo=s250",
      "animationUrls": [],
      "fungible": true,
      "attributes": [
        {
          "type": "property",
          "name": "Rarity",
          "value": "Common"
        },
        {
          "type": "property",
          "name": "Minecraft item",
          "value": "Sword"
        },
        {
          "type": "property",
          "name": "GTAV item",
          "value": "Assault rifle"
        }
      ],
      "contract": {
        "chain": "MATIC",
        "address": "0xb00e62813579d22f143dc194a6377433ad1b2032",
        "count": 0,
        "imageUrl": "https://lh3.googleusercontent.com/0j-L-f-q6UV4RQn7QXYNBy32EzhthOK7lJNzWldVw_zYpXehgQFquIycEZwJvYw0O8G0DQs4fyXAFEcqjcOUFG4eAbDzzq6NLiGS",
        "media": [
          {
            "type": "image",
            "value": "https://lh3.googleusercontent.com/0j-L-f-q6UV4RQn7QXYNBy32EzhthOK7lJNzWldVw_zYpXehgQFquIycEZwJvYw0O8G0DQs4fyXAFEcqjcOUFG4eAbDzzq6NLiGS"
          }
        ],
        "verified": false,
        "premium": false,
        "categories": []
      },
      "collectionIdentifier": "15025743-748f-479d-87d5-10ae3c9436f3"
    },
    "sellerId": "6eb26b77-268d-4772-a788-21b09e099df3",
    "sellerNickname": "Moon via Anonymous",
    "sellerAddress": "0x722c4b8649d54ae2feb9697b178cb37c955d6b48",
    "startDate": "2023-10-24T10:44:03.331Z",
    "endDate": "2023-10-27T10:44:03.331Z",
    "type": "SALE",
    "status": "NEW",
    "dataToSign": "99aa8976-972c-4598-9cce-052947424aa0_0x722c4b8649d54ae2feb9697b178cb37c955d6b48_0x3acF8B1F74a4Dd9e6f1EA5e76ea24D46E401610c_6",
    "createdOn": "2023-10-23T10:54:41.231749459Z",
    "createdBy": "cc16bf97-cb64-45d4-8096-b16c20db790c",
    "modifiedOn": "2023-10-23T10:54:41.231749459Z",
    "modifiedBy": "cc16bf97-cb64-45d4-8096-b16c20db790c",
    "signed": false,
    "currency": "USDC",
    "seller": {
      "id": "6eb26b77-268d-4772-a788-21b09e099df3",
      "nickname": "Moon via Anonymous"
    },
    "amountPurchased": 0,
    "amountReimbursed": 0,
    "amountTerminated": 0,
    "visibility": "PUBLIC",
    "price": 1,
    "amount": 1,
    "remainingAmount": 1,
    "minBuyAmount": 1
  }
}

👍

Congrats! You have successfully placed an item on sale.