Technical Developer Walkthrough
Interactive API calls with code snippets
# fakeexpedia/backend/app/middleware/hmac_verify.py
import hashlib, hmac, time
from fastapi import Request, Response
SHARED_SECRET = os.environ["PAYFENCE_HMAC_SECRET"]
MAX_AGE = 300 # 5 minutes
async def verify_hmac(request: Request, call_next):
sig_header = request.headers.get("x-payfence-signature", "")
timestamp = request.headers.get("x-payfence-timestamp", "")
request_id = request.headers.get("x-payfence-request-id", "")
# Reject stale requests
if abs(time.time() - int(timestamp)) > MAX_AGE:
return Response(status_code=403, ...)
# Build canonical string
body_hash = hashlib.sha256(await request.body()).hexdigest()
canonical = f"{request.method}\n{request.url.path}?{request.url.query}\n"
canonical += f"{timestamp}\n{request_id}\n{body_hash}"
# Compute expected HMAC
expected = hmac.new(
SHARED_SECRET.encode(), canonical.encode(), hashlib.sha256
).hexdigest()
# Timing-safe comparison
if not hmac.compare_digest(f"v1={expected}", sig_header):
return Response(status_code=403,
content='{"error":"origin_protection_failed"}')
return await call_next(request)Health Check
PendingGET /healthz — hit the SkyRoute origin directly. No auth needed. Confirms the server is running.
Direct Access Blocked (403)
PendingTry calling the origin directly with a valid token. The HMAC middleware rejects it — only gateway traffic is allowed.
Gateway Access Works (200)
PendingSame request routed through the PayFence Gateway. The gateway adds HMAC headers, validates the token, deducts 1 unit, and proxies to the origin.
Search Hotels (1 unit)
PendingGET hotels via the gateway. Different endpoint, same proxy flow. 1 unit deducted.
Place Hold (10 units)
PendingPOST a booking hold through the gateway. Higher-value operations cost more — this one costs 10 units.
Confirm Booking (25 units)
PendingPOST booking confirmation. The most expensive operation at 25 units. Watch the quota meter drop.
Quota Exhaustion (402)
PendingSwitch to a tiny token (5 units). Burn through quota until we hit 402 Payment Required with a checkout URL.
New: SDKs & Features
These steps are display-only concept demos — no live API calls. They showcase PayFence's free tier checkout, SDK integrations, and webhook system.
Free Tier: Email → Instant Access
Free plans don't require payment. Enter an email, get a token instantly.
# Free plan checkout — no credit card required
POST /api/checkout/fakeexpedia/starter-free/free
Content-Type: application/json
{
"email": "dev@example.com"
}
# Response (instant):
{
"token": "pf_live_free_abc123...",
"plan": "Starter Free",
"billingType": "free",
"quotaIncluded": 100,
"message": "You're all set! Use this token to access the API."
}3-Line Integration with Node.js SDK
Install @payfence/middleware and add one line to your Express app.
import { payfenceMiddleware } from '@payfence/middleware';
// Add to your Express app:
app.use(payfenceMiddleware({ apiKey: process.env.PAYFENCE_API_KEY }));3-Line Integration with Python SDK
Install payfence and wrap your ASGI app.
from payfence import PayFenceMiddleware
app = PayFenceMiddleware(app, api_key=os.environ["PAYFENCE_API_KEY"])Real-Time Webhook Notifications
PayFence fires signed webhooks when subscriptions, quotas, or tokens change.
// Webhook payload example:
{
"eventType": "quota.exceeded",
"data": { "customerId": "cust_abc", "tokenId": "tok_xyz" },
"timestamp": "2026-02-15T10:30:00Z"
}
// 5 event types:
// subscription.created, subscription.canceled,
// quota.warning, quota.exceeded, token.rotated
// Verify HMAC-SHA256 signature:
import { verifyPayFenceSignature } from '@payfence/middleware';
const isValid = verifyPayFenceSignature(req.body, signature, secret);What This Demonstrates
Proxy Mode — all API traffic flows through the PayFence Gateway. The origin server rejects direct access via HMAC verification. The gateway handles token validation, quota enforcement, and rate limiting.
Resource Rules — different endpoints cost different amounts. A search costs 1 unit, a hold costs 10, and a booking costs 25. This maps pricing to value.
402 Paywall — when quota hits zero, the response includes a checkout URL for self-serve upgrade via Stripe.