# more.md — agent integration primer

This guide is optimized for autonomous HTTP clients / LLMs. It is deliberately short and contains no privileged secrets.

**Bootstrap:** machine-readable orientation is at **`GET /<API origin>/?format=json`** (capabilities, discovery order, auth headers, x402 replay hint). Prefer that over scraping browser HTML landing pages.

## How to browse

Use normal HTTPS GET. Many resources are anonymous. Respect `robots.txt` and crawl politely.

## Gates and HTTP 402

When pricing or trust tiers block access, endpoints return HTTP **402** with JSON describing the refusal and cryptographic payment hints.

Important headers:

- `WWW-Authenticate: EEP realm="gate"` — site uses EEP-style gates (see DID document + gates_config URL below).
- `X-EEP-Gates-Config` — relative HTTPS path to retrieve `gate_configs` metadata for decoding tier expectations.
- `PAYMENT-REQUIRED` — base64 JSON object following **x402 v2** describing exact payment offers (`accepts[].scheme=="exact"` with `network`, `asset`, atomic `amount`, `payTo`, EIP-3009 typed data nested under `accepts[].extra.eip3009`).

Structured JSON repeats key fields (`docs_url`, `payment_required_b64`, `decoded_payment_required`, `inline_retry_supported`). Always prefer the verbatim `PAYMENT-REQUIRED` header when issuing payments.

## Paying inline (recommended)

Instead of coupling to bespoke settlement routes, wallets sign the advertised EIP-712 transfer authorization contained in PAYMENT-REQUIRED, assemble the canonical **PaymentPayload**, base64-wrap it into the **PAYMENT-SIGNATURE** header value, then **replay the identical GET request** URL (including desired `Accept`/`format`). On success you'll receive HTTP 200 with the resource.

If payment fails verify `PAYMENT-RESPONSE`, chain network, payer balance vs amount, timeouts, stale nonces.

## Fallback settlement

Some deployments still expose REST helpers under `/eep/payment/*`; treat those as transitional. Prefer inline retry wherever `inline_retry_supported: true`.

## Stripe Machine Payment Protocol (MPP) — link.com / link-cli

When the publisher accepts fiat through more.md's central Stripe merchant AND has onboarded to Stripe Link Agentic Commerce, the **same 402** carries a second `WWW-Authenticate` value alongside `EEP`:

```
WWW-Authenticate: EEP realm="gate", resource="/c/news/post-1"
WWW-Authenticate: Payment id="<JWS>", realm="api.more.md", method="stripe", intent="charge", request="<base64-json>", expires="2026-05-15T20:00:00Z"
```

The `request` payload decodes to `{"amount": "50", "currency": "usd", "methodDetails": {"networkId": "profile_xxx", "paymentMethodTypes": ["card", "link"]}}` — Stripe's standard MPP envelope.

### Happy path (link-cli, SPT)

Install `@stripe/link-cli` once (`npm install -g @stripe/link-cli` or `npx @stripe/link-cli`), then:

```bash
link-cli auth login --client-name "<your-agent-name>"     # one-time user approval in Link app
link-cli mpp decode --challenge '<the WWW-Authenticate Payment header>'
link-cli spend-request create \
    --credentialType shared_payment_token \
    --networkId <profile_xxx from decode> \
    --amount <cents> --currency usd \
    --paymentMethodId <pm_> \
    --context "..."
# user approves in Link app
link-cli mpp pay <gated resource URL> --spendRequestId <id>
```

`link-cli mpp pay` automatically re-issues the gated GET with `Authorization: Payment <SPT>` set; more.md confirms the SPT against Stripe in-band (one-time-use atomic) and serves the resource on the same response. Receipt + entitlement land via the existing webhook + ledger path.

Agents that prefer to drive the wire format themselves can POST the SPT to `/eep/payment/stripe/mpp/settle` instead (see OpenAPI: `operationId: mppSettle`).

### Virtual-card alternative (any browser-using agent)

If a browser/computer-use agent prefers a traditional checkout:

```bash
link-cli spend-request create --credentialType card --amount <cents> --currency usd --context "..."
link-cli spend-request retrieve <id> --include card   # → PAN, CVC, exp, billing_address
```

POST `/eep/payment/stripe/checkout-human` with the requirement coordinates → get a hosted Stripe Checkout URL → type the PAN. Same merchant account, same webhook receipt path.

### Capability hint

Send `X-EEP-Agent-Capabilities: stripe-mpp` (or `x402` / both, in preference order) on the original gated GET. The 402 `accepts[]` list reorders so your preferred rail surfaces first — fallback rails stay listed so a transient SPT failure can be retried against x402 USDC without re-fetching the 402.

## Auditing your payments

Every successful settlement persists two artifacts you can fetch later:

- **Receipt artifact JSON** — full record of seller, resource, on-chain settlement, your DID/wallet, and the gate-hit→payment timeline. `GET /eep/payment/receipts/{receiptId}`.
- **Receipt PDF** — human-readable, professionally typeset version of the same record. `GET /eep/payment/receipts/{receiptId}.pdf` returns **`200`** with **`application/pdf`** bytes (streamed via the API after server-side object storage read); use session or API key auth — no presigned redirect.

List your own receipts (paginated by `(issued_at DESC, receipt_id)`) at `GET /eep/payment/receipts`. Authenticate with either an API key on `X-API-Key` or by sending your stable agent identity on `X-EEP-Agent-DID`; both can match the receipt's `payer_did` or `payer_account_id`.

## Durable access (entitlements)

When a gate tier sets `requirement.per` to `hour | day | week | month | year | once`, settlement also writes a **`payment_entitlement`** row scoped to the matched tier `access` pattern. Subsequent requests that present the same payer subject are granted access without paying again until `valid_until` passes (NULL means permanent for `per: once`).

### Replaying the entitlement on the next request

The 200 response from a successful **PAYMENT-SIGNATURE** retry carries three replay hints:

```
Set-Cookie: eep_payer=<wallet>%7C<network>; HttpOnly; SameSite=Lax; Max-Age=604800; Path=/
X-EEP-Payer-Wallet: <wallet>
X-EEP-Payer-Network: <network>
```

On every subsequent fetch of the same (or any sibling) gated resource, pass one of:

- The `eep_payer` cookie — any HTTP client with a cookie jar (browser `fetch`, Python `httpx.Client`, `curl -b`) replays it transparently. **No code change needed.**
- The `X-EEP-Payer-Wallet` + `X-EEP-Payer-Network` request headers — fully stateless agents copy them from the previous response into the next request. Useful when each call is a fresh client instance.

The gate looks up an active `payment_entitlement` row keyed on `(profile_id, resource_pattern, payer_wallet_address, payer_network)`. If a match is found, the request is granted without re-paying. A wallet that has not paid for this resource gets a normal 402 — the wallet address alone is not a credential, it is just the lookup key for content that wallet already owns.

Authenticated agents have stronger options: `X-EEP-Agent-DID` (with a verified `EEP-Signature`) or a session cookie / API key bind the entitlement to a stable identity that survives wallet rotation.

`per: request` writes no entitlement: each new request must include a fresh PAYMENT-SIGNATURE.

## Discovery

Human + machine manifests:

| Resource | Purpose |
|---------|---------|
| `/.well-known/eep.json` | Platform capabilities, WS/SSE hubs, conformance notes |
| `/.well-known/eep/agent-guide.md` | Canonical copy of this document |
| `GET /discover` | Capability catalog for autonomous tooling |
| `GET /docs/openapi.json` | Full REST surface |

**Content URLs on the API origin:** use `GET /{prefix}/{username}/content[/…]` (for example `/u/alice/content` or `/u/alice/content/premium/page`). The path mirrors the marketing-site URL so a link copied from a profile page works against the API verbatim.

## Operational notes

- Default test network for USDC EIP-3009 demos: **Base Sepolia** (`eip155:84532`).
- Always surface spend authorization to humans unless your operator policy explicitly switches to autopilot.
- Log correlation headers such as `X-EEP-Funnel-Request-Id` when diagnosing payment failures.
