Skip to main content

Webhooks (Advanced sale)

The Primary Sales Widget requires a few different webhooks to be available in your backend. This section describes the request payloads we'll send and the expected responses.


Sample code

A sample implementation of these webhook endpoints can be found below:

Sample Primary Sales Webhook Implementation

Webhook authentication

Every webhook has its own api_key parameter associated to it. We'll pass this key within the Authorization header on every request.

Example confirmation request headers

curl --location 'CONFIRMATION_URL' \
--request POST
--header 'Content-Type: application/json' \
--header 'Authorization: CONFIRMATION_API_KEY' \
--data '{ ... }'

Quote endpoint

Method: POST

Before going through with a sale, the Primary Sales Widget needs to know how much an order may cost to the end user. This should include every currency supported in your store.

Request

Example request

{
"recipient_address": "0xdd9AAE1C317eE6EFEb0F3DB0A068e9Ed952a6CEB",
"products": [
{
"product_id": "P001",
"quantity": 1
},
{
"product_id": "P002",
"quantity": 3
}
]
}

Field request description

PropertyDescription
recipient_addressThe wallet address of the user that has initialised the quote.
productsAn array with all the requested products as part of this quote, along with their quantites.

Response

Example response

{
"products": [
{
"product_id": "P001",
"quantity": 1,
"pricing": [
{
"currency": "USDC",
"currency_type": "crypto",
"amount": 20
},
{
"currency": "ETH",
"currency_type": "crypto",
"amount": 0.00002
},
{
"currency": "USD",
"currency_type": "fiat",
"amount": 20
}
]
},
{
"product_id": "P002",
"quantity": 3,
"pricing": [
{
"currency": "USDC",
"currency_type": "crypto",
"amount": 30
},
{
"currency": "ETH",
"currency_type": "crypto",
"amount": 0.00003
}
{
"currency": "USD",
"currency_type": "fiat",
"amount": 30
}
]
}
],
"totals": [
{
"currency": "USDC",
"currency_type": "crypto",
"amount": 50
},
{
"currency": "ETH",
"currency_type": "crypto",
"amount": 0.00005
},
{
"currency": "USD",
"currency_type": "fiat",
"amount": 50
}
]
}

Field response description

PropertyDescription
productsAn array containing individual product cost breakdown, with the price for the request quantities.

In this example, product P002 has a price of 10 USD, 10 USDC, and 0.0001 ETH per item. Since the request specifies a quantity of 3, we multiply each pricing by 3 to come to the values returned in the request.
totalsAn array with all the sum of all product amount in each currency.

The total ETH for both prodcuts are 0.0005, so we will return ETH as 0.0005, and do the same addition with USDC and USD.

Sale authorisation endpoint

Method: POST

Every sale needs to be authorised by your Game Backend. Once an order is initialised, we’ll make a request to the sale authorisation webhook expecting confirmation for each sale item. The stock should be reserved in the game backend until expiry is reached.

Request

Example request

{
"recipient_address": "0xdd9AAE1C317eE6EFEb0F3DB0A068e9Ed952a6CEB",
"currency": "USDC",
"products": [
{
"product_id": "P001",
"quantity": 1
},
{
"product_id": "P002",
"quantity": 3
}
]
}

Field request description

PropertyDescription
recipient_addressThe wallet address of the user that has initialised the quote.
currencyThe currency used for payment on this transaction.
productsAn array with all the requested products as part of this quote, along with their quantites.

Response

Example response

{
"reference": "O00001",
"currency": "USDC",
"products": [
{
"product_id": "P0001",
"collection_address": "0xd27746683cCF357ED5190D248Cf0468a3dA28Ea8",
"contract_type": "ERC721",
"detail": [
{
"token_id": "0001",
"amount": 20
}
]
},
{
"product_id": "P0002",
"collection_address": "0xd27746683cCF357ED5190D248Cf0468a3dA28Ea8",
"contract_type": "ERC721",
"detail": [
{
"token_id": "0002",
"amount": 10
},
{
"token_id": "0003",
"amount": 10
},
{
"token_id": "0004",
"amount": 10
}
]
}
]
}

Field response description

PropertyDescription
referenceUnique identifier for this order (max length 32 characters).
currencyConfirms the ERC20 symbol used for payment on this transaction.
productsFlat list of each item that should be minted. If the same product_id was requested at quantities greater than one, we expect one line item for each individual token.
product_idItem identifier, same as the one sent on the request.
collection_addressAddress of the ERC721 collection this item belongs to.
contract_typeERC721 or ERC1155 depending of the collection contract type
detailAn array containing a list of objects with token ID and amount.

Token ID: Token ID generated by your service for this specific mint. The token should have all the metadata associated with the item populated.
Amount: The price of each token.

Since the ordered quantity of product P002 is 3 with a price of 10 USDC each, the response will contain 3 items in the array, each with an amount of 10 and individually generated token IDs.

Sale confirmation endpoint

Method: POST

When a sale transaction is finalised, we will send a confirmation to your game backend.

While the request contains a lot of data, as a game, you can pick and choose which data is relevant to you. As an example, you can use the reference field to link the sale to the order and mark it as completed and ignore the rest of the request fields.

The following diagram illustrates a successful sale that leads to a confirmation.

Request

Example request

{
"reference": "O00001",
"tx_hash": "0xd35a13da51e2f14c24ac7f8243c6e550ff990ddb3e0a555dee00997557d62245",
"recipient_address": "0xdd9AAE1C317eE6EFEb0F3DB0A068e9Ed952a6CEB",
"order": {
"contract_address": "0x1EC1677154305d94A2a69C091565AfA5d8690bC2",
"total_amount": 50,
"deadline": 1713864739,
"created_at": 1713863839302,
"currency": "USDC",
"products": [
{
"product_id": "P0001",
"collection_address": "0xd27746683cCF357ED5190D248Cf0468a3dA28Ea8",
"contract_type": "ERC721",
"quantity": 1,
"detail": [
{
"token_id": "0001",
"amount": 20
}
]
},
{
"product_id": "P0002",
"collection_address": "0xd27746683cCF357ED5190D248Cf0468a3dA28Ea8",
"contract_type": "ERC721",
"quantity": 3,
"detail": [
{
"token_id": "0002",
"amount": 10
},
{
"token_id": "0003",
"amount": 10
},
{
"token_id": "0004",
"amount": 10
}
]
}
]
}
}

Field request description

PropertyDescription
referenceUnique identifier for this order that was returned as a response of the sale authorisation endpoint.
tx_hashTransaction hash of the sale.
recipient_addressThe wallet address of the user that has initialised this sale.
contract_addressThe Primary Sales contract address.
orderAn object containing the order details. This is basically what was returned from the sale authorisation endpoint. This can be ignored if your backend doesn't require this data.

total_amount: The total amount of the order in the specified currency.
deadline: Order expiry deadline in unix epoch. This is generated from the configured value in Hub.
created_at: Timestamp order was created at.
currency: Currency order is transacted in.

Expired orders endpoint

Method: POST

If a transaction is not executed before its defined expiry time, your service will be notified to release the inventory back to stock.

The following diagram illustrates an abandoned sale that leads to an expired order.

Request

Example request

{
"reference": "O00001"
}

Status code - Success and errors

PropertyDescription
200Processed successfully
400Error with the request
404Products don't exist or stock is not sufficient
429Rate limited
500System error

Once you have these API's implemented within your own Game backend - Stock management system, you can add them to the Configuration tab in Hub - Primary Sales.