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

ParameterDescription
uuidUnique identifier generated for token minting and burning. See Request UUID.
accessTokenToken used for requests from RAMP to the dApp server. The dApp server must validate this token.
sessionIdUser’s session or account identifier.
networkTarget 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 NameDescription
Content-Typeapplication/json
X-HMAC-SIGNATUREHMAC signature value.

Request Body

Field NameTypeDescriptionRequired
Basic Info
player_idstringUnique Player ID in the gameN
namestringCharacter NameN
wallet_addressstringPlayer Wallet AddressN
serverstringGame Server Identifier accessed by the playerN
intent
intentobjectToken Mint/Burn InformationY
intent.networkstringNetwork (mainnet, testnet)Y
intent.project_idstringCROSS RAMP Project IDY
intent.tokenstringToken Contract AddressY
intent.mint_fee_bpsnumberMint Fee (bps based, 100 = 1%)Y
intent.burn_fee_bpsnumberBurn Fee (bps based)
0 fixed
Y
intent.mint_methodstringContract method name used for Token Mint
mint fixed
Y
intent.burn_methodstringContract method name used for Token Burn
burn-permit fixed
Y
intent.materials[]
intent.materialsarrayGame currency information used during Token MintingY
intent.materials[].idstringItem IDY
intent.materials[].amountnumberAmount of items consumedY
intent.materials[].icon_urlstringItem Icon Image URLY
intent.materials[].is_non_fungiblebooleanNFT Status (true = NFT, false = FT)Y
intent.outputs[]
intent.outputsarrayGame currency information provided during Token BurnY
intent.outputs[].idstringItem IDY
intent.outputs[].amountnumberAmount of items providedY
intent.outputs[].icon_urlstringItem Icon Image URLY
intent.outputs[].is_non_fungiblebooleanNFT 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 NameTypeDescription
data.uuidstringUUID 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 NameDescription
X-Dapp-AuthorizationaccessToken generated by the developer's server.
Uses the accessToken value added to the Query when loading RAMP F/E.
X-Dapp-SessionIDCharacter 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 NameTypeDescriptionRequired
successbooleanRequest success statusY
errorCodestringError code (null if successful)Y
dataobjectResponse data (null if failed)Y
data.v1objectAPI version 1 dataY
data.v1.player_idstringUser character unique IDN
data.v1.namestringUser character nameN
data.v1.wallet_addressstringUser wallet addressN
data.v1.serverstringUser character connection server infoN
data.v1.assetsarrayList of game assets held by the userY
data.v1.assets[].idstringGame asset unique identifier

The ‘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[].balancestringQuantity of game assets held by the user

The 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 NameDescription
X-HMAC-SIGNATUREHMAC signed value of Request Raw Data using the HMAC-Key generated in the RAMP Console.
X-Dapp-AuthorizationaccessToken generated by the developer's server.
Uses the accessToken value added to the Query when loading RAMP F/E.
X-Dapp-SessionIDCharacter 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 NameTypeDescriptionRequired
user_sigstringData signed through CROSSx for user's token issuance/burning.Y
user_addressstringUser's CROSSx addressY
project_idstringProject ID generated in RAMP ConsoleY
digeststringHash digest of transaction data
The original text to be signed using the Validator Key generated by the developer.
Y
uuidstringRequest Unique IdentifierY
intentobjectToken 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.methodstringExecution Method (mint, burn)Y
intent.typestringTransaction Type (assemble, disassemble)
  • assemble : Token Issuance
  • disassemble : Token Burning
Y
intent.fromarrayList of source asset informationY
intent.from[].typestringAsset Type (asset, ERC20)
  • asset : Game Asset
  • ERC20 : Game Token
Y
intent.from[].idstringGame asset ID registered in CROSS-RAMP Console.Y
intent.from[].amountnumberQuantity of game assets used for token issuanceY
intent.toarrayList of target asset informationY
intent.to[].typestringAsset Type (ERC20, NFT)Y
intent.to[].idstringToken Contract AddressY
intent.to[].amountnumberQuantity of tokens to issueY
intent.target_candidateobjectTarget 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 NameTypeDescriptionRequired
successbooleanRequest success statusY
errorCodestringError code (null if successful)Y
dataobjectResponse data (null if failed)
data.userSigstringData signed by the user through CROSSx for token issuance/burning.Y
data.validatorSigstringData 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 NameTypeDescription
session_idstringSession identifier managed by the client or server
uuidstring (UUID)Unique identifier for a single request
tx_hashstringBlockchain transaction hash
It is recommended to retain this information for the purpose of querying blockchain transaction results.
receiptobjectTransaction execution receipt object
receipt.typestringTransaction type (EIP-1559 or chain-specific custom type) (0x7: gas fee sponsored)
receipt.rootstringState root (usually empty)
receipt.statusstringTransaction execution status
(0x1 : success, 0x0 : failure)
receipt.cumulativeGasUsedstringCumulative gas used in the block
receipt.logsBloomstringBloom filter for event logs
receipt.logsarrayArray of event logs generated during the transaction
receipt.logs[].addressstringContract address that emitted the event
receipt.logs[].topicsstring[]Event signature and indexed parameters
receipt.logs[].datastringNon-indexed event data
receipt.logs[].blockNumberstringBlock number in which the event was included
receipt.logs[].transactionHashstringTransaction hash containing the event
receipt.logs[].transactionIndexstringTransaction index within the block
receipt.logs[].blockHashstringBlock hash containing the event
receipt.logs[].blockTimestampnumberBlock timestamp (0 on some chains)
receipt.logs[].logIndexstringEvent index within the transaction
receipt.logs[].removedbooleanWhether the event was removed due to chain reorganization
receipt.transactionHashstringTransaction hash
receipt.contractAddressstringContract address created by the transaction
(0x0 for non-creation TXs)
receipt.gasUsedstringActual gas used by this transaction
receipt.effectiveGasPricestringEffective gas price applied
receipt.blockHashstringBlock hash containing the transaction
receipt.blockNumberstringBlock number containing the transaction
receipt.transactionIndexstringTransaction index within the block
intentobjectIn-game token minting / burning information
intent.methodstringExecuted method
(mint for minting, burn-permit for burning)
intent.typestringProcessing type within Ramp
(assemble for minting, disassemble for burning)
intent.fromarrayConsumed assets
intent.from[].typestringConsumed asset type (e.g., asset)
intent.from[].idstringConsumed asset identifier (e.g., game item ID)
intent.from[].amountnumberAmount of asset consumed
intent.toarrayMinted tokens
intent.to[].typestringMinted token type (e.g., ERC20)
intent.to[].idstringMinted token contract address
intent.to[].amountnumberAmount of tokens minted
intent.target_candidateobjectTarget candidate information (currently empty)
intent.fee_ratenumberFee rate in basis points (bps), e.g. 2000 = 20%
intent.actualstringNet 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 NameTypeDescriptionRequired
successbooleanRequest success statusY
errorCodestringError code (null if successful)Y
dataobjectResponse 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,
       };
     }
   }