Skip to main content
Every time a user taps “Sign in with Telegram”, Bondify creates a session — a short-lived record that tracks a single authentication attempt from start to finish. The session is identified by a session_token string and lives for a maximum of 10 minutes. Your app uses this token to open Telegram, poll for the result, and ultimately retrieve the signed proof that confirms the user’s identity.

Session lifecycle

1

Created

Your server (or frontend, for public-access projects) calls POST /api/v1/generate/public with your project_id. Bondify creates a new session and returns a session_token and a Telegram deeplink.
2

Pending

Your app opens the deeplink, which launches Telegram and directs the user to the Bondify bot. The bot presents a confirmation message. The session status is pending while you wait.
3

Terminal

The session reaches one of three terminal outcomes:
  • The user taps ✅ Confirm → status becomes confirmed
  • The user taps ❌ Cancel → status becomes cancelled
  • 10 minutes elapse with no action → status becomes expired
Once confirmed and the proof is consumed by a verifyProof() call, the status moves to used.

Session statuses

StatusDescriptionWhat to do next
pendingWaiting for user action in TelegramContinue polling every 2 seconds
confirmedUser tapped ✅ ConfirmStop polling, verify the proof, create your app session
cancelledUser tapped ❌ CancelStop polling, show “You declined the request”
expired10-minute timeout reachedStop polling, offer the user a chance to try again
usedProof already consumed by verifyProof()Stop polling, generate a new session for the next attempt

Polling guidance

Poll POST /api/v1/verify/public every 2 seconds, passing the session_token. Stop polling as soon as you receive any terminal status (confirmed, cancelled, expired, or used).
# Poll every 2 seconds
curl -X POST https://api.bondify.io/api/v1/verify/public \
  -H "Content-Type: application/json" \
  -d '{"project_id": "proj_xxxxxxxx", "session_token": "sess_abc123"}'
// While waiting
{ "status": "pending" }

// On user confirmation
{
  "status": "confirmed",
  "telegram_id": "123456789",
  "telegram_name": "Alex Johnson",
  "telegram_username": "alexj",
  "proof": "eyJhbGci..."
}

// On user cancellation
{ "status": "cancelled" }

// On timeout
{ "status": "expired" }
Sessions are single-use. Once a session reaches confirmed and you call verifyProof(), Bondify marks it as used. Any subsequent poll will return { "status": "used" }. Always generate a fresh session for each new login attempt.
Never reuse a session_token across multiple login attempts. Each session is cryptographically tied to a single authentication event. Reusing tokens will result in a used or expired response.

The Session object

When you poll and the status is confirmed, the response includes the full session data:
FieldTypeDescription
idstringUnique session identifier
project_idstringThe project this session belongs to
project_namestringThe display name of the project that owns this session
telegram_idstringThe user’s Telegram account ID — only populated on confirmed
telegram_namestringThe user’s Telegram display name — only populated on confirmed
telegram_usernamestringThe user’s @handle — only populated on confirmed; empty string if the user has no username
statusstringCurrent status: pending, confirmed, cancelled, expired, or used
created_atstringISO 8601 timestamp of session creation
confirmed_atstring | nullISO 8601 timestamp of confirmation; null until the user confirms
Use confirmed_at on the server to double-check that the session was confirmed recently. If the timestamp is unexpectedly old (e.g., replayed from a log), treat the request as suspicious and reject it.

Next steps

Authentication Flow

See the complete end-to-end flow — from session creation through proof verification.

Security

Learn how Bondify’s signed proofs prevent fake and replayed auth events.