Grofomo API
Browse the docs

Examples use a fictional festival, summer-fest. Sign in at events.grofomo.com and they switch to your own events.

Prelaunch registration

POST/v1/events/{slug}/prelaunch/register

Post 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.

Send ?surface=webOmit it and the request is treated as coming from the mobile app, which is gated on a different visibility setting — so a perfectly live event can return 404 not_found for no visible reason.
No bot check todayThis write accepts a 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

200 OK
{
  "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"
    }
  }
}
successMessagestring
deviceLinkedboolean
verificationobject
verification.tokenstring
verification.email"sent" | "not_needed" | "failed"
verification.phone"sent" | "not_needed" | "failed" | "unavailable"
verification.phoneHintstring | null
Generated from PrelaunchRegisterResponse

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