Receipts are the proof-of-license in FX402, showing who paid, which tier was chosen, and how long access is valid.
FX402 supports two receipt mechanisms:
- JWT Receipts — signed, portable tokens
- On-chain Receipts (optional) — anchored for added permanence
🧩 1. JWT Receipts
JWT receipts are cryptographically signed tokens (ES256, Ed25519, etc.) issued after payment.
Example: JWT Receipt Payload
{
"sub": "user:wallet:SoLWallet111...",
"resource": "nft:solana:mint:9abc...xyz",
"tier_id": "7d",
"valid_from": "2025-10-29T00:00:00Z",
"valid_until": "2025-11-05T00:00:00Z",
"paid": {
"amount": "2.00",
"currency": "USDC",
"tx": "4sJQd2cA...FyW"
},
"issuer": "https://facilitator.fx402.xyz"
}Verifying a JWT Receipt
import { verifyReceipt } from "@fx402/r402";
const valid = await verifyReceipt(jwt);
if (valid) console.log("✅ verified!");Facilitator Best Practice:
Expose your public keys via/.well-known/jwks.jsonto enable secure, client-side JWT verification.
🧠 2. On-chain Anchors (Optional)
Receipts may optionally be anchored on-chain for added trust and permanence (e.g., via Solana Memo, IPFS).
| Field | Description |
|---|---|
receipt_cid | IPFS CID (content hash) of the signed receipt |
tx | Blockchain transaction anchoring the hash |
Anchoring allows for verification even if the facilitator goes offline.
🔐 3. Caching & Reuse Strategy
- Cache receipts locally: (IndexedDB, Redis, files, etc.)
- Re-use receipts until their
valid_untiltimestamp expires.
Example: Online Receipt Validation Endpoint
GET /verify?jwt=<token>Response:
{ "valid": true, "expires_in": 23422 }⚙️ 4. Security Considerations
- Always verify
valid_untilagainst server time before granting access. - Never trust unsigned JSON receipts in production.
- Rotate signing keys periodically.
- Include issuer and chain in JWT claims for auditability.
📚 Next Steps
Last updated on