Marketplace API
Quick start

Quick start#

Using Order API to create a listing#

In this guide, we will show you how to create a listing on OKX or OpenSea. This endpoint only supports one platform in a single request. This process includes:

  • Set up the necessary environment
  • Build header to create listing requests and hit the create-listing endpoint and get the data. The main purpose is to get the order information and signKind
  • Create a signature with the order data
  • Create submit listing request and hit the submit listing endpoint and get the success message

1. Set up the necessary environment#

For the necessary environment, refer to Import necessary Node.js libraries

2. Build header to create listing requests and hit the create-listing endpoint and get the data#

Step 1: Build header Params. For all other reusable variables, refer to Set up your environment variables

const requestUrl = 'https://www.okx.com/api/v5/mktplace/nft/markets/create-listing';
const chain = 'eth'; // we will use ethereum as example
const platform = 'okx'; // the platform you want to list on, for opensea use 'opensea'

const originalMessage = JSON.stringify({
    chain: chain,
    walletAddress: walletAddress,
    items:[
        {
            collectionAddress: '0x175edb154ed7a0e54410a7f547aaa7e3fbf21a34',  // the collection of nft you want to list
            tokenId: '3518',  // the token id of the nft from the collection
            price: '100000000000000',
            currencyAddress: '0x0000000000000000000000000000000000000000',  // ethereum main net token address
            count: 1,      // number of NFT
            validTime:1701760147,  // listing expire time
            platform: platform  // support opensea or okx only
        }
    ]
});

const headersParams = {
  'Content-Type': 'application/json',
  'OK-ACCESS-KEY': apiKey,
  'OK-ACCESS-SIGN': cryptoJS.enc.Base64.stringify(
    cryptoJS.HmacSHA256(timestamp + 'POST' + '/api/v5/mktplace/nft/markets/create-listing' + originalMessage , secretKey)
  ),
  'OK-ACCESS-TIMESTAMP': timestamp,
  'OK-ACCESS-PASSPHRASE': passphrase,
};

Step 2: Use the headersParam and originalMessage as the body and request the create-listing endpoint

return fetch(requestUrl, {method: 'post',headers: headersParams,body: originalMessage}).then((res) => res.json()).then((res) => {return JSON.stringify(res);});

When you do this request, you will get a large payload of data. The main purpose of this is to get the order data below, which can then be used for submitting listings on OKX or OpenSea. Step 3: Pull the order data from the response in Step 1 and assign it to a variable

const contractMessage = {
    conduitKey: '0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000',
    consideration: [
    {
        endAmount: '87500000000000',
        identifierOrCriteria: '0',
        itemType: 0,
        recipient: '0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf',
        startAmount: '87500000000000',
        token: '0x0000000000000000000000000000000000000000'
    },
    {
        endAmount: '10000000000000',
        identifierOrCriteria: '0',
        itemType: 0,
        recipient: '0x93162ca0806ec2876b7ec12002596e40549c3e02',
        startAmount: '10000000000000',
        token: '0x0000000000000000000000000000000000000000'
    },
    {
        endAmount: '2500000000000',
        identifierOrCriteria: '0',
        itemType: 0,
        recipient: '0x0000a26b00c1f0df003000390027140000faa719',
        startAmount: '2500000000000',
        token: '0x0000000000000000000000000000000000000000'
    }
    ],
    counter: '948892694796415917080870615203989852295',
    endTime: 1701760147,
    offer: [
    {
        endAmount: '1',
        identifierOrCriteria: '3518',
        itemType: 2,
        startAmount: '1',
        token: '0x175edb154ed7a0e54410a7f547aaa7e3fbf21a34'
    }
    ],
    offerer: '0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf',
    orderType: 0,
    salt: '0x0000000000000000000000000000000000000000000000003d0609f530d9214f',
    startTime: 1701185619,
    totalOriginalConsiderationItems: 3,
    zone: '0x0000000000000000000000000000000000000000',
    zoneHash: '0x0000000000000000000000000000000000000000000000000000000000000000'
}

3. Create a signature with the order data#

Step 1: Gather listing information such as type data, domain data from Part 2 Step 2.

const jsonMessage = JSON.stringify({
    domain: {
      // Defining the chain aka testnet or Ethereum Main Net
      chainId: 1, // 1 for mainnet
      // Give a user friendly name to the specific contract you are signing for.
      name: "Seaport",
      // If name isn't enough add verifying contract to make sure you are establishing contracts with the proper entity
      verifyingContract: "0x00000000000000adc04c56bf30ac9d3c0aaf14dc",
      // Just let's you know the latest version. Definitely make sure the field name is correct.
      version: "1.5",
    },

    // Defining the message signing data content.
    message: contractMessage,
    // Refers to the keys of the *types* object below.
    primaryType: "OrderComponents",
    types: {
        ConsiderationItem: [
            { name: 'itemType', type: 'uint8' },
            { name: 'token', type: 'address' },
            { name: 'identifierOrCriteria', type: 'uint256' },
            { name: 'startAmount', type: 'uint256' },
            { name: 'endAmount', type: 'uint256' },
            { name: 'recipient', type: 'address' }
          ],
          OrderComponents: [
            { name: 'offerer', type: 'address' },
            { name: 'zone', type: 'address' },
            { name: 'offer', type: 'OfferItem[]' },
            { name: 'consideration', type: 'ConsiderationItem[]' },
            { name: 'orderType', type: 'uint8' },
            { name: 'startTime', type: 'uint256' },
            { name: 'endTime', type: 'uint256' },
            { name: 'zoneHash', type: 'bytes32' },
            { name: 'salt', type: 'uint256' },
            { name: 'conduitKey', type: 'bytes32' },
            { name: 'counter', type: 'uint256' }
          ],
          EIP712Domain: [
            { name: 'name', type: 'string' },
            { name: 'version', type: 'string' },
            { name: 'chainId', type: 'uint256' },
            { name: 'verifyingContract', type: 'address' }
          ],
          OfferItem: [
            { name: 'itemType', type: 'uint8' },
            { name: 'token', type: 'address' },
            { name: 'identifierOrCriteria', type: 'uint256' },
            { name: 'startAmount', type: 'uint256' },
            { name: 'endAmount', type: 'uint256' }
          ]
    },
  });

Step 2: Sign the listing request using your private key. Note: You can use other tools to help you generate signatures using eth_signTypedData_v4 method.

// here we will use okx wallet utils with your private key and the message to do a signature
const param = {
    privateKey: privateKey,
    data: {
      type: 4,
      message: jsonMessage
    }
  };

return wallet.signMessage(param).then(res => console.log(res)); // here you will get a hex signature

After that, you will get a signature that is based on the listing and the wallet address which you will use in the next step.

4. Create submit-listing request with the signature and order data and hit the /submit-listing endpoint and get the success message#

Step 1: Grab the data from contractMessage and put it in the payload with order as the key and contractMessage as the value. Replace the signature and the wallet address and form your submitted listing request.

const submitListingBody = JSON.stringify({
    chain: "eth",
    walletAddress: '0xa03bb8d...dds'; // this is your wallet address
    items: [
        {
            platform: "opensea",
            signature: "0xf41ef.....9acc727631b", // signature returned #from Create a signature with the order data. Step 2
            order: {  // put the contractMessage data here
                conduitKey: "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
                consideration: [
                    {
                        endAmount: "1",
                        identifierOrCriteria: "5313",
                        itemType: 2,
                        recipient: "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
                        startAmount: "1",
                        token: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
                    }
                ],
                counter: "948892694796415917080870615203989852295",
                endTime: 1703301107,
                offer: [
                    {
                        endAmount: "1000000",
                        identifierOrCriteria: "0",
                        itemType: 1,
                        startAmount: "1000000",
                        token: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
                    }
                ],
                offerer: "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
                orderType: 0,
                salt: "0x0000000000000000000000000000000000000000000000002baea915c4bcf7be",
                startTime: 1700709107,
                totalOriginalConsiderationItems: 1,
                zone: "0x0000000000000000000000000000000000000000",
                zoneHash: "0x0000000000000000000000000000000000000000000000000000000000000000"
            }
        }
    ]
}

Step 2: Build a new header for the new request

const submitListingRequestUrl = 'https://www.okx.com/api/v5/mktplace/nft/markets/submit-listing'; // new endpoint for submitting listing
const submitListingTimestamp = date.toISOString();
const submitListingHeadersParams = {
  'Content-Type': 'application/json',
  'OK-ACCESS-KEY': apiKey,
  'OK-ACCESS-SIGN': cryptoJS.enc.Base64.stringify(
    cryptoJS.HmacSHA256(submitListingTimestamp + 'POST' + '/api/v5/mktplace/nft/markets/submit-listing' + submitListingBody, secretKey)
  ),
  'OK-ACCESS-TIMESTAMP': submitListingTimestamp,
  'OK-ACCESS-PASSPHRASE': passphrase,
};

Step 3: Do the post request to /submit-listing endpoint

return fetch(requestUrl, {method: 'post', headers: submitListingHeadersParams, body: submitListingBody}).then((res) => res.json()).then((res) => {return res;});

Then, at the end, you should see this message with success equals true.

{
    "code": 0,
    "data": {
        "results": [
            {
                "message": "",
                "order": {
                    "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
                    "consideration": [
                        {
                            "endAmount": "1",
                            "identifierOrCriteria": "5313",
                            "itemType": 2,
                            "recipient": "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
                            "startAmount": "1",
                            "token": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
                        }
                    ],
                    "counter": "948892694796415917080870615203989852295",
                    "endTime": 1703301107,
                    "offer": [
                        {
                            "endAmount": "1000000",
                            "identifierOrCriteria": "0",
                            "itemType": 1,
                            "startAmount": "1000000",
                            "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
                        }
                    ],
                    "offerer": "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
                    "orderType": 0,
                    "salt": "0x0000000000000000000000000000000000000000000000002baea915c4bcf7be",
                    "startTime": 1700709107,
                    "totalOriginalConsiderationItems": 1,
                    "zone": "0x0000000000000000000000000000000000000000",
                    "zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
                },
                "platform": "okx",
                "signature": "0xf41ef8e......c4a9acc727631b",
                "success": true
            }
        ]
    },
    "msg": ""
}