SDK reference
@mrcharles/sdk is zero-dependency TypeScript, shipped as ESM (import), as an IIFE for <script> (window.MrCharles) and with full types. About 11 kB gzipped. The usage guide is JavaScript SDK; this page is the surface.
createClient(config?) → MrCharlesClient
Section titled “createClient(config?) → MrCharlesClient”| Option | Type | Default | Notes |
|---|---|---|---|
env | 'production' | 'production' | The only public environment; kept for forward compatibility. |
apiBase, appBase, sitesBase | string | production hosts | Endpoint overrides for tests and proxies. |
fetch | typeof fetch | globalThis.fetch | Server runtimes, tests, custom agents. |
locale | string | site default | Any BCP-47 tag. Drives lang on links/embeds, the hold locale (mapped to es/ca/en), Accept-Language, t() and format. |
publishableKey | string | — | Your pk_live_…/pk_test_… key, sent as X-MC-Key. It only works from the website origins you listed for it, gives no access to your account, and records bookings as made on your website. Secret (sk_) and restricted (rk_) keys are refused here. |
headers | Record<string,string> | — | Extra headers on every request. Forwarding headers (X-Forwarded-For and the like) are ignored by the API. |
client.sites
Section titled “client.sites”| Method | Returns | Endpoint |
|---|---|---|
get(slug) | PublicSite | GET /public/sites/{slug} |
resolve(host) | PublicSite | GET /public/sites/resolve?host= |
availability(slug, roomId, { from, to }) | RoomAvailability | GET /public/sites/{slug}/rooms/{roomId}/availability |
quote(slug, roomId, { date, startTime, durationMinutes, groupSizeId?, partySize?, locale? }) | Quote | POST /public/sites/{slug}/rooms/{roomId}/quote |
client.holds
Section titled “client.holds”| Method | Returns | Endpoint |
|---|---|---|
create(slug, HoldRequest) | Hold | POST /public/sites/{slug}/holds |
verify(holdId, code) | Hold | POST /public/holds/{id}/verify |
resend(holdId) | Hold | POST /public/holds/{id}/resend |
confirm(holdId, { paymentMode, notes?, email? }) | Confirmation | POST /public/holds/{id}/confirm |
client.bookings
Section titled “client.bookings”| Method | Returns | Endpoint |
|---|---|---|
get(manageToken) | Booking | GET /public/bookings/manage/{token} |
cancel(manageToken, reason?) | Booking | POST /public/bookings/manage/{token}/cancel |
client.teachers
Section titled “client.teachers”| Method | Returns |
|---|---|
profile(instructorUserId) | TeacherProfile |
offers(instructorUserId) | LessonOffer[] (published only) |
offer(offerId) | LessonOffer |
windows(instructorUserId, { from, to }) | TeacherWindows |
policy(instructorUserId) | LessonPolicy |
slots({ instructorUserId, offerId, date, days? }) | LessonSlots |
client.links
Section titled “client.links”| Method | Builds |
|---|---|
site(slug) | https://{slug}.sites.mrcharles.app/ |
bookRoom({ slug, roomId, date?, start?, durationMinutes?, lang?, embed? }) | the hosted booking screen, prefilled |
manage(slug, manageToken) | the guest’s manage page |
bookLesson({ instructorId, offerId?, attribution? }) | the app’s lesson booking screen; attribution from client.attribution.handoff() |
teacherProfile(instructorUserId) | the teacher’s profile in the app |
client.attribution
Section titled “client.attribution”| Method | Returns |
|---|---|
handoff() | { attribution, expiresAt }: a signed token valid 30 minutes. Needs a teacher’s publishableKey and a page on one of its origins. |
client.mountRoomBooking(target, options) → EmbedHandle
Section titled “client.mountRoomBooking(target, options) → EmbedHandle”target is a selector or element. Options are RoomLinkOptions plus onBooked({ reference, manageUrl }). The iframe resizes itself and only accepts messages from the hosted site’s origin. handle.destroy() removes it.
Languages on the client
Section titled “Languages on the client”| Member | What |
|---|---|
locale / setLocale(tag) | the client’s language (undefined = each site’s default) |
hostedLocale | what the hosted screen and messages will use: es, ca or en |
t(key, params?) | a UI string: mc.t('hint.resendsLeft', { n: 2 }) |
errorMessage(err) | a guest-facing sentence for any error |
format | price, date, time, timeRange, duration, weekday, countdown |
pick(localized, default?) | one language out of { es, ca, en } |
SDK strings exist for es, ca, en, fr, pt, it, de (LOCALES); the hosted screen for es, ca, en (HOSTED_LOCALES). Standalone: t, messageFor, translator, normalizeLocale, toHostedLocale, intlTag, createFormatter, MESSAGES.
client.roomBooking(options) → RoomBooking
Section titled “client.roomBooking(options) → RoomBooking”The headless flow. options: slug, roomId, onChange(state), locale?. The state carries locale and errorMessage (the last error, translated); flow.t() and flow.setLocale() match the client’s.
| Method | Effect on state.step |
|---|---|
loadSite() | → pick (room, policy, captcha and Stripe keys on state.site) |
loadAvailability({ from?, days? }) | fills state.days |
startTimesFor(date, durationMinutes) / durationsFor(date, start) | pure helpers on the loaded availability |
rateAt(date, start, groupSizeId?) | hourly rate hint at a start time, from the loaded availability |
quote({ date, startTime, durationMinutes, groupSizeId?, partySize? }) | none; resolves the itemised price (labels in the flow’s language) |
hold(details) — details.groupSizeId?, details.partySize? | → verify (state.hold, state.hold.devCode in sandbox) |
verify(code) / resend() | → confirm |
confirm({ paymentMode, notes?, email? }) | → done (state.confirmation: reference, manageUrl, clientSecret for card) |
reset() | → pick |
Errors
Section titled “Errors”MrCharlesError has code (the API’s error.code), status, requestId and three predicates:
slotIsGone—SLOT_TAKEN,OUTSIDE_HOURS,ROOM_NOT_BOOKABLE: offer another time.holdIsDead—HOLD_EXPIRED,HOLD_NOT_FOUND,TOO_MANY_ATTEMPTS: start over.isTransient—RATE_LIMITED, network, 5xx: wait, then retry once.
Publishable-key errors: KEY_INVALID, KEY_REVOKED, KEY_EXPIRED, KEY_ENV_MISMATCH, ORIGIN_NOT_ALLOWED (the page’s origin is not one of the key’s), TEACHER_KEY_REQUIRED (handoff() with a studio key).
isMrCharlesError(e) narrows unknown errors.
Helpers
Section titled “Helpers”startTimes, durationOptions, toMinutes, toHHMM, addMinutes, formatPrice, dateKey, addDays, uuid, isTrustedOrigin, parseEmbedEvent, resolveEndpoints, ENVIRONMENTS, VERSION. Embed handles have setLang(tag).
Everything is exported from the package root: PublicSite, PublicRoom, RoomAvailability, Hold, HoldRequest, Confirmation, Booking, TeacherProfile, LessonOffer, LessonSlots, RoomBookingState, RoomStep, EmbedOptions, ErrorCode, Locale…
Versioning
Section titled “Versioning”Semver. Minor versions add; majors may rename. The CDN path /sdk/v0/ tracks the latest 0.x; pin the npm version in production builds.