Skip to content
Calendar · API reference

Flaxxa Calendar scheduling API and webhooks.

Drive Flaxxa Calendar from your own software: a REST API with workspace keys, signed webhooks and idempotency keys.

No credit card
Free plan
Cancel anytime
flaxxa.com / product / calendar / docs
cURLREST · JSON
# Flaxxa Calendar · first request
curl https://flaxxa.com/api/v1/calendar \
  -H "Authorization: Bearer $FLAXXA_KEY" \
  -H "Accept: application/json"

# webhooks: X-Flaxxa-Signature (HMAC-SHA256)
# retries: Idempotency-Key, 24 h
200 OKapplication/json
+ webhooks · HMAC-signed
REST
Requests per key by default
120/min
Idempotency window
24h
Quick start

How do I make my first API call?

Replace $FLAXXA_KEY with a key from your workspace. The first call returns a real id you can use for the next ones.

cURL
# 1. Free slots for an event type (public — no key; page = your booking page slug)
curl "https://flaxxa.com/api/v1/calendar/public/event-types/discovery-call/slots?from=2026-11-03&to=2026-11-07&timezone=Asia/Kolkata&page=acme"

# 2. Book one of them for the invitee (public)
curl -X POST "https://flaxxa.com/api/v1/calendar/public/bookings?page=acme" \
  -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{ "event_type_slug": "discovery-call", "starts_at": "2026-11-03T10:30:00+05:30",
        "booker_name": "Asha Verma", "booker_email": "[email protected]", "booker_timezone": "Asia/Kolkata" }'

# 3. Or book from your own backend with a key (no page needed)
curl -X POST https://flaxxa.com/api/v1/calendar/bookings \
  -H "Authorization: Bearer flx_live_YOUR_KEY" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{ "event_type_slug": "discovery-call", "starts_at": "2026-11-03T10:30:00+05:30",
        "booker_name": "Asha Verma", "booker_email": "[email protected]", "booker_timezone": "Asia/Kolkata" }'
PHP
$http = Http::withToken(env('FLAXXA_CALENDAR_KEY'))->acceptJson();

$slots = $http->get('https://flaxxa.com/api/v1/calendar/public/event-types/discovery-call/slots', [
    'from' => '2026-11-03', 'to' => '2026-11-07', 'timezone' => 'Asia/Kolkata', 'page' => 'acme',
])->json('data');

$booking = $http->post('https://flaxxa.com/api/v1/calendar/bookings', [
    'event_type_slug' => 'discovery-call',
    'starts_at'       => $slots[0]['start'],
    'booker_name'     => $customer->name,
    'booker_email'    => $customer->email,
    'booker_timezone' => 'Asia/Kolkata',
])->throw()->json('data');   // $booking['uid'], ['status'], ['starts_at'], ['host']
Node
const base = "https://flaxxa.com/api/v1/calendar";
const slots = await fetch(`${base}/public/event-types/discovery-call/slots?from=2026-11-03&to=2026-11-07&timezone=Asia/Kolkata&page=acme`)
  .then(r => r.json()).then(j => j.data);

const res = await fetch(`${base}/bookings`, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.FLAXXA_CALENDAR_KEY}`, Accept: "application/json", "Content-Type": "application/json" },
  body: JSON.stringify({ event_type_slug: "discovery-call", starts_at: slots[0].start,
    booker_name: "Asha Verma", booker_email: "[email protected]", booker_timezone: "Asia/Kolkata" }),
});
const { data } = await res.json(); // data.uid, data.status
Python
import requests
BASE = "https://flaxxa.com/api/v1/calendar"
H = {"Authorization": f"Bearer {KEY}", "Accept": "application/json"}

slots = requests.get(f"{BASE}/public/event-types/discovery-call/slots",
    params={"from": "2026-11-03", "to": "2026-11-07", "timezone": "Asia/Kolkata", "page": "acme"}).json()["data"]

r = requests.post(f"{BASE}/bookings", headers=H, json={
    "event_type_slug": "discovery-call", "starts_at": slots[0]["start"],
    "booker_name": "Asha Verma", "booker_email": "[email protected]", "booker_timezone": "Asia/Kolkata"})
r.raise_for_status()
booking = r.json()["data"]
Request
GET /api/v1/calendar/public/event-types/discovery-call/slots?from=2026-11-03&to=2026-11-07&timezone=Asia/Kolkata&page=acme HTTP/1.1
Host: flaxxa.com
Accept: application/json

— then —

POST /api/v1/calendar/bookings HTTP/1.1
Host: flaxxa.com
Authorization: Bearer flx_live_·············
Content-Type: application/json

{
  "event_type_slug": "discovery-call",
  "starts_at":       "2026-11-03T10:30:00+05:30",
  "booker_name":     "Asha Verma",
  "booker_email":    "[email protected]",
  "booker_timezone": "Asia/Kolkata",
  "custom_answers":  { "company": "Acme Ltd" }
}
Response · 201
HTTP/1.1 200 OK            (slots)
{ "data": [ { "start": "2026-11-03T10:30:00+05:30", "end": "2026-11-03T11:00:00+05:30" }, … ] }

HTTP/1.1 201 Created       (booking)
{
  "data": {
    "id": 9123, "uid": "4b1f…-…", "status": "confirmed", "source": "api",
    "starts_at": "2026-11-03T05:00:00+00:00", "ends_at": "2026-11-03T05:30:00+00:00",
    "booker_name": "Asha Verma", "booker_email": "[email protected]", "booker_timezone": "Asia/Kolkata",
    "location_type": "online", "location_details": "https://meet.google.com/…",
    "event_type": { "id": 41, "slug": "discovery-call", "title": { "en": "Discovery call" }, "duration_minutes": 30 },
    "host": { "id": 7, "name": "Rahul Gupta", "email": "[email protected]" }
  }
}
Authentication

How do I authenticate?

Every call requires Authorization: Bearer <key>. Rotate from workspace settings — old keys are revoked instantly. Server-side only; never ship a live key to the browser.

Base URLhttps://flaxxa.com/api/v1/calendar
Event types

Event types API

What can be booked: duration, location, hosts, questions. Keyed (calendar.event_type.view / .create / .edit / .delete).

GET/event-types

List event types

Paginated; each carries slug, title, duration_minutes, location_type, hosts and booking_pages_count (0 = not yet on a public page).

GET/event-types/{id}

Retrieve

Full event type with hosts, schedule and custom questions.

POST/event-types

Create

{ slug, title, duration_minutes, location_type, schedule_id, scheduling_type, … } — scope calendar.event_type.create.

PUT/event-types/{id}

Update

Any field; is_active=false hides it from booking pages.

POST/event-types/{id}/attach-page

Attach to a page

{ booking_page_id } — makes it bookable on that public page.

Availability (public)

Availability (public) API

No key. The slots the public booking page shows. Pass page=<booking-page-slug> so the request resolves to your workspace on flaxxa.com.

GET/public/event-types/{slug}/slots

Free slots

Query: from (date), to (date, ≤ from + max_advance_days), timezone (IANA), page. Returns { data: [{ start, end }] } in that timezone; honours schedules, holidays, buffers, host calendars.

GET/public/pages/{pageSlug}

Booking page

The page with its event types, branding and questions — what the hosted page renders.

GET/public/pages/{pageSlug}/event-types/{slug}

Event type on a page

One event type as the page shows it (questions, payment, duration).

Book (public)

Book (public) API

No key — the calls the hosted booking page makes. Use these from a browser or your own booking UI.

POST/public/bookings?page={pageSlug}

Create booking

{ event_type_slug, starts_at (ISO, from slots), booker_name, booker_email, booker_timezone, booker_phone?, custom_answers?, recurrence? { frequency, interval, count }, payment_method_token?/payment_gateway? for paid types }. 201 { uid, status, starts_at }; 422 { message } when the slot is gone.

GET/public/bookings/{uid}

Retrieve by uid

Status, times (UTC + invitee-local), location / meeting link, reschedule allowance.

PATCH/public/bookings/{uid}/reschedule

Reschedule

{ starts_at } — within the event type's max_reschedules.

POST/public/bookings/{uid}/cancel

Cancel

{ reason? } — recorded as cancelled by the invitee.

GET/public/bookings/{uid}.ics

Calendar file

iCalendar for the invitee's own calendar.

Bookings (keyed)

Bookings (keyed) API

Your workspace's bookings. calendar.booking.view lists the caller's own; calendar.booking.manage sees and manages every booking.

POST/bookings

Create for an invitee

{ event_type_slug | event_type_id, starts_at, booker_name, booker_email, booker_timezone?, booker_phone?, custom_answers?, send_emails? (default true), host_user_id? } — same atomic slot check as the public flow; source = api. Scope calendar.booking.manage.

GET/bookings

List / find

Query: email (invitee), uid, status (pending|confirmed|cancelled|completed|no_show|rescheduled), event_type_id, range (today|upcoming|past|7d), from, to. Paginated, newest first, with host and event type.

GET/bookings/{id}

Retrieve

Booking with event type, attendees, payment and host.

POST/bookings/{id}/confirm

Confirm

pending → confirmed (event types that require approval).

POST/bookings/{id}/reschedule

Reschedule

{ starts_at } — scope calendar.booking.reschedule.

POST/bookings/{id}/cancel

Cancel

{ reason? } — scope calendar.booking.cancel; cancelled by host.

POST/bookings/{id}/complete · /no-show

Outcome

Mark completed or no-show after the meeting.

POST/bookings/{id}/assign · /reassign

Assign host

{ user_id? } — assign (or round-robin when omitted) / move to another member.

GET/bookings/unassigned

Unassigned queue

Bookings no host has taken yet.

Contacts

Contacts API

GET/contacts

List contacts

People who booked with you: name, email, bookings count, last/next booking. search, per_page.

GET/contacts/{id}

Retrieve contact

The contact with their booking history.

Schedules, booking pages & reminders

Schedules, booking pages & reminders API

GET/schedules

List schedules

Availability rules per weekday with timezone; is_default.

POST/schedules/{id}/block

Block time

{ starts_at, ends_at, reason? } — a one-off unavailable window. DELETE …/block removes it.

GET/holidays

Holidays

Your holiday dates, which close availability across your event types; POST /holidays/import adds a list of dates.

GET/booking-pages

Booking pages

Public pages with slug (the page= hint), title and attached event types.

GET/reminders

Reminders

Reminder rules per event type: channel and timing in minutes before the start (or after the end). POST / PUT / DELETE to manage — scope calendar.reminder.manage.

Webhooks

Webhooks API

POST /api/v1/webhooks { url, subscribed_events[] } (scope workspace.webhooks.manage). Deliveries carry X-Flaxxa-Event and X-Flaxxa-Signature (HMAC-SHA256 of the raw body with the endpoint secret, shown once). Wildcards work: app.calendar.booking.*.

POST/../webhooks

Subscribe

Register your endpoint and the events below.

GET/../webhooks

List

Endpoints with failure counts and last delivery.

DELETE/../webhooks/{id}

Unsubscribe

Stops delivery.

Webhook events

Which webhook events can I subscribe to?

Subscribe via POST /webhooks. Verify X-Flaxxa-Signature on every payload.

  • app.calendar.booking.confirmed

    A booking was created and confirmed — uid, event type, invitee, starts_at, host.

  • app.calendar.booking.rescheduled

    A booking moved to a new time.

  • app.calendar.booking.cancelled

    A booking was cancelled (by invitee, host or system) with the reason.

  • app.calendar.booking.completed

    The meeting was marked completed.

  • app.calendar.booking.noshow

    The invitee did not show.

  • app.calendar.booking.assigned

    A booking got a host (or was claimed).

  • app.calendar.booking.reassigned

    A booking moved to another host.

  • app.calendar.booking.unassigned

    No eligible host could take the booking.

  • app.calendar.payment.received

    A paid booking was paid.

  • app.calendar.reminder.sent

    A reminder went out to the invitee.

  • app.calendar.event_type.created

    An event type was created (also .updated / .deleted).

Errors

What errors can the API return?

All errors return a JSON envelope: { error: { code, message, details } }. Retry idempotent calls on 5xx with exponential backoff.

CodeNameWhen it fires
401unauthenticatedAPI key missing, expired or revoked (keyed endpoints only).
403insufficient_scopeKey valid but lacks the scope — e.g. calendar.booking.manage to create bookings for invitees.
404not_foundUnknown event type slug / booking uid for this workspace, or a page hint that belongs to another workspace.
422slot_unavailableThe slot was taken, is outside availability, or no host is free: { message }. Re-fetch slots and retry.
422validation_failed{ message, errors } — missing booker_email, bad starts_at, unknown timezone.
429rate_limited120 requests/minute per key; the public endpoints are throttled per IP.
Conventions

Which rules apply to every request?

Every Flaxxa app's API follows the same authentication, rate limits, idempotency and webhook signing.

Bearer auth

Every API call uses a Bearer token. Keys belong to a workspace and are scoped per app. Create and revoke them from workspace API settings.

Rate limits

Each key can make 120 requests a minute unless the app sets its own limit. Going over returns 429 with a Retry-After header.

Idempotency

Send an Idempotency-Key header on a POST and a retry with the same key within 24 hours returns the first response instead of running again.

Signed webhooks

Every webhook payload carries an X-Flaxxa-Signature HMAC-SHA256 header made with the secret you get when you subscribe. Verify it before processing.

API FAQ

Flaxxa Calendar API: common questions

Frequently asked questions

Yes. The public endpoints need no key: fetch free slots for an event type, then create, read, reschedule or cancel the booking by its uid. Pass page= with your booking page slug.

Get started in minutes

Ship faster with Flaxxa Calendar.

Create a workspace, make an API key in its settings, and send your first request.

Free plan · No credit card · Cancel anytime