Appearance
Photographer Booking
Build a photography studio booking system with equipment management, multi-hour sessions, and deposit handling.
Domain Mapping
| Photography Concept | AvailEngine Concept | How to Set Up |
|---|---|---|
| Studio/Photographer | Business | Create one business per studio or solo photographer |
| Photographer | Resource | resource_type: "staff", capacity_min: 1, capacity_max: 1 |
| Studio space | Resource | resource_type: "room", capacity_min: 1, capacity_max: 5 |
| Equipment (camera, lighting) | Resource | resource_type: "equipment", capacity_min: 1, capacity_max: 1 |
| Session type | Service | Duration per session type (mini=30min, full=2hr, wedding=8hr) |
| Session | Booking | duration_minutes = session length, start_time = session start |
| Inquiry list | Waitlist | Clients interested in a date that's already booked |
Step-by-Step Setup
1. Create the Business
bash
curl -X POST https://api.availengine.com/v1/developer/businesses \
-H "Authorization: Bearer YOUR_JWT" \
-H "Content-Type: application/json" \
-d '{
"name": "Lens & Light Studio",
"business_type": "photographer"
}'2. Add Resources
bash
# Photographers
curl -X POST https://api.availengine.com/v1/manage/resources \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Dimitris (Lead)", "resource_type": "staff", "capacity_min": 1, "capacity_max": 1, "display_order": 1}'
curl -X POST https://api.availengine.com/v1/manage/resources \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Katerina (Second Shooter)", "resource_type": "staff", "capacity_min": 1, "capacity_max": 1, "display_order": 2}'
# Studio spaces
curl -X POST https://api.availengine.com/v1/manage/resources \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Main Studio", "resource_type": "room", "capacity_min": 1, "capacity_max": 5, "display_order": 3}'
curl -X POST https://api.availengine.com/v1/manage/resources \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Natural Light Room", "resource_type": "room", "capacity_min": 1, "capacity_max": 3, "display_order": 4}'
# Equipment (optional — for tracking rented/shared gear)
curl -X POST https://api.availengine.com/v1/manage/resources \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Canon R5 Kit", "resource_type": "equipment", "capacity_min": 1, "capacity_max": 1, "display_order": 5}'3. Define Session Types
bash
# Service records for different session lengths and prices:
# { "name": "Mini Session", "duration_minutes": 30, "price_cents": 5000 }
# { "name": "Portrait Session", "duration_minutes": 90, "price_cents": 15000 }
# { "name": "Family Session", "duration_minutes": 120, "price_cents": 25000 }
# { "name": "Wedding — Half Day", "duration_minutes": 480, "price_cents": 150000 }
# { "name": "Wedding — Full Day", "duration_minutes": 600, "price_cents": 250000 }4. Set Operating Hours
Photographers often have flexible schedules. Set wide availability and use bookings to control actual slots:
bash
curl -X PUT https://api.availengine.com/v1/manage/hours \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"hours": [
{"day_of_week": 0, "is_open": true, "open_time": "08:00", "close_time": "20:00", "last_booking_time": "12:00"},
{"day_of_week": 1, "is_open": true, "open_time": "08:00", "close_time": "20:00", "last_booking_time": "18:00"},
{"day_of_week": 2, "is_open": true, "open_time": "08:00", "close_time": "20:00", "last_booking_time": "18:00"},
{"day_of_week": 3, "is_open": true, "open_time": "08:00", "close_time": "20:00", "last_booking_time": "18:00"},
{"day_of_week": 4, "is_open": true, "open_time": "08:00", "close_time": "20:00", "last_booking_time": "18:00"},
{"day_of_week": 5, "is_open": true, "open_time": "08:00", "close_time": "20:00", "last_booking_time": "18:00"},
{"day_of_week": 6, "is_open": true, "open_time": "08:00", "close_time": "20:00", "last_booking_time": "12:00"}
]
}'Sunday Weddings
Keep Sundays open with last_booking_time: 12:00 — this allows full-day wedding bookings (10+ hours) but prevents new bookings starting in the evening.
5. Configure Settings
bash
curl -X PATCH https://api.availengine.com/v1/manage/settings \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"default_slot_interval_minutes": 30,
"default_slot_duration_minutes": 60,
"booking_window_days": 365,
"min_notice_hours": 48,
"max_capacity": 5,
"default_deposit_amount_cents": 50
}'| Setting | Why This Value |
|---|---|
slot_interval_minutes: 30 | Sessions start on the half-hour |
booking_window_days: 365 | Weddings book a year in advance |
min_notice_hours: 48 | 2-day cancellation policy |
default_deposit_amount_cents: 50 | €50 deposit to hold the date |
6. Book a Session
bash
curl -X POST https://api.availengine.com/v1/bookings/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"business_id": "YOUR_BUSINESS_ID",
"resource_id": "DIMITRIS_ID",
"service_id": "WEDDING_FULL_DAY_ID",
"customer": {
"first_name": "Alexandra",
"last_name": "Nikolaou",
"phone": "+306934445566",
"email": "alexandra@example.com"
},
"booking_date": "2026-09-12",
"start_time": "10:00",
"capacity": 1,
"customer_notes": "Wedding at Agios Georgios church, reception at Grand Hotel"
}'Response with deposit:
json
{
"booking_id": "uuid",
"status": "pending",
"confirmation_code": "AV-WD7K3L",
"deposit": {
"amount_cents": 5000,
"client_secret": "pi_xxx_secret_yyy",
"deposit_type": "charge"
}
}The €50 deposit holds the date. Show Stripe Elements to collect payment. On success, the booking auto-confirms.
Photography-Specific Patterns
Deposit as Date-Hold
Photography sessions (especially weddings) need a deposit to hold the date. Without it, another client could book the same date. The flow:
- Client inquires about a date → you send them your booking link
- Client fills booking form → AvailEngine creates a
pendingbooking - Client sees Stripe payment form → pays deposit
- Webhook fires
deposit.paid→ booking transitions toconfirmed - Date is now locked. Nobody else can book that photographer that day.
If the deposit isn't paid, the booking stays pending. You can decide: auto-cancel after 48 hours, or leave it and let the client pay when ready.
Multi-Day Events
For events spanning multiple days (festival coverage, destination wedding):
bash
# Day 1 — Friday setup + rehearsal dinner
curl -X POST ... -d '{"booking_date": "2026-09-11", "start_time": "14:00", "duration_minutes": 360, ...}'
# Day 2 — Saturday wedding
curl -X POST ... -d '{"booking_date": "2026-09-12", "start_time": "10:00", "duration_minutes": 600, ...}'
# Day 3 — Sunday brunch + sendoff
curl -X POST ... -d '{"booking_date": "2026-09-13", "start_time": "10:00", "duration_minutes": 180, ...}'Add a confirmation_code prefix or grouping in customer_notes to link multi-day bookings.
Second Shooter Booking
When a client books the lead photographer and also needs a second shooter:
- Lead photographer is booked as primary resource
- Second shooter is booked separately for the same time slot
- Use
staff_notesto cross-reference:"Second shooter for AV-WD7K3L"
Or create a combined resource: "Dimitris + Second Shooter" with capacity 2.
Mini Session Days
Photographers often run "mini session" days — multiple 30-min slots back to back:
- Create a blackout date for all other dates that month
- Open only one specific Saturday
- Set
slot_interval_minutes: 30,slot_duration_minutes: 30 - Clients book individual 30-min slots
- All 12-16 slots fill up fast — use webhooks to post "only 3 slots left!" on social media
Weather-Dependent Sessions
Outdoor sessions need a rain date. Two approaches:
Option A: Book the rain date as a separate pending booking. If the weather is good, cancel the rain date. If bad, confirm the rain date.
Option B: Use staff_notes to record the backup date: "Rain date: Sept 13". If needed, reschedule by PATCHing the booking date.
Client Galleries & Follow-Up
Use webhooks to automate post-session workflow:
booking.completedfires → trigger: "Thanks for your session!" email with gallery linkbooking.checked_infires → trigger: "Your photographer is ready" SMS (for studio sessions)booking.confirmedfires → trigger: "Session confirmed for [date]" with prep guide
Widget Integration
js
const client = new AvailEngine('avail_live_YOUR_KEY');
// Photography booking widget flow:
// 1. Client selects session type (mini, portrait, wedding)
// 2. Session type sets duration + price
// 3. Show calendar with available dates
// 4. Only dates with enough open time for the session duration appear
// 5. Client picks date + start time
// 6. Collect client info + event details
// 7. Show deposit payment form
// 8. On payment success → confirmation page with booking code
async function getAvailableDates(businessId, month, sessionType) {
// Check each weekend day in the month
// Filter to days where the full session duration is available
const slots = await client.availability(businessId, {
date: '2026-09-12',
durationMinutes: sessionType.durationMinutes,
capacity: 1
});
return slots;
}Dashboard Tips
- Blackout Dates: Block out vacation weeks and personal time so clients can't book them
- Google Calendar: Connect to sync sessions to your phone calendar with client name and location
- Staff notes: Record shot lists, locations, and special requests — visible to you and your second shooter
- Webhooks: Set up booking created → auto-reply email with prep guide and what to wear
Next: Back to all guides → | Back to Clinic →