Signing Blockchain Messages

Developers can sign blockchain messages using their API keys and the wallets they have access to.


This feature is only available for EVM and Solana based blockchains.


POST /api/v1-alpha1/wallets/signMessage

Required Scopes


If you do not have an API key with the WALLET_MESSAGE_SIGN scope, create an API key in the Crossmint developer console.


Staging is currently self-service, reach out to our team if you need production access.

chainstringThe blockchain network you're using (Ethereum, Polygon, or BSC). For Optimism or Arbitrum support, please reach out to us.
addressstringThe wallet address you want to sign the message with.
messagestringThe message to be signed, passed in the request body.


On successful execution, the API will return a JSON object with the signedMessage field.

Example Response:

{ "signedMessage": "0x7b226d657373616765223a202268656c6c6f2c20776f726c6421222c20227369676e6174757265223a2022307837316237386537333732333430303132303930653130313562323439373335333339656135303737323438333333613833653635373831326438653534373639373333333334227d" }

Error Handling

The following errors may be returned by the API:

  • BadRequestException (400 error): If the requested blockchain is not supported.
  • NotFoundException (404 error): If the specified wallet address is not found.
  • ForbiddenException (401 error): If the project does not have access to the requested wallet.

Usage Example

Here's an example of how to call the /api/v1-alpha1/wallets/signMessage endpoint using JavaScript and the fetch API:

const chain = "ethereum";
const address = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
const message = "Hello, world!";

fetch("/api/v1-alpha1/wallets/signMessage", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "Authorization": "your-api-key"
    body: JSON.stringify({ chain, address, message })
.then(response => response.json())
.then(data => console.log("Signed message:", data.signedMessage))
.catch(error => console.error("Error:", error));

Replace your-api-key with your actual Crossmint API key.

Implementation Notes

The parseParams function validates and parses the request parameters, while the fetchWallet function retrieves the wallet based on the specified address and blockchain network.

The endpoint checks if the project has access to the wallet by calling the assertProjectHasAccessToWallet function. Currently, only whitelisted projects are allowed to sign messages. In the future, this check will be based on the wallet.projectId.

Once the project access is validated, the message is signed using the wallet's signMessage method, and the resulting signature is returned in the response.

While these are extremely rare occurrences, our wallets are MPC based, which means signing may have outlier times of ~30 seconds.