Call the Edesy number masking REST API from Node.js with plain HTTP: create a masked session, place a click-to-call and verify signed event webhooks. There is no Node.js SDK to install; any HTTP client works.
Number masking at a glance
From API key to first masked call
Sign up at masking.edesy.in, complete KYC and create an API key (it starts with vp_). The full key is shown once, so store it in an environment variable.
Enroll a number from your Edesy account for masking. One number can serve many sessions at once.
POST /v1/masking/sessions with party_a, party_b and your reference, using the built-in fetch (Node.js 18+). Give the returned virtual_number to both parties.
Set your endpoint with PUT /v1/masking/event-webhook and verify the X-Edesy-Signature header before trusting an event.
Create a masked session and verify an event webhook. Replace the numbers with real 10-digit Indian mobiles.
// Node.js 18+: plain HTTP with the built-in fetch. No SDK to install.
import crypto from "node:crypto";
import express from "express";
const API = "https://voice-api.edesy.in/v1";
const headers = {
Authorization: `Bearer ${process.env.EDESY_API_KEY}`, // vp_... from masking.edesy.in
"Content-Type": "application/json",
};
// 1. Create a two-way masked session
const res = await fetch(`${API}/masking/sessions`, {
method: "POST",
headers,
body: JSON.stringify({
party_a: "9876543210",
party_b: "9123456789",
reference: "ORD-4821", // your order / ride / ticket id
expiry_minutes: 60,
}),
});
const { data } = await res.json();
console.log(data.virtual_number); // share this number with both parties
// 2. Receive and verify event webhooks (X-Edesy-Signature: sha256=<hex>)
const app = express();
app.post("/edesy/events", express.raw({ type: "application/json" }), (req, res) => {
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.EDESY_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
const got = req.get("X-Edesy-Signature") || "";
if (got.length !== expected.length ||
!crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString());
console.log(event.event, event.reference, event.duration_sec);
res.sendStatus(200);
});
app.listen(3000);JSON in, JSON out. Use the built-in fetch (Node.js 18+) or any HTTP client you already have.
Send Authorization: Bearer vp_... on every request. Missing or invalid keys get 401.
Events are signed with HMAC-SHA256 over the raw body, sent as sha256=<hex>. Verify with crypto.createHmac and crypto.timingSafeEqual.
Errors come back as JSON with a code and message, for example insufficient_balance (402) or rate_limited (429).
Rs 1.50/min in 60-second pulses, 1-minute minimum, plus number rental (Rs 499/month mobile, Rs 449/month landline). Prices exclude 18% GST. New accounts get a Rs 20 welcome credit; no card needed to sign up.
Get started on the self-serve portal. Rs 1.50 per minute plus number rental. New accounts get a Rs 20 welcome credit; no card needed to sign up.