IntoCal
    REST API v1

    IntoCal API

    Resource-oriented scheduling API. Build booking into any app, website, or AI agent.

    Optional API key
    OpenAPI 3.0.3
    Idempotent writes
    ISO-8601 timestamps

    Booking Flow

    Four steps to book a meeting programmatically

    1

    Discover

    List event types

    GET /v1/event-types?host_id=HOST_ID
    2

    Check

    Query available slots

    POST /v1/slots/query
    3

    Book

    Create booking

    POST /v1/bookings
    4

    Confirm

    Get booking details

    GET /v1/bookings/{id}

    Authentication

    Optional API key via Bearer token. Public read endpoints work without auth.

    Authorization: Bearer sk_live_your_api_key_here

    Generate API keys in Settings → API. Cancel and reschedule require either API key or guest_email verification.

    Idempotency

    All write endpoints accept an Idempotency-Key header to prevent duplicate operations.

    Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

    Same key + same body → returns cached response. Same key + different body → VALIDATION_ERROR.

    Response Envelope

    Every response uses a consistent shape

    Success

    {
      "ok": true,
      "data": { ... }
    }

    Error

    {
      "ok": false,
      "error": {
        "code": "SLOT_NOT_AVAILABLE",
        "message": "The selected slot is no longer available.",
        "suggested_action": "fetch_slots_again"
      }
    }

    Endpoints

    GET
    /v1/event-types

    List Event Types

    Returns active event types. Optionally filter by host_id.

    curl "https://api.intocal.com/v1/event-types?host_id=HOST_ID"
    GET
    /v1/hosts/{host_id}/availability

    Get Host Availability

    Returns weekly availability rules and date overrides for a host.

    curl "https://api.intocal.com/v1/hosts/HOST_ID/availability"
    POST
    /v1/slots/query

    Query Available Slots

    Returns computed available time slots for a date range, respecting duration, buffers, min notice, and max booking window.

    curl -X POST "https://api.intocal.com/v1/slots/query" \
      -H "Content-Type: application/json" \
      -d '{
        "event_type_id": "evt-123",
        "host_id": "host-123",
        "from": "2026-03-24T00:00:00Z",
        "to": "2026-03-25T00:00:00Z",
        "timezone": "Europe/Tallinn"
      }'
    POST
    /v1/bookings

    Create Booking

    Creates a confirmed booking. Validates slot availability at write time. Supports Idempotency-Key header.

    curl -X POST "https://api.intocal.com/v1/bookings" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: $(uuidgen)" \
      -d '{
        "event_type_id": "evt-123",
        "host_id": "host-123",
        "slot_start": "2026-03-24T13:00:00Z",
        "timezone": "Europe/Tallinn",
        "invitee": {
          "name": "Jane Doe",
          "email": "jane@example.com"
        },
        "metadata": { "source": "agent" }
      }'
    GET
    /v1/bookings/{booking_id}

    Get Booking

    Retrieves a single booking by ID.

    curl "https://api.intocal.com/v1/bookings/bk-789"
    POST
    /v1/bookings/{booking_id}/cancel

    Cancel Booking

    Cancels a confirmed booking. Requires API key auth or guest_email verification.

    curl -X POST "https://api.intocal.com/v1/bookings/bk-789/cancel" \
      -H "Content-Type: application/json" \
      -d '{
        "reason": "Invitee requested cancellation",
        "guest_email": "jane@example.com"
      }'
    POST
    /v1/bookings/{booking_id}/reschedule

    Reschedule Booking

    Moves a booking to a new time slot. Validates new slot availability. Requires API key auth or guest_email.

    curl -X POST "https://api.intocal.com/v1/bookings/bk-789/reschedule" \
      -H "Content-Type: application/json" \
      -d '{
        "new_slot_start": "2026-03-25T15:00:00Z",
        "timezone": "Europe/Tallinn",
        "guest_email": "jane@example.com"
      }'

    Error Codes

    All possible error codes returned by the API

    CodeStatusDescription
    VALIDATION_ERROR400Invalid input, missing fields, or unknown fields in request body
    UNAUTHORIZED401Authentication required (guest_email missing or mismatched)
    FORBIDDEN403Insufficient permissions for this action
    NOT_FOUND404Resource not found
    METHOD_NOT_ALLOWED405HTTP method not supported for this endpoint
    HOST_INACTIVE403Host is not currently accepting bookings
    EVENT_TYPE_INACTIVE403Event type is disabled
    SLOT_NOT_AVAILABLE409Time slot is taken, outside notice window, or past max booking range
    BOOKING_ALREADY_CANCELED409Booking has already been canceled
    BOOKING_NOT_RESCHEDULABLE409Canceled bookings cannot be rescheduled
    INVALID_TIMEZONE400Unrecognized IANA timezone string
    RATE_LIMITED429Too many requests
    INTERNAL_ERROR500Server error

    SDK Patterns

    TypeScript

    Full booking flow example

    const BASE = "https://api.intocal.com/v1";
    const headers = {
      "Content-Type": "application/json",
      "Authorization": "Bearer sk_live_your_api_key"
    };
    
    // 1. List event types
    const { data: types } = await fetch(
      `${BASE}/event-types?host_id=HOST_ID`, { headers }
    ).then(r => r.json());
    
    // 2. Query available slots
    const { data: { slots } } = await fetch(`${BASE}/slots/query`, {
      method: "POST", headers,
      body: JSON.stringify({
        event_type_id: types[0].id,
        host_id: "HOST_ID",
        from: "2026-03-24T00:00:00Z",
        to: "2026-03-25T00:00:00Z",
        timezone: "Europe/Tallinn"
      })
    }).then(r => r.json());
    
    // 3. Book the first available slot
    const available = slots.filter(s => s.available);
    const { data: booking } = await fetch(`${BASE}/bookings`, {
      method: "POST",
      headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
      body: JSON.stringify({
        event_type_id: types[0].id,
        host_id: "HOST_ID",
        slot_start: available[0].start,
        timezone: "Europe/Tallinn",
        invitee: { name: "Jane Doe", email: "jane@example.com" },
        metadata: { source: "sdk" }
      })
    }).then(r => r.json());
    
    console.log("Booked:", booking.id, booking.start);

    Python

    Using requests library

    import requests, uuid
    
    BASE = "https://api.intocal.com/v1"
    headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer sk_live_your_api_key"
    }
    
    # 1. List event types
    types = requests.get(f"{BASE}/event-types?host_id=HOST_ID",
                         headers=headers).json()["data"]
    
    # 2. Query slots
    slots = requests.post(f"{BASE}/slots/query", headers=headers, json={
        "event_type_id": types[0]["id"],
        "host_id": "HOST_ID",
        "from": "2026-03-24T00:00:00Z",
        "to": "2026-03-25T00:00:00Z",
        "timezone": "Europe/Tallinn"
    }).json()["data"]["slots"]
    
    # 3. Book
    available = [s for s in slots if s["available"]]
    booking = requests.post(f"{BASE}/bookings",
        headers={**headers, "Idempotency-Key": str(uuid.uuid4())},
        json={
            "event_type_id": types[0]["id"],
            "host_id": "HOST_ID",
            "slot_start": available[0]["start"],
            "timezone": "Europe/Tallinn",
            "invitee": {"name": "Jane", "email": "jane@example.com"},
        }
    ).json()["data"]
    
    print(f"Booked: {booking['id']} at {booking['start']}")

    LLM Agent Tools

    Map these 1:1 to the API endpoints for structured tool calls. Read actions (list, query, get) don't need confirmation. Write actions (book, cancel, reschedule) should confirm with the user first.

    get_event_types
    read
    { host_id }
    get_available_slots
    read
    { event_type_id, host_id, from, to, timezone }
    create_booking
    write
    { event_type_id, host_id, slot_start, timezone, invitee }
    get_booking
    read
    { booking_id }
    cancel_booking
    write
    { booking_id, reason }
    reschedule_booking
    write
    { booking_id, new_slot_start, timezone }

    Base URL

    https://api.intocal.com/v1

    IntoCal API v1 · OpenAPI Spec · llms.txt · AI Plugin