> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bondify.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How Bondify works

> A technical deep-dive into Bondify's stateless, JWT-based authentication architecture.

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

<Steps>
  <Step title="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`.
  </Step>

  <Step title="Open Telegram">
    The client opens the `deeplink` (`https://t.me/<bot>?start=<session_token>`). The user lands in the bot.
  </Step>

  <Step title="Confirm in Telegram">
    The user taps **Confirm**. Bondify marks the session `confirmed` and records the Telegram identity.
  </Step>

  <Step title="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](/guides/webhooks/webhooks) to be pushed the confirmed identity directly.
  </Step>

  <Step title="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).
  </Step>
</Steps>

## The proof format

A proof is a **JWT (HS256)**. Decoded, the payload looks like this:

```json theme={null}
{
  "telegram_id": "123456789",
  "telegram_name": "Ada Lovelace",
  "telegram_username": "ada",
  "project_id": "proj_xxxxxxxx",
  "session_token": "a1b2c3d4e5f6…",
  "iss": "bondify",
  "iat": 1700000123,
  "exp": 1700000423
}
```

The token is signed with your project's **webhook secret** (`whsec_…`):

```
HS256( header.payload, webhook_secret )
```

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.

<Note>
  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](/guides/backend-verification/backend-verification).
</Note>

## 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](/security/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](/guides/webhooks/webhooks).

## Infrastructure

| Service       | URL                        |
| ------------- | -------------------------- |
| REST API      | `https://api.bondify.dev`  |
| Dashboard     | `https://bondify.dev`      |
| Documentation | `https://docs.bondify.dev` |

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.
