Channels and security
Let users choose their delivery channel, and see the security features the widget runs.
Letting Users Choose Their Channel
Let the person receiving the code decide where it arrives — WhatsApp, Telegram or SMS — instead of the pipeline deciding for them. Like passkeys, this layers onto the existing widget: same attempt lifecycle, same result contracts, and no change to your integration at all.
Opt-in, and backward-compatible
Your backend's create-attempt call and your integration need no change, and there is no SDK upgrade — the widget runs the picker itself, and its own internal calls carry the user's choice. Change nothing and the widget keeps routing exactly as it does today. Switched on per account by Akedly, and per pipeline by you in Dashboard > Pipelines.
How it works
The picker only ever appears after the user has passed the standard checks — it is never the first thing they see.
- Captcha. The user passes the Cloudflare Turnstile check, exactly as today.
- The choice appears, in one of two shapes depending on the pipeline's mode:
- Ask first — nothing has been sent yet, and the user is asked up front where they want the code.
- Send first — the code goes out on the pipeline's normal channel immediately, and the other channels are offered under the OTP input, for when it has not arrived.
- They pick, and the code is sent on that channel. From there the flow is the ordinary OTP flow.
- Success is identical — same redirect, same signed webhook, same postMessage. Nothing about your callback handling changes.
Only phone channels can be chosen
whatsapp, telegram and sms are pickable. Email is not — if your
pipeline sends email, it is still sent alongside the phone channel when that
phone channel succeeds; if the chosen phone channel fails, the attempt ends
there and no email goes out. A pipeline with only one eligible phone channel
shows no picker at all; the user simply gets their code as before.
One resend per attempt
This is the part integrators most often get wrong: an attempt allows exactly one resend in total — and choosing a different channel is that resend.
- The first send goes out on the channel the user picked (or, in send-first mode, on the pipeline's own first channel).
- They then get one more send. They may spend it on the same channel or on a different one; either way it is the same single resend.
- After that, further resends are refused with
RESEND_LIMIT_EXCEEDEDand the user must start a new attempt. This cap is not new and is not specific to channel choice — it is the widget's existing resend limit.
Do not promise your users unlimited retries
A second resend fails, whichever channel it names. If your interface offers a "didn't get it? send again" affordance, disable it once the one resend is spent, rather than letting the user tap into an error.
When a channel cannot be reached at all
telegram is the only channel whose reachability we can test before spending a send. If the number is not on Telegram, the user is returned to the picker with Telegram removed and their resend is not consumed — nothing was sent, so nothing was spent.
whatsapp and sms cannot be tested up front. A number with no WhatsApp is only discovered after the message is accepted by the provider and later reported undelivered, which is a delivery failure rather than a bounce — so it is handled by the settings below, not by returning the user to the picker.
When a chosen channel fails to deliver
Two settings, chosen per pipeline. Both concern a send the provider accepted and later reported as failed:
- Fallback (default) — the pipeline's normal fallback order takes over, so the user still gets their code, just not where they asked.
- Hard pin — no fallback is sent; the attempt is left to fail rather than arriving somewhere the user did not choose. Choose this when "this channel or nothing" matters more than delivery.
An immediately-rejected channel never falls back
These settings govern late failures only. If the provider rejects the send outright, the request fails then and there under either setting — the fallback chain is not consulted for a channel the user chose explicitly.
Billing
Each channel bills at its own rate, exactly as sending does today — a user choosing SMS costs what SMS costs on that country's rate. The feature adds no charge of its own, and a bounce that sent nothing bills nothing. Your own per-country rates are in Dashboard > Cost.
Security Features
V2.0 Widgets include enterprise-grade security features at no additional cost. Our multi-layered approach combines visible and invisible protection mechanisms.
Proprietary Security Layers
In addition to the security features documented below, V2.0 Widgets include 3 additional proprietary security layers that operate behind the scenes. These undisclosed mechanisms handle a significant portion of fraud prevention and are kept confidential for security reasons.
Bot Protection
Invisible bot protection runs automatically before any OTP delivery, blocking automated attacks without user friction.
What It Does:
- Validates request authenticity using behavioral analysis
- Blocks bot traffic before OTP delivery
- Reduces fraudulent authentication attempts
- Saves costs by preventing fake verification requests
Device Intelligence
Advanced device analysis creates risk profiles to enable fraud detection and enforce security policies.
Capabilities:
- Generates unique device identifiers for tracking
- Detects suspicious behavior patterns across sessions
- Enables device-based rate limiting and analytics
- Supports fraud metrics in your dashboard
Akedly does not disclose every attribution signal or risk heuristic to prevent
reverse-engineering attempts. The required validation fields are documented in
the FINGERPRINT_INCONSISTENT entry in the Error Reference.
Circuit Breaker
Automatic flood protection suspends widgets under attack with progressive suspension durations.
How It Works:
- Monitors traffic patterns across multiple time windows
- Triggers automatically when abnormal activity is detected
- Applies progressive suspension durations
- Resumes automatically when threat subsides
Rate Limiting
Multi-dimensional rate limiting protects at phone number, device, and widget levels.
Configurable Limits:
- Per phone number limits (attempts and OTP requests)
- Per device limits (attempts and OTP requests)
- Per widget global limits
Default values are suitable for most use cases. Configure custom limits under Authentication → Setup → Widgets → edit your widget → the Rate Limiting section.
Cluster Gate AI Protection
Cluster Gate AI Protection is coming soon to the V2.0 Widget: an AI-powered layer designed to stop coordinated attacks such as SMS pumping before they run up your bill. It needs no change to your integration, and availability may vary by region. Learn more
