Getting started

The platform is headless: a JSON API plus an embeddable booking widget that drops into any site — plain HTML, React, Next.js, Astro, or anything else that can load a script tag. There’s no iframe and no redirect; the widget renders inside a Shadow DOM on your page and talks to the API directly.

The two-tag embed

The fastest integration is the auto-mount. Add a mount element and the widget script:

<div
  data-booking-widget
  data-api-base="https://api.example.com"
  data-publishable-key="pk_YOUR_KEY"
></div>

<script src="https://api.example.com/widget.global.js"></script>

That’s the whole integration. On load, the script finds every [data-booking-widget] element and mounts the full booking flow — trip selection, live availability with weather/tide, add-ons, waiver, payment, confirmation.

Mount attributes

AttributeRequiredWhat it does
data-booking-widgetyesMarks the element for auto-mount.
data-publishable-keyyesYour pk_… key — scopes everything to your operator account. The widget does not mount without it.
data-api-basenoAPI origin. Omit (or set "") when the page is served from the same origin as the API — the widget then uses relative URLs.
data-trip-type-idnoSkip trip selection and open directly on one trip type.

Serve the embed from a page you trust. The widget reads data-api-base off its host element and sends the publishable key and the customer’s contact details to that origin. The publishable key is a public credential by design, but the host page is part of your security boundary — don’t embed on pages where third-party scripts could rewrite the attribute.

The mount() API

Framework hosts usually skip the data-attributes and call mount() on a node they own. It returns an unmount function:

const unmount = window.BookingWidget.mount(element, {
  apiBase: "https://api.example.com", // "" for same-origin
  publishableKey: "pk_YOUR_KEY",
  tripTypeId: "tt_…", // optional
});

Per-framework guides, each lifted verbatim from a working example app in the repo:

Make it yours

The widget is deliberately neutral out of the box — it inherits your page’s look until you theme it. One CSS custom property makes it match your brand; the full contract is small and documented in the theming guide.

Behind the widget: the API

Everything the widget does is public API you can call yourself — availability, holds, bookings, promo codes, gift cards, waitlists, weather. The same surface powers the operator admin and the customer portal. See the API reference for every route, auth tier, and shape.

TierCredentialFor
Publishable keyX-Publishable-Key: pk_… headerWidget-side reads + checkout writes. Safe to ship in a page.
Operator sessionPOST /v1/operator/login → cookie or BearerYour back office: schedule, bookings, money, CRM.
Customer sessionMagic-link exchange → cookie or BearerThe angler’s self-service portal.

Money is always integer cents. Errors are uniform: { "error": { "code": "…", "message": "…" } }.