Events reference
This page lists what Events adds to your server: hooks, routes, tables and translations. It is for app developers and module authors. Set up the module first: Overview.
Hooks
Your app answers these Nitro hooks from a server plugin (server/plugins/*.ts).
| Hook | When | Payload |
|---|---|---|
events:purchase:before | During a purchase, after the capacity checks. Throw to deny. | PurchaseBeforeContext |
events:ticket:paid | A ticket became paid, or a free ticket was issued. Send confirmations here. | TicketHookContext |
events:ticket:refunded | A ticket was fully refunded. | TicketHookContext |
events:membership:check | A membership requirement is checked. | MembershipCheckContext |
events:membership:options | The admin area asks which memberships can be picked. | MembershipOptionsContext |
type PurchaseBeforeContext = { event: H3Event, userId: number, eventId: string, ticketTypeId: string, addonIds: string[] }
type TicketHookContext = { ticket: TicketDto }
type MembershipCheckContext = { userId: number, requirement: 'any' | string[], satisfied: boolean }
type MembershipOptionsContext = { available: boolean, options: Array<{ value: string, label: string }> }
A membership rule (requiresMembership, excludesMembership) is null for nobody, 'any' for any active membership,
or a list of membership keys.
Routes
Routes the module registers, and who may call them. Public and self-service routes are under /api/events, and staff
routes under /api/admin/events. Build the paths with eventsApi from @frigear-nu/events/api, for example
eventsApi.admin.event(id).
- Permissions. A row names the permission the route checks with
authorize. A token also needs a scope that covers it, as Access control explains. - Staff means the caller holds
events:managethrough a role. See Let staff manage events. - Errors carry a snake_case
data.code, such asnot_foundorconflict. Validation failures are h3's400.
| Method | Path | Auth | Status | Purpose |
|---|---|---|---|---|
GET | /api/events | public | 200 | Published events. |
GET | /api/events/:slug | public (optional tickets:read) | 200 | One event. Signed in, each ticket type carries a blocked reason. |
POST | /api/events/:slug/purchase | tickets:write | 200 | Buy a ticket: { ticket, url? }. |
GET | /api/events/me/tickets | tickets:read | 200 | The caller's tickets. |
GET | /api/events/me/tickets/:id | tickets:read | 200 | One of the caller's tickets, to poll after returning from Stripe. |
POST | /api/events/me/tickets/:id/pay | tickets:write | 200 | Resume paying a pending ticket: { url }. |
GET | /api/admin/events | events:manage | 200 | Events, paginated. Query parameters below. |
POST | /api/admin/events | events:manage | 201 | Create an event, with its whole catalogue if given. |
GET | /api/admin/events/:id | events:manage | 200 | One event, whatever its status, with all ticket types, add-on groups and add-ons. |
PATCH | /api/admin/events/:id | events:manage | 200 | Update an event. 409 conflict for a taken slug. |
DELETE | /api/admin/events/:id | events:manage | 204 | Delete an event. 409 when it has paid tickets: archive it instead. |
POST | /api/admin/events/:id/clone | events:manage | 201 | Copy into a new draft (<slug>-copy, -copy-2, …). Dates stay, and tickets are not copied. |
GET | /api/admin/events/:id/tickets | events:manage | 200 | Attendees, paginated, with each QR code. Query parameters below. |
POST | /api/admin/events/:id/ticket-types | events:manage | 201 | Add a ticket type. 404 for an unknown event, 409 for a taken key. |
PATCH | /api/admin/events/ticket-types/:id | events:manage | 200 | Update a ticket type. |
DELETE | /api/admin/events/ticket-types/:id | events:manage | 204 | Delete a ticket type. 409 while it has active tickets. |
POST | /api/admin/events/ticket-types/:id/addon-groups | events:manage | 201 | Add an add-on group. 404 for an unknown ticket type. |
PATCH | /api/admin/events/addon-groups/:id | events:manage | 200 | Update an add-on group. |
DELETE | /api/admin/events/addon-groups/:id | events:manage | 204 | Delete an add-on group and its add-ons. |
POST | /api/admin/events/addon-groups/:id/addons | events:manage | 201 | Add an add-on. 404 for an unknown group. |
PATCH | /api/admin/events/addons/:id | events:manage | 200 | Update an add-on. |
DELETE | /api/admin/events/addons/:id | events:manage | 204 | Delete an add-on. |
POST | /api/admin/events/tickets/:id/cancel | events:manage | 200 | Cancel an unpaid or free ticket. Answers the attendee. |
POST | /api/admin/events/tickets/:id/refund | events:refund | 200 | Start a full refund of a paid ticket. |
GET | /api/admin/events/membership-options | events:manage | 200 | { available, options } from the membership provider. |
GET | /api/admin/events/upcoming | events:manage | 200 | { total, items }: the next published events, for the admin dashboard. |
POST | /api/admin/events/check-in | events:manage | 200 | Check a ticket in. Body { code }. |
GET /api/admin/events takes page, pageSize (at most 100), q (the name in any language, or the slug),
status, sort (startsAt, createdAt, slug or status) and order. It answers
{ items, total, page, pageSize }.
GET /api/admin/events/:id/tickets takes q (the holder's name or email), status and sort (createdAt,
status, checkedInAt, name or email).
POST /api/admin/events/tickets/:id/refund moves money, so events:refund is a session-only permission. A token
gets 403 session_required. Only a paid ticket
with a payment can be refunded.
Deletes answer 404 not_found when the row does not exist. Static segments such as me, upcoming and check-in
win over :slug and :id.
Database
Tables the module adds. Generate and commit a migration after installing. Payments, Users and Subscriptions need theirs too.
| Table | Holds |
|---|---|
events | Translated name, description and body, the place, startsAt / endsAt, status (draft, published, archived) and requiresMembership. |
event_ticket_types | Per event: a unique key, price (0 is free), currency (default DKK), capacity, the sale window and schedule, maxPerUser (default 1) and membership rules. |
event_addon_groups | Per ticket type, such as "Food": required, multiple and sortOrder. |
event_addons | The choices in a group: label, price, an optional capacity and sortOrder. |
event_tickets | status (pending, paid, cancelled, refunded, expired), the add-ons, amount and currency bought, paymentId, the unique QR code, locale and check-in. |
Translated texts are a string or a { da, en } map.
Translations
Override any string in your app's i18n/locales/<code>.json. The module registers da and en files under
events.*. See overriding module strings.
Without @nuxtjs/i18n, the pages use en.
{ "events": { "upcoming": { "title": "What's on" } } }
Key groups: upcoming.*, ongoing.*, past.*, detail.* (with the purchase flow), tickets.* (with
tickets.status.*), cart.*, menu.* and admin.* (with admin.tabs.* and admin.statuses.*). Top-level keys
include title, empty, loading, ticketReady, paymentReceived and purchaseFailed.
Next steps
- Server API – the purchase checks behind these routes.
- Send an email – send the ticket confirmation from
events:ticket:paid. - Payments – the
payments:*hooks and refunds behind a ticket's status.