RAMP Webhook Informations
Interfaces are required for integration between the developer's server and the RAMP platform server.
1. RAMP F/E URL
To mint or burn tokens in the dApp, the RAMP F/E page must be loaded.
Access via the following URL pattern:
https://ramp.crosstoken.io/exchange?uuid={{uuid}}&accessToken={USERACCESSTOKEN}&sessionId={USERSESSIONID}&network=testnet
Parameters
| Parameter | Description |
|---|---|
uuid | Unique identifier generated for token minting and burning. See Request UUID. |
accessToken | Token used for requests from RAMP to the dApp server. The dApp server must validate this token. |
sessionId | User’s session or account identifier. |
network | Target network (e.g., testnet, mainnet). |
2. Request UUID
Retrieve the UUID required to open the RAMP F/E Webview from the application (dApp).
The generated UUID is valid for only 5 minutes.
Endpoint
POST https://cross-ramp-api.crosstoken.io/api/v2/initialize
Request Headers
| Field Name | Description |
|---|---|
Content-Type | application/json |
X-HMAC-SIGNATURE | HMAC signature value. |
Request Body
| Field Name | Type | Description | Required |
|---|---|---|---|
| Basic Info | |||
| player_id | string | Unique Player ID in the game | N |
| name | string | Character Name | N |
| wallet_address | string | Player Wallet Address | N |
| server | string | Game Server Identifier accessed by the player | N |
| intent | |||
| intent | object | Token Mint/Burn Information | Y |
| intent.network | string | Network (mainnet, testnet) | Y |
| intent.project_id | string | CROSS RAMP Project ID | Y |
| intent.token | string | Token Contract Address | Y |
| intent.mint_fee_bps | number | Mint Fee (bps based, 100 = 1%) | Y |
| intent.burn_fee_bps | number | Burn Fee (bps based)0 fixed | Y |
| intent.mint_method | string | Contract method name used for Token Mintmint fixed | Y |
| intent.burn_method | string | Contract method name used for Token Burnburn-permit fixed | Y |
| intent.materials[] | |||
| intent.materials | array | Game currency information used during Token Minting | Y |
| intent.materials[].id | string | Item ID | Y |
| intent.materials[].amount | number | Amount of items consumed | Y |
| intent.materials[].icon_url | string | Item Icon Image URL | Y |
| intent.materials[].is_non_fungible | boolean | NFT Status (true = NFT, false = FT) | Y |
| intent.outputs[] | |||
| intent.outputs | array | Game currency information provided during Token Burn | Y |
| intent.outputs[].id | string | Item ID | Y |
| intent.outputs[].amount | number | Amount of items provided | Y |
| intent.outputs[].icon_url | string | Item Icon Image URL | Y |
| intent.outputs[].is_non_fungible | boolean | NFT Status (true = NFT, false = FT) | Y |
Request Sample
POST https://cross-ramp-api.crosstoken.io/api/v2/initialize
Content-Type: application/json
X-HMAC-SIGNATURE: {{HMAC-SIGNATURE-VALUE}}
{
"player_id": "player_id_01",
"name": "character_name_01",
"wallet_address": "0xwalletaddresss",
"server": "server_01",
"intent": {
"network": "testnet",
"project_id": "79bc87b18d7941caee2fb2f5226d1736",
"token": "0xFFF6dCEa241a974283C0ECEea8ED81b478062AF1",
"mint_fee_bps": 2000,
"burn_fee_bps": 0,
"mint_method": "mint",
"burn_method": "burn-permit",
"materials": [
{
"id": "item_gold",
"amount": 100,
"icon_url": "https://console-contents.crosstoken.io/studios/projects/assets/019ac48c-ed97-7a09-be8e-2fdb499e3c11.png",
"is_non_fungible": false
}
],
"outputs": [
{
"id": "item_gold",
"amount": 80,
"icon_url": "https://console-contents.crosstoken.io/studios/projects/assets/019ac48c-ed97-7a09-be8e-2fdb499e3c11.png",
"is_non_fungible": false
}
]
}
}Response
| Field Name | Type | Description |
|---|---|---|
| data.uuid | string | UUID used to load the RAMP F/E page in the application (dApp). The generated UUID is valid for only 5 minutes. |
Response Sample
{
"code": 200,
"message": "OK",
"data": {
"uuid": "9cf3a7e5-7d2c-4ef3-ba6f-911d5078416b"
}
}Failure Response Samples
Case 1: 'X-HMAC-Signature' is missing
{
"code": 400,
"message": "Bad Request",
"data": "X-HMAC-Signature is required"
}Case 2: Invalid HMAC Signature
{
"code": 500,
"message": "Internal Server Error",
"data": "invalid mac"
}Case 3: 'Project ID' is missing
{
"code": 500,
"message": "Internal Server Error",
"data": "ramp not found"
}Case 4: Invalid 'network'
{
"code": 500,
"message": "Internal Server Error",
"data": "ramp not exists"
}3. Developer Server APIs (Webhooks)
The following APIs must be implemented on the developer's server and registered in the CROSS-RAMP Console.
3.1 User Game Asset Inquiry API
RAMP B/E requests user asset information to display on the RAMP F/E page.
The developer server must verify the X-Dapp-Authorization (accessToken) header.
When RAMP B/E calls the Game Asset Inquiry API, it transmits the accessToken and sessionId contained in the query parameters of the RAMP F/E URL loaded for token issuance or burning within the game, including them in the Request Header.
Therefore, the developer server must verify the accessToken and return an appropriate Response based on the verification result.
Requests will be made to the Get Assets Endpoint configured in the CROSS-RAMP Console project.

Request Headers
RAMP B/E requests user asset information from the Endpoint implemented by the developer.
| Field Name | Description |
|---|---|
X-Dapp-Authorization | accessToken generated by the developer's server. Uses the accessToken value added to the Query when loading RAMP F/E. |
X-Dapp-SessionID | Character identification ID of the user managed by the developer. Uses the sessionId value added to the Query when loading RAMP F/E. |
Request Sample
GET /api/assets
Host: https://your-server.com
Content-Type: application/json
X-Dapp-Authorization: Bearer {{accessToken}}
X-Dapp-SessionID: {{sessionId}}Response Fields
| Field Name | Type | Description | Required |
|---|---|---|---|
| success | boolean | Request success status | Y |
| errorCode | string | Error code (null if successful) | Y |
| data | object | Response data (null if failed) | Y |
| data.v1 | object | API version 1 data | Y |
| data.v1.player_id | string | User character unique ID | N |
| data.v1.name | string | User character name | N |
| data.v1.wallet_address | string | User wallet address | N |
| data.v1.server | string | User character connection server info | N |
| data.v1.assets | array | List of game assets held by the user | Y |
| data.v1.assets[].id | string | Game asset unique identifierThe ‘Game Asset ID’ is used when minting and burning tokens through the CROSS-RAMP platform; therefore, it is recommended to manage it as a game asset–related environment variable on the game server. | Y |
| data.v1.assets[].balance | string | Quantity of game assets held by the userThe quantity of assets held by the user in the game must be entered. | Y |
Response Sample
Success Response (200 OK)
{
"success": true,
"errorCode": null,
"data": {
"v1": {
"player_id": "player_id",
"name": "player_name",
"wallet_address": "0x62c5...6707",
"server": "test",
"assets": [
{
"id": "item_gold",
"balance": "1000.123"
}
]
}
}
}
3. 2 User Signature Verification Query API
Important
Developers must verify the game asset values included in the Request parameters requested by RAMP B/E.
In the token issuance process, implementation of an API is required to verify whether the user's signature value matches the transaction request data sent by the developer.
To verify data integrity, data signed with HMAC-SHA256 generated in the CROSS-RAMP Console is included in the Request Header.
Therefore, the developer server must use the HMAC value from the CROSS-RAMP Console to verify integrity.

A response is required after verifying whether the user's token issuance/burning request violates the developer's policy (authentication, game asset quantity, etc.).
Requests will be made to the Validate Order Endpoint configured in the CROSS-RAMP Console project.

Request Headers
| Field Name | Description |
|---|---|
| X-HMAC-SIGNATURE | HMAC signed value of Request Raw Data using the HMAC-Key generated in the RAMP Console. |
| X-Dapp-Authorization | accessToken generated by the developer's server. Uses the accessToken value added to the Query when loading RAMP F/E. |
| X-Dapp-SessionID | Character identification ID of the user managed by the developer. Uses the sessionId value added to the Query when loading RAMP F/E. |
Request Body
| Field Name | Type | Description | Required |
|---|---|---|---|
| user_sig | string | Data signed through CROSSx for user's token issuance/burning. | Y |
| user_address | string | User's CROSSx address | Y |
| project_id | string | Project ID generated in RAMP Console | Y |
| digest | string | Hash digest of transaction data The original text to be signed using the Validator Key generated by the developer. | Y |
| uuid | string | Request Unique Identifier | Y |
| intent | object | Token Issuance/Burning Information This is the game asset information used during token minting and burning, and the game server must verify whether the quantity requested by the user is valid. | Y |
| intent.method | string | Execution Method (mint, burn) | Y |
| intent.type | string | Transaction Type (assemble, disassemble)
| Y |
| intent.from | array | List of source asset information | Y |
| intent.from[].type | string | Asset Type (asset, ERC20)
| Y |
| intent.from[].id | string | Game asset ID registered in CROSS-RAMP Console. | Y |
| intent.from[].amount | number | Quantity of game assets used for token issuance | Y |
| intent.to | array | List of target asset information | Y |
| intent.to[].type | string | Asset Type (ERC20, NFT) | Y |
| intent.to[].id | string | Token Contract Address | Y |
| intent.to[].amount | number | Quantity of tokens to issue | Y |
| intent.target_candidate | object | Target candidate information (additional option) | N |
Request sample
POST /api/validate
Host: https://your-server.com
Content-Type: application/json
x-dapp-authorization: Bearer {{accessToken}}
x-dapp-sessionid: {{sessionId}}
x-hmac-signature: {{hmac_signature}}
{
"user_sig": "0x58ea88cc20a571d2bc4f4a7ab687158e1924887c005a8a2ccce9a7c8f669adbb222932f9e760b923b6f359870169d58a171d47516ee71167313d5068dbd84c631c",
"user_address": "0x6de346a7333d97fe0d39a49178ac65918c257b28",
"project_id": "3a4----------------------2d7",
"digest": "0x6d196d0881bb8e322c194fbf53518089b240055134044491a78b14920098e395",
"uuid": "86b555dd-e622-43fe-a799-c5c4536dd8c6",
"intent": {
"method": "mint",
"type": "assemble",
"from": [
{
"type": "asset",
"id": "item_gold",
"amount": 100
}
],
"to": [
{
"type": "ERC20",
"id": "0x14f6f0057274c3519d6258EB66F5d01D79821D81",
"amount": 1
}
],
"target_candidate": {}
}
}POST /api/validate
Host: https://your-server.com
Content-Type: application/json
x-dapp-authorization: Bearer {{accessToken}}
x-dapp-sessionid: {{sessionId}}
x-hmac-signature: {{hmac_signature}}
{
"user_sig": "0xb1378a978b5e77d750c44d4b9bdf4d883d2e2bad8e09c8928e8d83176359cc9376a959c3576c82f2214c9fece66c73417669bf667734ec8f94880885c5d1b82a1c",
"user_address": "0x6de346a7333d97fe0d39a49178ac65918c257b28",
"project_id": "3a4f5838f7cdfe31873a43ca021a92d7",
"digest": "0x7bd721630a8c7e6b1c1050934fc3bf69cadaef0253c46f92f1b03242c5f2e733",
"uuid": "d7360515-8547-427e-acb5-6556c8376fd4",
"intent": {
"method": "burn-permit",
"type": "disassemble",
"from": [
{
"type": "ERC20",
"id": "0x14f6f0057274c3519d6258EB66F5d01D79821D81",
"amount": 1
}
],
"to": [
{
"type": "asset",
"id": "item_gold",
"amount": 50
}
],
"target_candidate": {}
}
}Response Fields
| Field Name | Type | Description | Required |
|---|---|---|---|
| success | boolean | Request success status | Y |
| errorCode | string | Error code (null if successful) | Y |
| data | object | Response data (null if failed) | |
| data.userSig | string | Data signed by the user through CROSSx for token issuance/burning. | Y |
| data.validatorSig | string | Data signed with ECDSA using the Validator Key generated by the developer. The Validator Key's address must be registered in the CROSS-RAMP Console. | Y |
Response Sample
{
"success": true,
"errorCode": null,
"data": {
"userSig": "0x58ea88cc20a571d2bc4f4a7ab687158e1924887c005a8a2ccce9a7c8f669adbb222932f9e760b923b6f359870169d58a171d47516ee71167313d5068dbd84c631c",
"validatorSig": "0xfd7c12023378170c615bdd63be3e7aa195ff98b42fe84dad34348017fc1050db157e077dd5053328040b476479edebfe5d773bb8602de6bc088951de7b597fd31b"
}
}3.3 User Token Issuance / Burning Result API
Transmits the blockchain transaction result for the user's token issuance/burning request to the game server via Webhook.
The transaction result is delivered to the Endpoint registered in the CROSS-RAMP Console, and the developer server must respond with an HTTP status value of 200 after receiving the result.

If RAMP B/E does not receive a response or receives an HTTP 500 code, RAMP B/E will attempt to resend.
An HTTP 200 code must be returned for normal processing.
Retry Information
After the first Webhook delivery attempt, up to 20 retries are attempted over 12 hours.
- 2 attempts at 5-minute intervals
- 7 attempts at 15-minute intervals
- 10 attempts at 60-minute intervals
Request Body
If receipt.status is not 0x1, the transaction request on the blockchain network has failed, so game currency must be restored.
| Field Name | Type | Description |
|---|---|---|
| session_id | string | Session identifier managed by the client or server |
| uuid | string (UUID) | Unique identifier for a single request |
| tx_hash | string | Blockchain transaction hash It is recommended to retain this information for the purpose of querying blockchain transaction results. |
| receipt | object | Transaction execution receipt object |
| receipt.type | string | Transaction type (EIP-1559 or chain-specific custom type) (0x7: gas fee sponsored) |
| receipt.root | string | State root (usually empty) |
| receipt.status | string | Transaction execution status ( 0x1 : success, 0x0 : failure) |
| receipt.cumulativeGasUsed | string | Cumulative gas used in the block |
| receipt.logsBloom | string | Bloom filter for event logs |
| receipt.logs | array | Array of event logs generated during the transaction |
| receipt.logs[].address | string | Contract address that emitted the event |
| receipt.logs[].topics | string[] | Event signature and indexed parameters |
| receipt.logs[].data | string | Non-indexed event data |
| receipt.logs[].blockNumber | string | Block number in which the event was included |
| receipt.logs[].transactionHash | string | Transaction hash containing the event |
| receipt.logs[].transactionIndex | string | Transaction index within the block |
| receipt.logs[].blockHash | string | Block hash containing the event |
| receipt.logs[].blockTimestamp | number | Block timestamp (0 on some chains) |
| receipt.logs[].logIndex | string | Event index within the transaction |
| receipt.logs[].removed | boolean | Whether the event was removed due to chain reorganization |
| receipt.transactionHash | string | Transaction hash |
| receipt.contractAddress | string | Contract address created by the transaction (0x0 for non-creation TXs) |
| receipt.gasUsed | string | Actual gas used by this transaction |
| receipt.effectiveGasPrice | string | Effective gas price applied |
| receipt.blockHash | string | Block hash containing the transaction |
| receipt.blockNumber | string | Block number containing the transaction |
| receipt.transactionIndex | string | Transaction index within the block |
| intent | object | In-game token minting / burning information |
| intent.method | string | Executed method ( mint for minting, burn-permit for burning) |
| intent.type | string | Processing type within Ramp ( assemble for minting, disassemble for burning) |
| intent.from | array | Consumed assets |
| intent.from[].type | string | Consumed asset type (e.g., asset) |
| intent.from[].id | string | Consumed asset identifier (e.g., game item ID) |
| intent.from[].amount | number | Amount of asset consumed |
| intent.to | array | Minted tokens |
| intent.to[].type | string | Minted token type (e.g., ERC20) |
| intent.to[].id | string | Minted token contract address |
| intent.to[].amount | number | Amount of tokens minted |
| intent.target_candidate | object | Target candidate information (currently empty) |
| intent.fee_rate | number | Fee rate in basis points (bps), e.g. 2000 = 20% |
| intent.actual | string | Net amount of tokens received after fees |
Request Sample
POST /api/result
Host: https://your-server.com
Content-Type: application/json
x-dapp-authorization: Bearer {{accessToken}}
x-dapp-sessionid: {USER_UNIQUE_ID}
x-hmac-signature: {{hmac_signature}}
{
"session_id": "{USER_UNIQUE_ID}",
"uuid": "26e7ee8f-008d-4337-8e26-a7a061361785",
"tx_hash": "0x685d9a05d5d280ff707610876691f3a9ee32319cec46a47a5d785dd4dca207a8",
"receipt": {
"type": "0x7",
"root": "0x",
"status": "0x1",
"cumulativeGasUsed": "0x1f531",
"logsBloom": "0x00000000080040000000200000000000000000000000000000000000000000000000010000000000008000044000000000000000000008000000000000000000000000100000000002000008000000000000000000000000000000000000000000000000020000000000001000000800000040000000000000000010000400000002000000000000000000000000000000000000000000040000000000100000000008000800040000000000000000000000000000100000000000100000000000000002000000000000000000000000000002000000000000000000000020000080002000000000000000000000000000000000000000000800000004000000",
"logs": [
{
"address": "0xe9fae10bb4d5b69d967147f78d100d7799274579",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x000000000000000000000000a18eee8f2afa2c7c591b404636b4ba4ad3b3d310"
],
"data": "0x0000000000000000000000000000000000000000000000000b1a2bc2ec500000",
"blockNumber": "0x11655a0",
"transactionHash": "0x685d9a05d5d280ff707610876691f3a9ee32319cec46a47a5d785dd4dca207a8",
"transactionIndex": "0x0",
"blockHash": "0x865bed1d085e0136f4d04eee86e59c6fa6288d73c216635cce847b2580803e61",
"blockTimestamp": 0,
"logIndex": "0x0",
"removed": false
},
{
"address": "0x7189d67b9ded72e9f1dcfce1c23ea3af418f4a57",
"topics": [
"0x9612604afba70e4cf03261d7d86ca03d08911d9887aa41621dea929e34cfd7b1",
"0x3464386436306431323364313037373531656132306438356264363937663562",
"0x40d4e653d95cae3c09647722b3cfe396be67488fa4b711157bad4bd55ed0e11c",
"0x000000000000000000000000a18eee8f2afa2c7c591b404636b4ba4ad3b3d310"
],
"data": "0x000000000000000000000000e9fae10bb4d5b69d967147f78d100d77992745790000000000000000000000000000000000000000000000000de0b6b3a7640000",
"blockNumber": "0x11655a0",
"transactionHash": "0x685d9a05d5d280ff707610876691f3a9ee32319cec46a47a5d785dd4dca207a8",
"transactionIndex": "0x0",
"blockHash": "0x865bed1d085e0136f4d04eee86e59c6fa6288d73c216635cce847b2580803e61",
"blockTimestamp": 0,
"logIndex": "0x2",
"removed": false
}
],
"transactionHash": "0x685d9a05d5d280ff707610876691f3a9ee32319cec46a47a5d785dd4dca207a8",
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x1f531",
"effectiveGasPrice": "0xee6b2800",
"blockHash": "0x865bed1d085e0136f4d04eee86e59c6fa6288d73c216635cce847b2580803e61",
"blockNumber": "0x11655a0",
"transactionIndex": "0x0"
},
"intent": {
"method": "mint",
"type": "assemble",
"from": [
{
"type": "asset",
"id": "item_gold",
"amount": 100
}
],
"to": [
{
"type": "ERC20",
"id": "0xe9fae10bb4D5b69d967147f78d100D7799274579",
"amount": 1
}
],
"target_candidate": {},
"fee_rate": 2000,
"actual": "0.8"
}
}Response Field
| Field Name | Type | Description | Required |
|---|---|---|---|
success | boolean | Request success status | Y |
errorCode | string | Error code (null if successful) | Y |
data | object | Response data |
response sample
POST /api/result
Host: https://your-server.com
Content-Type: application/json
{
"success": true,
"errorCode": null,
"data": null
}4. HMAC Signature and Validator Signature Samples
HMAC Signature Sample
import { ethers } from "ethers";
/**
* generateValidatorSignature
*
* Signs the given digest using the validator's private key.
* The digest must be a 32-byte hash (e.g. "0xabc123...").
*
* @param {string} userSig - (optional) user's signature
* @param {string} digest - 32-byte digest to sign
* @returns {Promise<{ success: boolean, signature?: string, error?: string }>}
*/
export async function generateValidatorSignature(userSig, digest) {
try {
// Load validator private key (from env or default)
const privateKey =
process.env.VALIDATOR_PRIVATE_KEY;
// Create an Ethers.js Wallet instance
const wallet = new ethers.Wallet(privateKey);
// Convert digest (hex) to byte array
const digestBytes = ethers.getBytes(digest);
// Sign the digest (must be 32 bytes)
const rawSignature = await wallet.signingKey.sign(digestBytes);
// Serialize signature (r + s + v)
const signature = ethers.Signature.from(rawSignature).serialized;
// Return success response
return {
success: true,
signature,
};
} catch (error) {
console.error("Error generating validator signature:", error);
// Return failure response
return {
success: false,
error: error.message,
};
}
}