HTTP API reference
Base URL is your deployment origin (for example http://localhost:8080).
JSON endpoints expect Content-Type: application/json unless noted otherwise.
Public
HTML landing page.
Liveness probe. Returns ok or 503 if MySQL health check fails when MySQL is configured for the app.
Gmail ingestion (Google Cloud)
Pub/Sub push delivery endpoint for Gmail watch notifications. Body is the standard Pub/Sub JSON envelope with base64-encoded Gmail notification in message.data. Returns 204 on success.
- Not part of the admin API — secured by Pub/Sub / your ingress rules.
Payment provider webhooks
Public ingress that accepts raw provider webhooks (currently rapyd, stripe, trust_payments) and forwards them
to one or more internal endpoints registered as provider routes. Signature is verified on the raw body using the access/secret stored on the matching ingress.
Each matched route receives its own POST signed with X-Mailhub-Signature: sha256=<hex> using the route's HMAC secret.
Raw webhook ingress. Body must be the exact bytes sent by the provider (do not re-serialize). Returns 204 on accepted, 200 on duplicate or unrouted, 401 on invalid signature, 404 on unknown ingress.
- Headers (Rapyd):
signature,salt,timestamp. - Headers (Stripe):
stripe-signature. - Trust Payments is pass-through — Mailhub does not verify the upstream signature, the receiving backend does, so the body is form-urlencoded and gets routed by JSONPath (e.g.
$.orderreference) like JSON payloads. - Behind a proxy that rewrites the path, set
PROVIDER_INGRESS_TRUSTED_PROXIES+ sendX-Forwarded-Pathor pin the path withPROVIDER_INGRESS_RAPYD_PATH_OVERRIDE.
Authentication
Token mode (MAILHUB_ADMIN_AUTH=token): set ADMIN_TOKEN.
Sign in via POST /api/admin/login with { "token": "…" } to receive an HTTP-only session cookie mailhub_session,
or send Authorization: Bearer <token> or header X-Mailhub-Admin-Token on each request.
Database mode (MAILHUB_ADMIN_AUTH=database): use POST /api/auth/login with email and password;
session cookie mailhub_admin_session. If ADMIN_TOKEN is also set, the same Bearer / X-Mailhub-Admin-Token headers are accepted and treated as superadmin for automation.
Auth routes (database mode)
Returns { openRegistration: boolean } — true only while no admin users exist.
Body: { "email": "…", "password": "…" } (password min 10 characters). Sets session cookie; response { ok, user, role, expiresAt }.
Body: same shape as login. Allowed only when there are zero admin users; creates the first superadmin. Returns 201 and session on success.
Legacy admin login (token mode)
Body: { "token": "…" }. Returns mailhub_session cookie.
Clears admin session cookies. Body can be empty JSON.
Admin API
All routes below require an authenticated admin session or Bearer / X-Mailhub-Admin-Token when configured.
Returns authentication state: configured, authenticated, and in database mode authMode plus user when signed in.
Summary: alias route count, feature flags, mysqlConfigured, adminConfigured.
Recent monitoring events (limit 1–500, default from server config).
Provider webhook audit log: inbound ingress results and outbound forwards. List entries omit raw bodies; each row includes hasPayloadBody when bodies are captured (PROVIDER_WEBHOOK_CAPTURE_BODIES). Filters: kind ingress | forward, provider, ingress_key.
Single event including payloadBody when it was captured at ingress time, plus verificationSnapshot (signature headers and signed URL path) for inbound events.
/api/admin/provider-webhook-events/:eventId/revalidate
Re-deliver a captured inbound webhook to a backend route. JSON body optional{ "route_id": "…" }; if omitted and the ingress event matched exactly one route, that route is used. Returns { delivery } from the forwarder.
Alias routes (HTTP JSON)
Same behaviour on /api/admin/alias-routes and shorter /api/alias-routes (GET list, POST upsert, DELETE by alias).
Use a normal admin session or Authorization: Bearer / X-Mailhub-Admin-Token with ADMIN_TOKEN.
If MAILHUB_ALIAS_ROUTES_TOKEN is set, you may also send that value as Authorization: Bearer … or header X-Mailhub-Alias-Routes-Token — only for these alias-route endpoints (useful for CI or narrow automation).
List configured alias routes (secrets omitted). Same as GET /api/alias-routes.
Create or update a route. Body: aliasAddress, webhookUrl, optional webhookHmacSecret, description, active. Same as POST /api/alias-routes. Returns 201 and { route }.
Remove a route by alias email (URL-encoded). Same as DELETE /api/alias-routes/:aliasAddress.
Provider ingresses and routes
Authentication: normal admin session, Authorization: Bearer <ADMIN_TOKEN>, or — when set — Authorization: Bearer <MAILHUB_API_TOKEN>.
Error responses follow { "message": "…", "code": "…" }. verify_secret and webhook_hmac_secret are write-only and never returned on read.
List provider ingresses (without secrets). Returns { ingresses: [...] }.
List supported provider names with form-field hints for the admin UI. Returns { providers: [{ name, requiresVerifySecret, fields }] }.
Upsert by (provider, key). Body: provider (rapyd | stripe | trust_payments | nikulipe | shift4 | paypal), key, display_name, verify_access_key, verify_secret (required on create except pass-through providers), active. verify_secret is updated only when provided non-empty. Returns { ingress }.
Delete an ingress and (cascade) its routes. Returns 204 or 404.
List provider routes (without secrets). Optional filter by ingress_key (+ ingress_provider, default rapyd). ingress_provider may be rapyd, stripe, trust_payments, nikulipe, shift4, or paypal.
Upsert by (ingress_id, description). Body: ingress_provider, ingress_key, description, matcher_jsonpath, matcher_regex, webhook_url, webhook_hmac_secret (required on create), priority, active. Returns { route }.
Remove a route by id. Returns 204 or 404.
Snapshot of provider webhook counters and forward attempt histogram.
Start or renew a watch. Body: emailAddress, optional topicName, labelIds, labelFilterAction.
List saved Gmail watch states.
Body: optional { "emailAddress": "…" } to renew one mailbox, or omit to renew all saved watches.
Administrators (database mode only)
List admin users (email, role, createdAt).
Create an admin. Body: email, password (min 10 chars), role admin | superadmin. Requires superadmin session (or Bearer token when ADMIN_TOKEN is set).
HTML UI (browser)
/admin— overview/admin/alias-routes,/admin/gmail-watch,/admin/activity/admin/providers,/admin/provider-routes— manage provider ingresses and routes (when provider hub is enabled)/admin/provider-webhooks— inbound/outbound provider webhook log (when provider hub is enabled)/admin/users— database auth only/admin/register— first superadmin registration when the user table is empty