The Hypno Academy

Suite

Integrations

Connect any external site so every new enrollment lands here as a draft invoice.

How it works

  1. In Sources, create a source for the site (e.g. soulkey) and mark it active.
  2. On that site, store the shared secret as an environment variable named ENROLLMENT_SECRET. Use the same value that is set here as SOULKEY_WEBHOOK_SECRET.
  3. After a successful enrollment, the site POSTs the payload below to the webhook.
  4. A draft invoice is created and shows up under Invoices, tagged with the source.

Endpoint

POST https://pay.thehypnoacademy.com/api/public/enrollment
Required header
X-Enrollment-Secret: <your shared secret>
Payload schema
FieldTypeRequiredNotes
sourcestringyesMatches a slug in Sources
idstringyesUnique enrollment id (idempotency key)
fullNamestringyes
emailstringyes
phonestringno
countrystringno
tierstringnoPackage / bundle name (shown on invoice)
amountnumbernoIgnored for safety; configure pricing in this app
currencystring (3)noISO code, default USD
descriptionstringnoOverrides invoice line label
metaobjectnoArbitrary extra data, stored on invoice

Copy-paste snippets

Paste this into the chat of any other Lovable project to wire it up.

When a new enrollment is completed on this site, send it to my invoicing app so a draft invoice is created automatically.

Add a server-side handler that POSTs to:
  https://pay.thehypnoacademy.com/api/public/enrollment

Headers:
  Content-Type: application/json
  X-Enrollment-Secret: <value of the ENROLLMENT_SECRET env var / Lovable Cloud secret>

Body (JSON):
  {
    "source": "soulkey",          // identifies this site in my dashboard
    "id": "<unique enrollment id>", // used as idempotency key
    "fullName": "<full name>",
    "email": "<email>",
    "phone": "<phone, optional>",
    "country": "<country, optional>",
    "tier": "<package or tier name, optional>",
    "currency": "<3-letter ISO code, optional, default USD>"
  }

Requirements:
- Call this from server-side code only (server function / edge function / API route). Never from the browser.
- Add ENROLLMENT_SECRET as a secret in Lovable Cloud (do not hardcode).
- Treat any non-2xx response as a failure and log the response body for debugging.
- The same "id" must always represent the same enrollment so retries do not create duplicates.
- Do not send invoice pricing from the website; this app calculates pricing from the source settings / server-side rules.

Responses

  • 200 — invoice created (or deduped if the same id was sent before).
  • 400 — invalid JSON or payload failed validation.
  • 401 — missing or wrong X-Enrollment-Secret.
  • 403 — unknown source slug, or the source is disabled in the dashboard.
  • 500 — server error; the response body includes details.

Team Staff Suite sync

A secured read-only API (plus limited write) so the Staff Suite works off this database — one source of truth, no duplicated invoices and no drift.

Base URL & auth header
https://pay.thehypnoacademy.com/api/public/sync
X-Sync-Secret: <value of STAFF_SUITE_SYNC_SECRET>

The secret is stored here as STAFF_SUITE_SYNC_SECRET. Add the same value as a secret in the Staff Suite — never hardcode it or call these endpoints from the browser.

Endpoints
  • GET /invoices — list with limit, offset, updated_since, status, include=items,fees,customers.
  • GET /customers — list with limit, offset, updated_since, search.
  • GET /invoices/:id — one invoice with customer, items, fees and timeline.
  • PATCH /invoices/:id — limited write: status, payment method/note, notes, reminders toggle.
Connect this app to my invoicing app (InvoiceSuite) so it reads live invoice and customer data instead of keeping its own copies.

Base URL: https://pay.thehypnoacademy.com/api/public/sync
Auth header on every request: X-Sync-Secret: <value of the STAFF_SUITE_SYNC_SECRET env var>
Store that value as a Lovable Cloud secret named STAFF_SUITE_SYNC_SECRET. Call these endpoints from server-side code only — never from the browser.

Endpoints:
  GET  /invoices?limit=100&offset=0&updated_since=<ISO date>&status=<status>&include=items,fees,customers
       -> { invoices: [...], items?, fees?, customers?, count, limit, offset, synced_at }
       Each invoice includes public_url (the customer-facing payment link).
  GET  /customers?limit=200&offset=0&updated_since=<ISO date>&search=<name or email>
       -> { customers: [...], count, limit, offset, synced_at }
  GET  /invoices/<invoice id>
       -> { invoice, customer, items, fees, events }
  PATCH /invoices/<invoice id>
       Body (all fields optional): { "status": "draft|awaiting_approval|approved|sent|paid|cancelled",
         "payment_method": "...", "payment_note": "...", "notes": "...",
         "reminders_enabled": true, "actor": "<staff member name>" }
       -> { ok: true, invoice }

Requirements:
- Read data live through these endpoints; do not duplicate invoices into a local table (cache briefly if needed).
- Use updated_since with the previous synced_at value for incremental polling.
- Always send "actor" on PATCH so the change is attributed in the invoice timeline.
- Treat any non-2xx as a failure and log the response body.