Verify Silent Network Auth quickstart Disabled
Silent Network Auth (SNA) verifies a phone number by checking the SIM directly with the mobile carrier, with no code sent and nothing for the user to type. It is the lowest-friction phone verification possible: the user does nothing beyond being on their mobile data connection. The committed contract below is stable; the disabled-for-sending state is called out where it applies.
Setup time: 2-4 weeks$0.03 per successful verification
SNA is currently disabled. POST /v1/verify with channel: "sna" returns 422 with { "error": "channel_not_available", "channel": "sna" }. The generic start and check shapes shown below are the committed, channel-agnostic contract every channel uses.
What Silent Network Auth is
Every delivered channel (SMS, email, voice, WhatsApp) sends a code and asks the user to read it back. SNA skips the code entirely. When the device is on its mobile network, the carrier can confirm that the SIM in the device matches the number being verified, over the data connection, without an SMS or a user action. This makes SNA both the smoothest experience and the hardest to spoof, since there is no code in transit to intercept. It depends on direct integration with mobile network operators, which is why setup runs 2-4 weeks.
When to choose SNA
Choose SNA when you want to verify possession of a mobile number with zero user friction and the strongest resistance to interception, and your users are on mobile data at the moment of verification. It does not work over Wi-Fi-only sessions or for landlines, and it needs the operator integration in place for the user's carrier. Keep SMS as the fallback for those cases, and use email when the identifier is an email address.
Prerequisites
- A message.com workspace with Verify activated and a positive credit balance. See Get started with Verify.
- A Verify Service with
snain itsenabledChannels. - An API key with the
verifyscope (mk_live_...). See Authentication. - The destination country in the service's
allowedCountriesallowlist: SNA is a phone channel and subject to the same allowlist as SMS. - Direct carrier and mobile-network-operator integration for the target market. That operator integration is the 2-4 week setup step and is outside message.com's unilateral control. See setup times.
Full verification walk
The API keeps the same two-call shape as every channel. Your backend starts a verification, the carrier check happens silently, and your backend confirms the result with the check call. No code is shown to the user, but the request and response shapes are identical to the delivered channels.
1. Start the verification
Call POST /v1/verify with the phone number as to and "sna" as the channel. E.164 format is preferred.
curl -X POST https://api.message.com/v1/verify \
-H 'Authorization: Bearer mk_live_...' \
-H 'Content-Type: application/json' \
-d '{
"to": "+14155550142",
"channel": "sna"
}'curl -X POST https://api.message.com/v1/verify ^
-H "Authorization: Bearer mk_live_..." ^
-H "Content-Type: application/json" ^
-d "{\"to\": \"+14155550142\", \"channel\": \"sna\"}"const start = await fetch('https://api.message.com/v1/verify', {
method: 'POST',
headers: {
Authorization: 'Bearer mk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({ to: '+14155550142', channel: 'sna' }),
});
const verification = await start.json();
// Today:
// { error: 'channel_not_available', channel: 'sna' } (HTTP 422)import requests
start = requests.post(
"https://api.message.com/v1/verify",
headers={"Authorization": "Bearer mk_live_..."},
json={"to": "+14155550142", "channel": "sna"},
)
verification = start.json()
# Today:
# { "error": "channel_not_available", "channel": "sna" } (HTTP 422)Today, this call returns 422:
{
"error": "channel_not_available",
"channel": "sna"
}The SNA-specific surface (the operator check handoff and any device-side reachability step) is not part of the committed API yet, so this page documents only the generic start and check contract, not SNA-specific endpoints. When SNA is live, the start call returns the same flat body every channel returns, and the check call below confirms the result.
2. Check the result
The check call is channel-agnostic and works today across live channels. It resolves the verification id to a { id, verified } result.
curl -X POST https://api.message.com/v1/verify/check \
-H 'Authorization: Bearer mk_live_...' \
-H 'Content-Type: application/json' \
-d '{
"id": "1f6a2e4c-9d3b-4a1e-8f2c-6b7a9e0d5c3f",
"code": "482913"
}'curl -X POST https://api.message.com/v1/verify/check ^
-H "Authorization: Bearer mk_live_..." ^
-H "Content-Type: application/json" ^
-d "{\"id\": \"1f6a2e4c-9d3b-4a1e-8f2c-6b7a9e0d5c3f\", \"code\": \"482913\"}"const check = await fetch('https://api.message.com/v1/verify/check', {
method: 'POST',
headers: {
Authorization: 'Bearer mk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: verification.id, code: userSubmittedCode }),
});
const result = await check.json();
// { id: '1f6a2e4c-...', verified: true }check = requests.post(
"https://api.message.com/v1/verify/check",
headers={"Authorization": "Bearer mk_live_..."},
json={"id": verification["id"], "code": user_submitted_code},
)
result = check.json()
# { "id": "1f6a2e4c-...", "verified": True }A verified result returns 200 with { id, verified: true } and bills $0.03. A result that did not verify returns 200 with verified: false and a reason. Read the verified field, not the HTTP status.
Fraud interactions
SNA is the strongest phone channel against interception, because there is no code to steal. It still lives inside the same Verify guard stack, and as a phone channel it inherits the phone-side controls when live:
- Country allowlist. A number whose country is not in the service's
allowedCountriesreturns403 country_not_allowed. - Per-destination throttle. Repeated verifications against the same number in a 60-second window return
429 rate_limitedwithscope: "destination". - Per-service velocity. The per-minute and per-day caps return
429 rate_limitedwithscope: "workspace". - Carrier binding. Because the operator confirms the SIM itself, an attacker cannot satisfy the check with a number they do not physically control the SIM for.
Country allowlists, velocity caps, and destination throttles are covered in depth in the Verify fraud guide.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
422 channel_not_available | Expected today: SNA is disabled. Use SMS or email now. Do not retry this call for the same channel; it will not become available mid-session. |
400 channel_not_enabled | The resolved service does not list sna in enabledChannels. This is a per-service setting, distinct from the platform-wide channel_not_available. |
403 country_not_allowed (when live) | The number's country is not in the service's allowedCountries, or no operator integration exists for that market. Add the country to the allowlist and confirm operator coverage. |
400 invalid_number | The to value fails the phone-shape check. Send digits, optionally with a leading +. |
Every reason above, with its exact firing condition, is on the Verify API error codes page.