HaloMail docs
API-firstConnectRPC Go + Next.jsMIT

HaloMail Documentation

An open-source platform for meeting scheduling and portfolio contact forms — one typed API, a generated SDK, webhooks, and a polished dashboard.

Raw docs page — the seed of HaloMail's own docs engine. Real content, no external framework.

Introduction

HaloMail gives every user a public booking page and an embeddable contact form, behind a clean ConnectRPC API that speaks gRPC, gRPC-Web, and plain JSON from a single definition. The dashboard, the SDK, and your own integrations all share one contract.

Scheduling

Booking pages, availability, Google & Outlook sync, confirmations, reschedule/cancel.

Contact forms

Embeddable widget, REST + SDK, spam protection, rate limiting, storage, forwarding.

Email designer

Themes — Minimal, Apple, Notion, Glass, Terminal — plus custom HTML and live preview.

Developer

API keys, signed webhooks, generated SDK, OpenAPI, audit logs.

Quickstart

Run the whole stack locally. Full guide: docs/DEVELOPMENT.md.

# 1. infra: postgres, redis, mailpit, jaeger
task up

# 2. generate code from the proto contracts
task proto

# 3. deps + database schema
task bootstrap && task migrate

# 4. run the API (all services in one process)
task api:run        # http://localhost:8080
Locally, email is captured by Mailpit at :8025 and traces by Jaeger at :16686 — nothing leaves your machine.

Authentication

Two credential types, both via the Authorization header:

CallerHeaderObtained from
Dashboard / userBearer <jwt>AuthService/Login
Developer / serverApiKey hl_live_…Dashboard → API Keys

The gateway verifies the credential, then injects the caller's user_id, org_id, and scopes into the request.

Services

The backend is a set of modular Go microservices behind one gateway.

ServiceOwns
gatewayPublic edge: auth, rate limiting, REST/OpenAPI, aggregation
identityUsers, orgs, auth/JWT, API keys, audit log
schedulingEvent types, availability, bookings, calendar sync
contactForms, messages, spam protection, forwarding
templateEmail themes, render, preview
notificationEmail delivery, webhook dispatch

Scheduling

Availability is weekly rules in the owner's timezone, minus date overrides, existing bookings (plus buffers), and busy time from connected calendars — sliced into the event type's duration and projected into the invitee's timezone.

List open slots (public)

POST /halomail.scheduling.v1.BookingService/ListSlots
# body
{ "event_type_id": "evt_…",
  "from_date": "2026-06-15",
  "to_date": "2026-06-20",
  "invitee_timezone": "Europe/Berlin" }

Contact forms

Drop the widget on any site; submissions are rate-limited, spam-scored, stored, forwarded to your inbox, and pushed to webhooks.

<!-- embed -->
<script src="https://<api-host>/widget.js"
        data-form="contact" defer></script>

Email themes

Minimal

Clean, system font, whitespace.

Apple

SF-style, soft shadows, rounded.

Notion

Document-like, neutral dividers.

Glass

Translucent panels, gradients.

Terminal

Monospace, dark, developer.

Custom

Your own HTML with {{variables}}.

Calling the API

ConnectRPC speaks plain JSON over HTTP, so any HTTP client works — no gRPC tooling required.

# Log in and get a session
curl https://<api-host>/halomail.identity.v1.AuthService/Login \
  -H 'Content-Type: application/json' \
  -d '{"email":"me@example.com","password":"••••••"}'
# Use the access token
curl https://<api-host>/halomail.identity.v1.UserService/GetCurrentUser \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Content-Type: application/json' -d '{}'

Endpoints

All procedures are POST /halomail.<service>.v1.<Service>/<Method>.

ProcedurePurposeAuth
identity.v1.AuthService/RegisterCreate account + sessionnone
identity.v1.AuthService/LoginEmail + password → sessionnone
identity.v1.ApiKeyService/CreateApiKeyIssue an API keyBearer
scheduling.v1.BookingService/ListSlotsOpen slots for an event typenone
scheduling.v1.BookingService/CreateBookingBook a slotnone
contact.v1.MessageService/SubmitMessageSubmit a contact formnone
template.v1.TemplateService/RenderPreviewRender an email themeBearer/ApiKey
notification.v1.WebhookService/CreateWebhookSubscribe to eventsBearer/ApiKey

Webhooks

Subscribe to booking.created, booking.cancelled, booking.rescheduled, and message.received. Each delivery is signed with HMAC-SHA256 in an X-HaloMail-Signature header; verify it before trusting the payload.

Errors

Errors use Connect status codes mapped from the domain:

DomainConnect codeHTTP
invalid inputinvalid_argument400
not foundnot_found404
conflictalready_exists409
unauthorizedunauthenticated401
rate limitedresource_exhausted429

Self-hosting

HaloMail is open source — run it wherever you can run a container. In monolith mode it's a single binary backed by PostgreSQL and, optionally, Redis.

# build one image, run it anywhere
docker build -f deploy/Dockerfile --build-arg SERVICE=gateway -t halomail .
docker run -p 8080:8080 --env-file .env halomail

All configuration is via environment variables — see .env.example in the repository.


HaloMail is MIT-licensed and open to contributions — see CONTRIBUTING.md.