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.

Ambassador programme

GET/v1/events/{slug}/ambassadors

The event's Ambassador programme as the organiser runs it in Grofomo: the reward ladder, the rules, whether every ticket buyer is enrolled automatically, and whether the partner application form is open.

Build your "bring your mates" page on this rather than copying the tiers into it: the organiser edits the programme in Grofomo and the page follows within a minute. ambassadors.js renders all of it for you.

programme is null until the organiser publishes one with at least one reward, and while they have it switched off for this event. Keep your own copy on the page for that case; the drop-in does exactly that.

Tiers are cumulative: an Ambassador who reaches the 10-ticket tier keeps everything below it. Each tier carries offer and prize in Grofomo's wording, and the raw thresholdTickets and rewards to write your own ("Bring 10 mates" rather than "Sell 10 tickets").

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.

Request

curl -sS \
  -H 'X-Grofomo-Key: pk_live_YOUR_PUBLISHABLE_KEY' \
  'https://api.grofomo.com/v1/events/summer-fest/ambassadors?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": {
    "eventSlug": "summer-fest",
    "eventName": "Summer Fest 2026",
    "programme": {
      "name": "Summer Fest Ambassadors",
      "description": "Bring your mates and the bigger your group, the more we give back on the night.",
      "rules": [
        "Buying a ticket makes you an Ambassador. There is nothing to join and nothing to pay.",
        "A mate counts when their ticket is bought through your own link, right up to the day of the show.",
        "Rewards add up. Every reward you reach is yours to keep.",
        "Collect your rewards at the bar with the Grofomo app. Bring ID."
      ],
      "tiers": [
        {
          "thresholdTickets": 2,
          "name": "Crew",
          "prize": "2 drinks",
          "offer": "Sell 2 tickets, get 2 drinks",
          "rewards": [
            {
              "title": "2 free drinks",
              "description": null,
              "rewardType": "drink",
              "quantity": 2,
              "fulfilmentInstructions": "At any bar, with the Grofomo app"
            }
          ]
        },
        {
          "thresholdTickets": 5,
          "name": "Headliner",
          "prize": "a meal",
          "offer": "Sell 5 tickets, get a meal",
          "rewards": [
            {
              "title": "Street food voucher",
              "description": "Any trader on the main field.",
              "rewardType": "food",
              "quantity": 1,
              "fulfilmentInstructions": null
            }
          ]
        },
        {
          "thresholdTickets": 10,
          "name": "Legend",
          "prize": "your ticket refunded",
          "offer": "Sell 10 tickets, get your ticket refunded",
          "rewards": [
            {
              "title": "Your ticket refunded",
              "description": "One standard ticket at the price you paid, refunded after the show.",
              "rewardType": "ticket_refund",
              "quantity": 1,
              "fulfilmentInstructions": null
            }
          ]
        }
      ]
    },
    "automaticEnrolment": true,
    "ticketsUrl": "https://grfm.to/e/summer-fest/tickets",
    "partnerApplications": {
      "open": true,
      "estimatedTicketsOptions": [
        {
          "value": "under_10",
          "label": "Under 10"
        },
        {
          "value": "10_25",
          "label": "10–25"
        },
        {
          "value": "25_50",
          "label": "25–50"
        },
        {
          "value": "50_plus",
          "label": "50+"
        }
      ],
      "audienceReachOptions": [
        {
          "value": "under_1k",
          "label": "Under 1k"
        },
        {
          "value": "1k_5k",
          "label": "1k–5k"
        },
        {
          "value": "5k_20k",
          "label": "5k–20k"
        },
        {
          "value": "20k_plus",
          "label": "20k+"
        }
      ]
    }
  }
}
eventSlugstring
The event's current slug (an old one still resolves).
eventNamestring
programmeobject | null
The published programme. Null while the organiser has none, has it in draft, has switched it off for this event, or has not added a reward yet.
programme.namestring
The programme's name, e.g. "Twisted Roots Ambassadors".
programme.descriptionstring | null
The organiser's short pitch for it, or null.
programme.rulesstring[]
The rules, one per entry, in the order the organiser set. Render as a list. Empty when they have written none.
programme.tiersobject[]
The reward ladder, lowest threshold first. Rewards add up: reaching a tier keeps every tier below it.
programme.tiers[].thresholdTicketsnumber
Tickets that must be bought through an Ambassador's link to reach this tier.
programme.tiers[].namestring | null
The organiser's name for the tier ("Ringmaster"), or null when unnamed.
programme.tiers[].prizestring | null
Everything on the tier as one phrase for a sentence: "2 drinks and a meal". Null for a tier with no rewards.
programme.tiers[].offerstring | null
The tier as a whole deal: "Sell 5 tickets, get 2 drinks". Grofomo's wording; write your own from the fields above if the site says it differently.
programme.tiers[].rewardsobject[]
What the tier pays, in the organiser's order.
programme.tiers[].rewards[].titlestring
What the reward is, as the organiser named it, e.g. "2 free drinks".
programme.tiers[].rewards[].descriptionstring | null
The organiser's own detail on the reward, or null.
programme.tiers[].rewards[].rewardType"drink" | "food" | "merchandise" | "ticket_refund" | …
`drink`, `food`, `merchandise`, `ticket_refund` or `custom`.
programme.tiers[].rewards[].quantitynumber
How many of it: 2 for "2 free drinks". 1 for anything that is not counted.
programme.tiers[].rewards[].fulfilmentInstructionsstring | null
How it is collected, in the organiser's words ("At the bar with your app"), or null.
automaticEnrolmentboolean
True when every ticket buyer becomes an Ambassador automatically, with nothing to sign up for.
ticketsUrlstring
The event's Grofomo ticket page, where a buyer is enrolled.
partnerApplicationsobject
The form for promoters with an audience, who want a cash rate rather than the rewards. Approved applicants become commission partners.
partnerApplications.openboolean
partnerApplications.estimatedTicketsOptionsobject[]
partnerApplications.estimatedTicketsOptions[].valuestring
What to send back in the application.
partnerApplications.estimatedTicketsOptions[].labelstring
What to show, e.g. "10–25".
partnerApplications.audienceReachOptionsobject[]
partnerApplications.audienceReachOptions[].valuestring
What to send back in the application.
partnerApplications.audienceReachOptions[].labelstring
What to show, e.g. "10–25".
Generated from AmbassadorProgrammePageResponse

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

Notes

  • Rate limited to roughly 60 requests per minute per caller. Guidance, not a contract — see caching and rate limits.
  • The same for every visitor, so it is cached for 60 seconds and refreshed when the organiser saves the programme.
  • Nothing per-person is here. An Ambassador's own progress and link live in the Grofomo app.