Skip to content

REST quickstart

Run your own instance, sign in, and use Settings, Availability and Event types to set a profile handle, working hours and an active individual event type. For the examples below the booking page is /ada/intro. Replace it with your own handle/slug.

Open API keys at /app/api-keys, create a key for the intended organization and copy it once into your secret store. It acts as its creator in that organization. Keep API keys and booking manage tokens out of URLs, shared transcripts and source control. Set these shell variables privately (placeholders below are not working credentials):

Terminal window
export HOURMERE_URL='http://localhost:3000'
export HOURMERE_API_KEY='<your API key>'
Terminal window
curl --fail-with-body "$HOURMERE_URL/api/v1/me" \
-H "Authorization: Bearer $HOURMERE_API_KEY"

Use /api/v1/openapi.json on your instance as the full request/response reference. Strict request schemas reject unknown fields. Errors use { "error": "stable_code", "message": "…" }.

Choose a future UTC range within the event type’s booking window, at most 62 days. The public slots endpoint returns UTC instants:

Terminal window
curl --fail-with-body --get "$HOURMERE_URL/api/v1/public/ada/intro/slots" \
-H "Authorization: Bearer $HOURMERE_API_KEY" \
--data-urlencode 'start=2026-11-02T00:00:00Z' \
--data-urlencode 'end=2026-11-04T00:00:00Z'

Adjust these example dates so they remain in the future. Take the desired returned slot’s start unchanged. For local date/time-zone queries, the MCP find_available_slots tool performs that conversion. A selected Google calendar with missing, failed or stale sync yields calendar_sync_unavailable; fix or deliberately disable that calendar instead of assuming unknown busy data is free.

Bookings send email to the host/invitee when workers are enabled. Additional guests require the host to enable allowGuests on the event type (off by default, at most ten). Otherwise nonempty guests return 400 guests_not_allowed. Existing guests keep receiving updates and cancellations after the host disables new guests. Use an address you control for a test. Use a new idempotency key per intended booking and keep the same body/key for retries:

Terminal window
curl --fail-with-body "$HOURMERE_URL/api/v1/public/ada/intro/bookings" \
-H "Authorization: Bearer $HOURMERE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: <new random UUID>' \
-d '{"start":"<chosen slot start>","invitee":{"name":"Test Invitee","email":"<your test address>","timeZone":"America/Los_Angeles"}}'

Save the returned manageToken privately. Only its hash is stored; it is returned once. A same-key retry returns HTTP 200 (rather than 201) with the original booking and manageToken: null. Reusing the key with different arguments fails with idempotency_key_reused; use a new key for a genuinely new booking.

The public booking and invitee management endpoints do not require an API key; the examples include it for consistency with the authenticated calls above. A public create request’s idempotency key uses the shared anonymous namespace for that organization, so make it random. For invitee management send the manage token in a header. Choose a new available slot for rescheduling; it returns a replacement booking and a new manage token:

Terminal window
curl --fail-with-body "$HOURMERE_URL/api/v1/bookings/manage/reschedule" \
-H "Authorization: Bearer $HOURMERE_API_KEY" \
-H "X-Manage-Token: $HOURMERE_MANAGE_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"start":"<new slot start>"}'

Use the new token for subsequent operations. Cancelling with the current token:

Terminal window
curl --fail-with-body "$HOURMERE_URL/api/v1/bookings/manage/cancel" \
-H "Authorization: Bearer $HOURMERE_API_KEY" \
-H "X-Manage-Token: $HOURMERE_MANAGE_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"reason":"Test cleanup"}'

An API response token stays with the cancelled booking after an invitee move and follows host moves. The token in a booking email always follows the reschedule chain. Treat both as credentials. The public management page carries email tokens in a fragment (/booking#token=…); API calls use headers, never query parameters. Set HOURMERE_MANAGE_TOKEN privately to the current returned token before running either management example.

List the key owner’s hosted bookings with GET /api/v1/bookings. A key does not grant access to arbitrary hosts’ private bookings. Results default to ascending start time and ID; request order=desc for newest first. Pass nextCursor as cursor and keep the time filters and order unchanged for every page. Rate limits return 429 and Retry-After; slot races return slot_taken or slot_unavailable. Recheck availability before retrying with a new key.

To move a booking you host, read GET /api/v1/bookings/{id}/slots?start=…&end=…, then send POST /api/v1/bookings/{id}/reschedule with JSON { "start": "<chosen slot start>" }. Both require a session or API key in the booking’s organization. Slots ignore the current booking, so the new time may overlap it. A host move returns the successor booking with manageToken: null and preserves existing invitee links. The web booking detail page uses these same public APIs. Do not retry a move automatically; inspect your booking list if the answer is lost.