wellknown

Wellknown partner API

For spas, massage studios, saunas and float centres that already run their own booking system. Keep Wellknown in step with your own diary: push your treatments, opening hours and your own appointments, and receive Wellknown bookings the moment they're paid.

Authentication

The venue creates an API key in their partner portal (Connect systems → API). Send it on every request. Keys are per venue; revoke them in the portal at any time. Limit: 120 requests per minute.

Authorization: Bearer wk_XXXXXXXX_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Base URL: https://wellknown.online/api/v1/. Every path ends with a slash. Dates are YYYY-MM-DD and times HH:MM (24-hour), always in the venue's own timezone (returned by /venue/). Money is in minor units: pence for UK venues, cents for US venues.

Venue

GET /api/v1/venue/
→ { "venue": { "name": "…", "market": "uk", "currency": "gbp", "timezone": "Europe/London",
     "slotMinutes": 15, "bufferMinutes": 15, "leadHours": 2, "maxDaysAhead": 90,
     "hours": [ { "weekday": 2, "opens": "09:00", "closes": "20:00" }, … ],
     "cancellation": [ { "hoursBefore": 48, "refundPct": 100 }, { "hoursBefore": 24, "refundPct": 50 } ],
     "treatments": [ … ] } }

weekday is 0 for Sunday to 6 for Saturday. A day can have more than one opening window (split days).

Bookings

Poll for changes with since (the updatedAt high-water mark), or use webhooks.

GET /api/v1/bookings/?since=2026-10-01T00:00:00Z
GET /api/v1/bookings/WK-7KQ2MD/

{
  "ref": "WK-7KQ2MD", "status": "confirmed",
  "treatment": { "id": 12, "name": "Full body massage" }, "guests": 2,
  "guestDetails": [ { "name": "Sarah", "health": { "age": 34, "pregnant": false, "conditions": [], "details": "" } }, … ],
  "date": "2026-12-20", "startTime": "14:00", "endTime": "15:00", "durationMin": 60, "currency": "gbp",
  "customer": { "name": "Sarah Jones", "email": "…", "phone": "…", "notes": null },
  "total": 14000, "fee": 195, "venueShare": 12320, "commission": 1680, "charity": 0,
  "createdAt": "…", "paidAt": "…", "cancelledAt": null
}

Statuses: confirmed, checked in, completed, cancelled. Bookings are paid in full, so never charge the customer again. Health answers are sensitive: store them only as long as you need them.

Treatments and peak dates

Items with an id are updated; items without one are created. Treatments are never deleted (past bookings point at them); send "active": false to hide one. price is per person. capacity is how many people can have that treatment at the same moment (rooms, therapists, tanks or sauna places). seasons, if sent, replaces all your peak dates.

GET /api/v1/treatments/

PUT /api/v1/treatments/
{
  "treatments": [
    { "id": 12, "name": "Full body massage", "kind": "massage", "durationMin": 60, "price": 7000, "maxGuests": 1, "capacity": 3 },
    { "name": "Thermal suite, 2 hours", "kind": "sauna", "durationMin": 120, "price": 3500, "maxGuests": 4, "capacity": 12 },
    { "name": "Pregnancy massage", "kind": "massage", "durationMin": 60, "price": 7000, "pregnancySafe": true }
  ],
  "seasons": [ { "name": "Valentine's week", "from": "2027-02-08", "to": "2027-02-14", "upliftPct": 15 } ]
}

Kinds: massage, facial, body, day-pass, sauna, float, package, other.

Free times

Exactly what we'll sell, per treatment per day, up to 31 days per call (to is exclusive):

GET /api/v1/availability/?from=2026-12-01&to=2026-12-08&treatment=12
→ { "timezone": "Europe/London", "days": [ { "date": "2026-12-01", "treatments": [ { "id": 12, "slots": [ { "time": "09:00", "end": "10:00", "free": 2 }, … ] } ] }, … ] }

Change opening hours for single dates. Send a date with nothing else to go back to normal hours:

PUT /api/v1/availability/
{ "days": [ { "date": "2026-12-24", "opens": "10:00", "closes": "14:00" }, { "date": "2026-12-25", "closed": true }, { "date": "2026-12-27" } ] }

Your own appointments (outside Wellknown)

The simplest integration: push the time your own clients take and we never double-book. units is how many places it takes from every treatment at that time; units: 0 closes the whole venue for that time. This is a full replace: anything you don't send is removed.

PUT /api/v1/blocks/
{ "blocks": [ { "id": "your-appt-123", "date": "2026-12-20", "from": "14:00", "to": "15:30", "units": 1 },
              { "id": "staff-training", "date": "2026-12-22", "from": "09:00", "to": "12:00", "units": 0 } ] }

Webhooks

Set an https URL in the portal. We POST booking.created and booking.cancelled with the booking object above, and retry with back-off for about 8 hours if you don't answer 2xx.

POST https://your-system.example/wellknown
X-WK-Event: booking.created
X-WK-Timestamp: 1791800000
X-WK-Signature: sha256=<hex HMAC-SHA256 of "<timestamp>.<raw body>" with your signing secret>

{ "id": "a1b2c3d4e5f6a7b8", "event": "booking.created", "createdAt": "…", "data": { …booking… } }

Verify every delivery, and reject timestamps more than 5 minutes old:

// Node.js
const expected = crypto.createHmac("sha256", SECRET).update(`${ts}.${rawBody}`).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature.replace("sha256=", "")));

Calendar feeds (no code)

Venues without booking software can sync any calendar instead: a secret iCal link of their Wellknown bookings to subscribe to, and an iCal import whose events block those times. An event titled “CLOSED” closes the venue for that time; “2 people” or “x2” takes two places; anything else takes one. See Connect systems in the portal.

Errors

{ "error": { "code": "bad_range", "message": "from/to must be YYYY-MM-DD…" } }   // 400, 401, 404, 429, 500

Questions: hello@wellknown.online