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

# List the global public feed of peg state-transition alerts (all assets)

> Public, unauthenticated feed of peg state transitions across ALL tracked assets, newest first. For alerts scoped to only the assets YOU subscribe to, use the authenticated `GET /v1/me/alerts` instead.



## OpenAPI

````yaml https://api.pegana.xyz/openapi.json get /v1/alerts
openapi: 3.1.0
info:
  title: Pegana API
  description: >-
    The peg-risk oracle for Solana. Read real-time peg state, history, alerts,
    and delivery health across the live mainnet asset universe spanning 6
    classes — LSTs, fiat / CDP / delta-neutral / yield-bearing / FX stables, and
    a leveraged synthetic. Some assets are flagged `monitoring_only` (beta):
    their alerts are live but the calibration is provisional. Public read
    endpoints require no API key but ARE rate-limited per IP (300/min global,
    10/min on /v1/audit.csv); exceeding the limit returns 429 with a Retry-After
    header. User-scoped /v1/me/* routes require a JWT obtained via Telegram
    Login. Every state transition emits a public receipt at /v1/audit/{id} with
    the methodology version, frozen inputs, and an on-chain SPL Memo commit (SAS
    deferred per ADR-0004 — SPL Memo gives 90% of the value). EVERY error
    response across the API is JSON — the envelope is `{error, message, asset?}`
    (the `ApiError` schema); branch on the stable `error` code, never on
    `message`. Malformed request bodies surface as `{error:"invalid_body"}`. Any
    endpoint may also return 500 `{error:"internal"}` on an unexpected server
    error. Value conventions: monetary and ratio amounts are exact decimal
    STRINGS (parse with a decimal library, never a float) with trailing zeros
    trimmed; USD aggregate fields (e.g. `market_cap`, `loop_exposure_usd`,
    `liquidatable_usd`) are rounded to the cent while price/discount signal
    fields keep full precision. All timestamps are RFC3339 UTC with millisecond
    precision and a `Z` suffix (`2026-07-24T15:33:14.545Z`). Every response
    carries an `x-request-id` header (quote it when reporting an issue) and the
    rate-limit budget as `RateLimit-Limit` / `RateLimit-Remaining` /
    `RateLimit-Reset` (mirrored as `X-RateLimit-*`); a 429 also sets
    `Retry-After`.
  contact:
    name: Rafael Souza
    email: rafael@pegana.xyz
  license:
    name: MIT
    identifier: MIT
  version: 1.0.0
servers:
  - url: https://api.pegana.xyz
    description: Production
security: []
tags:
  - name: Health
    description: Liveness and readiness probes
  - name: Assets
    description: Public read access to asset state, history, and metadata
  - name: Alerts
    description: Global feed of state transitions
  - name: Stats
    description: Aggregate counters and delivery health
  - name: Auth
    description: Telegram Login Widget → JWT
  - name: Me
    description: Authenticated user profile and preferences
  - name: Subscriptions
    description: User alert subscriptions
  - name: Webhooks
    description: User-managed Ed25519-signed webhooks
  - name: WebSocket
    description: Live state stream
  - name: audit
    description: >-
      Public receipts for alerts — methodology version, inputs frozen, replay
      bundles. All endpoints public, no auth, cacheable. ADR-0006 four-state
      response on /v1/audit/:id (200/202/404/410); ADR-0014 bounds (90-day max,
      100-row max, 50k-row cap).
  - name: methodology
    description: >-
      Public lifecycle status of the active methodology — version + status
      (active/deprecated/broken) + optional fix_url when broken. Consumed by
      web/app/api/methodology to power the home-page trust strip.
  - name: peg
    description: >-
      Peg-signal feed for tokens.xyz / aggregator consumption — a `data` array
      of per-asset signals (each carries its own `mint`). Public, no auth,
      cacheable. Honest beta status via `calibration` + `monitoring_only`;
      freshness via `updated_at` + `stale`.
paths:
  /v1/alerts:
    get:
      tags:
        - Alerts
      summary: List the global public feed of peg state-transition alerts (all assets)
      description: >-
        Public, unauthenticated feed of peg state transitions across ALL tracked
        assets, newest first. For alerts scoped to only the assets YOU subscribe
        to, use the authenticated `GET /v1/me/alerts` instead.
      operationId: list_alerts
      parameters:
        - name: asset
          in: query
          description: Restrict to a single asset symbol.
          required: false
          schema:
            type: string
        - name: class
          in: query
          description: Restrict to a single asset class.
          required: false
          schema:
            type: string
        - name: limit
          in: query
          description: |-
            Page size, must be in `[1, 500]`. Default `50`. Out-of-range
            values are rejected with 400 rather than silently clamped.
          required: false
          schema:
            type: integer
            format: int64
        - name: since
          in: query
          description: Inclusive lower bound on `detected_at`. Defaults to now − 7 days.
          required: false
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Global alert feed, newest first
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiList_AlertRow'
        '400':
          description: Invalid ?limit= (must be 1..=500)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
components:
  schemas:
    ApiList_AlertRow:
      type: object
      description: 'List envelope: `{ ok, generated_at, count, data: [...] }`.'
      required:
        - ok
        - generated_at
        - count
        - data
      properties:
        count:
          type: integer
          description: Number of items in `data`.
          minimum: 0
        data:
          type: array
          items:
            type: object
            required:
              - id
              - asset
              - class
              - from_state
              - to_state
              - detected_at
              - monitoring_only
              - calibration
            properties:
              asset:
                type: string
              calibration:
                $ref: '#/components/schemas/Calibration'
                description: >-
                  Consumer-facing calibration label, `provisional` |
                  `calibrated` —

                  the self-describing form of `monitoring_only`, in the SAME
                  vocabulary

                  the dispatcher puts on the webhook canonical event.
                  `provisional` ⇔

                  `monitoring_only=true`.
              class:
                type: string
              detected_at:
                type: string
                format: date-time
              discount:
                type:
                  - string
                  - 'null'
                description: >-
                  Signed discount (spread) captured at detection, as a
                  rust_decimal

                  string. Lets the /events feed show each transition's spread
                  magnitude

                  without a second per-row lookup. `None` for older rows where
                  the

                  `alerts.discount` column is NULL — the client falls back to
                  the asset's

                  live spread, so the field is additive (omitted, never `null`).
              dispatched_at:
                type:
                  - string
                  - 'null'
                format: date-time
                description: >-
                  `null` until the dispatcher delivers this alert to its first
                  fan-out

                  target (Telegram or a webhook subscriber); stamped once at
                  least one

                  delivery succeeds. Stays `null` when the alert matched no
                  subscriber —

                  nothing was delivered — so a `null` here means "not
                  delivered", NOT

                  "delivery failed". Distinct from `detected_at` (when the
                  engine saw the

                  transition) and from on-chain commit (a separate evidence
                  path).
              from_state:
                $ref: '#/components/schemas/PegState'
              id:
                type: string
                format: uuid
              monitoring_only:
                type: boolean
                description: >-
                  True for a released `monitoring_only` (beta) asset — its
                  calibration is

                  provisional, so this alert should be read as experimental.
                  Always

                  present so public-ledger consumers can label beta rows.
              to_state:
                $ref: '#/components/schemas/PegState'
        generated_at:
          type: string
          description: RFC3339 (UTC, millisecond, `Z`) build time of this response.
        ok:
          type: boolean
          description: >-
            Always `true` on a 2xx; errors use the `{error, message}` envelope
            instead.
    ApiError:
      type: object
      required:
        - error
        - message
      properties:
        asset:
          type:
            - string
            - 'null'
          description: The offending asset symbol, present only for asset-scoped errors.
        error:
          type: string
          description: Stable, machine-readable code. Branch on this, never on `message`.
        message:
          type: string
          description: >-
            Human-readable explanation. NOT stable — for humans/logs; do not
            parse.
    Calibration:
      type: string
      description: >-
        Calibration status of an asset (and of an alert that asset emitted).


        - `provisional` — a "beta" asset: released and alerting publicly, but
        its
          thresholds are not yet validated over a full post-launch calibration
          window. Equivalent to `monitoring_only=true`. Read its alerts as
          experimental.
        - `calibrated` — a fully calibrated asset that counts in the launch
          denominator.

        This is the SAME vocabulary the dispatcher emits on the webhook
        canonical

        event (`"calibration":"provisional"|"calibrated"`), so a machine
        consumer

        reading both the webhook fan-out and the REST read surfaces sees one
        word

        for the concept instead of `calibration` there and `monitoring_only`
        here.
      enum:
        - provisional
        - calibrated
    PegState:
      type: string
      description: >-
        Class-aware peg state. Mirrors the engine `PegState` enum and the

        `peg_state` Postgres enum. Used for `state`, `from_state`, and
        `to_state`

        fields across the API.


        The state is CLASS-AWARE: an LST reading a −1.4% discount (normal
        unstaking

        spread) is `PEGGED`, while a fiat stable at far less would be `DRIFT`.
        Trust

        this value directly rather than imposing a naive discount cut.
      enum:
        - PEGGED
        - DRIFT
        - DEPEG
        - CRITICAL
        - BLACK_SWAN
        - UNKNOWN

````