Manage Registrations
Control team enrollment — publish registrations, review submissions, and manage waitlists.
Create a Registration
- Open your league in the Admin dashboard
- Click “Create Registration”
- Configure:
- Open date and Close date — the enrollment window
- Max teams — cap enrollment automatically (
config.capacity;0= unlimited) - Waitlist — allow overflow registrations beyond capacity (
config.hasWaitlist) - Team size — min and max players (
config.minPlayers,config.maxPlayers); these are the registration-wide defaults, and an individual contest or division can override them (see Why does a division allow more players than my registration setting?) - Custom fields — collect extra info from team captains
- Waiver — attach a digital liability waiver
- Optionally attach a Payment Product to collect fees
- Click Publish
Your registration link is now ready to share with teams.
Registration Start-Date Gate
You can make a registration publicly viewable while keeping enrollment locked until a specific date and time. This lets you publish the registration page early for teams to see details, without accepting sign-ups yet.
Enable it during registration creation (Step 1 — Payment & Registration Settings) by toggling “Set Registration Start Date” and picking a date and time. This sets registration.config.gateByStartDate = true and records registration.startDate.
How it works:
- When
gateByStartDateis on, the public registration page shows the registration details but replaces the sign-up form with a notice: “Registration opens on <date>.” - Once
registration.startDatepasses, the gate lifts automatically — no admin action needed. - The gate is read directly from
registration.config.gateByStartDate(not resolved through the config hierarchy) and evaluated viaisBeforeRegistrationStart()inpackages/shared/utils/registrationSchedule.ts. - The
startDatefield already exists on all registrations (defaults to now), so the boolean flag — not the mere presence ofstartDate— controls whether the gate is active.
gateByStartDate is a registration-level-only exception to the config hierarchy. Do not set it on a division or league — it is only read from registration.config.
Registration End-Date Gate (Close Date)
You can automatically close a registration once a deadline passes. New teams can no longer sign up, but teams that already registered stay fully viewable and editable, and the public “Teams by Division” roster keeps showing.
Enable it during registration creation (Step 1 — Payment & Registration Settings) by toggling “Set Registration End Date” and picking a date and time. This sets registration.config.gateByEndDate = true and records registration.endDate.
How it works:
- When
gateByEndDateis on andregistration.endDatehas passed, every “register / start a new team” button (on the registration details page, the registration list, and the team form) becomes disabled with a “Registration is closed” message. The API also rejects new-team creation with a403. - Existing teams are unaffected — their edit/players/pay links keep working (the gate applies only to new teams), so organizers and teams can still finish or amend a submission after the deadline.
- The gate is read directly from
registration.config.gateByEndDate(a registration-level-only exception, likegateByStartDate) and evaluated viaisAfterRegistrationEnd()inpackages/shared/utils/registrationSchedule.ts.
Time Zone
When either date gate is on, pick a Time Zone (Step 1). One registration.timeZone (an IANA name like America/Los_Angeles) governs how both the start and end date/times are interpreted and displayed — so “closes at 11:59 PM Pacific” is unambiguous regardless of where the admin or a registrant is. The open/close comparison itself uses absolute instants, so it is always correct; the time zone controls the wall-clock you type and the times shown to users.
Review Submissions
In the Admin dashboard, navigate to Registrations → Submissions to:
- View all registered teams
- Check payment status per team
- Download roster data
- Export to CSV
Recording a custom/manual payment (money collected outside Stripe — cash, check) requires a short note, and Staty records which admin entered it.
Edit a Player
Open a team (Team page) to see its roster. Each player row has an Edit button that lets you correct the player’s first name, last name, email, and any custom registration fields. A player’s linked account profile (their personal profile details) isn’t changed here — only their registration info for this team.
If you add or change a player’s email and the registration requires a waiver, Staty automatically emails the waiver signing link to that new address. Saving with an unchanged email — or editing a non-email field — doesn’t send anything.
Download a Release Form (for walk-up players)
Need a paper copy of your Release Statement for a last-second walk-up player to sign? Two spots give you a one-click PDF download:
- Team page — a Download Release Form button sits next to Create New Player / Invite Player.
- Registration admin — a Release Statement row in the Exports ”…” menu (next to the Teams / Players CSV exports).
Either downloads a clean PDF (no browser headers, page numbers, or URLs) — print it and hand it to the player. The form includes the Release Statement and any required player waivers, each on its own page with blank Printed Name / Signature / Date lines.
Remove & Restore Teams
Removing a team from a registration is a soft delete — nothing is lost permanently, and there are two ways to bring a team back:
- Undo — right after you remove a team, a toast appears with an Undo action for quick recovery.
- Deleted teams — a collapsed section below the teams table lists every removed team (loaded when you open it). Click Restore to return the team — its division placement is restored along with it.
A team with unrefunded payments cannot be removed. Fully refund the team first (see Issue Refunds), then remove it. This prevents payments from being orphaned in your ledger.
Invite a Team Manager to Register
Instead of entering a team’s whole registration yourself, you can add the team and invite its manager — the person who will sign up as the account owner and add themselves and their players — to complete registration and payment.
From the Structure tab, open a division and click Add Team. When the division has a registration, the dialog shows a “Send registration invite to team manager” checkbox. Check it, enter the manager’s email (name optional), and submit. Staty:
- Creates the team and a linked registration for it, so the team appears immediately as a pending registered team.
- Emails the manager a link to sign up, finish registration, and pay — with this division already selected for them.
When the manager opens the link and completes registration, it fills in that same team (no duplicate), and the team becomes theirs to manage.
To send the email again later, open the team from the division (or Registrations → Submissions) and click Resend registration invitation — the manager’s email is prefilled and editable.
Remind players to finish their registration
On the team page, when a registration has a player waiver and/or charges players individually, each player row in the team’s roster gets a checkbox. Select the players you want to nudge and click Email selected to finish registration. Each selected player is emailed a link to the registration page, where they sign in with that email address and complete whatever they still owe — sign the required waiver and/or pay their share. Players who are already fully done are automatically skipped (reported in the confirmation), so you can safely select a whole roster.
Adding a team without checking the invite box behaves as before: it creates a quick placeholder team marked Unregistered with no email sent.
How do I set a team’s status (Pending, Accepted, Waitlist, Withdrawn)?
Every team row on Registrations → Submissions has a Status dropdown. This is your decision about the team, and it is separate from the capacity state described in the next section — the two are shown together on each row so you can see both.
| Status | What it does |
|---|---|
| Pending | The default for a new registration. You haven’t placed the team yet. |
| Accepted | You’ve officially placed the team in its division; it appears on the public site. |
| Waitlist | Forces the team onto the waitlist, whatever the payment order says, and frees its spot for the next team in line. |
| Withdrawn | The team dropped out. |
Accepted does not guarantee a spot. Accepting a team is a placement decision, not a payment one — an accepted team that hasn’t paid is still Pending on capacity, and an accepted team in a full division is still Waitlisted. This is deliberate: it stops a division being pushed past its capacity by accepting teams.
What happens when I mark a team Withdrawn?
The team is removed from the competition everywhere it would be visible, but nothing is deleted and no money moves:
- Hidden from Structure (
/admin/organize), from the public division team list, and from the public “Teams by Division” roster. - Excluded from division counts — a withdrawn team no longer occupies a spot in its division.
- Still counted in the Registrations and Players totals: the team really did register, and its payments are already included in the totals beside them.
- It gives up its capacity spot, so the next team in line can be promoted into it.
- The team stays on this page with the status “Withdrawn”, keeps its division, and keeps its payments — Total Payments and Total Donations still include them, so the page continues to reconcile against Stripe.
- The team’s manager sees Application Status: Withdrawn on the registration details page.
Set the status back at any time and the team returns everywhere.
Withdrawing never issues a refund. If money should go back, issue a refund separately. This is exactly why Withdrawn exists: a team with unrefunded payments cannot be removed, so Withdrawn is how you record a paid team that drops out.
Withdrawn is not the same as Remove Team — removing is a soft delete that hides the team from everything including this page (see Remove & Restore Teams).
Capacity & Waitlist States
Each team’s spot in a division is derived from capacity and payment — it is not a stored status. In a paid division, a team only occupies a spot once it has at least a partial payment (free divisions place teams immediately):
| State | Meaning |
|---|---|
| Secured | Paid and within the division’s capacity (first-come, first-served by registration/promotion order). |
| Waitlisted | Paid but over capacity — holding a place in line for the next open seat. |
| Pending | Registered but not yet paid in a paid division — holds neither a secured nor a waitlist spot. The team must make at least a partial payment to claim a spot. |
Two of the statuses above override this derivation: a team set to Waitlist is waitlisted regardless of payment or order, and a team set to Withdrawn drops out of the table entirely.
Unpaid teams are pending, not “temporarily reserved” — there is no grace-period seating. A team joins the waitlist (and can be promoted) only after it has partially paid.
Waitlist Promotion
When config.autoPromote is enabled, the next eligible waitlisted team is automatically seated whenever a capacity spot opens (a cancellation, removal, or capacity bump). A waitlist_promoted email is sent to the team at that moment.
Teams are only eligible for promotion if they have at least a partial payment on record (or the division is free). Unpaid teams remain in a pending state and do not hold a waitlist spot — they must partially pay first to queue for promotion. config.promotionPaymentWindowHours controls the FIFO ordering of promoted teams but does not gate seating.
Auto-promote requires a Payment Product to be attached to the registration.
Roster Size (Min & Max Players)
The min/max players a team may enter is a config field, so it follows the config hierarchy: division > contest > tournament. The numbers entered in the registration wizard are stored on the registration’s parent tournament or contest; override them only where a competition differs — e.g. a 4-on-4 contest that allows 8-player rosters under a tournament whose default is 5.
The resolved numbers drive the roster form, the embedded registration form, and the check that runs when the roster is saved — a team is never shown a limit the save will reject.
Why does a division allow more players than my registration setting?
Because a more specific level wins. If the contest or division a team registered into sets its own maxPlayers, that value overrides the registration’s for those teams. To make one number apply everywhere, clear minPlayers/maxPlayers on the contests and divisions (Structure → ⋯ → Settings) and leave them set only on the registration.
Two related rules:
- Leaving both blank at every level means no maximum (and a minimum of 1) — it does not fall back to a hidden default.
- If you lower a max after teams have registered, any roster already above it stays editable: the team can save it as-is or remove players, but cannot add more.
Roster Lock
Roster Lock freezes roster/player changes after a date you choose — handy once a season starts. On the registration’s admin page, enable “Manually Lock Roster Changes” and set a lock date; the same controls are available under Settings. These persist as rosterLock and rosterLockDate.
Roster Lock is distinct from the Registration End-Date Gate above: the close date stops new teams from signing up, while Roster Lock freezes edits to the rosters of teams that already registered.
View Payment Status for Teams
On the registration’s admin page, the Payment Status filter narrows the team list to Partial Paid, Fully Paid, or Unpaid (or All), and each team row shows a payment badge. To mark a team paid manually (cash/check), see Accept Registration Payments — Mark a team paid manually. For the full money ledger, see the Payments (Transactions) page.
API: Registration Endpoints
# List registrations for a league
curl https://api.staty.io/api/v1/registrations?league=LEAGUE_ID \
-H "Authorization: Bearer sk_live_..."
# Get a single registration
curl https://api.staty.io/api/v1/registrations/REG_ID \
-H "Authorization: Bearer sk_live_..."
# Update registration settings
curl -X PUT https://api.staty.io/api/v1/registrations/REG_ID \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"active": false,
"deadlineDate": "2026-03-28T00:00:00.000Z"
}'See the full Registrations API reference for all fields and endpoints.