API reference
The backend receives verification, content, analytics, and earnings events from the widget, package, and dashboard.
Endpoint names can still move while the backend settles. Treat this page as the intended public shape and keep implementation docs updated as routes stabilize.
Base URL
https://api.nibgate.xyzThe host is already api., so routes live under their group name directly (/hub/..., /nibshare/...) — no /api prefix. The legacy /api/... forms still work.
API groups
Auth
Sign-In with Ethereum (SIWE) powers creator sessions on both the hub and Subblogs.
GET /auth/nonce # request a nonce for a wallet
POST /auth/verify # verify the signed SIWE message, issues auth_session cookie
GET /auth/me # current session (wallet, profile)
POST /auth/logout # clear the session(Both /auth/... and /api/auth/... forms work — the /api prefix is redundant with the api. host.)
On Subblogs the same flow lives under /api/auth/* (nonce, verify, me, logout) and issues the sb_auth_session HttpOnly cookie; sessions resolve to a wallet via User.walletAddress. A session wallet is a possession signal — it can satisfy proof-bound access without a bare ?wallet= claim.
Status & stats
GET /api/nibgate/status # service liveness
GET /hub/stats # platform totals: creators, sites, content, views, unlocks, revenue
GET /hub/sitemap-sites # verified sites feed for sitemaps
GET /hub/sitemap/content # verified content feed for sitemapsSite registration
Dashboard APIs create sites, issue verification tokens, recheck widget health, and archive removed sites.
POST /hub/sites/register
GET /hub/sites
POST /hub/sites/:websiteId/verify
DELETE /hub/sites/:websiteIdNote: the path param is websiteId (the site UUID), and registration is /sites/register — not POST /hub/sites.
Event ingestion
Widget and package event routes should reject unknown origins, removed sites, stale verification, and malformed content ids.
POST /hub/evtAccepts the same payload as the legacy /hub/track endpoint (still available for backward compatibility). The rename avoids adblocker filter lists targeting the word “track”.
Intended event shape:
{
"siteId": "site_123",
"token": "verify_token",
"event": "resource_view",
"resource": {
"id": "post_123",
"title": "Paid research note",
"url": "https://creator.com/research",
"recipient": "0xCreator"
}
}The siteId + token (the site’s verification token) prove the creator origin. The recipient wallet links the content to the creator account and payment receiver for the verified site. A missing siteId or token returns 400, and an invalid token returns 403.
Hosted payments
The hosted pay endpoint runs the x402 payment flow on behalf of creators. No server access route needed.
POST /hub/payRequest:
{
"price": "0.01",
"recipient": "0xCreatorWallet",
"title": "Premium Post",
"paymentRail": "gateway",
"contentId": "content-uuid-or-external-id",
"path": "/posts/my-post"
}| Field | Required | Description |
|---|---|---|
price | No | Defaults to 0.01. Overridden server-side when contentId maps to a tracked content record |
recipient | No | Wallet to receive payment. Falls back to NIBGATE_SELLER_ADDRESS env var; tracked records’ recipientWallet wins. Hosted mode routes through the creator’s fee wallet (99% creator / 1% platform) |
title | No | Content title for the payment challenge |
paymentRail | No | 'gateway' (Circle Gateway, default) or 'transfer' (direct USDC transfer to the resolved payTo) |
contentId | No | Content record id — pins price/recipient server-side and scopes the direct-rail txHash claim |
path | No | Resource path used in the payment challenge and ownership-proof message |
Returns a 402 Payment Required challenge on first call. For the gateway rail the browser settles Circle’s batching challenge and retries with a Payment-Signature; for the transfer rail the browser broadcasts the USDC transfer and retries with x-nibgate-transfer-tx plus an x-nibgate-tx-owner EIP-191 signature binding the txHash to this resource (transferOwnershipMessage). Direct-rail txHashes are claimed single-use per contentId — replays against other content fail with txhash-claimed-elsewhere. On success, returns 200 with { success: true, payment: { paymentProvider, verified, recipient, network, amount, revenue, currency, payer, txHash } }.
The widget handles this automatically when using data-nibgate-premium attributes — no manual API calls needed.
Explore content
Explore reads verified content metadata from the backend.
GET /hub/explore/content?q=music&type=music&sort=trendingPublic ledger
The ledger provides a live, auditable feed of views, unlocks, payments, and ratings across all sites.
GET /hub/ledger?limit=50&skip=0&type=&domain=| Param | Default | Description |
|---|---|---|
limit | 50 | Items per page (max 100) |
skip | 0 | Offset for pagination |
type | — | Filter by activity type: views, unlocks, payments, ratings |
domain | — | Filter by site domain (e.g. fortune.nibgate.xyz for per-site activity) |
Returns sorted activity list plus total counts across all records.
{
"success": true,
"activities": [
{
"type": "payment",
"id": "…",
"websiteId": "…",
"actor": "0x…",
"contentId": "…",
"contentTitle": "Premium Post",
"contentUrl": "https://fortune.nibgate.xyz/writing/premium-post",
"domain": "fortune.nibgate.xyz",
"amount": 0.01,
"currency": "USDC",
"timestamp": "2026-07-28T19:17:24.000Z",
"paymentId": "…",
"txHash": "0x…",
"chainId": "5042002",
"network": "eip155:5042002",
"paymentProvider": "circle-gateway",
"receiptUrl": "…",
"payerWallet": "0x…",
"recipientWallet": "0x…",
"status": "verified"
}
],
"totals": {
"views": 300,
"unlocks": 160,
"payments": 175,
"ratings": 70,
"total": 705
},
"hasMore": false
}The ledger is also available as a UI at https://nibgate.xyz/ledger with search, filtering, expandable row details, and live updates.
Reputation & ratings
Ratings are built from verified unlock eligibility, not raw votes:
POST /hub/reputation/ratings/prepare # sign a deterministic rating message (eligibility checked first)
POST /hub/reputation/ratings/index # index a delivered rating (onchain or signed)
POST /hub/reputation/ratings/sync # reconcile indexed rating proofs
GET /hub/reputation/leaderboards # content / site / creator leaderboards
POST /hub/content/:contentId/rate # rating surface for a resourceNibshare
The hosted quick-share rail lives at /ns/<slug> on the hub and /api/nibshare on the API host. Every gated share enforces the shared access rule — a bare ?wallet= is a claim only, never an identity:
GET /api/nibshare/:slug/quote # price + policy for the share
GET /api/nibshare/:slug/meta # public metadata
GET /api/nibshare/:slug/manifest # machine-readable contract for agents
GET /api/nibshare/:slug/access # access decision; 200 grant / 402 challenge / 403 deny
POST /api/nibshare/:slug/unlock # x402 unlock; binds proof to (wallet, share)
GET /api/nibshare/:slug/media/:kind # encrypted media (proof-gated for paid/invite-only)
DELETE /api/nibshare/:slug/entitlements/:wallet # restore (un-ban / un-revoke) an entitlement
POST /api/nibshare/:slug/entitlements/:wallet/ban # ban (hard deny, no re-purchase)
POST /api/nibshare/:slug/entitlements/:wallet/revoke # revoke (may re-purchase)
PUT /api/nibshare/:slug/access-control # edit price/whitelist/publicAccess (owner + SIWE)
GET /api/nibshare/:slug/access-control # read current whitelist/tier/invite policy
POST /api/nibshare/:slug/view # imply a view
GET /api/nibshare/stats # public platform aggregates
GET /api/nibshare/dashboard # per-owner dashboard stats (owner + SIWE)
POST /api/nibshare/gateway/balance # depositor USDC balanceError semantics: 402 = payment challenge, 403 = denied (invite-only, banned, revoked, or payer ≠ possessed wallet), 404 = draft/unpublished, 410 = revoked, 419 = expired. Full detail: backend/src/server/nibshare/API.md.
Subblogs
Subblog content gates mirror the hub under the subblog’s own origin (/api/... on *.nibgate.xyz):
GET /api/nibgate/access?path=/<type>/<slug> # x402 access; 200 with decrypted content / 402
GET /api/nibgate/manifest?path=… # per-post agent contract
GET /api/nibgate/media/:postId/:kind # encrypted media proxy (proof-gated for paid)
GET /api/nibgate/posts/:key/quote # price + access decision for a post
GET /api/<type>/<slug> # short mirror of the access route
PUT /api/nibgate/posts/:key/access-control # edit whitelist/tier/publicAccess (admin only)
GET /api/nibgate/posts/:key/access-control # read whitelist/tier/invite policy (admin only)
POST /api/nibgate/posts/:key/entitlements/:wallet/{ban,revoke} # gating actions (admin only)
DELETE /api/nibgate/posts/:key/entitlements/:wallet # restore (admin only)
GET /api/nibgate/gateway/balances # depositor USDC balance (admin)Non-published posts return 404; invite-only denies non-whitelisted wallets with 403 before any payment. Subblogs admin actions require the sb_auth_session cookie and the admin role (authorize('admin')).