Skip to main content

Sign Endpoint

Sign messages and transactions without broadcasting them to the network.

Endpoint​

POST /wallet/sign

Requires: an API key (web sessions are not accepted) with Wallet API (walletApiEnabled) enabled and read-only off.

Overview​

The sign endpoint supports three signature types:

  • personal_sign — Sign a plain text message
  • eth_signTypedData_v4 — Sign EIP-712 structured data
  • eth_signTransaction — Sign a transaction without submitting it

This is a synchronous endpoint that returns immediately with the signature.

Request​

personal_sign​

{
"signatureType": "personal_sign",
"message": "Hello, Bankr!"
}

eth_signTypedData_v4​

{
"signatureType": "eth_signTypedData_v4",
"typedData": {
"domain": { "name": "MyApp", "version": "1", "chainId": 8453 },
"types": {
"Message": [{ "name": "content", "type": "string" }]
},
"primaryType": "Message",
"message": { "content": "Hello" }
}
}

eth_signTransaction​

{
"signatureType": "eth_signTransaction",
"transaction": {
"to": "0x...",
"chainId": 8453,
"value": "1000000000000000000"
}
}

Response​

Success (200 OK)​

{
"success": true,
"signature": "0xabc123...",
"signer": "0x1234...5678",
"signatureType": "personal_sign"
}

Error (403)​

{
"error": "Read-only API key",
"message": "This API key has read-only access..."
}

A request that fails validation, or that the signer rejects, answers 400 (the latter with success: false and an error).

Access Control​

  • Read-only keys are rejected with 403
  • Allowed recipients configured on the key will block eth_signTransaction, eth_signTypedData_v4 and a personal_sign message that is exactly 32 bytes (or 0x + 64 hex characters), which some order protocols accept as an order signature, with 403 Restricted API key: none of them shows who it pays. Other messages, such as logins, still sign. The agent behind /agent/prompt refuses the same signatures for a restricted key.
  • NFT permits: signed ERC-4494 Permit and Uniswap v4 PermitForAll typed data count against the wallet's NFT transfer setting.
  • Hyperliquid: typed data that sends or withdraws to any address but the signing wallet, or hands account control to another key (agent approval, multisig conversion, a builder fee for anyone but Bankr), is refused.
  • Region checks: a transaction or typed-data order that buys a stock-bearing index, and a personal_sign message that is exactly 32 bytes (or 0x + 64 hex characters), which some order protocols accept as an order signature, are refused from sanctioned regions (INDEX_REGION_BLOCKED); a stock auction fill still needs the location check (INDEX_REGION_VERIFY / INDEX_REGION_BLOCKED). A Hyperliquid trading action (typed data in Hyperliquid's Exchange domain, chain id 1337: orders, cancels and leverage changes alike) is refused when the request's country or the wallet's saved country is one where opening perps positions isn't available (PERPS_REGION_BLOCKED); the agent can still close positions there. Each refusal answers 403 with that errorCode.
  • Wallet security settings: a paused wallet refuses every signature with 403. While Enable arbitrary contract calls is off, eth_signTransaction, eth_signTypedData_v4 and a personal_sign message that is exactly 32 bytes (or 0x + 64 hex characters) are refused with 403, as "MFA required" (code: "MFA_REQUIRED") on a wallet without MFA, where the switch can't be on; other messages, such as logins, still sign. While the wallet's permitted recipients list is on, a signature other than a plain personal_sign message must name one payee Bankr can check: a standard token permit or transfer authorization (ERC-2612, DAI-style or ERC-4494 Permit, Permit2 PermitSingle / PermitBatch / PermitTransferFrom / PermitBatchTransferFrom, or EIP-3009 TransferWithAuthorization / ReceiveWithAuthorization, each with its standard type definition) whose spender or recipient is the wallet itself or on the list; an address still in its cooldown is refused with errorCode RECIPIENT_COOLDOWN. Everything else is refused with 403 and errorCode RECIPIENT_NOT_PERMITTED, since it doesn't show who it pays: eth_signTransaction, a 32-byte personal_sign message, exchange and NFT orders (CoW, 1inch, Seaport and others, whatever their receiver, because whoever fills an order takes what it sells at the signed price), Permit2 witness transfers, permits with a non-standard type definition, and any other typed data, including typed data that moves no tokens. Turn the list off to sign these; other personal_sign messages, such as logins, still sign. Bankr's own swap, NFT, Polymarket and Hyperliquid tools are unaffected.

Examples​

curl​

curl -X POST https://api.bankr.bot/wallet/sign \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"signatureType":"personal_sign","message":"Hello, Bankr!"}'

Bankr CLI​

bankr wallet sign --type personal_sign --message "Hello, Bankr!"
bankr wallet sign --type eth_signTransaction --transaction '{"to":"0x...","chainId":8453}'