Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions public/agents.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 <macaroon-from-402>: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/<ref_id>?expand=edges`
"what node types exist" | `GET /api/v2/schema/domains` (free) or `GET /schema`
"how many nodes / topics / people" | `GET /api/stats` (free)
Expand All @@ -265,13 +272,15 @@ Two earn events:

1. **Unlocks (reveals).** When another user fetches a node you added
via `GET /api/v2/nodes/<ref_id>?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": <server-set payout>,
"related_transaction_id": "<unlocker's debit row>",
"node_ref_id": "<your node>",
"created_at": ... }
Expand All @@ -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 <macaroon>:paid` header. The body is
`{"payment_request": "<BOLT11>"}`: 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**
Expand Down
37 changes: 32 additions & 5 deletions public/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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: <yours>, amount: <sats>}` (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 <macaroon>:paid`. Body `{payment_hash: <from top_up_lsat>}`. 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 <macaroon>:paid`. Body `{payment_request: <BOLT11>}` — 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

Expand Down Expand Up @@ -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`).
Expand Down Expand Up @@ -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/<ref_id>?expand=edges` → you receive 10 sats as
`{action:"payout", type:"credit", amount:10, node_ref_id:"<yours>"}`.
`GET /api/v2/nodes/<ref_id>?expand=edges` → you receive a flat,
server-set payout as
`{action:"payout", type:"credit", amount:<payout>, node_ref_id:"<yours>"}`.
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
Expand All @@ -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 <macaroon>: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
Expand Down
Loading