Getting Started
This page gets you from zero to a working appointment backend.
The fastest path is:
- install Slotify
- define working hours
- generate slots
- add an availability engine
- reserve a slot
- add the rules your application actually needs
You do not need Django, a database, or a frontend to learn the core API.
1. Install
pip install slotify-scheduling
Check the installed version:
python -c "import slotify; print(slotify.__version__)"
2. Your first working scheduler
Start with one provider who works from 9:00 to 17:00 and accepts 30-minute appointments.
from slotify import SlotGenerator
generator = SlotGenerator(
start="09:00",
end="17:00",
duration=30,
timezone="Asia/Kolkata",
)
slots = generator.generate("2026-10-05")
for slot in slots[:3]:
print(slot.start, "->", slot.end)
The important idea is:
SlotGenerator creates possible slots. It does not know whether somebody has already booked them.
3. Make the slots bookable
Use AvailabilityEngine when your application needs bookings, capacity, resources, policies, or conflicts.
from slotify import AvailabilityEngine
engine = AvailabilityEngine(
generator,
resource_id="provider-123",
capacity=1,
)
available = engine.available_slots("2026-10-05")
booking = engine.reserve(available[0])
print(booking.booking_id)
Trying to reserve the same slot again raises BookingConflictError.
from slotify import BookingConflictError
try:
engine.reserve(available[0])
except BookingConflictError:
print("Someone already booked this slot.")
4. Build a realistic weekly schedule
from slotify import Schedule, SlotGenerator
schedule = Schedule(
weekly={
"monday": [("09:00", "17:00")],
"tuesday": [("09:00", "17:00")],
"wednesday": [("12:00", "20:00")],
"thursday": [("09:00", "17:00")],
"friday": [("09:00", "14:00")],
}
)
generator = SlotGenerator(
schedule=schedule,
duration=30,
timezone="Asia/Kolkata",
)
5. Add breaks
generator = SlotGenerator(
start="09:00",
end="18:00",
duration=30,
breaks=[("13:00", "14:00")],
timezone="Asia/Kolkata",
)
6. Add holidays and one-off changes
schedule = Schedule(
weekly={"monday": [("09:00", "17:00")]},
overrides={
"2026-10-12": [("13:00", "18:00")],
"2026-10-19": [],
},
closed_dates=["2026-10-02"],
)
An empty override closes that date.
7. Add booking rules
from datetime import timedelta
from slotify import BookingPolicy
policy = BookingPolicy(
minimum_notice=timedelta(hours=2),
maximum_horizon=timedelta(days=30),
cancellation_window=timedelta(hours=12),
)
engine = AvailabilityEngine(
generator,
resource_id="provider-123",
policy=policy,
)
8. Add a resource pool
If a customer can be served by any one of several providers, use a pool.
engine = AvailabilityEngine(
generator,
resource_pool=("doctor-1", "doctor-2", "doctor-3"),
resource_strategy="least_loaded",
)
booking = engine.reserve(
generator.generate_for_date("2026-10-05")[0]
)
print(booking.resource_id)
Available strategies:
- first_available — use the configured order
- round_robin — rotate through resources
- least_loaded — prefer the resource with the fewest overlapping bookings
9. Hold a slot during checkout
Temporary holds are useful when a customer selects a slot and needs time to complete payment.
from datetime import datetime
hold = engine.hold(
slot,
expires_at=datetime.fromisoformat("2026-10-05T09:10:00+05:30"),
now=datetime.fromisoformat("2026-10-05T09:00:00+05:30"),
)
booking = engine.confirm_hold(
hold.hold_id,
now=datetime.fromisoformat("2026-10-05T09:05:00+05:30"),
)
Release it when checkout is abandoned:
engine.release_hold(hold.hold_id)
An expired hold stops blocking availability automatically in the included in-memory hold store.
For distributed production systems, implement HoldStore using the same database/concurrency guarantees as your booking store.
10. Recurring appointments
from slotify import RecurrenceRule
template = generator.generate_for_date("2026-10-05")[0]
series = engine.reserve_recurring(
template,
RecurrenceRule(
weekdays=(0,),
count=8,
),
)
Daily, weekly, monthly, and yearly recurrence are supported.
11. Cancel and reschedule
Cancel:
engine.cancel(booking.booking_id)
Reschedule:
new_slot = generator.generate_for_date("2026-10-06")[2]
booking = engine.reschedule(
booking.booking_id,
new_slot,
)
12. Build an API around it
A typical Django/DRF flow is:
GET /providers/123/availability
|
v
Load provider configuration
|
v
Create SlotGenerator
|
v
Create AvailabilityEngine
|
v
engine.available_slots(...)
|
v
Return JSON to frontend
|
v
User chooses a slot
|
v
POST /bookings
|
v
engine.reserve(slot)
|
+--> BookingConflictError
| retry/show another slot
|
+--> Booking
See Django / DRF for an application example.
13. Production storage
The included InMemoryBookingStore and InMemoryHoldStore are useful for learning, tests, prototypes, and simple single-process applications.
Do not treat them as a shared database for multiple workers.
For a real multi-worker deployment, implement BookingStore and HoldStore against your database. The final reservation must be atomic so competing requests cannot both win the same capacity.
See Testing & Production.
Mental model
Schedule
↓
SlotGenerator
↓
AvailabilityEngine
↓
Booking / Hold
Schedule
Defines when a resource normally works and its exceptions.
SlotGenerator
Turns those rules into concrete time slots.
AvailabilityEngine
Applies current bookings, capacity, resources, policies, holds, and conflicts.
Booking / Hold
Represents a confirmed reservation or temporary checkout reservation.
What Slotify does not own
Keep these concerns in your application:
- users and authentication
- permissions
- customer records
- payments
- emails/SMS/WhatsApp
- frontend/UI
- your main database models
- business-specific reporting