JSON-RPC API Documentation
The Hookah JSON-RPC API provides programmatic access to Radix blockchain operations, webhook management, trigger configuration, and transaction intent handling.
Base URL
- Development/Local:
http://localhost:3000/api/jsonrpc - Production:
https://app.hookah.ing/api/jsonrpc
API Structure
All requests follow JSON-RPC 2.0 specification:
- Use HTTP POST method
- Include
Content-Type: application/jsonheader - Authentication required for protected endpoints via
Authorization: Bearer <token>header
Authentication Requirements
🔓 Public Methods (No authentication required):
auth.generateChallengeret.virtualAccountAddressFromPublicKeytrigger.getValidEventNames
🔐 Protected Methods (Authentication required):
auth.getSessionauth.signInWithProof(generates token)- All
webhook.*methods - All
trigger.*methods (exceptgetValidEventNames) - All
transactionIntent.*methods - All
log.*methods
Authentication Flow
1. Generate Challenge 🔓
Generate a cryptographic challenge for authentication.
{
"jsonrpc": "2.0",
"id": 1,
"method": "auth.generateChallenge"
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": "challenge_string_here"
}
2. Sign In with Proof 🔓
Authenticate using a signed challenge.
{
"jsonrpc": "2.0",
"id": 1,
"method": "auth.signInWithProof",
"params": {
"challenge": "challenge_string",
"proof": {
"signature": "hex_signature",
"curve": "curve25519",
"publicKey": "hex_public_key"
}
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"token": "jwt_token",
"session": {
"userId": "user_id"
}
}
}
3. Get Session 🔐
Retrieve current session information.
{
"jsonrpc": "2.0",
"id": 1,
"method": "auth.getSession"
}
Headers:
Authorization: Bearer <jwt_token>
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"session": {
"userId": "user_id"
}
}
}
Radix Engine Toolkit (RET) Methods
Get Virtual Account Address 🔓
Derive a virtual account address from a public key.
{
"jsonrpc": "2.0",
"id": 1,
"method": "ret.virtualAccountAddressFromPublicKey",
"params": {
"publicKey": "hex_public_key",
"curve": "curve25519",
"networkId": 1
}
}
Parameters:
publicKey: Hex-encoded public keycurve: Cryptographic curve (currently supports "curve25519")networkId: Network identifier (1 for mainnet, 2 for stokenet)
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": "account_rdx129cd6fa9x5pmwx02j3zmqucpxlemqgh8lrjcgg932pppm349l0uud2"
}
Transaction Intent Management
Create Transaction Intent 🔐
Create a new transaction intent from a manifest.
{
"jsonrpc": "2.0",
"id": 1,
"method": "transactionIntent.createTransactionIntent",
"params": {
"manifest": {
"instructions": {
"kind": "String",
"value": "CALL_METHOD\n Address(\"component_address\")\n \"method_name\"\n Args();"
},
"blobs": []
},
"networkId": 2
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "transaction_id",
"intentHash": "hex_intent_hash"
}
}
Provide Signature 🔐
Add a signature to a transaction intent.
{
"jsonrpc": "2.0",
"id": 1,
"method": "transactionIntent.provideSignature",
"params": {
"transactionId": "transaction_id",
"signerPublicKey": "hex_public_key",
"curve": "EddsaEd25519",
"signature": "hex_signature"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"status": "ReadyToSubmit"
}
}
Submit Transaction Intent 🔐
Submit a signed transaction intent to the network.
{
"jsonrpc": "2.0",
"id": 1,
"method": "transactionIntent.submitTransactionIntent",
"params": {
"transactionId": "transaction_id"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"duplicate": false
}
}
Example: Complete Transaction Flow
- Get Virtual Account Address
- Authenticate (generate challenge, sign, get session)
- Create Transaction Intent with manifest
- Sign Intent Hash with private key
- Provide Signature to transaction
- Submit Transaction Intent
Webhook Management
Create Webhook 🔐
Create a new webhook endpoint.
{
"jsonrpc": "2.0",
"id": 1,
"method": "webhook.create",
"params": {
"name": "My Webhook",
"url": "https://example.com/webhook",
"headerKey": "X-Custom-Header",
"headerValue": "custom-value"
}
}
Parameters:
name: Optional webhook nameurl: Webhook URL (must be valid URL)headerKey: Optional custom header keyheaderValue: Optional custom header value
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "webhook_id",
"name": "My Webhook",
"userId": "user_id",
"definition": {
"type": "webhook",
"url": "https://example.com/webhook",
"headerKey": "X-Custom-Header",
"headerValue": "custom-value"
},
"createdAt": "2025-01-01T00:00:00Z"
}
}
Note: The webhook URL and headers are stored in the definition object, not directly in the result.
Get Webhook by ID 🔐
Retrieve a specific webhook.
{
"jsonrpc": "2.0",
"id": 1,
"method": "webhook.getById",
"params": {
"id": "webhook_id"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "webhook_id",
"name": "My Webhook",
"userId": "user_id",
"definition": {
"type": "webhook",
"url": "https://example.com/webhook",
"headerKey": "X-Custom-Header",
"headerValue": "custom-value"
},
"createdAt": "2025-01-01T00:00:00Z"
}
}
Get User's Webhooks 🔐
Retrieve all webhooks for the authenticated user.
{
"jsonrpc": "2.0",
"id": 1,
"method": "webhook.getByUserId"
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": "webhook_id_1",
"name": "My First Webhook",
"userId": "user_id",
"definition": {
"type": "webhook",
"url": "https://example.com/webhook1"
},
"createdAt": "2025-01-01T00:00:00Z"
},
{
"id": "webhook_id_2",
"name": "My Second Webhook",
"userId": "user_id",
"definition": {
"type": "webhook",
"url": "https://example.com/webhook2",
"headerKey": "Authorization",
"headerValue": "Bearer token"
},
"createdAt": "2025-01-02T00:00:00Z"
}
]
}
Update Webhook 🔐
Update an existing webhook.
{
"jsonrpc": "2.0",
"id": 1,
"method": "webhook.update",
"params": {
"id": "webhook_id",
"name": "Updated Webhook",
"url": "https://example.com/new-webhook",
"headerKey": "X-New-Header",
"headerValue": "new-value"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "webhook_id",
"name": "Updated Webhook",
"userId": "user_id",
"definition": {
"type": "webhook",
"url": "https://example.com/new-webhook",
"headerKey": "X-New-Header",
"headerValue": "new-value"
},
"createdAt": "2025-01-01T00:00:00Z"
}
}
Remove Webhook 🔐
Delete a webhook.
{
"jsonrpc": "2.0",
"id": 1,
"method": "webhook.remove",
"params": {
"id": "webhook_id"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": "webhook_id",
"name": "Deleted Webhook",
"userId": "user_id",
"definition": {
"type": "webhook",
"url": "https://example.com/webhook"
},
"createdAt": "2025-01-01T00:00:00Z"
}
]
}
Get Dashboard Data 🔐
Retrieve webhook statistics and counts.
{
"jsonrpc": "2.0",
"id": 1,
"method": "webhook.getDashboardData"
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": "webhook_id",
"name": "My Webhook",
"userId": "user_id",
"definition": {
"type": "webhook",
"url": "https://example.com/webhook"
},
"createdAt": "2025-01-01T00:00:00Z",
"successCount": 152,
"errorCount": 3,
"lastTriggered": "2025-01-15T14:30:00Z"
}
]
}
Trigger Management
Create Trigger 🔐
Create a new trigger to monitor blockchain events.
{
"jsonrpc": "2.0",
"id": 1,
"method": "trigger.create",
"params": {
"emitterAddress": "component_rdx1...",
"webhookId": "webhook_id",
"eventName": "DepositEvent",
"conditions": [
{
"id": "condition_1",
"field": "amount",
"comparator": "gt_n",
"value": "100"
}
]
}
}
Parameters:
emitterAddress: Radix component address to monitorwebhookId: ID of webhook to call when triggeredeventName: Name of the event to monitorconditions: Optional array of trigger conditions
Trigger Conditions:
id: Unique identifier for the conditionfield: Field name in the event datacomparator: Comparison operator:- Numeric:
eq_n,neq_n,gt_n,lt_n,gte_n,lte_n - String:
eq_s,neq_s,c_s(contains),nc_s(not contains),sw_s(starts with),ew_s(ends with) - Boolean:
eq_b,neq_b
- Numeric:
value: Value to compare against
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "trigger_id",
"webhookId": "webhook_id",
"userId": "user_id",
"status": "active",
"definition": {
"version": 2,
"rules": [...]
}
}
}
Get User's Triggers 🔐
Retrieve all triggers for the authenticated user.
{
"jsonrpc": "2.0",
"id": 1,
"method": "trigger.getByUserId"
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": "trigger_id_1",
"webhookId": "webhook_id",
"userId": "user_id",
"status": "active",
"emitterAddress": "component_rdx1...",
"eventName": "DepositEvent",
"definition": {
"version": 2,
"rules": [
{
"emitterAddress": "component_rdx1...",
"eventName": "DepositEvent",
"conditions": [
{
"id": "condition_1",
"field": "amount",
"comparator": "gt_n",
"value": "100"
}
]
}
]
},
"createdAt": "2025-01-01T00:00:00Z"
}
]
}
Get Triggers by Webhook ID 🔐
Retrieve triggers associated with a specific webhook.
{
"jsonrpc": "2.0",
"id": 1,
"method": "trigger.getByWebhookId",
"params": {
"webhookId": "webhook_id"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": "trigger_id_1",
"webhookId": "webhook_id",
"userId": "user_id",
"status": "active",
"definition": {
"version": 2,
"rules": [
{
"emitterAddress": "component_rdx1...",
"eventName": "DepositEvent",
"conditions": []
}
]
},
"createdAt": "2025-01-01T00:00:00Z"
}
]
}
Get Valid Event Names 🔓
Retrieve available event names for a component address.
{
"jsonrpc": "2.0",
"id": 1,
"method": "trigger.getValidEventNames",
"params": {
"emitterAddress": "component_rdx1..."
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"DepositEvent",
"WithdrawEvent",
"TransferEvent",
"SwapEvent",
"MintEvent",
"BurnEvent"
]
}
Update Trigger 🔐
Update an existing trigger.
{
"jsonrpc": "2.0",
"id": 1,
"method": "trigger.update",
"params": {
"id": "trigger_id",
"emitterAddress": "component_rdx1...",
"eventName": "DepositEvent",
"status": "active",
"webhookId": "webhook_id",
"conditions": [
{
"id": "condition_2",
"field": "status",
"comparator": "eq_s",
"value": "active"
}
]
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "trigger_id",
"webhookId": "webhook_id",
"userId": "user_id",
"status": "active",
"definition": {
"version": 2,
"rules": [
{
"emitterAddress": "component_rdx1...",
"eventName": "DepositEvent",
"conditions": [
{
"id": "condition_2",
"field": "status",
"comparator": "eq_s",
"value": "active"
}
]
}
]
},
"createdAt": "2025-01-01T00:00:00Z"
}
}
Remove Trigger 🔐
Delete a trigger.
{
"jsonrpc": "2.0",
"id": 1,
"method": "trigger.remove",
"params": {
"id": "trigger_id"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": "trigger_id",
"webhookId": "webhook_id",
"userId": "user_id",
"status": "active",
"definition": {
"version": 2,
"rules": [
{
"emitterAddress": "component_rdx1...",
"eventName": "DepositEvent",
"conditions": []
}
]
},
"createdAt": "2025-01-01T00:00:00Z"
}
]
}
Log Management
Get Logs by Trigger ID 🔐
Retrieve execution logs for a specific trigger.
{
"jsonrpc": "2.0",
"id": 1,
"method": "log.getByTriggerId",
"params": {
"triggerId": "trigger_id"
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"id": "log_id_1",
"triggerId": "trigger_id",
"status": "success",
"webhookUrl": "https://example.com/webhook",
"responseCode": 200,
"responseBody": "OK",
"eventData": {
"transactionId": "txid_rdx1...",
"amount": "150.50",
"from": "account_rdx1...",
"to": "account_rdx1..."
},
"createdAt": "2025-01-15T14:30:00Z"
},
{
"id": "log_id_2",
"triggerId": "trigger_id",
"status": "error",
"webhookUrl": "https://example.com/webhook",
"responseCode": 500,
"responseBody": "Internal Server Error",
"error": "Connection timeout",
"eventData": {
"transactionId": "txid_rdx1...",
"amount": "75.25"
},
"createdAt": "2025-01-15T13:15:00Z"
}
]
}
Error Handling
All methods follow JSON-RPC 2.0 error format:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000,
"message": "Error description"
}
}
Common Error Codes:
-32700: Parse error (invalid JSON)-32600: Invalid request-32601: Method not found-32602: Invalid params/Internal errorNOT_FOUND: Resource not foundUNAUTHORIZED: Authentication requiredINTERNAL_SERVER_ERROR: Server error
Network IDs
- Mainnet: 1
- Stokenet (Testnet): 2
Cryptographic Notes
- Authentication: Uses Ed25519 signatures with curve25519
- Transaction Signing: Uses EddsaEd25519 curve
- Key Format: All keys and signatures are hex-encoded
- Challenge Signing: Sign the raw challenge bytes
- Intent Signing: Sign the intent hash (hex-decoded first)
Complete Workflow Example
Here's a practical example showing how to set up webhook monitoring for blockchain events:
1. Authenticate
// Generate challenge
const challengeResponse = await fetch(baseUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'auth.generateChallenge'
})
});
// Sign challenge and authenticate
const challenge = challengeResponse.result;
const signature = ed25519.sign(challenge, privateKey);
const authResponse = await fetch(baseUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'auth.signInWithProof',
params: {
challenge,
proof: {
signature: toHex(signature),
curve: 'curve25519',
publicKey: toHex(publicKey)
}
}
})
});
const token = authResponse.result.token;
2. Create Webhook
const webhookResponse = await fetch(baseUrl, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'webhook.create',
params: {
name: 'DEX Trade Monitor',
url: 'https://myapp.com/webhook/dex-trades',
headerKey: 'X-API-Key',
headerValue: 'your-api-key'
}
})
});
const webhookId = webhookResponse.result.id;
3. Create Trigger
const triggerResponse = await fetch(baseUrl, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'trigger.create',
params: {
emitterAddress: 'component_rdx1...dex_component',
webhookId: webhookId,
eventName: 'TradeEvent',
conditions: [
{
id: 'min_amount_filter',
field: 'amount',
comparator: 'gt_n',
value: '1000'
}
]
}
})
});
4. Monitor Events
Your webhook will now receive HTTP POST requests when trades > 1000 tokens occur on the specified DEX component.