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
Property | Description |
---|---|
recipient_address | The wallet address of the user that has initialised the quote. |
products | An 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
Property | Description |
---|---|
products | An 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. |
totals | An 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
Property | Description |
---|---|
recipient_address | The wallet address of the user that has initialised the quote. |
currency | The currency used for payment on this transaction. |
products | An 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
Property | Description |
---|---|
reference | Unique identifier for this order (max length 32 characters). |
currency | Confirms the ERC20 symbol used for payment on this transaction. |
products | Flat 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_id | Item identifier, same as the one sent on the request. |
collection_address | Address of the ERC721 collection this item belongs to. |
contract_type | ERC721 or ERC1155 depending of the collection contract type |
detail | An 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
Property | Description |
---|---|
reference | Unique identifier for this order that was returned as a response of the sale authorisation endpoint. |
tx_hash | Transaction hash of the sale. |
recipient_address | The wallet address of the user that has initialised this sale. |
contract_address | The Primary Sales contract address. |
order | An 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
Property | Description |
---|---|
200 | Processed successfully |
400 | Error with the request |
404 | Products don't exist or stock is not sufficient |
429 | Rate limited |
500 | System 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.