# btcpayserver.md

Everything to configure BTCPayServer so the **shout box** (top-left of the Lightning view) works — where supporters pay sats and leave a public message (the demo shows a "happy birthday" for 21 sats).

The block currently renders in **demo mode** with rotating sample shouts and an "awaiting configuration" badge. This doc turns it real.

---

## 1. Stand up BTCPayServer

Pick one:
- **One-click**: Umbrel / Start9 / RaspiBlitz app store → BTCPay Server.
- **LunaNode / VPS**: the official BTCPay docker-compose deployment.
- **Third-party host**: e.g. Voltage, or a shared BTCPay instance.

You need a domain (e.g. `pay.highermark.xyz`) pointed at it with HTTPS.

---

## 2. Create the store

1. **Server Settings → Stores → Create a new store** → name it `highermark`.
2. **Wallet**: connect an on-chain wallet (xpub from your hardware wallet — keep keys off the server).
3. **Lightning**: Store → Lightning → connect your internal node (LND/CLN) or an external node via connection string.

---

## 3. Turn on tips + messages (the shout box source)

The shout box is a **Pay Button / Tip** with a comment field:

1. Store → **Apps → Create app → Point of Sale** (or **Pay Button**).
2. Item: "Shout / Tip", price **custom** (let payers choose, min 21 sats).
3. Enable **"Allow customer to enter a comment"** (LNURL `commentAllowed`). That comment is the shout.
4. Save and grab the embed/link.

---

## 4. API access (Greenfield) for the live feed

Create an API key so the site can pull recent paid shouts:

1. **Account → Manage Account → API Keys → Generate Key**.
2. Permissions: `btcpay.store.canviewinvoices` (read-only is enough to list paid invoices + their comments).
3. Store the key in **Infisical / env** — never in the repo.

Pull recent shouts:

```bash
curl -H "Authorization: token $BTCPAY_API_KEY" \
  "https://pay.highermark.xyz/api/v1/stores/$STORE_ID/invoices?status=Settled&take=20"
```

Each settled invoice exposes the amount and the buyer comment (`metadata.buyerComment` / posData depending on app). Map to the shout box:

```js
// replace the demo rotateShout() in pay.js with real data
async function loadShouts() {
  const r = await fetch('/api/shouts');          // your backend proxies BTCPay (keeps key secret)
  const items = await r.json();                  // [{ who, sats, msg }]
  // render newest into #shoutMsg, rotate every 5s
}
```

> Proxy BTCPay through your own backend so the API key never reaches the browser.

---

## 5. Webhooks (instant updates)

Store → **Webhooks → Add webhook**:
- URL: `https://highermark.xyz/api/btcpay/webhook`
- Events: `InvoiceSettled`
- On receipt, push the new shout to connected clients (WebSocket / SSE) so the box updates the moment someone zaps.

Verify the `BTCPay-Sig` header against your webhook secret.

---

## 6. Settings checklist

| Setting | Where | Value |
|---|---|---|
| Domain + HTTPS | host | `pay.highermark.xyz` |
| On-chain wallet | Store → Wallet | your xpub (keys offline) |
| Lightning node | Store → Lightning | LND/CLN connection |
| Tip/PoS app | Store → Apps | comment field ON, min 21 sats |
| API key | Account → API Keys | `canviewinvoices`, in Infisical |
| Webhook | Store → Webhooks | `InvoiceSettled` → your backend |
| LNURL comment | Store → Settings | `commentAllowed` ≥ 210 |

---

## 7. Front-end wiring

- The block lives in `index.html` (`.shout` inside the Lightning modal view) and is driven by `rotateShout()` in `assets/js/pay.js`.
- Swap the hard-coded `shouts[]` array for `loadShouts()` (section 4).
- Remove the `▢ awaiting configuration` badge once live.
- Optionally show a small "zap to post a shout" Pay Button under the box that opens your BTCPay PoS link.

---

## 8. Notes

- Min shout 21 sats keeps spam down and matches the demo.
- Moderate: keep a denylist / hold-for-review for comments if the box is public.
- BTCPay is self-hosted and fee-free — fitting for a "pay once, own it" product.
