Back to Integrations
Backend Framework

Herald + Express.js

Add Herald notification capabilities to any Express.js server. Define routes for sending liquidation warnings, broadcasting governance proposals, receiving delivery webhooks, and checking API usage — all with input validation and error handling.

Ready to ship?

Start sending zero-PII notifications in minutes.

REGISTER YOUR WALLET
ZK-SECURE SOLANA NATIVE

Package: @herald-protocol/sdk

Install: npm install @herald-protocol/sdk express

View full example on GitHub →

Server Setup

Mount all Herald routes on an Express app.

Source →
Express.js / Server Setup
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import express from 'express';
import { liquidationRouter } from './routes/liquidation';
import { governanceRouter } from './routes/governance';
import { webhookRouter } from './routes/webhooks';
import { usageRouter } from './routes/usage';
const app = express();
app.use(express.json());
app.use(liquidationRouter);
app.use(governanceRouter);
app.use(webhookRouter);
app.use(usageRouter);
app.listen(3001, () => {
console.log('Herald API running on http://localhost:3001');
});

Liquidation Route

POST /liquidation with idempotency key and defi category.

Source →
Express.js / Liquidation Route
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { Router } from 'express';
import { Herald } from '@herald-protocol/sdk';
const herald = new Herald({ apiKey: process.env.HERALD_API_KEY! });
export const liquidationRouter = Router();
liquidationRouter.post('/liquidation', async (req, res) => {
const { wallet, positionId, healthFactor, debtAmount, asset } = req.body;
if (!wallet || !positionId) {
res.status(400).json({ error: 'wallet and positionId are required' });
return;
}
const idempotencyKey = `liquidation_${positionId}_${Math.floor(Date.now() / 30000)}`;
const result = await herald.notify({
wallet,
subject: `⚠️ Liquidation Warning — Health factor: ${healthFactor}`,
body: [
`Position #${positionId} is approaching liquidation.`,
`Health factor: ${healthFactor}`,
`Debt: ${debtAmount} ${asset}`,
`Add collateral or repay immediately.`,
].join('\n'),
category: 'defi',
receipt: true,
idempotencyKey,
});
res.status(202).json(result);
});

Webhook Verification

Verify HMAC-SHA256 signatures and dispatch delivery events.

Source →
Express.js / Webhook Verification
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { Router } from 'express';
import { Herald } from '@herald-protocol/sdk';
export const webhookRouter = Router();
const WEBHOOK_SECRET = process.env.HERALD_WEBHOOK_SECRET!;
webhookRouter.post('/webhooks/herald', async (req, res) => {
const signature = req.headers['x-herald-signature'] as string;
const rawBody = JSON.stringify(req.body);
if (!signature || !WEBHOOK_SECRET) {
res.status(401).json({ error: 'Missing signature or webhook secret' });
return;
}
const isValid = await Herald.verifyWebhookSignature(rawBody, signature, WEBHOOK_SECRET);
if (!isValid) {
res.status(401).json({ error: 'Invalid signature' });
return;
}
const { event, notificationId } = req.body;
switch (event) {
case 'delivery.confirmed':
console.log(`${notificationId} delivered via ${req.body.channel}`);
break;
case 'delivery.failed':
console.error(`${notificationId} failed: ${req.body.error}`);
break;
case 'delivery.bounced':
console.warn(`⚠️ ${notificationId} bounced: ${req.body.bounceType}`);
break;
}
res.json({ received: true });
});

Usage Endpoint

GET /usage — check current quota and usage stats.

Source →
Express.js / Usage Endpoint
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import { Router } from 'express';
import { Herald } from '@herald-protocol/sdk';
const herald = new Herald({ apiKey: process.env.HERALD_API_KEY! });
export const usageRouter = Router();
usageRouter.get('/usage', async (_req, res) => {
try {
const usage = await herald.getUsage();
res.json(usage);
} catch (err) {
res.status(500).json({ error: 'Failed to fetch usage' });
}
});

Common Patterns

POST /liquidation — single notification with defi category
POST /governance — bulk notify with governance category
POST /webhooks/herald — delivery callback verification
GET /usage — quota and usage monitoring

Start building with Herald

Clone the examples repo, copy the code that fits your stack, and deploy.