Clients

Create the client’s wallet

POST https://mpc-client.portalhq.io/v1/generate This endpoint generates MPC shares for both SECP256K1 (EVM, etc) and ED25519 (Solana, XRP, etc) curves (a Portal wallet).
After receiving MPC shares from this endpoint, be sure to verify the shares with this endpoint before attempting to sign.
Headers
NameTypeDescription
Authorization*StringBearer <Client API Key>
Content-Type*Stringapplication/json
Body Parameters
You can leave the request body empty.
{}
Example Request
Be sure to replace the [token] with either a Client API Key or a Client Session Token.
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/generate \
  --header 'Authorization: Bearer [token]' \
  --header 'Content-Type: application/json' \
  --data '{}'
Example Response
{
  "SECP256K1": {
    "share": "eyJjbG...",
    "id": "cm0r6nkek00ej10dwwx8wdjmf"
  },
  "ED25519": {
    "share": "eyJjbG...",
    "id": "cm0r6nk7c00hbzefaq9s93s0x"
  }
}

Send the client’s assets

POST https://mpc-client.portalhq.io/v1/assets/send This endpoint allows you to easily send a token the client holds to another address.
The Send Assets endpoint builds, signs, and submits a transaction to an RPC gateway.Important: A 200 response only confirms that the transaction was received by the RPC gateway — it does not mean the transaction is confirmed on-chain. The transaction must first be placed in the mempool of the RPC gateway nodes, submitted to miner/validator nodes, and then validated and finalized by the network. This process can take seconds to minutes, depending on the blockchain.
Headers
NameTypeDescription
Authorization*StringBearer <Client API Key>
Content-Type*Stringapplication/json
Body Parameters
NameTypeDescription
share (Required)StringThe MPC share generated from “Create Wallets” for a specific curve.
chain (Required)

String

CAIP-2 Chain ID or one of:

"base"

"base-sepolia"

"ethereum"

"bitcoin-segwit"

"bitcoin-segwit-testnet"

"bitcoin-p2wpkh"

"bitcoin-p2wpkh-testnet"

"polygon"

"polygon-amoy"

"celo"

"celo-alfajores"

"sepolia"

"solana"

"solana-devnet"

"stellar"

"stellar-testnet"

"tron"

"tron-nile"

"tron-shasta"

The blockchain network.
to (Required)StringThe recipient’s address.
token (Required)StringThe token contract address (for ERC20 tokens on EVM chains) or the mint address (for Solana SPL tokens). You can also use “USDC” or “USDT” for the respective tokens. For native token transfers, use "NATIVE".
amount (Required)StringThe amount of tokens to send (“0.1” is 0.1 USDC)
rpcUrlStringThe node provider RPC URL. Not required for Solana or Solana Devnet.
nonceStringThe hex string of the nonce to set on the transaction (“0x01” sets the nonce of the transaction to 1). Note that the hex string needs to include the “0x” and for single digits to include a leading zero like “0x0”.
metadataStrStringOptional metadata string for the transaction.
When submitting multiple transactions for a single client in quick succession (or in parallel), each transaction may initially have the same nonce if the blockchain hasn’t processed the earlier ones yet. This can cause errors, as the RPC gateway interprets identical nonces as attempts to overwrite transactions in the mempool.To prevent this, track the nonce in your application and increment it manually for each transaction sent to the Send Assets endpoint, ensuring unique nonces for concurrent requests.
Example Request
Be sure to replace the [token] with either a Client API Key or a Client Session Token.
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/assets/send \
  --header 'Authorization: Bearer [token]' \
  --header 'Content-Type: application/json' \
  --data '{
	"share": "share",
	"chain": "ethereum",
	"to": "0xdFd8302f44727A6348F702fF7B594f127dE3A902",
	"token": "NATIVE",
	"amount": "0.0001"
}'
Example Response
If your client is using Account Abstraction, then transactionHash is actually a User Operation hash. You can manually look up the user operation hash here.
{
  "transactionHash": "0x02073df9ba08895d681f80ae45440ba57e766602c97ee6321df5ac81bca900cc",
  "metadata": {
    "amount": "0.01",
    "rawAmount": "10000000000000000",
    "tokenAddress": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
    "tokenDecimals": 18
  }
}

Sign a transaction or message by chain

POST https://mpc-client.portalhq.io/v1/sign This endpoint allows you to sign a transaction or message by chain.
Headers
NameTypeDescription
Authorization*StringBearer <Client API Key>
Content-Type*Stringapplication/json
Body Parameters
NameTypeDescription
methodd;”>*StringThe signer RPC method (e.g. “personal_sign”, “eth_sendTransaction”, “sol_signAndSendTransaction”, etc).
paramsd;”>*StringA JSON stringified array of the parameters for the RPC method (e.g. ”[\“test\”]”).
shared;”>*StringThe MPC share generated from “Create Wallets” for a specific curve.
chainIdd;”>*StringThe blockchain network (a CAIP-2 chain ID like “eip155:11155111” for Sepolia).
tod;”>*StringThe recipient’s address.
rpcUrld;”>*StringThe node provider RPC URL.
metadataStrStringOptional metadata string for the transaction.
Example Request
Be sure to replace the [token] with either a Client API Key or a Client Session Token.
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/sign \
  --header 'Authorization: Bearer [token]' \
  --header 'Content-Type: application/json' \
  --data '{
	"share": "share",
	"method": "eth_sendTransaction",
	"params": "{\"value\": \"0x01\",\"from\": \"\",\"to\": \"0xdFd8302f44727A6348F702fF7B594f127dE3A902\",\"data\": \"\"}",
	"rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/1",
	"chainId": "eip155:1"
}'
Example Response
{
  "data": "0xf7a6a07fa599db56fca50fa1202670b59054e7ed452ea57b3f5b43148b8bdb165beb3a4b0fd532162a1f0fd475de1a9ecd07c95186f7a0856ce1bffa45e3acc91b"
}

Sign a transaction or message by curve

POST https://mpc-client.portalhq.io/v1/raw/sign/:curve This endpoint allows you to sign a raw message by curve.
Headers
NameTypeDescription
Authorization*StringBearer <Client API Key>
Content-Type*Stringapplication/json
Path Parameters
NameTypeDescription
curved;”>*StringThe curve you want to use (e.g. SECP256K1 for EVM chains and ED25519 for Solana).
Body Parameters
NameTypeDescription
paramd;”>*StringA hex string of the digest to sign without the leading 0x (e.g. "param": "7369676e2074686973").
shared;”>*StringThe MPC share generated from “Create Wallets” for a specific curve.
Example Request
Be sure to replace the [token] with either a Client API Key or a Client Session Token.
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/raw/sign/SECP256K1 \
  --header 'Authorization: Bearer [token]' \
  --header 'Content-Type: application/json' \
  --data '{
	"params": "0x123",
	"share": "share"
}'
Example Response
{
  "data": "0xf7a6a07fa599db56fca50fa1202670b59054e7ed452ea57b3f5b43148b8bdb165beb3a4b0fd532162a1f0fd475de1a9ecd07c95186f7a0856ce1bffa45e3acc91b"
}

Back up the client’s wallet

POST https://mpc-client.portalhq.io/v1/backup This endpoint allows you to create backup shares for your wallet.
Headers
NameTypeDescription
Authorization*StringBearer <Client API Key>
Content-Type*Stringapplication/json
Body Parameters
NameTypeDescription
generateResponsed;”>*JSONThe response body from “Create Wallets”.
Example Request
Be sure to replace the [token] with either a Client API Key or a Client Session Token.
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/backup \
  --header 'Authorization: Bearer [token]' \
  --header 'Content-Type: application/json' \
  --data '{
  "generateResponse": "{\"SECP256K1\":{\"share\":\"share\",\"id\":\"shareId\"},\"ED25519\":{\"share\":\"share\",\"id\":\"shareId\"}}"
}'
Example Response
{
  "SECP256K1": {
    "share": "eyJjbGl...",
    "id": "clu32l6c8008wuvz52jokyo3r"
  },
  "ED25519": {
    "share": "eyJjbGl...",
    "id": "clu32l9310087evz5u5v9k1ao"
  }
}

Recover the client’s wallet

POST https://mpc-client.portalhq.io/v1/recover This endpoint allows you to recover shares for your wallet using your backup shares.
Headers
NameTypeDescription
Authorization*StringBearer <Client API Key>
Content-Type*Stringapplication/json
Body Parameters
NameTypeDescription
backupResponsed;”>*JSONThe response body from “Back Up Wallets”.
Example Request
Be sure to replace the [token] with either a Client API Key or a Client Session Token.
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/recover \
  --header 'Authorization: Bearer [token]' \
  --header 'Content-Type: application/json' \
  --data '{
  "backupResponse": "{\"SECP256K1\":{\"share\":\"share\",\"id\":\"shareId\"},\"ED25519\":{\"share\":\"share\",\"id\":\"shareId\"}}"
}'
Example Response
{
  "SECP256K1": {
    "share": "eyJjbGl...",
    "id": "clu32l6c8008wuvz52jokyo3r"
  },
  "ED25519": {
    "share": "eyJjbGl...",
    "id": "clu32l9310087evz5u5v9k1ao"
  }
}