Use Shared mode when you want a user‑controlled wallet that works across Paywalls‑enabled apps, minimal setup (built‑in provider available), and automatic revenue split that preserves your margin.

What it is

  • Users authorize your paywall once, top up their shared wallet, and can spend across apps.
  • You can use the built‑in provider (powered by OpenRouter) with no keys, or BYOK.
  • Charges deduct from the user’s shared wallet; your developer earnings accrue for withdrawal.

When to use it

  • You want the lowest‑friction launch (no provider setup required).
  • Your users may use multiple apps; a single wallet improves UX and conversion.
  • You’re fine with hosted top‑ups and later withdrawals rather than instant settlement to your Stripe.

Key behaviors

  • Authorization required: the first time a user interacts with your paywall, they’ll be asked to authorize it.
  • Assistant messages: if authorization or funding is needed, the proxy returns a normal assistant message containing the correct link—render it as a typical model reply.
  • Pricing: per‑model pricing + optional markup is enforced by the proxy; manual charges are also supported.

Blockchain & settlement

Shared mode settles on-chain. Today it runs on Polygon and is designed to be chain‑agnostic, so it can operate on additional EVM chains without app changes (more chains coming soon).
  • Network: Polygon
  • Currency: USDC (on Polygon) — used for all Shared mode operations: deposits/top‑ups, balances, charges, and payouts.
  • Accounting: all amounts in Shared mode are tracked and displayed in USDC.
  • Interop: the settlement layer is abstracted; enabling more chains won’t require client‑side changes.
If you show balances to users, label them as USDC and avoid implicit fiat conversions in the UI.

Typical flow

  1. First chat request (not authorized yet)
  • You call POST /chat/completions. If the user isn’t connected, you receive a normal assistant message with an authorization link.
  • Show that message verbatim in your UI. After the user authorizes, requests proceed.
  1. Insufficient funds
  • If balance is low, the assistant message contains a top‑up link (hosted).
  • After payment, the next request succeeds automatically.
  1. Normal usage
  • Requests are metered and charged automatically; responses stream as usual.

Useful endpoints

Minimal example (manual charge + renderable fallback)

// If success === false, the 'message' field is a renderable assistant message (auth/top‑up link).
const res = await fetch("https://api.paywalls.ai/v1/user/charge", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAYWALLS_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": requestId,
  },
  body: JSON.stringify({ user, amount: "0.001", metadata: { requestId } }),
});
const json = await res.json();
if (json.success) {
  // proceed
} else {
  // show json.message to the user (no special branching needed)
}

Tips

  • Always send a stable, pseudonymous user id (body user or header X‑Paywall‑User).
  • Treat assistant messages as normal chat replies—just render them.
  • Use idempotency keys for all non‑idempotent POSTs (manual charges, your own side effects).
See also: