Skip to content
lessonluma
Menu ▾
Developers

The Lessonluma API

Everything the coach app, the booking pages and the AI assistant do is a call to this API, so anything you can click you can automate. JSON over HTTPS, OpenAPI 3.1, signed webhooks for every event.

Download the OpenAPI spec (openapi.json)

Authentication

Create a key in the coach app under API & webhooks. Send it as a bearer token. A key has full access to its own coach account only; keep it on your server.

curl https://new.lessonluma.com/api/v1/lessons?days=7 \
  -H "Authorization: Bearer ll_live_xxxxxxxxxx_..."

Base URL: https://new.lessonluma.com/api/v1

Conventions

  • Money is integer cents in CAD: "priceCents": 7000 is CA$70.00.
  • Times are ISO 8601 in UTC; each coach account has a timezone.
  • Lists return { data, hasMore, nextCursor }; pass limit (max 500) and cursor.
  • Errors return { "error": { "code", "message" } } with a 4xx/5xx status.
  • Sign-up, booking and login endpoints are rate-limited per IP.

Webhooks

Add an endpoint (dashboard or POST /webhooks) and choose events, or * for all. Each delivery is a JSON POST with headers Lessonluma-Event, Lessonluma-Delivery and Lessonluma-Signature: t=<unix>,v1=<hex>, where v1 is an HMAC-SHA256 of <t>.<raw body> with the endpoint secret. Failed deliveries retry after 1, 5, 30, 120 and 720 minutes. Return any 2xx to acknowledge.

import crypto from "node:crypto";

// rawBody: the exact request body string; header: req.headers["lessonluma-signature"]
export function verifyLessonluma(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  const a = Buffer.from(expected), b = Buffer.from(parts.v1 || "");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return fresh && a.length === b.length && crypto.timingSafeEqual(a, b);
}

Payload: { "id", "type", "created", "business_id", "data" }. Every coach account also has a built-in test endpoint that records what it receives, so you can see real payloads before wiring up Zapier or your own code.

Events: family.created family.updated person.created person.updated lesson.created lesson.updated lesson.moved lesson.cancelled lesson.rained_out booking.created booking.waitlisted booking.promoted booking.cancelled booking.skipped booking.attended booking.no_show recurring.created recurring.ended pack.purchased credits.added credits.low payment.created payment.succeeded payment.failed payment.refunded etransfer.matched etransfer.unmatched waiver.signed note.sent review.requested review.submitted lesson_type.created lesson_type.updated pack.created pack.updated business.created business.updated business.setup_applied business.plan_changed site.published site.unpublished

Endpoints

Auth

post/signupCreate a coach account (Solo free for 30 days, no card) and its booking pagepublic
post/auth/loginCoach login (sets a session cookie)public
post/auth/reset-requestEmail a coach password-reset linkpublic
post/auth/resetSet a new coach password from a reset linkpublic
post/auth/logoutLog out (coach)public

Coach page

get/public/{slug}A coach's public page: lessons, prices, packs, clinics, places, badges, reviews, policiespublic
get/public/{slug}/slotsOpen private/semi times for a lesson type, day by daypublic
get/public/{slug}/lessonsOpen clinics and camps with spots left (camps listed once, by their first day)public
post/public/{slug}/bookBook as a family: a private/semi time (lessonTypeId + startsAt) or a clinic/camp (lessonId), for yourself or a childpublic
get/public/{slug}/pay/{ref}How to pay one lesson or pack (e-transfer address + code, or card)public
post/public/{slug}/pay/{ref}Pay by card (test rail until the coach connects Stripe; then use checkoutUrl)public
get/public/rebook/{token}After a rainout: the next open times for this lessonpublic
post/public/rebook/{token}Rebook in one tap with the rainout creditpublic
get/public/{slug}/review/{token}A review requestpublic
post/public/{slug}/review/{token}Leave a review (1-5 stars and a few words)public

Family

get/public/{slug}/meYour family: people, balance, upcoming lessons, unpaid, waivers, notesfamily
post/public/{slug}/me/peopleAdd a child or the second parent/guardianfamily
post/public/{slug}/me/bookings/{id}/cancelCancel a booking (free inside the coach's window; later the lesson counts)family
post/public/{slug}/me/bookings/{id}/skipSkip one week of a weekly lessonfamily
post/public/{slug}/me/packsBuy a pack (credits land now; card, e-transfer or cash)family
post/public/{slug}/me/waiverSign this season's waiver for a student (guardian signs for a child)family
post/public/{slug}/me/recurringMake a lesson weekly (same day and time) until a datefamily
post/public/{slug}/loginFamily loginpublic
post/public/{slug}/logoutFamily logoutpublic
post/public/{slug}/magic-linkEmail a one-time sign-in linkpublic
post/public/{slug}/claimSign in from an emailed link (optionally set a password)public

Account

get/businessThis coach account, its page and settingsAPI key
patch/businessUpdate the page (name, headline, about, city, sports, e-transfer address, tax number, settings)API key
get/business/planPlan, trial, active students vs the Free limit, pause days leftAPI key
get/locationsPlaces you teachAPI key
post/locationsAdd a place (outdoor places get the evening forecast heads-up)API key
patch/locations/{id}Edit a placeAPI key
get/badgesDated credentials you show on your page (certification, police check, insurance, first aid)API key
post/badgesAdd a dated badge (shown as your claim with its date, never as 'verified')API key
delete/badges/{id}Remove a badgeAPI key
patch/staff/{id}A coach's public name and short bioAPI key

Setup

post/setup/describeDescribe your coaching in a sentence or two; the page, lessons, packs, clinics and hours are set up from itAPI key

Lessons

get/lesson-typesWhat you sell: privates, semi-privates, clinics, campsAPI key
post/lesson-typesAdd a lesson typeAPI key
patch/lesson-types/{id}Change a lesson type (price, length, capacity, runs-with, active)API key
get/packsLesson packs on saleAPI key
post/packsAdd a pack (3/5/10 lessons, optional expiry)API key
patch/packs/{id}Change or retire a packAPI key
get/availabilityWeekly windows when privates can be bookedAPI key
put/availabilityReplace your weekly windows (windows[], or text lines like 'Mon-Fri 16:00-20:00')API key
get/slotsOpen private/semi start times on a dateAPI key
get/lessonsYour calendar: lessons with rosters (default today + 14 days)API key
post/lessonsSchedule a clinic, or a camp across several days (one checkout books every day)API key
patch/lessons/{id}Move a lesson (families are told) or change its notes/capacityAPI key
post/lessons/{id}/cancelCancel a lesson (credits back, families told)API key
get/todayToday and tomorrow at a glance (lessons, unpaid, forecast)API key

Rain

post/lessons/{id}/rainThe rain button for one lesson: credits back, everyone texted with the next open timesAPI key
post/rainThe rain button for a whole day (outdoor places, or all places)API key
post/forecast/checkRun tomorrow's forecast check now (normally automatic in the evening)API key

Families

get/familiesFamilies (search by name, email, phone or reference code)API key
post/familiesAdd a family: a guardian (or adult learner) and studentsAPI key
get/families/{id}One family: people, balance, bookings, payments, waivers, notesAPI key
post/families/{id}/peopleAdd a child, an adult learner or the second guardianAPI key
patch/people/{id}Edit a personAPI key
post/families/{id}/creditsGive credits (make-up, goodwill)API key
post/families/{id}/packsSell a pack to a family (e-transfer/cash tracked, card via the pay link)API key
post/notesSend a two-line progress note (and a clip link) to the familyAPI key
post/waivers/signRecord a waiver signed on the coach's phone at the courtAPI key
get/waivers/{id}/pdfA signed waiver as PDFAPI key
get/messagesOutbox: every email/text sent for this account (with CASL basis and status)API key

Bookings

get/bookingsBookings (filter by family, student or lesson)API key
post/bookingsBook a student: a private/semi at a time (lessonTypeId + startsAt) or a clinic/camp seat (lessonId)API key
post/bookings/{id}/cancelCancel a booking (coach cancels never count as late)API key
post/bookings/{id}/skipSkip one week of a weekly series (the series keeps going)API key
post/bookings/{id}/attendanceMark attended or no-showAPI key
post/recurringWeekly series: 'Tuesdays 4:30 with Maya until June' (each week booked 3 weeks ahead)API key
get/recurringWeekly seriesAPI key
delete/recurring/{id}End a weekly series (future weeks cancelled, credits back)API key

Payments

get/paymentsPayments (pending = unpaid e-transfer/cash/card)API key
post/payments/{id}/paidOne tap: mark paid (e-transfer arrived, cash in hand)API key
post/payments/{id}/voidCancel an unpaid chargeAPI key
get/payments/inboxDeposit emails forwarded to your private address, and what they matchedAPI key
post/payments/inboxPaste a bank deposit email (same matching as forwarding it)API key
post/payments/stripe/connectConnect your own Stripe account (cards, Apple Pay, Google Pay)API key
post/payments/stripe/refreshRe-check the Stripe connectionAPI key

AI

post/operatorAsk the AI operator in plain words ('move Thursday's 4:30 to Friday and tell Maya's mum')API key

Plan

post/billing/checkoutStart an upgrade checkout (Solo CA$19/mo or CA$190/yr, Academy CA$49, Academy 15 CA$99)API key
post/billing/checkout/completeFinish the simulated (test) checkout; only while Lessonluma's Stripe keys are not setAPI key
post/billing/pausePause for the off-season (CA$0, up to 6 months a year; a new booking wakes the plan)API key
post/billing/resumeEnd the pause nowAPI key
post/billing/cancelCancel the paid plan (back to Free; nothing is deleted)API key

Internal

post/smoke/tickSmoke tests only: run one cron job nowpublic
post/smoke/forecastSmoke tests only: run tomorrow's forecast check with a supplied forecastAPI key

Developers

get/api-keysAPI keys (the secret is shown once, at creation)API key
post/api-keysCreate an API key (full access to this business; keep it secret)API key
delete/api-keys/{id}Revoke an API keyAPI key
get/webhooksWebhook endpointsAPI key
post/webhooksSubscribe a URL to events (signed with Lessonluma-Signature: t=,v1=HMAC-SHA256)API key
patch/webhooks/{id}Pause, resume or change eventsAPI key
delete/webhooks/{id}Delete a webhook endpointAPI key
post/webhooks/{id}/testSend a webhook.test event nowAPI key
get/webhooks/{id}/deliveriesRecent deliveries with response codesAPI key
get/webhook-sinkWhat the built-in test endpoint received (point a webhook at testEndpoint to try it)API key

Website

post/sitesPublish the public website: a zip, files as JSON, or {url} to snapshot. Live at https://<slug>.lessonluma.com/ unless publish=false.API key
get/sitesWebsite versions (newest first) and which one is liveAPI key
post/sites/{id}/publishMake a version live (also the one-click rollback)API key
delete/sites/liveTake the custom site down (the default coach page returns)API key
post/sites/handoff-tokensStart a Build-with-AI session: a 24-hour token that can only publish this website, and the one-line prompt for each AIAPI key
get/sites/handoff-tokensBuild-with-AI tokens (the secret is only shown at creation)API key
delete/sites/handoff-tokens/{id}Revoke a Build-with-AI tokenAPI key
post/sites/build-clicksRecord a Build-with-AI click and what happened (opened=app|web|pending); feeds the 'what worked' table and AdJump site_build_startedAPI key
get/sites/build-clicks/statsWhich launch route worked, per AI and platformAPI key
get/sites/publishable-keyThe publishable key used in the AI kit (public by design: reads only)API key
get/sites/{id}One version with its file listAPI key

Website data

get/public/{slug}/lesson-typesLessons with exact prices and a booking link eachAPI key
get/public/{slug}/packsLesson packs with prices, per-lesson price, validity and a buy linkAPI key
get/public/{slug}/coachesCoaches shown publicly (name, role, bio) and their dated credentialsAPI key
get/public/{slug}/reviewsPublished reviews and the average ratingAPI key