diff --git a/public/agents.txt b/public/agents.txt index f075be5..8554cec 100644 --- a/public/agents.txt +++ b/public/agents.txt @@ -223,8 +223,9 @@ When the human says… | Hit this endpoint | this file never states them. "show my transactions / history" | `GET /api/transactions` → `{transactions[], scope}` "how much have I earned" / | `GET /api/transactions` and sum rows where - "show my payouts" / | `action="payout"` (unlock earnings, 10 sats - "earnings" | each, with `node_ref_id` for per-node + "show my payouts" / | `action="payout"` (unlock earnings — a flat + "earnings" | server-set amount per unlock; read it from the + | row's `amount`, with `node_ref_id` for per-node | attribution). Boost earnings: if your LSAT is | Sphinx-signed they arrive as off-ledger keysend | to your wallet and won't appear here; if @@ -239,6 +240,12 @@ When the human says… | Hit this endpoint "mint a fresh token" | `POST /api/buy_lsat` (no body) → 402 with | macaroon+invoice → pay → use | `LSAT :paid` +"withdraw" / "cash out" / | `POST /api/withdraw` body `{payment_request}` + "send my sats to my wallet" | (a BOLT11 invoice from the receiving wallet, + | with an amount ≤ balance). Same LSAT header. + | Server-set minimum — a too-small invoice gets + | `BELOW_MINIMUM` with the figure in `message`. + | See "Withdrawing" below. "open this node" / "show details" | `GET /api/v2/nodes/?expand=edges` "what node types exist" | `GET /api/v2/schema/domains` (free) or `GET /schema` "how many nodes / topics / people" | `GET /api/stats` (free) @@ -265,13 +272,15 @@ Two earn events: 1. **Unlocks (reveals).** When another user fetches a node you added via `GET /api/v2/nodes/?expand=edges`, the server pays - you a flat **10 sats per unlock**, debited from the unlocker. + you a **flat per-unlock payout**, debited from the unlocker. The + amount is a server-side constant, not stated here — never quote a + figure; read it from the `amount` on the credit rows below. Self-unlock is blocked — you can't pay yourself. The credit appears in `GET /api/transactions` as: { "action": "payout", "type": "credit", - "amount": 10, + "amount": , "related_transaction_id": "", "node_ref_id": "", "created_at": ... } @@ -291,6 +300,28 @@ Two earn events: ledger as `{action:"boost", type:"credit", amount:N}` in `/api/transactions`. +### Withdrawing — earnings are not trapped + +Anything on the token's balance, earned or topped up, can be paid out +to a Lightning wallet with `POST /api/withdraw` and the usual +`Authorization: LSAT :paid` header. The body is +`{"payment_request": ""}`: the invoice *is* the destination, +so it must come from the wallet that should receive the sats, carry an +explicit amount no larger than the balance, and be unexpired. The +server debits first, pays the invoice from its own LN node, and refunds +the debit if the payment fails. + +There is a server-set minimum withdrawal. Do not assume a figure — +send the invoice and, on `400 BELOW_MINIMUM`, read the current minimum +from the response `message` and tell the human. + +If you cannot generate invoices yourself, ask the human for one exactly +as you ask them to pay: in one short message say how many sats are +available (`GET /api/balance`), ask them to open their wallet, tap +"receive", enter an amount, and paste you the `lnbc…` string. Then +call `/api/withdraw` with it. Keysend boost earnings on a Sphinx-signed +token are already in the wallet and never need this route. + ### Identity binding (important for agents) Earnings are bound to the LSAT macaroon **at the moment of** diff --git a/public/llms.txt b/public/llms.txt index 89ce07f..ed336a2 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -127,7 +127,8 @@ direct LN-node check (see `/agents.txt`). Any non-empty string after | POST | `/api/top_up_lsat` | Tops up an existing LSAT. Body `{macaroon: , amount: }` (max 10000 sats). Returns `200 {success, payment_request, payment_hash}` — a new BOLT11 invoice + its hash. Pay it, then call `/api/top_up_confirm`. | | POST | `/api/top_up_confirm` | Settles a paid top-up. Requires `Authorization: LSAT :paid`. Body `{payment_hash: }`. Returns `200 {success, new_balance}` once the LN node sees the invoice settled. Idempotency-protected: a payment_hash can only be confirmed once, by the LSAT it was issued for. | | GET | `/api/top_up_status/:payment_hash` | Poll whether a top-up's invoice has settled yet. Useful while waiting for the human to pay. | -| GET | `/api/transactions` | History. Returns `{transactions: [{action, type:"debit"\|"credit", amount, created_at, related_transaction_id?, node_ref_id?}, ...], scope}`. Amount is always positive; sign comes from `type`. Credits = top-ups, refunds, **and earnings**: `payout` (10 sats per unlock of a node you added, `node_ref_id` attributes the payout to that node) and `boost` with `type="credit"` (someone boosted your content — anonymous L402 path only; Sphinx-signed recipients get off-ledger keysend and won't see anything here). Debits = `search`, `purchase` (you unlocked a node), `boost` (you boosted someone), `add_content`, `add_source`. Filter out rows where `action="purchase"` and `amount=0` (synthetic free-re-access grants). See `/agents.txt` "Earnings" for the full earnings model. | +| POST | `/api/withdraw` | **Cash out balance (including earnings) to a Lightning wallet.** Requires `Authorization: LSAT :paid`. Body `{payment_request: }` — the invoice is the destination, so generate it in the receiving wallet first. The invoice must carry an amount (amountless is rejected), be unexpired, not previously paid, and be within the token's balance. A server-set minimum applies; below it you get `400 BELOW_MINIMUM` whose `message` states the current figure. Boltwall debits the balance, pays the invoice from its LN node, and refunds the debit if the payment fails (`PAYMENT_FAILED`). Errors: `MISSING_AUTH`, `LSAT_NOT_FOUND`, `MISSING_PAYMENT_REQUEST`, `INVALID_INVOICE`, `AMOUNTLESS_INVOICE`, `BELOW_MINIMUM`, `INVOICE_EXPIRED`, `ALREADY_WITHDRAWN`, `INSUFFICIENT_BALANCE` (401). | +| GET | `/api/transactions` | History. Returns `{transactions: [{action, type:"debit"\|"credit", amount, created_at, related_transaction_id?, node_ref_id?}, ...], scope}`. Amount is always positive; sign comes from `type`. Credits = top-ups, refunds, **and earnings**: `payout` (a flat server-set amount per unlock of a node you added — read it from the row's `amount`; `node_ref_id` attributes the payout to that node) and `boost` with `type="credit"` (someone boosted your content — anonymous L402 path only; Sphinx-signed recipients get off-ledger keysend and won't see anything here). Debits = `search`, `purchase` (you unlocked a node), `boost` (you boosted someone), `add_content`, `add_source`, `withdrawal` (paid out to your wallet). Filter out rows where `action="purchase"` and `amount=0` (synthetic free-re-access grants). See `/agents.txt` "Earnings" for the full earnings model. | ## Worked examples @@ -276,8 +277,9 @@ Response: - **Debits (you spent)**: `search`, `purchase` (node unlock), `boost` (you boosted someone else's node), `add_content`, `add_source`. - **Credits (you received)**: `top_up`, `refund`, `payout` (someone - unlocked content you added — currently 10 sats each; the - `node_ref_id` field attributes the payout to a specific node), + unlocked content you added — a flat server-set amount per unlock, + read it from the row's `amount`; the `node_ref_id` field + attributes the payout to a specific node), `boost` with `type="credit"` (someone boosted your content, anonymous L402 recipients only — Sphinx-signed recipients get off-ledger keysend, see `/agents.txt`). @@ -369,8 +371,10 @@ auto-credit the same balance you spend from, and `/api/balance` lifts on the next call. Two earn events: - **Unlock payout** — another user fetches a node you added via - `GET /api/v2/nodes/?expand=edges` → you receive 10 sats as - `{action:"payout", type:"credit", amount:10, node_ref_id:""}`. + `GET /api/v2/nodes/?expand=edges` → you receive a flat, + server-set payout as + `{action:"payout", type:"credit", amount:, node_ref_id:""}`. + The amount is not stated in these docs; read it from the row. Self-unlock is blocked. - **Boost credit** — another user calls `POST /boost` on your node → full amount credited to you (no platform fee). Anonymous L402 @@ -397,6 +401,29 @@ payouts across every macaroon owned by that pubkey; otherwise See `/agents.txt` "Earnings" for the full model (including the non-atomic debit/payout caveat). +### Withdraw ("cash out my sats") + +Balance — top-ups and earnings alike — can be paid out to any Lightning +wallet. The wallet generates an invoice; you hand it to the server: + +``` +curl -sS -X POST -H 'Content-Type: application/json' \ + -H 'Authorization: LSAT :paid' \ + -d '{"payment_request":"lnbc..."}' \ + https://ai.sphinx.chat/api/withdraw +``` + +Response on success: `{ "success": true }` and a `withdrawal` debit +row appears in `/api/transactions`. On failure the body carries an +`errorCode` (see the Payment table). The minimum withdrawal is a +server-side constant, not stated here — a too-small invoice returns +`BELOW_MINIMUM` with the current figure in `message`, so check +`/api/balance` first and let the human size the invoice accordingly. + +If you cannot generate invoices yourself, ask the human for one the same +way you ask them to pay: they open their wallet, choose "receive", enter +the amount, and paste you the `lnbc…` string. + ## Node properties (common fields) - `text` — tweet/claim body