Bookings

Show your booking types and open times on your own website, and book a time from your own form.

Use these endpoints to build your own booking form, for example a "Reserve studio time" page that matches the rest of your site. You set up booking types, hours and questions in the dashboard. Your site reads the open times and books one, and the person gets the same confirmation email and calendar entry as when they book on your Lahuta booking page.

You want toUse
List what people can bookGET /v1/bookings/types
Show the open times for a range of daysGET /v1/bookings/types/{slug}/slots?from=...&to=...
Book a timePOST /v1/bookings

If you don't need a custom form, link to your hosted booking page instead: lahuta.org/<your-org>/book/<type slug>. See Booking pages.

List booking types

GET /v1/bookings/types returns your active booking types as a plain array, with the questions each one asks.

curl https://api.lahuta.org/v1/bookings/types \
  -H "X-Api-Key: $LAHUTA_API_KEY"
[
  {
    "id": "0197a7e3-5c02-7b19-8f4a-2d6e1c9b3a58",
    "slug": "open-studio",
    "title": "Open studio time",
    "description": "Two hours at a wheel, with clay and tools.",
    "durationMinutes": 120,
    "timezone": "America/Los_Angeles",
    "instructions": "Wear clothes you don't mind getting muddy.",
    "emailField": "required",
    "phoneField": "optional",
    "questions": [
      {
        "id": "0197a7e3-5c10-7e62-9b05-4a8f3d1c7e29",
        "question": "Have you thrown on a wheel before?",
        "type": "radio",
        "options": ["Never", "A few times", "Regularly"],
        "required": true
      }
    ],
    "organizer": { "name": "Northside Pottery", "slug": "northside-pottery" }
  }
]

emailField and phoneField tell you which contact details your form must ask for. Build your form's extra fields from questions.

Show open times

Ask for the slots of one type between two dates. Days are counted in the booking type's time zone, and both dates are included.

curl "https://api.lahuta.org/v1/bookings/types/open-studio/slots?from=2026-10-05&to=2026-10-11" \
  -H "X-Api-Key: $LAHUTA_API_KEY"
[
  {
    "startsAt": "2026-10-05T17:00:00.000Z",
    "endsAt": "2026-10-05T19:00:00.000Z"
  },
  {
    "startsAt": "2026-10-05T19:00:00.000Z",
    "endsAt": "2026-10-05T21:00:00.000Z"
  },
  {
    "startsAt": "2026-10-06T17:00:00.000Z",
    "endsAt": "2026-10-06T19:00:00.000Z"
  }
]
  • Only times that are still open and still ahead are returned. Past times and taken times are left out.
  • from and to are both required, as YYYY-MM-DD. A range longer than 62 days is cut to its first 62 days.
  • Times are UTC. Show them in the booking type's timezone, or the visitor's, and say which.

Book a time

Send the time the person picked, who they are, and their answers.

curl -X POST https://api.lahuta.org/v1/bookings \
  -H "X-Api-Key: $LAHUTA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "studio-form:3307",
    "type": "open-studio",
    "startsAt": "2026-10-05T17:00:00.000Z",
    "contact": {
      "kind": "person",
      "firstName": "Alex",
      "lastName": "Moreno",
      "emails": [{ "label": null, "value": "alex.moreno@example.com" }],
      "phones": [{ "label": null, "value": "+15035550192" }]
    },
    "answers": {
      "0197a7e3-5c10-7e62-9b05-4a8f3d1c7e29": "A few times"
    },
    "source": "website"
  }'
{
  "bookingId": "0197b355-0d61-7a2f-8c94-1e5b7d3f2a06",
  "contactId": "0197b355-0d4e-7f10-9a38-6c2e4b8d1f53",
  "startsAt": "2026-10-05T17:00:00.000Z",
  "endsAt": "2026-10-05T19:00:00.000Z",
  "manageUrl": "https://lahuta.org/bookings/q2Vt8LmR4xPz",
  "opened": true
}
FieldRequiredWhat it does
keyYesYour name for this booking. Sending it again returns the same booking with "opened": false, and nobody is booked or emailed twice
typeYesThe booking type's slug
startsAtYesOne of the startsAt values from the slots call
contactYesWho's booking. Saved the same way as PUT /v1/contacts. The confirmation goes to their first email address and first phone number
answersNoAnswers to the type's questions, keyed by question id
sourceNoWhere the booking came from, up to 100 characters. Saved on the booking, and on the contact if it has no source yet

manageUrl is the person's own page for moving or cancelling the booking. Their confirmation email links to it with a Manage your booking button, so you only need it if you want to show it on your thank-you page.

Answer formats

Question typeAnswer
textA string
numberA number
date"YYYY-MM-DD"
radioOne of the question's options, as a string
checkboxtrue or false. A required checkbox must be true
multiSelectAn array of the question's options
addressAn object with street, city, state and zip

What happens next

  • The person gets a confirmation email with a calendar entry, the same one your booking page sends.
  • The booking shows up under Bookings in the dashboard, and the person is saved to your CRM.
  • Your team gets an email, for everyone who has New bookings turned on under Settings → Notifications.

Errors

ErrorWhenWhat to do
404 NotFoundNo active booking type has that slugRefresh your list of types
409 SlotUnavailableThe time was taken or isn't open anymoreFetch the slots again and let the person pick another
409 BookingClosedThe booking type stopped taking bookingsStop offering it
422 AnswersInvalidRequired questions are unanswered, or answers have the wrong shape. questionIds lists themMark those questions on your form
422 ContactInfoRequiredA required email or phone is missing, or neither was given. fields lists what's neededAsk for those fields
429 TooManyRequestsMore than 300 bookings this hourWait retryAfterSeconds. See Rate limits

Two people can pick the same time at once. The first booking wins and the second gets SlotUnavailable, so always handle it.

See Bookings in the API reference for every field.

On this page