• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
ianmenethil

ianmenethil

ZenServer

Unlisted
Like
ZenServer
Home
Code
10
.cursor
docs
9
src
10
tasks
tests
.gitignore
.vtignore
README.md
deno.json
H
main.ts
Branches
1
Pull requests
Remixes
History
Environment variables
22
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
docs
/
ENDPOINTS.md
Code
/
docs
/
ENDPOINTS.md
Search
7/7/2025
Viewing readonly version of main branch: v280
View latest version
ENDPOINTS.md

API Endpoints & Security Flows v3.5

This document provides the definitive specification for all API endpoints with comprehensive debug integration and honeypot bot detection. It covers both the public "Browse & Pay" journey and the admin-driven "Shareable Link" journey, detailing the purpose, requirements, security controls, and debug visibility for each step.

NEW Features in v3.5:

  • Debug Integration: 9+ numbered security checks with correlation IDs
  • Honeypot Detection: Advanced bot detection using emoji injection pattern
  • Security Visibility: Comprehensive debug output for all security validations
  • Performance Monitoring: Request duration and check timing analysis

Flow 1: Public "Browse & Pay" Journey

This is the primary flow for a user who visits the website, browses tours, and decides to make a payment.

Flow Diagram

sequenceDiagram participant C as Browser (Client) participant S as Server (API) participant G as Zenpay Gateway Note over C,S: User browses site and clicks "Pay Now" on a tour page. C->>S: 1. GET /api/v1/tour/{id} S-->>C: Returns Tour Details<br/>**Sets `SESSION` & `XSRF-TOKEN` cookies** C->>S: 2. POST /api/v1/create-nonce S-->>C: Returns `{ "nonce": "..." }` C->>S: 3. POST /api/v1/payment/exchange-nonce S-->>C: Returns `{ "fingerprint": "..." }` Note over C,G: Client initializes Zenpay plugin with fingerprint. C->>G: 4. User completes payment via Zenpay UI G-->>S: 5. POST /api/v1/payment/callback S-->>G: 200 OK

Endpoint Breakdown

EndpointMethodRequirementsSecurity ControlsUsed ByHow & Why (Justification)
GET /api/v1/toursGETβ€’ Query params: page, limit, featured (optional)β€’ HSTS, CSP HeadersFrontendTours List: Returns paginated list of tours (max 10/page). Security-neutral endpoint - no cookies set. Enables 1-call tour fetching vs 3 separate calls.
GET /api/v1/tour/{id}GETTour ID in path.β€’ HSTS, CSP Headers<br>β€’ Cookie SeedingFrontendEntry Point: Establishes a secure, temporary session context for the browser by setting SESSION and XSRF-TOKEN cookies.
POST /api/v1/create-noncePOSTβ€’ X-XSRF-TOKEN Header<br>β€’ Body: { tourId, cfToken, email_verify }β€’ CSRF Protection<br>β€’ Bot Detection (Turnstile + Honeypot)<br>β€’ Rate Limiting<br>β€’ 9+ Security Checks with DebugFrontendSecurity Gate: Issues a 60-second, single-use "permission slip" (nonce) only after passing comprehensive security validation including honeypot bot detection.
POST /api/v1/payment/exchange-noncePOSTβ€’ X-Payment-Nonce Header<br>β€’ Body: { apiKey, ... }β€’ Nonce Validation<br>β€’ Atomic ConsumptionFrontendFingerprint Generation: Securely consumes the nonce to generate the Zenpay fingerprint. Server injects secrets; they are never exposed.
POST /api/v1/payment/callbackPOSTZenpay JSON body.β€’ Callback AuthenticationBackendPayment Confirmation: Securely verifies the transaction outcome by re-computing and matching Zenpay's ValidationCode. This is the definitive source of truth.

Flow 2: "Shareable Link" (Email) Journey

This flow is for when an administrator generates a direct payment link to send to a specific customer.

Flow Diagram

sequenceDiagram participant A as Admin participant S as Server (API) participant C as Customer's Browser Note over A,S: Admin needs to create a direct payment link. A->>S: 1. POST /api/v1/admin/generate-pay-token S-->>A: Returns `{ "shareableUrl": "..." }` Note over A,C: Admin sends the URL to the customer. C->>S: 2. GET /api/v1/booking/{token} S-->>C: Returns Tour Details<br/>**Sets `SESSION` & `XSRF-TOKEN` cookies** Note over C: From here, the payment process is IDENTICAL to Flow 1. C->>S: 3. POST /api/v1/create-nonce S-->>C: `{ "nonce": "..." }` C->>S: 4. POST /api/v1/payment/exchange-nonce S-->>C: `{ "fingerprint": "..." }`

Endpoint Breakdown

EndpointMethodRequirementsSecurity ControlsUsed ByHow & Why (Justification)
POST /api/v1/admin/generate-pay-tokenPOSTAuthorization Header with Admin API Key.β€’ API Key AuthenticationBackend/Admin ScriptLink Creation: An admin-only, protected endpoint to create a secure, single-use token that forms the basis of a shareable link.
GET /api/v1/booking/{token}GETSecure pay-token in path.β€’ Token Validation (single-use)<br>β€’ Cookie SeedingFrontendLink Entry Point: Validates the one-time token from the URL and then establishes the same secure session context as the public flow by setting SESSION and XSRF-TOKEN cookies.

Where is create-fingerprint? at what point are you creating the actual fingerprint thats needed for zp.init ?

Of course, Menethil. That is an excellent and critical question. I apologize if my previous summary was not clear enough on this point.

You are correct to ask where the fingerprint is created. Let's pinpoint it exactly.

The actual fingerprint needed for $.zpPayment().init() is created by the server during Step 3 of the "Browse & Pay" flow.

Specifically, it happens inside this endpoint call:

POST /api/v1/payment/exchange-nonce

Here is the sequence:

  1. Your frontend calls POST /api/v1/create-nonce and gets a nonce back.
  2. Your frontend immediately calls POST /api/v1/payment/exchange-nonce, sending that nonce in the header.
  3. The server receives this request. It validates the nonce, then securely adds its secret username and password to the other payment details you sent. It combines everything into the pipe-delimited string and creates the SHA3-512 hash. This hash is the fingerprint.
  4. The server's response to this call is a simple JSON object containing the fingerprint: { "fingerprint": "the_hash_value_goes_here" }.
  5. Your frontend code then takes this fingerprint from the response and uses it to initialize the Zenpay plugin.

In the table I provided, this is covered in the row for POST /api/v1/payment/exchange-nonce, under the "How & Why" column:

Fingerprint Generation: Securely consumes the nonce to generate the Zenpay fingerprint. Server injects secrets; they are never exposed.

You are right to want this clarified. The endpoint /api/v1/payment/exchange-nonce is where the server does the work of creating the fingerprint.

how is the frontend sending apikey, mode, paymentamount, merchantuniquepaymentid, tiomestamp to server, at what point, is that how its creating noce or something and exchanging it?

Of course, Menethil. That is the perfect question, and the distinction between the two API calls is the most important part of the entire security design. I will clarify it precisely.

The frontend sends those parameters (apiKey, paymentAmount, etc.) to the server during the second API call.

Here is the exact, step-by-step process:


Step 1: Creating the Nonce with Enhanced Security

First, when the user clicks "Pay Now", the frontend makes a call to POST /api/v1/create-nonce.

  • Purpose: This call performs comprehensive security verification through 9+ numbered security checks. Its job is to get a "permission slip" (the nonce) only after passing all validations.
  • Payload Sent to Server: The frontend sends security validation information:
    { "tourId": "tour_123", "cfToken": "cloudflare_turnstile_token", "email_verify": "🍯" }
  • NEW: Honeypot Field - The email_verify field contains the exact 🍯 emoji for human verification. Bots that fill this field with any other value receive fake nonces.
  • What is NOT sent: At this stage, the server does not need and the client does not send the apiKey, paymentAmount, or timestamp.

Security Validation Process (9+ Checks):

  1. Check1: CORS Origin Check - validates request origin
  2. Check2: CORS Validation Passed - ensures proper CORS headers
  3. Check3: User Agent Security Scan - detects suspicious user agent patterns
  4. Check4: Referer Validation - validates referer for sensitive endpoints
  5. Check5: Origin Validation - validates origin for sensitive endpoints
  6. Check6: Header Content Security Scan - scans headers for malicious content
  7. Check7: Request Size Validation - enforces 1MB request size limit
  8. Check8: Rate Limit Validation - IP-based token bucket algorithm
  9. Check9: Honeypot Bot Detection - validates 🍯 emoji for human verification
  10. CSRF Protection: X-XSRF-TOKEN header verification
  11. Turnstile Verification: Cloudflare bot detection with 90s caching

The server validates this request (checks CSRF, Turnstile, rate limits) and, if it's valid, sends back a nonce.

Step 2: Exchanging the Nonce for the Fingerprint

Now that the frontend has the valid nonce (the permission slip), it immediately makes the second API call to POST /api/v1/payment/exchange-nonce.

  • Purpose: This call's job is to use the permission slip to get the final, valuable item (the fingerprint).
  • Payload Sent to Server: This is when the frontend sends all the payment details:
    { "apiKey": "YOUR_PUBLIC_API_KEY", "mode": "0", "paymentAmount": "15000", "merchantUniquePaymentId": "booking-demo-abc-123", "timestamp": "2025-07-06T04:23:38" }
  • What the Server Does: The server receives these details, validates the nonce from the header, adds its own secret username and password, and then creates the final SHA3-512 hash (the fingerprint). It then returns just the fingerprint to the client.

In short:

  • create-nonce = "Am I a legitimate user allowed to ask for a payment?" (Sends security validation info including honeypot).
  • exchange-nonce = "Okay, I am legitimate. Here are the payment details; please create the fingerprint for me."

Enhanced Security Features v3.5

Debug Integration

NEW: All endpoints now include comprehensive debug integration when DEBUG_MODE=true:

Debug Output Example:

πŸ” DEBUG SESSION STARTED
Correlation ID: 550e8400-e29b-41d4-a716-446655440000
POST /api/v1/create-nonce
IP: 192.168.1.1
───────────────────────────────────────
Check1: βœ… CORS Origin Check
Check2: βœ… CORS Validation Passed  
Check3: βœ… User Agent Security Scan
Check4: βœ… Referer Validation
Check5: βœ… Origin Validation
Check6: βœ… Header Content Security Scan
Check7: βœ… Request Size Validation
Check8: βœ… Rate Limit Validation
Check9: βœ… Honeypot Bot Detection
───────────────────────────────────────
πŸ”’ SECURITY CHECKS SUMMARY
Total checks: 9
Passed: 9 | Failed: 0
Response: 200
Duration: 45ms
πŸ” DEBUG SESSION ENDED

Honeypot Bot Detection

Advanced bot detection using emoji injection pattern:

Frontend Implementation:

// Frontend automatically injects honeypot field const payload = { tourId: selectedTour, cfToken: turnstileResponse, email_verify: "🍯" // Required for human verification };

Response Types:

  1. Human User (Valid Honeypot):
{ "nonce": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4", "expiresAt": "2025-07-06T13:28:40Z" }
  1. Bot Detected (Invalid Honeypot):
{ "nonce": "fake_1b2c3d4e5f6a1b2c3d4e5f6a1b2c", "expiresAt": "2025-07-06T13:28:40Z" }

Detection Logic:

  • Field Missing: Suspicious (sophisticated bot possible) - logs warning but continues
  • Wrong Value: Definite bot detected - returns fake nonce to waste bot resources
  • Correct Emoji (🍯): Human verified - proceeds with real nonce generation

API Endpoint Security Matrix

EndpointSecurity ChecksDebug IntegrationHoneypot Support
GET /api/v1/toursSecurity-neutral - HSTS/CSP headers onlySession trackingN/A
GET /api/v1/tour/{id}Cookie seeding, headersSession trackingN/A
POST /api/v1/create-nonce9+ checks + CSRF + TurnstileFull debug outputβœ… Emoji validation
POST /api/v1/payment/exchange-nonceNonce validation, atomic consumptionSession trackingN/A
POST /api/v1/payment/callbackValidationCode verificationSession trackingN/A
POST /api/v1/admin/generate-pay-tokenAPI key authenticationSession trackingN/A
GET /api/v1/booking/{token}Token validation, cookie seedingSession trackingN/A

Environment Configuration

# Security Configuration ZENPAY_USERNAME="zenpay_username" ZENPAY_PASSWORD="zenpay_password" TURNSTILE_SECRET_KEY="cloudflare_turnstile_secret" ADMIN_API_KEY="admin_api_key" # Debug Configuration (NEW) DEBUG_MODE=true # Enable comprehensive debug output LOG_LEVEL=INFO # Logging level # Server Configuration PORT=5000 # Server port

Performance Considerations

  • Debug Overhead: Debug code only executes when DEBUG_MODE=true
  • Memory Management: Automatic cleanup prevents debug session memory leaks
  • Correlation Efficiency: UUID generation optimized for high throughput
  • Security Check Optimization: Patterns compiled once, reused across requests
FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
Β© 2026 Val Town, Inc.