Prelaunch registration
/v1/events/{slug}/prelaunch/registerPost a registration for the event in the path from a form you rendered with the prelaunch form endpoint. firstName and email are required, and at least one consent must be granted. Send consentEmail: true: registering is the email consent, under the wording you printed. consentPost when the form asks for post.
How to send a number depends on fields.phone.consentMode from the form endpoint. Under checkbox, phone and consentSms go together and neither is accepted without the other. Under implied there is no tick to send: post the phone alone and it IS the request, so the same body that earns a 400 phone_without_sms_consent on a checkbox form succeeds on an implied one. A consentSms with no number is refused either way, because there is nothing for it to apply to.
Double opt-in. The registration is saved at once, but nothing is granted until it is proven: the email by the confirmation link we send (verification.email is sent; tell the person to check their inbox), a mobile number by the SMS code we text (verification.phone is sent; show a code box and post it to the verify endpoint with verification.token). A person who already proved that address or number is registered on the spot (not_needed). The prelaunch.registration webhook fires each time a channel is proven, carrying the consents as they stand.
There is no bot check on this endpoint today, so you do not need to render a Turnstile widget. What gates it is your publishable key and the organiser's domain allowlist, plus a rate limit. Refused with 410 closed once the form's closesAt has passed.
404 not_found for no visible reason.turnstileToken, but it is not currently verified, so you do not need to render a widget to call it. What gates it is your publishable key and the organiser’s domain allowlist, plus a per-address rate limit. We will announce it in the changelog before a token starts being required.Request
curl -sS \
-X POST \
-H 'X-Grofomo-Key: pk_live_YOUR_PUBLISHABLE_KEY' \
-H 'Content-Type: application/json' \
-d '{"firstName":"Alex","email":"alex@example.com","consentEmail":true,"phone":"07400 123456","consentSms":true}' \
'https://api.grofomo.com/v1/events/summer-fest/prelaunch/register?surface=web'Path parameters
slugstringrequired- The event's URL slug. Globally unique. It can change if the organiser renames the event, but an old slug keeps reaching the same event, so a stored one never breaks. Example: `summer-fest`.
Query parameters
surface'web'required- Must be `web` for a website. Omit it and you get the mobile-app surface, which is gated on a different visibility setting — so a perfectly live event can return 404. Example: `web`.
Response
{
"apiVersion": 1,
"data": {
"successMessage": "You're on the list. We'll email you with tickets, presales and news.",
"deviceLinked": false,
"verification": {
"token": "<verification token>",
"email": "sent",
"phone": "sent",
"phoneHint": "••••••456"
}
}
}successMessagestringdeviceLinkedbooleanverificationobjectverification.tokenstringverification.email"sent" | "not_needed" | "failed"verification.phone"sent" | "not_needed" | "failed" | "unavailable"verification.phoneHintstring | null
Errors
unauthorizedHTTP 401- No key was sent and the organiser requires one — or the key is invalid, revoked, belongs to another organisation, or is scoped to a different event.
origin_not_allowedHTTP 403- Your site's domain is not on the organiser's allowed list. Browser calls only: a server sends no Origin header and is unaffected.
not_foundHTTP 404- No event with that slug is published on this surface. Check the slug, and check you sent `?surface=web`.
bad_requestHTTP 400- A required field is missing, or a consent was sent for a channel the form does not ask for.
phone_invalidHTTP 400- The mobile number did not parse. Include the country code or a valid UK number.
phone_without_sms_consentHTTP 400- A number was sent without the messaging tick (or the tick without a number).
closedHTTP 410- The form closed at `closesAt`.
rate_limitedHTTP 429- More than ten registrations a minute from one address.
Notes
- Rate limited to roughly 10 requests per minute per caller. Guidance, not a contract — see caching and rate limits.
Cache-Control: no-store