JSON-RPC API Documentation
The Hookah JSON-RPC API provides programmatic access to Radix blockchain operations, webhook management, and trigger configuration.
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
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"
}
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",
"hasHeaderValue": true,
"headerValuePreview": "********"
},
"createdAt": "2025-01-01T00:00:00Z"
}
}
Note: The webhook URL and header key are stored in the definition object, not directly in the result. Header values are stored for delivery but are never returned by the API.
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",
"hasHeaderValue": true,
"headerValuePreview": "********"
},
"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",
"hasHeaderValue": true,
"headerValuePreview": "********"
},
"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",
"hasHeaderValue": true,
"headerValuePreview": "********"
},
"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
- Key Format: All keys and signatures are hex-encoded
- Challenge Signing: Sign the raw challenge bytes
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.