Skip to main content

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/json header
  • Authentication required for protected endpoints via Authorization: Bearer <token> header

Authentication Requirements

🔓 Public Methods (No authentication required):

  • auth.generateChallenge
  • ret.virtualAccountAddressFromPublicKey
  • trigger.getValidEventNames

🔐 Protected Methods (Authentication required):

  • auth.getSession
  • auth.signInWithProof (generates token)
  • All webhook.* methods
  • All trigger.* methods (except getValidEventNames)
  • 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 key
  • curve: 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 name
  • url: Webhook URL (must be valid URL)
  • headerKey: Optional custom header key
  • headerValue: 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 monitor
  • webhookId: ID of webhook to call when triggered
  • eventName: Name of the event to monitor
  • conditions: Optional array of trigger conditions

Trigger Conditions:

  • id: Unique identifier for the condition
  • field: Field name in the event data
  • comparator: 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
  • 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 error
  • NOT_FOUND: Resource not found
  • UNAUTHORIZED: Authentication required
  • INTERNAL_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.