Hope Events — API Documentation
Full interactive docs (with request/response examples) are available at GET /docs?token=<admin-jwt> on the running backend.
All authenticated requests require:
Tokens are issued by POST /api/users/login.
Table of Contents
Users
| Method |
Path |
Auth |
Description |
| POST |
/api/users |
public |
Register new account |
| POST |
/api/users/login |
public |
Login, returns JWT |
| POST |
/api/users/forgot |
public |
Request password reset email |
| POST |
/api/users/reset |
public |
Reset password with token |
| POST |
/api/users/activate |
public |
Activate account from email link |
| GET |
/api/users/profile |
user+ |
Own profile |
| PUT |
/api/users/profile |
user+ |
Update own profile |
| POST |
/api/users/revoke-sessions |
user+ |
Revoke own sessions |
| POST |
/api/users/close-account |
user+ |
Deactivate own account |
| GET |
/api/users |
supervisor+ |
List users — supports ?search=, ?role=, ?isActive=true|false, ?page=, ?limit= |
| GET |
/api/users/:id |
admin |
Get user by ID |
| PUT |
/api/users/:id |
admin |
Update user (name, email, role, isActive, phoneNumber) |
| DELETE |
/api/users/:id |
admin |
Deactivate user (isActive: false) |
| POST |
/api/users/:id/revoke-sessions |
admin |
Revoke all sessions for a user |
| POST |
/api/users/:id/anonymize |
admin |
Erase personal data — sets name to "Deleted User", clears email/phone, deactivates account |
POST /api/users
Returns: { _id, name, email, role, token }
POST /api/users/login
Returns: { _id, name, email, role, token }
PUT /api/users/profile
notificationPreference: "email" | "whatsapp" | "both"
Events
| Method |
Path |
Auth |
Description |
| GET |
/api/events |
public |
Active, public, upcoming events. Includes isSoldOut: boolean per event. |
| GET |
/api/events/all |
staff+ |
All events including hidden/past (?includePast=true, ?includeInactive=true) |
| GET |
/api/events/admin/all |
admin |
Admin view of all events |
| GET |
/api/events/:id |
public |
Full event detail — options, variants, earlyBirdTiers, attachments, form, availableCount per option/variant |
| GET |
/api/events/by-alias/:redirectUrl |
public |
Get event by URL alias |
| POST |
/api/events |
supervisor+ |
Create event |
| PUT |
/api/events/:id |
supervisor+ |
Update event |
| DELETE |
/api/events/:id |
admin |
Delete event |
| POST |
/api/events/:id/email-attendees |
supervisor+ |
Bulk email attendees (dryRun: true to preview) |
| POST |
/api/events/:id/email-attendees/schedule |
supervisor+ |
Schedule bulk email |
| POST |
/api/events/:id/whatsapp-attendees |
supervisor+ |
Bulk WhatsApp to attendees (dryRun: true to preview) |
| POST |
/api/events/:id/whatsapp-attendees/schedule |
supervisor+ |
Schedule bulk WhatsApp |
| GET |
/api/events/attachments/status |
admin |
Attachment manifest sync status |
| POST |
/api/events/attachments/sync |
admin |
Re-sync attachment manifests to DB |
isSoldOut logic (GET /api/events)
isSoldOut is true when every option on the event that has stockLimit > 0 has sold out its full allocation (computed from non-cancelled RegistrationOption quantities). Events with no limited options are never marked sold out.
POST /api/events
Event Options & Variants
| Method |
Path |
Auth |
Description |
| POST |
/api/events/:id/options |
supervisor+ |
Add option to event |
| PUT |
/api/events/options/:id |
supervisor+ |
Update option (name, price, stockLimit, variants, earlyBirdTiers) |
| DELETE |
/api/events/options/:id |
admin |
Delete option (fails if registrations exist) |
| POST |
/api/events/options/:id/variants |
supervisor+ |
Add variant to option |
| PUT |
/api/events/variants/:id |
supervisor+ |
Update variant |
| DELETE |
/api/events/variants/:id |
admin |
Delete variant |
POST /api/events/:id/options
PUT /api/events/options/:id — with variants and early-bird tiers
stockLimit: 0 means unlimited. Early-bird tiers can be option-level (variantId: null) or variant-level (variantId: "<uuid>").
Event Attachments
| Method |
Path |
Auth |
Description |
| GET |
/api/events/:id/attachments |
public |
List attachments for event |
| POST |
/api/events/:id/attachments |
supervisor+ |
Upload attachment (multipart/form-data, field file) |
| DELETE |
/api/events/:eventId/attachments/:id |
supervisor+ |
Delete attachment |
Accepted file types: .pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .txt, .csv, .zip. Max 10 MB.
Registrations
| Method |
Path |
Auth |
Description |
| POST |
/api/registrations |
optional |
Create registration |
| GET |
/api/registrations/myregistrations |
user+ |
Own registrations |
| GET |
/api/registrations/:id |
optional |
Get registration by ID |
| PUT |
/api/registrations/:id/options |
user+ |
Update selected options |
| DELETE |
/api/registrations/:id |
user+ |
Cancel registration (blocked if positive payments exist unless admin) |
| GET |
/api/registrations/:id/forms/draft |
optional |
Get form draft |
| PUT |
/api/registrations/:id/forms/draft |
optional |
Save form draft |
| POST |
/api/registrations/:id/forms/responses |
optional |
Submit form responses |
| PUT |
/api/registrations/:id/forms/responses |
supervisor+ |
Replace form responses |
| GET |
/api/registrations |
staff+ |
All registrations |
| PUT |
/api/registrations/:id |
staff+ |
Update registration status |
| GET |
/api/registrations/event/:eventId |
staff+ |
Registrations for an event |
| POST |
/api/registrations/manual |
supervisor+ |
Manual registration |
POST /api/registrations
For unauthenticated (guest) registration on events with requiresAuth: false:
Cancellation rules
| Actor |
Condition |
Result |
| Owner |
No positive payments |
200 — status set to cancelled |
| Owner |
Any positive payment exists |
403 — must contact organisation |
| Admin |
Any state |
200 — always allowed |
| Anyone |
Already cancelled |
400 |
Payments
| Method |
Path |
Auth |
Description |
| POST |
/api/payments |
supervisor+ |
Record manual payment (cash/EFT) |
| POST |
/api/payments/yoco-checkout |
user+ |
Initiate Yoco checkout; re-evaluates early-bird pricing first — returns { priceUpdated: true, newTotal } if prices changed |
| GET |
/api/payments/mypayments |
user+ |
Own payments |
| GET |
/api/payments/:id |
user+ |
Payment by ID |
| GET |
/api/payments/registration/:registrationId |
user+ |
Payments for a registration |
| GET |
/api/payments |
supervisor+ |
All payments |
| GET |
/api/payments/event/:eventId |
staff+ |
Payments for an event |
| PUT |
/api/payments/assign-donation |
supervisor+ |
Assign a donation payment to a registration |
| POST |
/api/payments/refund |
supervisor+ |
Create refund record |
| GET |
/api/payments/admin/stats |
admin |
Payment statistics |
POST /api/payments (manual)
POST /api/payments/yoco-checkout
Returns: { redirectUrl } or { priceUpdated: true, newTotal, message } if early-bird prices changed.
Tickets
| Method |
Path |
Auth |
Description |
| GET |
/api/tickets/mytickets |
user+ |
Own tickets (excludes cancelled registrations) |
| GET |
/api/tickets/:id |
user+ |
Ticket by ID |
| POST |
/api/tickets/email |
user+ |
Email own tickets as PDF |
| POST |
/api/tickets/send-to |
staff+ |
Send tickets to a specific user |
| GET |
/api/tickets/scan-preview/:qrCode |
staff+ |
Preview scan (no mark) |
| GET |
/api/tickets/qr/:qrCode |
staff+ |
Ticket by QR code |
| POST |
/api/tickets/scan/:qrCode |
staff+ |
Scan/redeem ticket |
| GET |
/api/tickets/event/:eventId |
staff+ |
All tickets for an event |
| GET |
/api/tickets/scans/recent |
staff+ |
Recent scan activity |
| GET |
/api/tickets/scans/stats |
staff+ |
Scan statistics |
| POST |
/api/tickets/generate |
supervisor+ |
Generate tickets for a registration |
| GET |
/api/tickets |
supervisor+ |
All tickets |
| PUT |
/api/tickets/email-sent |
admin |
Bulk mark tickets as emailed |
Broadcasts (Email)
| Method |
Path |
Auth |
Description |
| POST |
/api/broadcasts/preview |
supervisor+ |
Dry-run — returns recipient count and sample |
| POST |
/api/broadcasts/send |
supervisor+ |
Send email broadcast immediately |
| POST |
/api/broadcasts/schedule |
supervisor+ |
Schedule email broadcast |
POST /api/broadcasts/send
Dynamic placeholders: {{name}}, {{event.title}}, {{event.start}}, {{event.link}}, {{balance}}, {{promo.title}}, {{promo.link}}
WhatsApp Broadcasts
| Method |
Path |
Auth |
Description |
| POST |
/api/whatsapp-broadcasts/preview |
supervisor+ |
Dry-run |
| POST |
/api/whatsapp-broadcasts/send |
supervisor+ |
Send WhatsApp broadcast immediately |
| POST |
/api/whatsapp-broadcasts/schedule |
supervisor+ |
Schedule WhatsApp broadcast |
Scheduled Messages
| Method |
Path |
Auth |
Description |
| GET |
/api/scheduled-emails |
supervisor+ |
List all queued/scheduled jobs |
| PATCH |
/api/scheduled-emails/:id |
supervisor+ |
Edit scheduled job (reschedule, update content) |
| DELETE |
/api/scheduled-emails/:id |
supervisor+ |
Cancel a queued job |
Automations
| Method |
Path |
Auth |
Description |
| POST |
/api/automations/schedule |
supervisor+ |
Schedule event lifecycle automations (pre-event reminder, thank-you, promo, etc.) |
Reports
| Method |
Path |
Auth |
Description |
| POST |
/api/reports/pdf |
user+ |
Generate and download PDF attendance/payment report |
| POST |
/api/reports/email |
user+ |
Email PDF report to current user |
Uploads
| Method |
Path |
Auth |
Description |
| POST |
/api/uploads/event-image |
supervisor+ |
Upload event cover image (multipart/form-data, field image). Returns { url }. Max 5 MB. Formats: jpg, jpeg, png, webp, gif. |
| POST |
/api/uploads/logo |
admin (or unauthenticated during setup) |
Upload site logo (multipart/form-data, field image). Returns { url }. Max 2 MB. Formats: jpg, jpeg, png, webp, svg. |
Sections
Groups of event options shown as labelled sections on the registration page (e.g. "Tickets", "Add-ons", "Accommodation").
| Method |
Path |
Auth |
Description |
| GET |
/api/sections |
staff+ |
List sections |
| POST |
/api/sections |
supervisor+ |
Create section |
| PUT |
/api/sections/:id |
supervisor+ |
Update section |
| DELETE |
/api/sections/:id |
admin |
Delete section |
POST /api/sections
Banner
| Method |
Path |
Auth |
Description |
| GET |
/api/banner |
public |
Get current site-wide banner (text, colour, active flag) |
| POST |
/api/banner |
supervisor+ |
Set site banner |
POST /api/banner
Forms
| Method |
Path |
Auth |
Description |
| GET |
/api/forms/responses |
staff+ |
List all submitted form responses across all events; supports filtering |
Yoco Transactions
Raw webhook events from Yoco. Used for reconciling payments that weren't matched automatically.
| Method |
Path |
Auth |
Description |
| GET |
/api/yoco-transactions |
supervisor+ |
All Yoco webhook transactions |
| GET |
/api/yoco-transactions/unreconciled |
supervisor+ |
Transactions not yet matched to a payment |
| POST |
/api/yoco-transactions/:id/reconcile |
supervisor+ |
Manually link transaction to a registration |
| POST |
/api/yoco-transactions/:id/ignore |
supervisor+ |
Mark transaction as intentionally ignored |
WhatsApp Admin
Manages the WAWP WhatsApp API instance. Credentials are stored in AppSetting (preferred) or .env (fallback).
| Method |
Path |
Auth |
Description |
| GET |
/api/whatsapp/config |
admin |
Get current WAWP credentials |
| POST |
/api/whatsapp/config |
admin |
Save WAWP credentials to DB |
| GET |
/api/whatsapp/status |
admin |
WAWP session status |
| GET |
/api/whatsapp/qr |
admin |
QR code for WhatsApp device linking |
| POST |
/api/whatsapp/create-instance |
admin |
Create a new WAWP instance |
| POST |
/api/whatsapp/delete-instance |
admin |
Delete WAWP instance |
| POST |
/api/whatsapp/request-code |
admin |
Request pairing code (alternative to QR) |
| POST |
/api/whatsapp/logout |
admin |
Logout current WAWP session |
| POST |
/api/whatsapp/start |
admin |
Start WAWP instance |
| POST |
/api/whatsapp/restart |
admin |
Restart WAWP instance |
Webhooks
| Method |
Path |
Auth |
Description |
| POST |
/api/webhooks/yoco |
HMAC-verified |
Yoco payment webhook — verifies X-Yoco-Signature, creates Payment + YocoTransaction, updates registration status, generates tickets |
| POST |
/api/webhooks/whatsapp |
— |
WAWP inbound event webhook |
Settings
Runtime configuration stored in the AppSetting table. Sensitive values (SMTP credentials, WAWP token) are stored AES-256-GCM encrypted.
| Method |
Path |
Auth |
Description |
| GET |
/api/settings |
public |
Public settings (org name, tagline, colour, logo, legal keys) |
| GET |
/api/settings/all |
admin |
All settings — smtp_pass masked as ••••••••, smtp_user decrypted |
| GET |
/api/settings/needs-setup |
public |
{ needsSetup: bool } — true until setup wizard completes |
| PUT |
/api/settings |
admin |
Upsert settings; smtp_user/smtp_pass encrypted before storage; sending •••••••• for smtp_pass keeps existing value |
| POST |
/api/settings/test-smtp |
admin |
Test SMTP with provided credentials; sends real test email to admin on success. The admin JWT returned by POST /api/setup/register also qualifies during the setup wizard. |
POST /api/settings/test-smtp
Success (200):
Failure (400):
The message field is always a human-readable sentence. The raw field is included on errors only and contains the original SMTP error for debugging. Error code 530 (Microsoft "Client not authenticated") maps to the authentication-failure message.
Setup
One-time first-run wizard. Both endpoints are blocked once any user exists and setup is complete.
| Method |
Path |
Auth |
Description |
| POST |
/api/setup/register |
public (one-time) |
Create the first admin account; returns a short-lived setup JWT |
| POST |
/api/setup |
setup token or admin |
Save initial site settings (org name, branding, SMTP) |
Static Files
| Path |
Description |
/uploads/events/* |
Event cover images |
/uploads/branding/* |
Site logo |
/uploads/event-files/* |
Event attachments (PDFs, docs, etc.) |
/uploads/tickets-temp/* |
Temporarily hosted ticket PDFs for WhatsApp delivery (auto-deleted after 5 min) |
Auth error responses
| Status |
Body |
Meaning |
| 401 |
{ message: "Not authorised, no token" } |
Missing or malformed Authorization header |
| 401 |
{ message: "Not authorised, token failed" } |
Invalid or expired JWT |
| 401 |
{ message: "Session has been revoked" } |
Token version mismatch (sessions revoked) |
| 403 |
{ message: "Not authorised as an admin" } |
Insufficient role |
For full interactive docs with expandable examples visit GET /docs?token=<admin-jwt> on the running backend.