Skip to main content

Troubleshoot contact onboarding

Use this guide when someone shared their contact with the client bot but the Mini App still reports contact_required, when bot permission looks wrong, or after an API or database outage. It covers authentication facts only. Notification preferences are a separate client setting; see Client booking notifications.

How facts are applied is explained in Channel authentication.

Prerequisites​

  • A read-only SQL session on the database, as an operator.
  • Access to the API's logs and the client bot's token, for getWebhookInfo.

Check for pending facts​

Facts that were recorded but not applied to an account yet:

SELECT 'contact' AS "fact", c."source_app_id" AS "app",
c."source_version", c."applied_version", c."updated_at",
p."supabase_user_id" IS NOT NULL AS "signed_in"
FROM "channel_auth"."channel_contacts" AS c
JOIN "channel_auth"."provider_identities" AS i ON i."id" = c."provider_identity_id"
JOIN "channel_auth"."principals" AS p ON p."id" = i."principal_id"
WHERE c."applied_version" < c."source_version"
UNION ALL
SELECT 'permission', m."app_id", m."source_version", m."applied_version",
m."updated_at", p."supabase_user_id" IS NOT NULL
FROM "channel_auth"."channel_permissions" AS m
JOIN "channel_auth"."provider_identities" AS i ON i."id" = m."provider_identity_id"
JOIN "channel_auth"."principals" AS p ON p."id" = i."principal_id"
WHERE m."applied_version" < m."source_version"
ORDER BY "updated_at";
What you seeWhat it means
No rowsEvery recorded fact is applied
signed_in is falseThe person has never signed in. Their first sign-in applies the fact
signed_in is true, app is the client app, the person has only used the professional appThey have no client account yet. Their first client Mini App sign-in creates it and applies the fact
app is no longer in CHANNEL_AUTH_TELEGRAM_APPS_JSONThe fact has nowhere to go and stays pending
signed_in is true, recent rowsApplication failed. Telegram redelivers the update, which applies it; check the API logs
signed_in is true, rows older than a dayTelegram stopped redelivering. The person's next update or sign-in applies the fact

The API logs a failed webhook as telegram update failed with the error name, and a failed application during sign-in as pending facts could not be applied. Logs never include the phone or the fact.

A shared contact did not arrive​

Work through these in order:

  1. The bot did not receive it. Run getWebhookInfo for the client bot, as in Move Telegram webhooks to channel authentication. A last_error_message points at the webhook URL, the secret, or a 500 while applying. An empty url means no webhook is set, for example because the local preview bot (apps/client_tg_app/bot.py) polls this bot. That script receives the contact and replies, but the API never sees it; stop it and set the webhook.
  2. The update was not a verified contact. Someone else's contact card, a forwarded contact, a group chat, and a phone that is not a valid international number are ignored. Ask the person to use the Mini App's contact request, which shares their own contact from a private chat.
  3. The person has not signed in to the client Mini App yet. A contact shared before the first client sign-in is kept and applied right after that sign-in.
  4. Application failed. Use the pending check above. While a fact is pending, the account stays contact_required, and the session stays usable.

Channel authentication never fills in a contact from a Mini App request, a display name, or editable user metadata. Only a bot update proves a contact.

After an outage​

Fix the cause first: the API must reach the database. There is nothing to replay. Telegram redelivers every update the API did not acknowledge, for up to a day, and each redelivered update applies whatever is still pending for that person. Facts that outlive Telegram's retries are applied at the person's next update or sign-in.