Skip to main content

Public reads — no auth

The asset state, history, alerts and stats endpoints are public:
GET /v1/assets
GET /v1/assets/:symbol
GET /v1/assets/:symbol/state
GET /v1/assets/:symbol/history
GET /v1/alerts
GET /v1/stats
GET /v1/ws         (WebSocket)
No Authorization header required. There is a soft per-IP rate limit (300 req/min by default). The embed widget, the Telegram bot and the public dashboard all read through these endpoints.

Authenticated routes — JWT

User-scoped routes (subscriptions, webhooks, preferences, delivery history) require a JWT in the Authorization: Bearer <token> header:
GET    /v1/me
PATCH  /v1/me/preferences
GET    /v1/me/subs        POST /v1/me/subs       PATCH /v1/me/subs/:asset    DELETE /v1/me/subs/:asset
GET    /v1/me/alerts
GET    /v1/me/webhooks    POST /v1/me/webhooks   DELETE /v1/me/webhooks/:id
POST   /v1/auth/logout
The token is HS256, 7-day lifetime, with revocation tracked server-side in web_sessions.

How to obtain a JWT

The only way to get a JWT in v1 is the Telegram Login Widget. Reasons:
  • Telegram is already the identity for the alert bot (@PeganaWatchBot).
  • No password storage, no email verification, no captcha.
  • One account links Telegram subscriptions, web dashboard sessions, and webhook ownership.
POST /v1/auth/telegram
Content-Type: application/json

{
  "id": 12345678,
  "first_name": "Rafael",
  "username": "raffx",
  "auth_date": 1779889253,
  "hash": "<HMAC-SHA256(bot_token, payload)>"
}
Response:
{
  "token": "eyJhbGciOi...",
  "expires_at": "2026-06-03T14:32:11Z",
  "user": {
    "telegram_id": 12345678,
    "username": "raffx",
    "locale": "en"
  }
}
In practice you do not call this endpoint directly. The Pegana web app embeds the Telegram Login Widget which produces and posts the signed payload.

API keys

There are no API keys in v1. If your use case needs them (server-to-server reads under a quota, key rotation, scoped permissions), open an issue: github.com/lrafasouza/pegana/issues.

x402 — payment, not auth

The two MCP paid tools (getAssetHistory, subscribePegEvents) use x402 instead of JWT. The MCP client opens an HTTP 402 challenge, signs a USDC transfer (via Coinbase CDP), and replays the request. No persistent credentials, no API key. See MCP paid tools — x402 for the full flow.