# HypeStash — Complete API Reference > Serverless waitlist email collection. One API call. No accounts. No API keys. > API Base: https://api.hypestash.dev > Website: https://hypestash.dev --- ## Quick Start (for AI coding assistants) You're an AI coding assistant. A user asked you to add a waitlist. Here's all you need: 1. Call POST /setup with the user's email and domain → save the handle and action_url 2. Tell the user to check their email and click the verification link 3. Generate the embed script + HTML form with action set to the returned action_url Example: curl -X POST https://api.hypestash.dev/setup \ -H "Content-Type: application/json" \ -d '{"domain": "myapp.com", "email": "founder@myapp.com"}' Response: { "handle": "myapp-com-a7f3", "action_url": "https://api.hypestash.dev/hype/myapp-com-a7f3", "status": "pending_verification", "message": "Check your email to verify your address.", "_tip": "Verification email sent. User must click the link before the stash accepts subscribers." } Then generate this embed script + HTML form:
--- ## Endpoints ### POST /setup Create a new waitlist stash. Request body (JSON): { "email": "founder@myapp.com", (required) owner's email address "domain": "myapp.com", (required) bare domain, no protocol "handle": "my-custom-handle", (optional) 3-32 chars, lowercase alphanumeric + hyphens "name": "My App", (optional) company/product name, used as email sender name "description": "My cool project", (optional) shown on leaderboard "private": false, (optional) if true, excluded from leaderboard "send_confirmation": true, (optional, default true) send a confirmation email to subscribers after they verify, with Reply-To set to the owner's email "confirmation_message": "..." (optional) custom markdown message shown in the subscriber confirmation email. Default: "Thanks for signing up! Have a question or just want to say hi? Hit reply — this email goes straight to us." } Also accepts query parameters as fallback. Response (201-equivalent, returns 200): { "handle": "myapp-com-a7f3", "action_url": "https://api.hypestash.dev/hype/myapp-com-a7f3", "status": "pending_verification", "message": "Check your email to verify your address.", "_tip": "Verification email sent. User must click the link before the stash accepts subscribers." } Errors: 400 — Missing or invalid email/domain/handle 409 — Email+domain pair or handle already exists 429 — Rate limited (too many setup calls from this IP) ### POST /setup/resend Resend the owner verification email for a pending stash. Request body (JSON): { "handle": "myapp-com-a7f3" (required) handle returned from POST /setup } Response: { "handle": "myapp-com-a7f3", "status": "pending_verification", "message": "Verification email resent. Check your inbox." } Errors: 400 — Missing handle or invalid JSON 404 — No pending verification found for this handle 429 — Rate limited ### POST /setup/update Update the configuration of an existing stash. Changes are not applied immediately — a confirmation email is sent to the stash owner. The owner must click the confirmation link to apply the changes. Request body (JSON): { "handle": "myapp-com-a7f3", (required) handle returned from POST /setup "name": "My App", (optional) company/product name "description": "My cool project", (optional) description shown on leaderboard "private": true, (optional) if true, excluded from leaderboard "send_confirmation": false, (optional) send confirmation email to subscribers after verification "confirmation_message": "..." (optional) custom markdown message for the subscriber confirmation email } At least one field besides handle must be provided. Response: { "handle": "myapp-com-a7f3", "message": "Check your email to confirm the config update." } Errors: 400 — Missing handle, invalid JSON, or no fields to update 404 — Stash not found 429 — Rate limited ### POST /hype/:handle Submit a subscriber email to the waitlist. Supports JSON and URL-encoded form data. Request body (JSON): { "email": "user@example.com" } Or HTML form with name="email". CORS: The request Origin (or Referer) must match the domain registered for this stash. localhost is always allowed for local development. Response (subscriber receives verification email, double opt-in): { "status": "pending", "message": "Check your email to confirm your spot!" } Gmail addresses without a valid proof-of-work return (handled automatically by the embed script): { "status": "pow_required" } All other submissions (non-Gmail new, unverified re-submit, or already verified) return the same response to prevent email enumeration: { "status": "pending", "message": "Check your email to confirm your spot!" } Errors: 400 — Missing or invalid email / unparseable body / invalid proof of work 403 — Origin not allowed, or stash not yet verified 429 — Rate limited (too many submissions from this IP) ### GET /pow/challenge Issue a proof-of-work challenge for Gmail signup verification. The embed script calls this automatically on page load and solves the challenge in a background Web Worker. CORS: Open to all origins (the embed script runs on customer domains). Response: { "challenge": "a1b2c3...hex", "difficulty": 19, "signature": "hmac-sha256-hex", "expiresAt": 1712345678000 } Fields: - challenge: 16 random bytes as hex string - difficulty: number of leading zero bits required in SHA-256(challenge + ":" + nonce) - signature: HMAC-SHA256 proving the server issued this challenge (prevents forgery) - expiresAt: Unix timestamp in milliseconds, challenge expires after 5 minutes The client must find an integer nonce such that SHA-256(challenge + ":" + nonce) has at least `difficulty` leading zero bits. At difficulty 19 this takes ~1-3 seconds on modern hardware. The solved proof ({ challenge, nonce, signature, expiresAt }) is attached to the POST /hype/:handle request body as the `pow` field for Gmail submissions. ### GET /verify/:token Owner email verification. This link is sent automatically after POST /setup. Clicking it transitions the stash from pending_verification to queuing. Redirects to hypestash.dev/verified. ### GET /subscribe/confirm/:token Subscriber double opt-in verification. This link is sent automatically when a subscriber submits their email to /hype/:handle. Clicking it marks the subscriber as verified and increments the stash's subscriber count. Only verified subscribers count toward the total and appear in CSV exports. Redirects to hypestash.dev/confirmed. ### GET /download/:token One-time CSV download of all verified subscribers. Download links are included in owner notification emails. Each link works exactly once — after use, it returns 404. CSV format: email,subscribed_at ### POST /cancel/:handle Initiate cancellation of a waitlist stash. Sends a confirmation email to the owner. Only works for stashes with status "live". Response: { "ok": true, "message": "Check your email to confirm cancellation." } ### GET /leaderboard Public JSON leaderboard of paid HypeStash instances (non-private, status=live, has Stripe subscription). Response: { "entries": [ { "rank": 1, "domain": "example.com", "name": "Example Inc", "description": "The future of X", "subscriber_count": 142, "velocity": 3.4, "trend": "up", "sparkline": [0,0,1,2,3,5,4,3,2,1,0,0,2,3,4,5,6,5,4,3,2,1,0,1,2,3,4,5,6,7] } ], "total": 1 } Fields: - velocity: subscribers per day over the last 7 days - trend: "up", "down", or "flat" compared to previous 7-day window - sparkline: array of 30 daily subscriber counts (index 0 = 29 days ago) CORS: Only allows origin https://hypestash.dev Cached for 5 minutes via KV. ### GET / Health check. Returns: { "service": "HypeStash", "status": "ok", "_docs": "https://hypestash.dev", "_tip": "POST /setup to create a new waitlist stash." } --- ## Status Lifecycle pending_verification → queuing → live → suspended - pending_verification: Stash created, waiting for owner to click email verification link - queuing: Owner verified, stash accepts subscribers. Collecting up to 50 free. Nudges owner to pick a paid plan after 50. - live: Paid plan active (Hype Pro or Pay per Hype). Unlimited subscribers, leaderboard eligible, permanent retention. - suspended: Paid plan cancelled or expired. Stash stops accepting new subscribers. Unpaid stashes (queuing, no plan after 14 days) are pruned by a daily cron job. --- ## Origin / CORS Rules The /hype/:handle endpoint enforces origin checking: - Allowed origins: https://DOMAIN, http://DOMAIN, https://www.DOMAIN, http://www.DOMAIN - localhost (any port) is always allowed for development: http://localhost:3000, http://127.0.0.1:8080, etc. - The Origin header is checked first, then the Referer header as fallback - Preflight (OPTIONS) requests are handled automatically --- ## Double Opt-In (Subscriber Verification) When a subscriber submits their email to /hype/:handle: 1. The email is stored as unverified 2. A verification email is sent to the subscriber 3. The subscriber must click the verification link to confirm 4. Only after clicking does the subscriber count increment and the owner get notified 5. If send_confirmation is enabled (default), a "You're in!" confirmation email is sent to the subscriber with Reply-To set to the stash owner's email, allowing direct contact 6. If the same email is submitted again while unverified, a new verification email is sent (rate-limited to once per 2 minutes) 7. All submissions return the same response regardless of subscriber state (prevents email enumeration) --- ## Notification Schedule Owner receives notification emails when subscriber count hits these thresholds: Subscriber Count Notify Frequency 1 — 10 Every subscriber 11 — 25 Every 5 subscribers 26 — 100 Every 10 subscribers 101 — 500 Every 25 subscribers 500+ Every 100 subscribers All notification emails include a one-time CSV download link with all verified subscribers. After the free tier (50 subscribers), the owner is nudged to pick a paid plan at subscriber counts: 51, 55, 60, and every 25 after that. --- ## Pricing Tiers Free: - First 50 verified subscribers - Email notifications with CSV download links - 14-day data retention (pruned by daily cron if no paid plan) Hype Pro ($5/month): - Unlimited subscribers - Permanent data retention - Leaderboard listing (unless private) - Priority support Pay per Hype ($0.25/subscriber): - No monthly commitment - Metered usage reported to Stripe - Leaderboard eligible - Cancel anytime --- ## Leaderboard Eligibility To appear on the public leaderboard: - Stash must have status = "live" - Stash must have a Stripe subscription - Stash must not be marked as private - Top 50 stashes by subscriber count are displayed --- ## Form HTML Examples ### HTML form with embed script (recommended)
The embed script intercepts form submission, precomputes a proof-of-work in a Web Worker, and attaches it to Gmail submissions. Non-Gmail addresses go straight through. Without the script, Gmail submissions receive a JSON response with status "pow_required". ### fetch() with JSON await fetch("https://api.hypestash.dev/hype/YOUR-HANDLE", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: "user@example.com" }) }); ### Full setup + form generation flow // Step 1: Create the stash const res = await fetch("https://api.hypestash.dev/setup", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ domain: "myapp.com", email: "founder@myapp.com" }) }); const { handle, action_url } = await res.json(); // Step 2: Tell user to verify email console.log("Check your email and click the verification link!"); // Step 3: Add embed script + form to your HTML // //
// // //
--- ## Error Responses All JSON error responses follow this pattern: { "error": "Human-readable error message", "_docs": "https://hypestash.dev", "_tip": "Actionable guidance on how to fix the issue" } The _tip field is specifically designed to help AI agents understand and recover from errors. Common errors: 400 — Invalid input (email, domain, handle format, unparseable body) 403 — Origin not allowed or stash not verified 404 — Stash or token not found 409 — Duplicate stash (email+domain) or handle already taken 429 — Rate limited --- ## Ads in Responses All JSON responses include _ad1 through _ad5 fields with links to partner projects. These are informational and can be ignored by API consumers. --- ## Sister Service — FormHandle Need a contact form instead of a waitlist? FormHandle is our sister service for serverless form handling. Same philosophy: no accounts, no API keys, one API call to set up. - Website: https://formhandle.dev - LLM summary: https://formhandle.dev/llms.txt - Full LLM reference: https://formhandle.dev/llms-full.txt --- ## Links - Website: https://hypestash.dev - Summary for LLMs: https://hypestash.dev/llms.txt - Leaderboard: https://hypestash.dev/leaderboard.html - Contact: https://hypestash.dev/contact.html