Creating Waitlists
Create, configure, and manage your waitlists.
Create a Waitlist
From the Dashboard, click Create Waitlist and enter a name. The waitlist is immediately live and ready to accept signups.
Each waitlist gets:
- A unique UUID (e.g.,
a1b2c3d4-e5f6-7890-abcd-ef1234567890) - A hosted signup page at
/waitlist.html?id=YOUR_ID - An embeddable widget code
- A shareable link you can copy from the dashboard
Waitlist Settings
Click Edit on any waitlist card to configure it. All settings are optional — the defaults work out of the box.
Display Settings
| Setting | Description |
|---|---|
| Name | The waitlist name shown in the dashboard and on the signup form |
| Headline | Custom headline on the signup form (max 100 characters) |
| Subheadline | Text below the headline (max 200 characters) |
| Hero Image URL | URL of an image displayed above the form |
Field Visibility
Control which fields appear on the signup form:
| Field | Options | Default |
|---|---|---|
| Name fields | required, optional, hidden |
optional |
| Phone field | required, optional, hidden |
hidden |
When set to required, signups must fill in the field to submit. When optional, the field appears but can be left blank. When hidden, the field is not shown.
Custom Questions
Add up to 10 custom questions to your signup form. Each question has:
| Property | Description |
|---|---|
| ID | A unique identifier string for the question (e.g., company_size). The dashboard auto-generates this, but API users must provide one. |
| Label | The question text shown to the user |
| Type | text (free-form input), dropdown (select from options), or checkbox (yes/no) |
| Required | Whether the question must be answered (optional, defaults to false) |
| Options | For dropdowns only — an array of choice strings (e.g., ["1-10", "11-50", "51-200"]). Must be a non-empty array when type is dropdown. |
Custom question answers are included in CSV exports and API responses. See the Custom Questions Format section below for the full JSON structure.
Waitlist Status
Control whether your waitlist is accepting signups:
| Setting | Description |
|---|---|
| Status | "open" (default) or "closed" — when closed, the signup form shows a “Waitlist Closed” message and the API rejects new signups with 403 |
Close your waitlist when you’re ready to launch or have enough signups. You can reopen it at any time.
Social Proof
| Setting | Description |
|---|---|
| Show social proof | Boolean (default: true) — displays a message like “Hundreds are already in line” on the signup form based on the current signup count |
The message adapts to the number of signups:
- 1–50: “Others are already signing up”
- 51–100: “Dozens have already joined”
- 101–500: “Hundreds are already in line”
- 501–1,000: “{count} people on the waitlist”
- 1,000+: “{count} people on the waitlist”
Social proof is shown on both the hosted signup page and the embed widget.
Consent Checkbox
Collect explicit consent from signups before they join your waitlist:
| Setting | Description |
|---|---|
| Require consent | Boolean (default: false) — shows an unchecked consent checkbox on the signup form |
| Consent text | Custom text for the checkbox label (max 500 characters). Supports markdown-style links: [Privacy Policy](/privacy). Default: “I agree to the Privacy Policy and Terms of Service” |
When enabled:
- The checkbox is unchecked by default
- The submit button is disabled until the checkbox is checked
- The server rejects signups without consent (
400 Bad Request) - A full consent record is stored with each signup:
consent_given_at(ISO timestamp),consent_text_version, andprivacy_policy_version - Consent fields are included in CSV exports
[Privacy Policy](/privacy) and [Terms](/terms)
Custom Share Message
| Setting | Description |
|---|---|
| Share message | Custom text pre-filled when users share their referral link via social sharing buttons |
Set a custom share message that appears when users click the sharing buttons on the success page:
PATCH /waitlists/{waitlist_id}
{
"settings": {
"share_message": "I just signed up for early access — join me!"
}
}
The share message is used as the pre-filled text for X/Twitter, LinkedIn, Facebook, and WhatsApp sharing buttons on the success page and in the embed widget. If not set, a default message is used (e.g., “I just joined the {waitlist name} waitlist! Join too:”).
Referral Boost
| Setting | Description |
|---|---|
| Referral boost | Integer (1–100, default: 1) — how many positions a referrer moves up for each successful referral |
By default, each referral moves the referrer up by 1 position. Increase this to reward sharing more aggressively. For example, setting it to 5 means each referral jumps the referrer up 5 positions.
Position Offset (Advanced+)
| Setting | Description |
|---|---|
| Position offset | Integer (0–1,000,000, default: 0) — added to displayed position numbers to create the appearance of a larger waitlist |
When set, all position numbers shown to signups are inflated by this amount. For example, with an offset of 500, the first signup sees “You’re #501 in line” instead of “#1”. Internal positions (used for referral ranking) are not affected.
Referral Notifications (Pro)
| Setting | Description |
|---|---|
| Notify referrer | Boolean (default: false) — sends an email to referrers when someone signs up through their link |
When enabled, referrers receive an email like: “Someone just joined using your referral link. You’ve moved up to position X. Keep sharing!” Notifications are rate-limited to one per referrer per hour.
Notifications (Pro)
Set up real-time notifications when someone joins your waitlist:
| Setting | Description |
|---|---|
| Webhook URL | An HTTPS URL that receives POST requests with signup data |
| Webhook Events | Which events trigger webhooks: signup.created, referral.credited |
| Slack Webhook URL | A Slack incoming webhook URL for formatted notifications |
| Discord Webhook URL | A Discord webhook URL for embed-style notifications |
See Webhooks & Integrations for payload formats and setup guides.
Access Control (Advanced+)
These settings require an Advanced plan or higher:
| Setting | Description |
|---|---|
| Hide branding | Remove the “Powered by MakeEmWait” link from the signup form |
| Hide position | Don’t show position numbers to signups |
| Allowed email domains | Only accept signups from specific domains (e.g., company.com) |
| Exclude personal emails | Block Gmail, Yahoo, Hotmail, Outlook, and other free email providers |
| Redirect URL | Redirect signups to your own URL (e.g., a thank-you page) instead of the default success page |
Email Templates (Pro)
Assign email templates to each waitlist so different waitlists send different emails. Each waitlist can have its own template for:
| Template Type | When It Sends |
|---|---|
| Signup confirmation | When someone joins the waitlist |
| Referral milestone | When a referrer hits a configured milestone count |
| Offboarding | When someone is removed from the waitlist |
| Blast | Used as the default template for email blasts sent to the waitlist |
Set these from the dashboard under Edit > Email Templates, or via the API using the email_templates setting. See Per-Waitlist Template Assignment for details.
Referral Milestones (Pro)
| Setting | Description |
|---|---|
| Referral milestones | An array of positive integers representing referral counts that trigger a milestone email (e.g., [5, 10, 25, 50]). Maximum 10 milestones, each with a maximum value of 10,000. |
When a referrer’s count reaches one of your thresholds, they automatically receive the referral milestone email template assigned to the waitlist. See Referral Milestones for setup details.
Email Verification (Pro)
| Setting | Description |
|---|---|
| Require email verification | Send a verification email with a clickable link after signup |
When enabled, signups receive a verification email with a link they click to confirm their address.
Update a Waitlist
Settings are merged when you update — only the fields you change are modified. Omitted fields keep their current values.
API: PATCH /waitlists/{waitlist_id}
{
"name": "Updated Name",
"settings": {
"headline": "Join the Beta",
"phone_field": "required"
}
}
The request body accepts two top-level fields:
| Field | Type | Description |
|---|---|---|
name |
string (max 100 chars) | The waitlist display name |
settings |
object | A settings object containing any of the fields listed below |
Complete Settings Reference
Every field below is optional. Pass only the fields you want to change inside the settings object. All other fields retain their current values.
Display
| Setting | Type | Default | Description |
|---|---|---|---|
headline |
string (max 100 chars) | — | Headline text shown on the hosted signup page and embed widget |
subheadline |
string (max 200 chars) | — | Text shown below the headline |
hero_image_url |
string (HTTPS URL) or null |
— | URL of an image displayed above the signup form. Must start with https://. Set to null to remove. |
Form Fields
| Setting | Type | Default | Description |
|---|---|---|---|
name_field |
"optional" | "required" | "hidden" |
"optional" |
Controls whether the name field appears on the signup form |
phone_field |
"optional" | "required" | "hidden" |
"hidden" |
Controls whether the phone field appears on the signup form |
custom_questions |
array of question objects (max 10) | [] |
Custom questions added to the signup form. See Custom Questions Format below. |
Behavior
| Setting | Type | Default | Description |
|---|---|---|---|
status |
"open" | "closed" |
"open" |
Whether the waitlist accepts signups. See Status Transitions below. |
show_social_proof |
boolean | true |
Show a social proof message (e.g., “Hundreds are already in line”) on the signup form |
require_consent |
boolean | false |
Show an unchecked consent checkbox that must be checked before submitting |
consent_text |
string (max 500 chars) | "I agree to the Privacy Policy and Terms of Service" |
Label text for the consent checkbox. Supports markdown-style links: [Privacy Policy](/privacy) |
referral_boost |
integer (1–100) | 1 |
How many positions a referrer moves up for each successful referral |
Access Control (Advanced+)
These settings require an Advanced plan or higher. Attempting to set them on a lower plan returns 403 TIER_REQUIRED.
| Setting | Type | Default | Description |
|---|---|---|---|
position_offset |
integer (0–1,000,000) | 0 |
Added to displayed position numbers. A value of 500 makes the first signup see “#501” instead of “#1”. Internal ranking is not affected. |
hide_position |
boolean | false |
Don’t show position numbers to signups on the success page |
hide_branding |
boolean | false |
Remove the “Powered by MakeEmWait” link from the signup form and embed widget |
redirect_url |
string (HTTPS URL, max 500 chars) or null |
— | Redirect signups to your own URL after submission instead of the default success page. Must start with https://. Set to null to remove. |
allowed_email_domains |
array of strings | [] |
Only accept signups from specific email domains (e.g., ["company.com", "partner.org"]). Empty array means all domains are allowed. |
exclude_personal_emails |
boolean | false |
Block signups from free email providers (Gmail, Yahoo, Hotmail, Outlook, and others) |
Notifications (Pro)
These settings require a Pro plan. Attempting to set them on a lower plan returns 403 TIER_REQUIRED.
| Setting | Type | Default | Description |
|---|---|---|---|
webhook_url |
string (HTTPS URL) or null |
— | An external HTTPS endpoint that receives POST requests with signup data. Blocks private IPs and localhost (SSRF protection). Set to null or "" to remove. |
webhook_events |
array of strings | [] |
Which events trigger webhooks. Valid values: "signup.created", "referral.credited" |
slack_webhook_url |
string or null |
— | A Slack incoming webhook URL for formatted signup notifications. Must start with https://hooks.slack.com/. Set to null or "" to remove. |
discord_webhook_url |
string or null |
— | A Discord webhook URL for embed-style signup notifications. Must start with https://discord.com/api/webhooks/. Set to null or "" to remove. |
notify_referrer |
boolean | false |
Send an email to referrers when someone signs up through their link. Rate-limited to one per referrer per hour. |
sms_notify_referrer |
boolean | false |
Send an SMS to referrers when someone signs up through their link (requires the referrer to have a phone number on file). Rate-limited to one per referrer per hour. |
Email & Verification (Pro)
These settings require a Pro plan.
| Setting | Type | Default | Description |
|---|---|---|---|
require_email_verification |
boolean | false |
Send a verification email with a clickable confirmation link after signup |
referral_milestones |
array of integers (1–10,000, max 10) | [] |
Referral counts that trigger a milestone email (e.g., [5, 10, 25, 50]). When a referrer hits one of these counts, they receive the referral milestone email template assigned to the waitlist. |
email_templates |
object | {} |
Per-waitlist email template assignments. Keys: signup_confirmation, referral_milestone, offboarding, blast. Values: a template ID string or null to unset. See Email Templates. |
Custom Questions Format
The custom_questions setting accepts an array of question objects. Each object has:
| Property | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | A unique identifier for the question (e.g., "company_size"). The dashboard auto-generates this, but API users must provide one. |
label |
string | Yes | The question text shown to the user (e.g., "How big is your company?") |
type |
string | Yes | One of: "text" (free-form input), "dropdown" (select from a list), or "checkbox" (yes/no toggle) |
required |
boolean | No | Whether the question must be answered. Defaults to false. |
options |
array of strings | Only for dropdown |
The list of choices for dropdown questions. Must be a non-empty array when type is "dropdown". Ignored for other types. |
Example:
{
"settings": {
"custom_questions": [
{
"id": "company_size",
"label": "How big is your company?",
"type": "dropdown",
"required": true,
"options": ["1-10", "11-50", "51-200", "200+"]
},
{
"id": "use_case",
"label": "What will you use this for?",
"type": "text",
"required": false
},
{
"id": "newsletter",
"label": "Subscribe to our newsletter",
"type": "checkbox"
}
]
}
}
Custom question answers are included in CSV exports and API responses.
Status Transitions
When you set status to "closed":
- The hosted signup page shows a “Waitlist Closed” message instead of the form
- The embed widget displays a closed state
- Any attempt to sign up via the API returns a
403error with codeWAITLIST_CLOSED - Existing signups, positions, and referral links are preserved — nothing is deleted
When you set status back to "open":
- The signup form is immediately available again
- All existing signups retain their positions
- Referral links start working again
You can toggle between "open" and "closed" as many times as you want. This is useful for pausing signups temporarily (e.g., during maintenance) or permanently closing the waitlist when you launch.
Delete a Waitlist
Click Delete on a waitlist card and confirm. All data is permanently deleted, including signup records, analytics, and blasts.
Related
- Signup Form — how the public signup form works and what happens when someone joins
- Embed Widget — add a signup form to any website with one line of code
- Managing Signups — list, export, delete, and import signups on your waitlists