Waitlist
The pre-launch waitlist behind the form on the marketing site (apps/web, /#waitlist). Signups are stored in WaitlistSignup. They aren't accounts and aren't linked to User. No email is sent yet: the form shows a success message.
Join
POST /waitlist is public (no auth) and has its own limit of 10 requests per hour per IP on top of the global one.
{
"email": "gamer@example.com",
"role": "creator",
"source": "tiktok",
"campaign": "launch",
"referrer": "https://t.co/…"
}| Field | Notes |
|---|---|
email | Required. Trimmed and lowercased; ≤ 254 chars |
role | Optional: creator, coach or player |
source | Optional, ≤ 100. The web form sends utm_source (or ref) from the landing URL |
campaign | Optional, ≤ 100. utm_campaign |
referrer | Optional, ≤ 500. document.referrer |
website | Honeypot. Real visitors never fill it; when set, the request "succeeds" and nothing is stored |
Every accepted request returns 201 { "success": true }, whether the email is new or already on the list, so the endpoint can't be used to check whether someone has signed up. A repeat signup keeps the first source, campaign and referrer, and only fills in role if none was given before.
| Status | When |
|---|---|
400 | Invalid email or field (message is shown to the user) |
429 | More than 10 signups from one IP in an hour |
Campaign links
Point campaigns at the landing page with UTM parameters and the #waitlist anchor:
https://www.playpalz.gg/?utm_source=tiktok&utm_campaign=launch#waitlistThe bare playpalz.gg redirects to www (web middleware.ts) with the query string kept, because CORS only allows WEB_APP_URL.
Admin
The admin panel's Waitlist page lists signups (newest first) with role tabs, search and CSV export. See Admin panel for the endpoints.
