Click-to-call bridge in 3 lines of code. Dial Party A, bridge Party B, both see the masked number. Webhooks for every call event. Rs 1.50/min, INR, GST invoice.
voice-api.edesy.in/v1
Base URL
6
Endpoints
8
Webhook Events
<100ms
Connect Latency
HTTPS + Bearer Auth
HMAC Signed Webhooks
INR + GST Invoice
99.9% Uptime
Sign up at masking.edesy.in, grab an API key, fund your wallet (minimum Rs 10), then run this:
# Initiate a masked call
# We dial Party A first, bridge Party B on answer.
curl -X POST https://voice-api.edesy.in/v1/masking/calls \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"party_a": "9876543210",
"party_b": "9123456789"
}'// Node.js (using fetch, native in Node 18+)
const response = await fetch("https://voice-api.edesy.in/v1/masking/calls", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.EDESY_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
party_a: "9876543210",
party_b: "9123456789",
}),
});
const { data } = await response.json();
console.log(data.call_sid, data.masked_number);# Python (using requests)
import os, requests
response = requests.post(
"https://voice-api.edesy.in/v1/masking/calls",
headers={
"Authorization": f"Bearer {os.environ['EDESY_API_KEY']}",
"Content-Type": "application/json",
},
json={"party_a": "9876543210", "party_b": "9123456789"},
)
data = response.json()["data"]
print(data["call_sid"], data["masked_number"])We dial Party A first. When they answer, we bridge Party B. Both see the masked number as caller ID. The response includes a call_sid you can use to poll status or fetch the recording.
Six endpoints cover the full call lifecycle. All requests authenticate with a Bearer token from your API key.
Dials Party A first, bridges Party B on answer. Both parties see the masked number as caller ID. Returns immediately with a call_sid.
Returns current call state. Poll every 2-3 seconds until terminal (completed, failed, no-answer).
Returns a short-lived signed URL streaming the MP3 recording. Valid for 1 hour.
Paginated call history with filters for status and date range. Up to 100 per page.
Aggregate usage statistics for a date range. Defaults to last 30 days.
Current wallet balance. Useful for checking funds before initiating a call programmatically.
Subscribe to call lifecycle events instead of polling. We POST signed JSON to your endpoint at each state transition. Failed deliveries retry with exponential backoff. Every payload includes an HMAC SHA-256 signature for verification.
call.initiatedParty A is being dialed. Call has not yet connected.
call.ringingParty A's phone is ringing.
call.answeredParty A answered. We are now dialing Party B to bridge.
call.bridgedBoth parties are connected and talking.
call.completedCall ended normally. Includes duration and recording URL.
call.failedCall failed. Includes hangup_cause for diagnostics.
call.no-answerParty A did not answer within the timeout window.
recording.readyRecording is processed and available for download.
{
"event": "call.completed",
"call_sid": "d28be7cd-9840-4b23-9627-199f1ef81fc6",
"data": {
"caller_number": "917969002802",
"target_number": "9876543210",
"masked_number": "917969002802",
"direction": "click_to_call",
"status": "completed",
"started_at": "2026-05-11T08:30:00Z",
"answered_at": "2026-05-11T08:30:08Z",
"ended_at": "2026-05-11T08:31:42Z",
"duration_sec": 94,
"bill_duration_sec": 120,
"price": 3,
"recording_url": "recordings/2026/05/11/d28be7cd.wav"
}
}Every request must include an Authorization: Bearer YOUR_API_KEY header. Create and rotate keys on the API Keys page of the portal.
Multiple keys per organization. Rotate without downtime.
Verify the X-Edesy-Signature header before processing.
Rate limit. Higher limits on Enterprise.
401 - unauthorized400 - invalid_numbers402 - insufficient_balance404 - not_found429 - rate_limitedNo monthly fees. No setup fees. No minimum commitment. Prepaid wallet, INR billing, 18% GST, GSTIN supported for Input Tax Credit. Top up via Razorpay.
Sign up, fund a wallet, ship masked calls today. No sales call required.