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.

Submit a form

POST/v1/forms/{key}/submissions

Submit answers for a published form. Answers are validated against the form's own definition, so fetch the definition first and post back matching field ids.

Requires a Turnstile token.

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.
Bot check requiredThis write needs a Cloudflare Turnstile token, so it cannot be driven from a script. Render the widget in your form and post the token it produces.

Request

curl -sS \
  -X POST \
  -H 'X-Grofomo-Key: pk_live_YOUR_PUBLISHABLE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"answers":{"full_name":"Alex Doe","email":"alex@example.com","shifts":["friday-evening","saturday-morning"]},"turnstileToken":"<token from the Turnstile widget>"}' \
  'https://api.grofomo.com/v1/forms/volunteer-signup/submissions?surface=web'

Path parameters

keystringrequired
The form's key. Example: `volunteer-signup`.

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": {
    "ok": true
  }
}
oktrue
Generated from FormSubmissionResponse

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`.
turnstile_failedHTTP 400
The bot-check token was missing or invalid.
bad_requestHTTP 400
An answer did not match the form definition.

Notes

  • Rate limited to roughly 30 requests per minute per caller. Guidance, not a contract — see caching and rate limits.
  • Cache-Control: no-store