Skip to main content
After you create a session with POST /api/v1/generate/public and open the deeplink in the user’s Telegram app, call this endpoint repeatedly to check whether the user has acted on the prompt. The endpoint is safe to call from a browser or mobile app — no Bearer token is required. Poll every 2 seconds and stop as soon as you receive a terminal status: confirmed, cancelled, expired, or used.

Endpoint

POST https://api.bondify.dev/api/v1/verify/public
No Authorization header is required.

Request body

project_id
string
required
Your Bondify project ID — the same value you passed to generate/public.
session_token
string
required
The session_token returned by POST /api/v1/generate/public.

Example request

curl -X POST https://api.bondify.dev/api/v1/verify/public \
  -H "Content-Type: application/json" \
  -d '{"project_id": "proj_xxxxxxxx", "session_token": "sess_abc123xyz"}'

Response by status

The shape of the response depends on the value of status.

pending

The user has not yet interacted with the Telegram prompt. Keep polling.
{ "status": "pending" }

confirmed

The user tapped Confirm in Telegram. Stop polling and log the user in. Always verify the proof JWT on your server using your project’s secret key before creating a session.
{
  "status": "confirmed",
  "telegram_id": "123456789",
  "telegram_name": "Alex Johnson",
  "telegram_username": "alexj",
  "proof": "eyJhbGciOiJIUzI1NiJ9..."
}

cancelled

The user tapped Cancel in Telegram. Stop polling and inform the user.
{
  "status": "cancelled",
  "cancelled_at": 1700000000000
}

expired

The session was not acted upon within 10 minutes. Stop polling and offer the user a way to try again.
{ "status": "expired" }

used

The session has already been successfully verified once. Stop polling and generate a fresh session if the user needs to authenticate again.
{ "status": "used" }

Response fields

status
string
The current state of the session. One of "pending", "confirmed", "cancelled", "expired", or "used". A session transitions to "used" after it has already been successfully verified once — do not attempt to reuse it.
telegram_id
string
The user’s numeric Telegram ID. Present only when status is "confirmed".
telegram_name
string
The user’s Telegram display name. Present only when status is "confirmed".
telegram_username
string | null
The user’s Telegram @handle, or null if the user has not set a username. Present only when status is "confirmed".
proof
string
A signed JWT that encodes the user’s Telegram identity. Present only when status is "confirmed". Verify this token server-side using your project’s secret key before trusting the identity and creating an application session.

Polling example

The function below polls every 2 seconds with a 10-minute hard deadline. It returns the confirmed payload on success and throws on any terminal failure:
async function pollSession(projectId: string, sessionToken: string) {
  const deadline = Date.now() + 10 * 60 * 1000; // 10 min timeout

  while (Date.now() < deadline) {
    await new Promise(r => setTimeout(r, 2000)); // wait 2 seconds

    const res = await fetch('https://api.bondify.dev/api/v1/verify/public', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ project_id: projectId, session_token: sessionToken }),
    });
    const data = await res.json();

    if (data.status === 'confirmed') return data;           // success
    if (data.status === 'cancelled') throw new Error('Cancelled by user');
    if (data.status === 'expired')   throw new Error('Session expired');
    if (data.status === 'used')      throw new Error('Session already used');
    // status === 'pending' → keep polling
  }
  throw new Error('Timed out');
}
Always handle cancelled, expired, and used explicitly — stop the poll loop immediately on any of these statuses and show the user a clear message. Continuing to poll after a terminal status wastes requests and can confuse your UI state.

Session status reference

StatusMeaningRecommended UI action
pendingWaiting for user action in TelegramKeep polling, show a loading indicator
confirmedUser tapped ✅ ConfirmStop polling, verify the proof, log the user in
cancelledUser tapped ❌ CancelStop polling, show “You declined the request”
expiredSession not used within 10 minutesStop polling, offer a “Try again” option
usedSession already consumedStop polling, generate a fresh session if needed