Create blockchain wallets and sign transactions using Para's MPC infrastructure where the private key never exists in a single place. Supports EVM and Solana chains via three REST endpoints.
Para provides MPC (Multi-Party Computation) wallets where the private key is split into shares and never assembled in a single place. This makes Para ideal for AI agents that need to create wallets and sign transactions without ever holding a full private key.
All operations use Para's REST API with a single API key for authentication.
https://api.beta.getpara.comhttps://api.getpara.comX-API-Key header on every requestapplication/jsonX-Request-Id (UUID) for tracing; Para generates one if omittedexport PARA_API_KEY="your-secret-api-key"
https://api.beta.getpara.com) during development. Switch to Production for mainnet.POST /v1/wallets
Creates a new MPC wallet for a user. Each combination of type + scheme + userIdentifier produces exactly one wallet. Attempting to create a duplicate returns a 409 with the existing walletId.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | EVM, SOLANA, or COSMOS |
userIdentifier | string | Yes | User identifier (email, phone, or custom ID) |
userIdentifierType | string | Yes | EMAIL, PHONE, CUSTOM_ID, GUEST_ID, TELEGRAM, DISCORD, or TWITTER |
scheme | string | No | Signature scheme: DKLS, CGGMP, or ED25519 (defaults based on wallet type) |
curl -X POST https://api.beta.getpara.com/v1/wallets \
-H "Content-Type: application/json" \
-H "X-API-Key: $PARA_API_KEY" \
-d '{
"type": "EVM",
"userIdentifier": "[email protected]",
"userIdentifierType": "EMAIL"
}'
curl -X POST https://api.beta.getpara.com/v1/wallets \
-H "Content-Type: application/json" \
-H "X-API-Key: $PARA_API_KEY" \
-d '{
"type": "SOLANA",
"userIdentifier": "[email protected]",
"userIdentifierType": "EMAIL"
}'
The wallet starts in creating status. You must poll until it reaches ready.
{
"id": "0a1b2c3d-4e5f-6789-abcd-ef0123456789",
"type": "EVM",
"scheme": "DKLS",
"status": "creating",
"createdAt": "2024-01-15T09:30:00Z"
}
The response includes a Location header with the wallet's URL:
Location: /v1/wallets/0a1b2c3d-4e5f-6789-abcd-ef0123456789
After creating a wallet, poll GET /v1/wallets/{walletId} until status becomes ready:
# Poll every 1 second until the wallet is ready
WALLET_ID="0a1b2c3d-4e5f-6789-abcd-ef0123456789"
while true; do
RESPONSE=$(curl -s https://api.beta.getpara.com/v1/wallets/$WALLET_ID \
-H "X-API-Key: $PARA_API_KEY")
STATUS=$(echo "$RESPONSE" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
if [ "$STATUS" = "ready" ]; then
echo "$RESPONSE"
break
fi
sleep 1
done
GET /v1/wallets/{walletId}
Retrieves the current status and details of a wallet.
curl https://api.beta.getpara.com/v1/wallets/0a1b2c3d-4e5f-6789-abcd-ef0123456789 \
-H "X-API-Key: $PARA_API_KEY"
When the wallet is ready, the response includes the address and public key:
{
"id": "0a1b2c3d-4e5f-6789-abcd-ef0123456789",
"type": "EVM",
"scheme": "DKLS",
"status": "ready",
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f...",
"publicKey": "04a1b2c3d4e5f6...",
"createdAt": "2024-01-15T09:30:00Z"
}
| Field | Type | Description |
|---|---|---|
id | string | Unique wallet identifier (UUID) |
type | string | Blockchain network: EVM, SOLANA, or COSMOS |
scheme | string | Signature scheme: DKLS, CGGMP, or ED25519 |
status | string | creating or ready |
address | string | Wallet address (present when status is ready) |
publicKey | string | Public key (present when status is ready) |
createdAt | string | ISO 8601 creation timestamp |
POST /v1/wallets/{walletId}/sign-raw
Signs arbitrary data using the wallet's MPC key shares. The private key is never assembled — each share signs independently and the results are combined.
Important: The wallet must be in ready status before signing.
| Field | Type | Required | Description |
|---|---|---|---|
data | string | Yes | Data to sign as a 0x-prefixed hex string |
Sign a message hash (e.g., a keccak256 hash of a transaction):
curl -X POST https://api.beta.getpara.com/v1/wallets/0a1b2c3d-4e5f-6789-abcd-ef0123456789/sign-raw \
-H "Content-Type: application/json" \
-H "X-API-Key: $PARA_API_KEY" \
-d '{
"data": "0x48656c6c6f20576f726c64"
}'
Sign a serialized Solana transaction:
curl -X POST https://api.beta.getpara.com/v1/wallets/aabbccdd-1122-3344-5566-778899aabbcc/sign-raw \
-H "Content-Type: application/json" \
-H "X-API-Key: $PARA_API_KEY" \
-d '{
"data": "0x01000103b5d..."
}'
{
"signature": "a1b2c3d4e5f6..."
}
The signature is a hex string without the 0x prefix.
Each combination of type + scheme + userIdentifier maps to exactly one wallet. If you try to create a duplicate, the API returns 409 Conflict with the existing wallet's ID in the response body. Use this to safely retry or look up existing wallets.
Wallet creation is asynchronous. The POST /v1/wallets call returns immediately with status: "creating". You must poll GET /v1/wallets/{walletId} until status becomes "ready" before you can use the wallet to sign.
Para uses Multi-Party Computation so the full private key never exists on any single machine. Key shares are distributed across independent parties. When you call sign-raw, each party signs with their share and the results are combined into a valid signature. This means:
All error responses include a message field describing the issue.
| Status | Message | Cause | Action |
|---|---|---|---|
| 400 | "type must be one of EVM, SOLANA, COSMOS" | Invalid or missing request body fields | Check required fields and enum values |
| 401 | "secret api key not provided" | Missing X-API-Key header | Add the X-API-Key header with your API key |
| 403 | "invalid secret api key" | API key is wrong or revoked | Verify your API key at developer.getpara.com |
| 404 | "wallet not found" | Wallet ID doesn't exist or doesn't belong to your account | Check the wallet ID |
| 409 | "a wallet for this identifier and type already exists" | Duplicate wallet creation attempted | Use the returned walletId to access the existing wallet |
| 500 | "Internal Server Error" | Server-side issue | Retry with exponential backoff |
The 409 response includes the existing wallet's ID so you can retrieve it:
{
"message": "a wallet for this identifier and type already exists",
"walletId": "0a1b2c3d-4e5f-6789-abcd-ef0123456789"
}
# 1. Create an EVM wallet
RESPONSE=$(curl -s -X POST https://api.beta.getpara.com/v1/wallets \
-H "Content-Type: application/json" \
-H "X-API-Key: $PARA_API_KEY" \
-d '{
"type": "EVM",
"userIdentifier": "[email protected]",
"userIdentifierType": "EMAIL"
}')
WALLET_ID=$(echo "$RESPONSE" | grep -o '"id":"[^"]*"' | cut -d'"' -f4)
echo "Created wallet: $WALLET_ID"
# 2. Poll until ready
while true; do
WALLET=$(curl -s https://api.beta.getpara.com/v1/wallets/$WALLET_ID \
-H "X-API-Key: $PARA_API_KEY")
STATUS=$(echo "$WALLET" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
if [ "$STATUS" = "ready" ]; then
echo "Wallet is ready"
echo "$WALLET"
break
fi
echo "Status: $STATUS — waiting..."
sleep 1
done
# 3. Sign data
SIGNATURE=$(curl -s -X POST https://api.beta.getpara.com/v1/wallets/$WALLET_ID/sign-raw \
-H "Content-Type: application/json" \
-H "X-API-Key: $PARA_API_KEY" \
-d '{"data": "0x48656c6c6f"}')
echo "Signature: $SIGNATURE"