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

# Merchant Events WebSocket

> Connect to the merchant events stream over WebSockets.

## Overview

Use this WebSocket endpoint to receive realtime merchant events (for example: invoice updates, payments, and commerce order events where applicable).

## Authentication

WebSocket connections use a token minted from the REST API. See: [Mint a WebSocket Token](/api-spec/endpoints/ws-token-mint).

## Request

### SDK (recommended)

```ts theme={null}
const stream = pepay.ws.connectMerchantEvents({ format: 'event_v1' });
stream.on('event', (event) => console.log(event));
```

### WebSocket URL (wss)

```bash theme={null}
WS_TOKEN="ws_..."

echo "wss://api-beta.pepay.io/ws/merchant/events?token=$WS_TOKEN"
```

## Response

WebSocket upgrade returns `101 Switching Protocols`. After connecting, you receive frames (for example `event_v1` events).

Example event frame:

```json theme={null}
{
  "id": "evt_1734780000000-123",
  "object": "event",
  "api_version": "2025-12-16",
  "created": 1734780000,
  "type": "invoice.updated",
  "livemode": false,
  "pending_webhooks": 0,
  "data": {
    "object": {
      "object": "invoice",
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "paid",
      "invoice_type": "standard",
      "environment": "devnet"
    }
  }
}
```

## Errors

* `401` invalid/expired ws\_token (connection is rejected/closed)
* Treat delivery as at-least-once; dedupe by `event.id` if you process idempotently.

## Examples

* Use `since=<event_id>` to resume from a known cursor when supported.

Next: [Merchant Invoices](/api-spec/merchant/invoices)


## OpenAPI

````yaml GET /ws/merchant/events
openapi: 3.0.0
info:
  title: Pepay API (SDK-scoped)
  version: 1.0.0
  description: API documentation for Pepay API
servers:
  - url: https://api-beta.pepay.io
    description: Beta server
  - url: http://localhost:3000
    description: Local development
security:
  - bearerAuth: []
tags:
  - name: Events
    description: Events API (history + debugging) for canonical notification envelopes.
  - name: Metrics
    description: Internal Prometheus metrics (restricted).
  - name: WebSockets
    description: WebSocket streams (upgrade endpoints) and message schemas.
  - name: Commerce - Devnet Simulator
    description: >
      Deterministic devnet-only endpoints for simulating Commerce V2 order state
      transitions.


      Use this when integrating as a merchant on devnet to test your backend/UI
      against realistic order lifecycle changes

      (payment confirmation, settlement gating, placement, tracking,
      cancellation, refunds) without placing real retailer

      orders or sending real on-chain refunds.


      How it works:

      - Requires a devnet `X-Commerce-Api-Key` (merchant-scoped).

      - Only operates on orders created in `networkEnvironment=devnet`.

      - Updates the order using the same reducer/persistence paths used in
      mainnet (provider snapshots are simulated).

      - After each simulation, Pepay emits the normal `commerce.order.updated`
      merchant webhook event.
  - name: Merchant Checkout
    description: >
      Merchant-scoped **three-step** checkout flow:

      1) `POST /api/commerce/merchant/checkout/estimate` — validate items
      against current eligible offers and return `validItems[]` +
      `invalidItems[]`.

      2) `POST /api/commerce/merchant/checkout/address` — attach and validate a
      shipping address for the estimate.

      3) `POST /api/commerce/merchant/checkout/invoice` — create the final
      invoice + commerce order.


      Cart behavior (when `useCart: true`):

      - The estimate call **reads** the saved cart but does **not** remove or
      modify cart items.

      - Items with no eligible offers are returned in `invalidItems[]`.

      - To remove items from the saved cart, call the Merchant Cart APIs (`PUT
      /api/commerce/merchant/carts/items/:itemId` with `quantity: 0`, or `DELETE
      /api/commerce/merchant/carts/items/:itemId`).

      - To exclude items for *this checkout attempt* without mutating the cart,
      use `itemOverrides[]` with `quantity: 0`.
  - name: Payment Sessions
    description: >
      Payor-facing APIs used by the hosted payment page and other embedded
      checkout clients.


      Canonical base path:

      - All documented endpoints are under `/api/v1/payments/*`.


      Authentication:

      - These endpoints do **not** accept merchant API keys or bearer JWTs.

      - Send `x-session-token` and `x-signature` headers on every request (both
      are returned when creating an invoice).


      Typical flow:

      1) Create an invoice (`POST /api/v1/invoices`) → receive `payment_url`,
      `session_token`, `signature`.

      2) Render/open the `payment_url` for the payor.

      3) Fetch invoice context (`GET /api/v1/payments/session-details`).

      4) List supported tokens (`GET /api/v1/payments/available-tokens`).

      5) Allocate a payment address (`POST /api/v1/payments/payment-addresses`)
      → use `ws_connection` for `/ws/payment`.

      6) Track progress via polling (`GET /api/v1/payments/payment-status`)
      and/or websocket (`/ws/payment`).


      Security notes:

      - Treat `session_token` and `signature` as sensitive values (anyone with
      them can read the invoice/payment status).

      - Do not store them in long-lived browser storage; prefer in-memory usage
      on the payment page.
  - name: Quotes
    description: Token settlement quotes and rate calculations
  - name: Subscriptions
    description: Recurring subscription plans and charges (X402 Flex).
  - name: Subscriptions - Admin
    description: Admin operations for subscription infrastructure.
  - name: Webhooks
    description: >
      Webhook endpoint management and delivery history for canonical
      notifications.


      Delivery model:

      - At-least-once delivery; receivers must dedupe by `event.id` (also sent
      as `X-Pepay-Event-ID`).

      - Payloads are canonical `PepayEvent` objects and match websocket
      `event_v1` frames for the same event type.


      Security:

      - Endpoints must be HTTPS.

      - Deliveries are signed using `HMAC_SHA256("${timestamp_ms}.${raw_body}")`
      and sent in `X-Pepay-Signature`.
paths:
  /ws/merchant/events:
    get:
      tags:
        - WebSockets
      summary: Merchant Monitor Stream (event_v1)
      description: >
        WebSocket upgrade endpoint that streams canonical `PepayEvent` frames
        for merchant-wide invoice activity.


        Auth options:

        - `x-api-key` header (server-to-server; product keys are limited to
        `invoice_type=products`, subscription keys to
        `invoice_type=subscription_recurring`), or

        - `token=<ws_token>` query param (browser/mobile; mint via `POST
        /api/v1/ws/token`), or

        - `token=<staff_membership_jwt>` query param (staff UI; restricted to
        product invoices).


        Replay:

        - Provide `since=evt_<ms>-<seq>` to replay from Redis Streams within
        retention.

        - If `since` is too old (trimmed/outside retention), the server sends a
        bounded snapshot (as synthetic
        `invoice.updated`/`invoice_payment.updated` events) and then resumes
        realtime.


        Delivery:

        - At-least-once; dedupe by `event.id`.

        - Slow clients are closed with `1013` when buffered frames exceed server
        limits.


        Frames:

        - `PepayEvent` (`object=event`) for business events.

        - `WebSocketControl` (`object=ws_control`) for replay truncation /
        resync hints.

        - `WebSocketError` (`object=ws_error`) for terminal errors (connection
        closes after sending).
      parameters:
        - in: query
          name: token
          schema:
            type: string
          description: Short-lived `ws_token` (browser/mobile auth).
        - in: query
          name: since
          schema:
            type: string
          description: Replay cursor (event id), e.g. `evt_1700000000000-123`.
        - in: query
          name: types
          schema:
            type: string
          description: >-
            Comma-separated allowlisted event type filters (e.g. `invoice.*`,
            `invoice_payment.updated`).
        - in: query
          name: invoice_type
          schema:
            type: string
          description: Optional invoice type filter (e.g. `standard`, `commerce`).
        - in: query
          name: customer_id
          schema:
            type: string
        - in: query
          name: invoice_id
          schema:
            type: string
        - in: query
          name: environment
          schema:
            type: string
            enum:
              - devnet
              - mainnet
        - in: query
          name: format
          schema:
            type: string
            enum:
              - event_v1
      responses:
        '101':
          description: Switching Protocols (WebSocket)
      security:
        - merchantApiKey: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token for wallet authentication
    merchantApiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: API key for server-to-server operations (scope=merchant or commerce)

````