Skip to main content
Veriqa takes a phone number only from the channel: the messenger hands it over, the user never types it. The sign-in page has no phone field, and a number typed into the chat as a message is not taken. Your application receives it as the standard phone_number claim in E.164 format, next to phone_number_verified.

When Veriqa asks for the number

Veriqa asks only when your application needs the number and the channel has not already given it. The need is the requirement level of the phone_number claim: A requirement counts only when the sign-in asks for the phone scope. With a Required number the sign-in window offers only the channels able to provide one; if none is left, /connect/authorize answers 400 no_channel_for_required_phone (troubleshooting). The request comes once the user has confirmed the sign-in — in the chat or with “Yes” on the confirmation page in the browser. The bot sends it to the chat the user signed in from: a short text, a button that shares the number and a second button whose meaning depends on the level. The texts are shown in the user’s language. The window is 60 seconds by default. Change it with Veriqa:ClaimCompletion:PhoneOptionalWindow, or for one application with the ClaimCompletionPhoneOptionalWindow member of its client entry (see keys in the declaration catalog). The window never runs past the transaction: the step is skipped at least 5 seconds before the transaction expires. When the shared number completes the sign-in, the chat shows the usual receipt of a confirmed sign-in; Cancel sign-in shows the receipt of a declined one.

What your application receives

  • phone_number — in E.164: + and digits. A number that does not convert to E.164 counts as absent: it is not issued, and the step waits as if the user had not answered.
  • phone_number_verified — a JSON boolean: true only when the channel proves that the number belongs to the user who sent it, otherwise false.
  • Both claims go out only under a granted phone scope.
A contact that fails the channel’s ownership check — somebody else’s contact card, a forwarded contact, a missing or wrong signature — is not taken, and the bot asks again. A request that cannot be delivered to the chat even after retries changes nothing: the step waits as it does with no answer.

Channel by channel

“Who” is whose code gets the number: Veriqa’s channel adapter, or your own integration with the platform. Channels whose adapter is not shipped yet show what the platform’s API allows.

Telegram

The bot sends a reply keyboard: the share button on top, the second button below it; the keyboard hides after a press. Veriqa takes only the user’s own contact: the user_id of the contact must be the sender, and a forwarded contact or a card from the address book is rejected. Telegram’s website login (Log In With Telegram) can return the phone number as well — that is your own integration with Telegram, outside Veriqa.
If you route the bot’s updates yourself — one bot shared by your code and Veriqa, and your code decides which update goes to Veriqa with OwnsInboundEvent (see phone number on request) — the Skip and Cancel sign-in buttons reach your bot, not Veriqa: in Telegram they are plain text buttons with no marker to recognise. The shared contact itself is recognised. An Optional number is then skipped by the window, and a Required one waits until the transaction expires.

MAX

The bot sends the share button and a callback button with the second action. The number is taken from vcf_info only when the contact’s hash signature matches — computed with the bot token of the tenant that received the contact. The phone number is requested only in webhook mode. With UpdateMode: Polling the MAX adapter declares no phone number and asks nothing: the signature is read from the raw webhook body, which polling does not have, so every contact would be rejected. A Required number then leaves MAX out of the sign-in window.

WhatsApp

Today the number arrives with every message: WhatsApp identifies the user by the phone number, so the token carries phone_number with phone_number_verified: true, and nothing is asked. The request is for users WhatsApp addresses without a number (business-scoped user IDs): the request_contact_info interactive message, followed by a separate message with the second button — the request carries no buttons of its own. A contact card the user sends by hand (origin = other) is rejected. The shipped Meta Cloud API provider sends the request; a WhatsApp provider of your own (IWhatsAppProvider) sends it only if it implements SendContactRequestAsync — otherwise the request is not delivered and the step waits as it does with no answer.

LINE, KakaoTalk, WeChat and Zalo — your integration

These platforms give the phone number only to their own login or mini-app, which you register and the platform approves — not to a bot. Veriqa does not get the number there. If your application needs it from these users, obtain it in your own code through the platform’s login and keep it on your side.

Discord and Threema

Neither platform gives a bot the user’s phone number.

Limitations

  • The window of an Optional number is kept in the memory of the instance that sent the request. If that instance stops before the window runs out, the step is not skipped, and the transaction waits until it expires.
  • The record that ties a chat to its waiting request is in-process by default. With more than one replica, move it to Redis together with the other channel stores (channel stores) — otherwise a number that arrives at another replica finds no request.
  • When one chat has two sign-ins waiting for a number, the number goes to the one whose request came last; the other waits for its window or until it expires.
  • The buttons of the request stay in the chat after the step ends without a press — the window of an Optional number runs out, the sign-in expires. Veriqa does not take them down: in Telegram the keyboard stays under the input field until the user presses one of its buttons. A number shared from it afterwards finds no waiting request and is not taken, and the bot does not answer it; a press of the second button is then an ordinary message to the bot.