# 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 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 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 "description": "My cool project", (optional) shown on leaderboard "private": false (optional) if true, excluded from leaderboard } 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 /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!" } If subscriber already verified: { "status": "hyped", "message": "You're already on the list!" } Errors: 400 — Missing or invalid email / unparseable body 403 — Origin not allowed, or stash not yet verified 429 — Rate limited (too many submissions from this IP) ### 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", "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 the same email is submitted again while unverified, a new verification email is sent 6. If the same email is already verified, a 200 "You're already on the list!" response is returned --- ## 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 ### Plain HTML form ### 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: Use action_url in your HTML form // --- ## 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