Step-by-step guide to setting up call masking for your business. From choosing a provider to going live with API integration.
Number masking at a glance
Call masking (also called number masking, privacy calling, or anonymous calling) is a service that sits between two parties on a phone call and shows them a virtual number instead of each other's real number. Neither party sees the other's actual phone number — both see the masked number as caller ID.
The most common setup pattern is click-to-call bridging: your application calls a masking API with two phone numbers. The API dials Party A first, and when they answer, it dials Party B and bridges both legs. Both parties talk normally, but both see the masked virtual number as caller ID. When the call ends, the connection is severed.
Teams set this up for one of three reasons:
This guide walks you through choosing a provider, integrating the API, going live, and handling the operational details — webhooks, error codes, recording retention, and compliance.
From signup to first masked call in production
Evaluate India-focused providers (Edesy, Exotel, Knowlarity, MSG91, Plivo, Twilio India) on price, billing currency, GST handling, contract terms, integration ergonomics, and compliance posture.
Create an account. With a prepaid provider like Edesy, complete business KYC (about 24 hours) and fund an INR wallet via Razorpay; new Edesy accounts get a Rs 20 welcome credit, no card needed to sign up. With contract-based providers, sign a service agreement and wait for onboarding.
In the portal, create an API key tied to your organization. Store it as an environment variable in your application — never commit keys to git.
From your application server, POST two phone numbers to the masking endpoint. Get back a call_sid. The system dials Party A first, then bridges Party B on answer.
Configure an event webhook URL in the portal or with PUT /v1/masking/event-webhook. Edesy POSTs JSON events (session.created, call.incoming, call.connected, call.ended, call.missed, session.expired) to your endpoint. Verify the HMAC signature before processing.
Watch for insufficient_balance, invalid_numbers, and rate_limited errors. Use status polling or webhook events to track outcomes (completed, failed, no-answer). Retry where appropriate.
Track success rate (answered vs no-answer vs failed), call duration distribution, and cost per call. Review recordings periodically for quality. Iterate on retry logic and call flow.
The decision usually comes down to four factors: pricing model, geographic focus, integration ergonomics, and compliance fit.
If your call volume is India-only, an India-native provider (Edesy, Exotel, Knowlarity, MSG91) is usually simpler for INR billing and GST invoices. If you need international masking, global providers (Twilio, Plivo) are necessary. Many teams run hybrid: India provider for India traffic, global provider for the rest.
Look for:
If you're in healthcare, banking/lending, or payment processing, ask each provider exactly which controls and certifications they have, and get the answer in writing. Edesy provides masked numbers, expiring sessions, a per-number recording toggle, encrypted recording storage with signed links and workspace roles; it does not hold HIPAA, PCI DSS or SOC 2 certification or sign BAAs. Verify fit with your compliance team before signing; this is not legal advice.
With Edesy as the example provider, the integration is three API calls plus webhook handling. Full code examples for the initiate-call endpoint in cURL, Node.js, and Python live in the API reference.
POST two 10-digit Indian mobile numbers to /v1/masking/calls with a Bearer token in the Authorization header. Body: { "party_a": "9876543210", "party_b": "9123456789" }. The response returns immediately with a call_sid and the masked number that will be shown to both parties.
You have two options:
/v1/masking/calls/{call_sid} every 2-3 seconds until status reaches a terminal state. Simpler to implement but consumes API rate-limit budget and adds latency. Use only if your stack can't accept inbound webhooks.If recording is on for the number, GET /v1/masking/calls/{call_sid}/recording after the call ends. Recordings are served from encrypted storage through signed links, so fetch them when you need them rather than storing public URLs.
When recording.ready fires, the webhook payload includes a recording_url. Alternatively, GET /v1/masking/calls/{call_sid}/recording to retrieve a signed URL valid for 1 hour. Store the recording reference against your call/order record for audit and dispute resolution.
When you set a secret, each delivery carries an X-Edesy-Signature header of the form sha256=<hex>: an HMAC-SHA256 of the raw request body. Recompute it with your secret over the exact bytes you received and compare with a constant-time check before trusting the payload. Respond with a 2xx within 5 seconds.
Every webhook POST includes an X-Edesy-Signature header with an HMAC SHA-256 signature of the request body, signed with your webhook secret. Verify this on every event before processing — otherwise an attacker who knows your webhook URL can spoof events. Reject any request that fails verification with HTTP 401.
| Status | Code | What to do |
|---|---|---|
| 400 | invalid_numbers | Validate Indian mobile format and de-dupe Party A vs Party B before calling the API |
| 401 | unauthorized | Rotate the API key and update the env var |
| 402 | insufficient_balance | Top up the wallet; consider implementing a low-balance alert at Rs 50 |
| 404 | not_found | The call_sid doesn't exist or recording isn't ready yet — re-check after a delay |
| 429 | rate_limited | Back off with exponential delay (the default limit is 100 requests/minute per key); contact sales if you need more |
Mistakes we've seen teams make on their first masking integration
Polling every 2 seconds for 100 concurrent calls = 50 req/sec, far above a 100 requests/minute limit. Use webhook events for state transitions; reserve polling for one-off lookups.
Without HMAC verification, anyone who knows your webhook URL can spoof events and cause downstream chaos. Verify the signature on every event before processing.
Use environment variables. Rotate periodically. Store secrets in a vault (AWS Secrets Manager, HashiCorp Vault, 1Password) — never commit to git, even in private repos.
Insufficient balance blocks new calls with a 402. Check GET /v1/masking/billing on a schedule and alert your own ops channel before the balance runs out.
Call recordings have privacy implications. Decide whether you need recordings at all, and how long you would keep them, before going live. On Edesy, recording is switched on or off per number.
Before cutting over from a previous provider, document the rollback: how do you flip traffic back if the new provider has an outage? Practice it. Keep both accounts live for at least 30 days.
If you forget to add your GSTIN at the first Razorpay top-up, the invoice is issued without it and you lose Input Tax Credit on that top-up. Update GSTIN in the portal before the first top-up.
If you treat 'no-answer' as a failure and retry immediately, you'll harass users with rapid-fire calls. Build backoff: 5 mins, 30 mins, 4 hours, give up. Match retry policy to use case.
Before flipping production traffic to the masking flow, walk through this list:
Most teams underestimate masking ROI because they only count direct cost (per-minute charges). The real ROI is in three buckets:
An illustrative calculation: at Rs 1.50/min with 60-second pulses, a 90-second call bills as 2 minutes, so it costs Rs 3. 10,000 such calls a month = Rs 30,000, plus number rental and 18% GST. Compare that with your own estimate of what leaked numbers cost you in fraud, disintermediation and support time. The numbers here are an example, not a benchmark.
If your team has 1-2 backend engineers comfortable with REST APIs and webhooks, building the integration takes 2-5 days. Time-to-live is fast and you own the code.
If you're a non-technical founder, an ops lead, or your engineering team is already over-allocated, Edesy can help with the integration as a quoted setup project. See setup services.
Either way, usage is billed the same: Rs 1.50/min plus number rental.
Discover solutions, integrations, and resources
Use cases for every industry
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.