Skip to Content
Articles & paywalls

Articles & paywalls

Articles are FudFi’s long-form format, separate from threads. They support drafts, tags, cover images, scheduling, and an optional paywall.

Access types

accessTypeBehaviour
publicFull content is returned to everyone.
paywallLocked for non-owners/non-buyers: only previewContent is returned with isLocked: true.

status is one of draft, published, archived, or scheduled.

Create an article

POST /api/articles x-wallet-address: 0xAbC... Content-Type: application/json { "title": "My research note", "subtitle": "Optional deck", "content": "<p>...</p>", "coverImage": "https://... or data:image/...", "tags": ["defi", "security"], "status": "published", "accessType": "public", "price": 0 }
  • The author is resolved from the x-wallet-address header (falling back to userId in the body).
  • A slug is auto-generated from the title (lowercase, non-alphanumerics collapsed, random numeric suffix) and must be unique (409 on collision).
  • readTime is estimated at 200 words per minute.
  • Base64 cover images are uploaded to Cloudinary when configured.

Paywalled articles must have price > 0 or the request fails with 400. The backend auto-generates previewContent from the first two paragraphs (or the first ~300 characters) so the locked view still shows something.

Read articles

GET /api/articles?page=1&limit=20&status=published&userId=...&tag=...&viewerId=... GET /api/articles/:slug
  • The list defaults to status=published. Pass viewerId to receive per-article hasAccess and isLocked, computed from ownership and confirmed purchases.
  • GET /api/articles/:slug returns fresh vote counts and userVote (pass userId), and either the full content or the preview. Authors always have access to their own paywalled articles.

Update & delete

PUT /api/articles/:id # owner or admin DELETE /api/articles/:id # soft delete

Updating a paywalled article regenerates the preview from the new content.

Paywall & payments flow

The shipped paywall checkout is Solana: the browser builds a SOL transfer, the wallet signs it, and the backend verifies the transaction on-chain. (The frontend also bundles @x402/* packages for the EVM stack.)

Read the locked article

The article response is locked (isLocked: true) and exposes price plus the preview.

Pay in the browser

The frontend’s paywall modal requests a SOL transaction with the split to the author (and platform), sends it via the wallet, and waits for confirmation.

Verify and record

POST /api/payments/verify Content-Type: application/json { "signature": "<tx signature>", "articleId": "...", "userId": "..." }

The backend fetches the parsed transaction from the Solana RPC, records a purchases row (status: 'confirmed', seller/buyer wallets, amount), and returns the purchase.

Check access

GET /api/payments/status/:articleId?userId=<id>

Returns { hasAccess: true | false }. Purchases are unique per (userId, articleId) and per signature, so verification is idempotent — re-submitting a signature returns the existing purchase.

Server-only env: SOLANA_RPC_URL (defaults to https://api.mainnet-beta.solana.com). The API never custodies funds — it only verifies and records purchases.