Skip to main content
Bondify uses a stateless proof model. Your server never receives a password or a credential that requires a round-trip to verify. Instead it receives a self-contained, signed JSON Web Token — the proof — which you verify locally with your project’s webhook secret.

Authentication flow

1

Create a session

Your client calls POST /api/v1/generate/public (browser/mobile) or your server calls POST /api/v1/generate (with the secret key). Bondify returns a deeplink, a session_token, and an expires_at.
2

Open Telegram

The client opens the deeplink (https://t.me/<bot>?start=<session_token>). The user lands in the bot.
3

Confirm in Telegram

The user taps Confirm. Bondify marks the session confirmed and records the Telegram identity.
4

Detect confirmation

Your client polls POST /api/v1/verify/public (the SDK does this for you), or your server polls POST /api/v1/verify. The moment the status is confirmed, the response includes a signed proof. Alternatively, configure a webhook to be pushed the confirmed identity directly.
5

Verify on your backend

Your client sends the proof to your own endpoint. Your server calls verifyProof(proof) — a local HMAC/JWT check. If valid, you create your own session (cookie, JWT, DB record — whatever you already use).

The proof format

A proof is a JWT (HS256). Decoded, the payload looks like this:
The token is signed with your project’s webhook secret (whsec_…):
Because it is signed, a valid signature proves Bondify issued the token and nobody tampered with it. Verification is local — there is no network call to Bondify at verify time.
The proof is signed with the webhook secret (whsec_…), not the secret key (sk_…). The same whsec_… verifies both proofs and webhook signatures, so your backend only needs one secret. See Backend verification.

Security properties

No verifying secret on the client

Your webhook_secret and secret_key never leave your server. The browser only ever sees the public project_id, which can initiate sessions but cannot verify proofs or call management APIs.

Proof is short-lived and single-use

  • A proof’s exp is 5 minutes after it is issued. JWT libraries reject it automatically once expired — verify it promptly after you receive it.
  • A session can be read once via /verify; on the first confirmed read it transitions to used and will not produce another proof.

Sessions expire fast

A pending session lives for 10 minutes. If the user never confirms, it becomes expired and the deep link stops working. Generate a fresh session for the next attempt.

Minimal data

Bondify stores only Telegram identity (telegram_id, telegram_name, telegram_username), session metadata (status, timestamps), and — only if you enable phone collection on Pro/Business — telegram_phone. It never stores passwords or OAuth tokens. See Security.

Signed webhooks

Every webhook delivery is signed with X-Bondify-Signature — a hex HMAC-SHA256 of the raw request body, keyed with your webhook_secret. Always verify it before processing. See Webhooks.

Infrastructure

All API requests are HTTPS only.

What Bondify does not do

  • It does not store your users in its own database (only Telegram identity + session metadata).
  • It does not manage your session cookies or JWTs — that is your responsibility.
  • It does not send emails or SMS.
  • It does not provide a UI for user profiles or settings — you build that.