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.

Quote a cart

POST/v1/events/{slug}/tickets/quote

Price a cart exactly as reserve would, without holding inventory or creating anything. Call it as the cart changes to show the running total and the booking fee, and when the buyer types a promo code to tell them whether it worked.

The server is authoritative: the figures here are what reserve will charge for the same cart a moment later, subject to availability.

promoApplied is the answer to "did the code work". A wrong or exhausted code does not fail the request. When unlocksVisibility is true the code also reveals held-back stock, whether a whole gated ticket type or a single hidden tier it names: fetch ticket availability again with ?promo= to list it.

Send the same affiliateCode and artistId you will send on reserve, or a gated tier the buyer can legitimately see prices as unavailable here.

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 \
  -X POST \
  -H 'X-Grofomo-Key: pk_live_YOUR_PUBLISHABLE_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"releaseId":"9c7e5a3b-1f0d-4b2e-8a6c-4d2f0b8e6a14","quantity":2}],"promoCode":"EARLYBIRD"}' \
  'https://api.grofomo.com/v1/events/summer-fest/tickets/quote?surface=web'

Request body

itemsobject[]required
The cart to price. Same shape as reserve.
items[].releaseIduuidrequired
A release id from the ticket availability feed.
items[].quantitynumberrequired
Units of that release.
promoCodestring
The code the buyer typed. Read `promoApplied` to learn whether it worked.
affiliateCodestring
Send whatever you will send on reserve, so gated tiers price the same way here.
artistIduuid
Send whatever you will send on reserve, so gated tiers price the same way here.
Generated from QuoteRequest

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": {
    "subtotalPennies": 22000,
    "discountPennies": 2200,
    "bookingFeePennies": 1535,
    "totalPennies": 21335,
    "currency": "GBP",
    "promoApplied": true,
    "appliedReleaseIds": [],
    "discountType": "percentage",
    "discountValue": 1000,
    "unlocksVisibility": false
  }
}
subtotalPenniesnumber
Face value of the cart before discounts, in minor units.
discountPenniesnumber
Everything taken off (automatic quantity discount plus promo code), in minor units.
bookingFeePenniesnumber
The booking fee, in minor units.
totalPenniesnumber
What the buyer would pay, in minor units.
currencystring
ISO 4217 code every amount is in.
promoAppliedboolean
True when the promo code was valid and applied to this cart. False with a code sent means the code is wrong, expired, used up, or does not cover these tiers.
appliedReleaseIdsuuid[]
Release ids the promo discounts. Empty means every release in the cart.
discountType"percentage" | "fixed" | "none"
How the promo discounts: `percentage` of the tier price, a `fixed` amount, or `none`.
discountValuenumber
Basis points for percentage (1000 = 10%), minor units for fixed, 0 for none.
unlocksVisibilitybooleanmay be absent
True when the code also reveals hidden ticket types. Fetch the ticket availability feed again with `?promo=<code>` to list them.
Generated from TicketQuoteResponse

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
The body did not match the schema.
unknown_releaseHTTP 400
A `releaseId` is not on this event or not visible to this caller.
not_on_saleHTTP 409
A release in the cart is closed, not yet open, or sold out.
per_order_minHTTP 400
Fewer units of a type than its `minPerOrder`.
per_order_maxHTTP 400
More units of a type than its `maxPerOrder`.
invalid_promoHTTP 400
The promo code does not exist or does not cover this cart.
expired_promoHTTP 400
The promo code is outside its dates.
promo_used_upHTTP 409
The promo code has reached its use limit.
promo_requiredHTTP 400
A release in the cart is gated behind a promo code and none was sent.
affiliate_requiredHTTP 400
A release in the cart is affiliate-gated and no valid `affiliateCode` was sent.
cancelledHTTP 410
The event has been cancelled.

Notes

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