---
title: Online booking and availability
description: Set up your ShootCal booking calendar with session types, sunset or studio timing, and booking rules, then share it, embed it, or add it to your website.
url: "https://shootcal.com/docs/online-booking-and-availability/"
updated: "2026-11-13"
category: "The ShootCal app / Schedule & clients"
---

# Online booking and availability

# Online booking and availability

## Set up your booking calendar, step by step

Everything happens in **Calendar > Booking setup** in the web app. New accounts start with an active **Consultation only** page, even before you add session types. Clients can share preferred dates and tell you what they need, then you follow up to confirm availability. A consultation request does not reserve a time or require a connected calendar.

Existing booking settings are kept, including pages you have paused. Use **Pause booking** to take your page and its website embed offline, or **Resume booking** when you are ready.

To showcase weddings, families, engagements, or other photography you offer, add custom session types with prices, session lengths, and sunset-based or fixed availability. In the **Booking page** card, change **What clients can request** to **Session types and consultation**, finish your timezone and calendar choices, then save. Creating a session type alone does not change a consultation-only page.

**Prefer to be guided?** Open **Help** (**?**) at the top of the screen. **Set up with AI** asks what kinds of shoots you do, how long they run and whether you shoot around sunset or at several times a day, then proposes your session types and booking hours as cards you approve. **Classic walkthrough > Online booking** gives a tour of the Booking setup page.

**Before you start, decide these:**

- **What clients can book:** one session type for each kind of shoot you offer online, named the way a client would read it (Family beach session, Engagement, Mini session, Headshots).
- **How long a session runs**, and the break you want between back-to-back sessions.
- **When you shoot:** around **sunset** or **sunrise** (ShootCal works out the time from the sun for that date and your location), at **studio hours** with several slots through the day, at **one fixed time**, or **all day** for weddings.
- **How many a day** you will take, how much notice you need, and how far ahead clients may book.
- **Request or instant:** approve each request before it lands on your calendar (the default), or let clients book instantly.

**The steps, in order:**

1. Add your session types and set the times you are available.
2. Choose the calendar that decides availability.
3. Check your business details.
4. Save your booking page.
5. Share your booking link, embed it on your website, or add it to your ShootCal Website.
6. Answer booking requests.

Each step is explained in the next sections.

## Booking setup step 1: add session types, like mini sessions, and set your available scheduling times

To offer specific sessions, first add the types clients can choose. You can keep accepting consultations while you set these up. Session types are also where you set which times and days you are available. In **Calendar > Booking setup**, beside **Your sessions**, choose **Add with walkthrough** or **Add manually** (clicking a faded example card also starts the walkthrough). For each type:

- Enter the **Session type name**, a **Price** if you want it shown, and a thumbnail photo (**Edit** on a saved card changes it later).
- Choose **Timing**: **Sunset** or **Sunrise** (the prime session ends at sunset or starts at sunrise, and any extra slots cascade from there; your location must be set), **Studio hours** (set **Opens**, **Closes**, **Session length** and **Turnover between sessions**, and sessions tile between them), **Fixed time** (one **Start time**), or **All day**.
- Type the **Session length** in whole minutes, from **5** to **600**, for sunrise, sunset, fixed-time, or studio sessions. For example, enter **30** or **60** directly. All-day sessions do not need a duration.
- Under **How bookings work**, choose **Request first**, **Instant book**, or **Contact first** (a date request with no published times).
- Set **Max per day**, **Min. notice** and **How far ahead**. To keep weekends or other weekdays off, open **Advanced booking rules**, turn on **Limit bookable days** and pick only the days you work.
- Keep **Offer this type on your booking page** on, then **Save session type**. Repeat for each kind of shoot.
- Need longer hours on one day, or a different schedule for a school break or a season? See [Longer Saturdays, school breaks and seasonal schedules](#longer-saturdays-school-breaks-and-seasonal-schedules).

Next: step 2, the calendar that decides availability. Help > Set up with AI can propose these session types for you.

## Longer Saturdays, school breaks and seasonal schedules

Both options are in a session type's **Advanced booking rules** and are off until you turn them on, so a simple schedule stays simple. Edit the session type, open **Advanced booking rules**, make your change, then **Save session type**.

**Different hours on some days** (Studio hours types). Turn it on to see each bookable day with its hours. Change only the days that differ, for example Saturday 9:00 AM to 6:00 PM while Friday and Sunday keep 1:00 PM to 5:00 PM. A day you leave alone uses the type's main **Opens** and **Closes** times. **Use main hours** puts a day back.

**Different schedule for certain dates**. Turn it on and choose **Add date range** for each period, such as a winter break or a summer season. For each range:

- Choose the **Start date** and **End date**.
- Under **Days open during these dates**, pick the days this type is bookable during the range. All seven days are selected to start. During the range these days replace your usual bookable days, so a Friday to Sunday type can open every day over a school break, or take Saturdays only in the summer.
- For Studio hours types, turn on **Different hours for these dates** to give the range its own opening and closing times. Leave it off to keep the usual hours, including any different hours you set for a weekday.

When ranges overlap, the shorter one wins, so a one-day change inside a season works. Dates outside every range follow your usual weekly schedule. Blackout dates still close a day, and min. notice, how far ahead, max per day and your calendar's busy times still apply on every date. Each date range belongs to one session type, so add it to every type you want it to change.

## Booking setup steps 2 to 4: availability calendar, business details, save

Steps 2 to 4 of setting up online booking, after you have added at least one session type.

**2. Choose the calendar that decides availability.** Below your sessions, pick the **Primary Business Calendar**. ShootCal's own calendar works with nothing connected; a connected Google or Microsoft calendar works too. Then choose **What blocks online booking?**: **Calendar events** holds a time as soon as an appointment is on your calendar, while **Confirmed sessions only** holds it only once the deposit is marked received or the session is confirmed. To let other calendars block times too, see [Choose which calendars block availability](#choose-which-calendars-block-availability).

**3. Check your business details.** Set the **Studio / business name** clients will see and the **Contact email** for booking questions. Add **Blackout dates** for vacations and days off. **Redirect after booking** is optional if you have your own thank-you page.

**4. Save your booking page.** Choose **Save booking page**. Your first save makes booking available to clients; before that nothing is public. Later, **Pause booking** stops bookings through every link and embed without losing your settings, and **Resume booking** turns them back on.

Next: step 5, let clients pick a time from your booking link or website.

## Booking setup step 5: let clients pick a time from your booking link or website

Step 5 of setting up online booking, once your session types are added and the booking page is saved. Clients book through your booking link, so put it wherever they find you. Preview the page as a client would, then use whichever of these fits:

- **Share the link.** Your booking link is `book.shootcal.com/<your ShootCal URL>` (the URL is set once in **Settings** and also serves your galleries and website). Put it in your Instagram bio, your email signature, a text to a client, or as a "Book now" button on your site.
- **Embed it on your own website** (Squarespace, Wix and others). Under **Put booking on your website**, choose **Copy embed** and paste the one-line snippet where you want the booking calendar. Pick **Light**, **Dark** or **Match website** so it fits your site.
- **WordPress.** Choose **Get the WordPress plugin**, install it, then **Copy WordPress ID** to connect it.
- **ShootCal Website.** Nothing to paste: add the **Availability calendar** block in the website builder and it shows your booking calendar automatically. With no online session types, visitors see the consultation calendar and contact form immediately. In the Website block, **Start with** lets you choose Automatic, Calendar and contact form, or Session type selection. A **Contact** block on the same site also shows a "check availability" button that leads to it.

If the link shows nothing to book yet, go back to step 1 and add a session type with **Offer this type on your booking page** on, then save the booking page.

## Booking setup step 6: answer booking requests

The last step of setting up online booking. Requests land in **Calendar > Booking requests** and in your email. **Accept** one and ShootCal saves the confirmed appointment; instant bookings go straight onto your calendar. New clients are added to **Clients** automatically. If something looks wrong, the answers below cover the common questions.

## Common questions

- [Can a member of the public ever see who I'm shooting, or what the shoot is, from my availability calendar?](#can-a-member-of-the-public-ever-see-who-i-m-shooting-or-what-the-shoot-is-from-my-availability-calendar)
  - [If I have a personal appointment on my calendar, will it block a client from booking over it, even though it's not published?](#if-i-have-a-personal-appointment-on-my-calendar-will-it-block-a-client-from-booking-over-it-even-though-it-s-not-published)
  - [Does submitting the booking form put the event on my calendar automatically?](#does-submitting-the-booking-form-put-the-event-on-my-calendar-automatically)
  - [Why does my public golden-hour booking page show only one time, when my session can fit several back-to-back?](#why-does-my-public-golden-hour-booking-page-show-only-one-time-when-my-session-can-fit-several-back-to-back)
  - [What stops two people from booking the same slot at the same instant?](#what-stops-two-people-from-booking-the-same-slot-at-the-same-instant)
  - [I deleted an accepted booking directly in my connected calendar. Will that slot stay blocked forever on my booking page?](#i-deleted-an-accepted-booking-directly-in-my-connected-calendar-will-that-slot-stay-blocked-forever-on-my-booking-page)
  - [How is the per-day capacity decided for the single embedded calendar, given it has no per-type data?](#how-is-the-per-day-capacity-decided-for-the-single-embedded-calendar-given-it-has-no-per-type-data)
  - [Is the public booking endpoint protected against spam and being used as a mail relay?](#is-the-public-booking-endpoint-protected-against-spam-and-being-used-as-a-mail-relay)
  - [Why can an older booking link differ from my ShootCal URL?](#why-can-an-older-booking-link-differ-from-my-shootcal-url)
  - [Can the availability calendar and booking page be embedded on Squarespace or Wix?](#can-the-availability-calendar-and-booking-page-be-embedded-on-squarespace-or-wix)
  - [Can a client request flexible dates or a date range instead of picking a time?](#can-a-client-request-flexible-dates-or-a-date-range-instead-of-picking-a-time)
  - [Can I set longer hours on Saturdays without changing my other days?](#can-i-set-longer-hours-on-saturdays-without-changing-my-other-days)
  - [Can I open weekdays for a school break without changing my weekly schedule?](#can-i-open-weekdays-for-a-school-break-without-changing-my-weekly-schedule)

On the web, open **Booking setup** to manage session types and their booking page together. Offer at least one session type for online booking, then choose your **Primary Business Calendar**: ShootCal's own calendar works with no provider connected, or you can use a connected Google or Microsoft calendar. Either way ShootCal uses it as the baseline for availability and saves new online bookings as ShootCal appointments in your account. Review your business details and choose **Save booking page**. Your first successful setup save makes booking available. Opening the page or following its walkthrough does not publish anything.

If you have no session types yet, the page shows your saved logo above faded example cards, or an **Add logo** placeholder. Click the example cards to add your first session type with the walkthrough, or choose **Add manually**. Example cards are illustrations only; they do not add content to your account. The booking walkthrough also offers first-session creation and can continue through all eight steps before you add one.

Use **Pause booking** when you need to stop accepting bookings through previously shared links or embeds. All settings remain visible and editable while paused. Saving those changes keeps the page paused; **Resume booking** makes it available again.

The quick walkthrough covers session types, thumbnails, the Primary Business Calendar, the main booking rule, business details, saving, sharing, and requests. It skips advanced settings. Booking rules, calendar selection, business details, redirects, and blackout dates all use **Save booking page**. Save or undo your draft before leaving the booking page.

**What blocks online booking?** chooses whether timed calendar appointments hold their time immediately (**Calendar events**) or wait until marked deposit received or confirmed (**Confirmed sessions only**). With Confirmed sessions only, unpaid or tentative appointments you create manually stay bookable. Accepted booking requests and instant bookings hold their time even before payment. Use blackout dates for days off.

## Your studio logo

In ShootCal **Settings**, choose your logo and review the full-image preview. A transparent PNG **500 px wide × 100 px tall** works well on the booking page. Square **500 × 500 px** logos and proportions in between also work. Choose **Use full image** to keep the original shape, or **Crop (optional)** to make a wide version.

Existing square logos have more room to display automatically. Previously saved crops keep their saved artwork; re-upload the original if you want to restore anything cropped away. A logo is optional and is not required to schedule sessions.

## Choose which calendars block availability

On the Calendar page, choose **Calendars** in the toolbar. Under **Show on calendar**, use **Show on my calendar** to control which events you see. Under **Booking availability** in the same panel, choose additional calendars that should block booking times. These choices are independent: a calendar can stay visible for awareness without blocking, or block availability while hidden from your calendar view.

The **Primary Business Calendar** remains the baseline and follows your booking rules. Additional blocking calendars are off by default. Select only calendars whose busy events mean you are unavailable. For example, you can keep a child's sports calendar visible without letting every practice block your photography sessions. Selected extra calendars block busy timed and all-day events; events marked free do not block. If a selected calendar cannot be checked, ShootCal does not assume those times are available. These private conflicts do not count as paid photography sessions or expose event details.

**Request first** is a separate choice: it lets you review and approve requests even when the availability calendar is accurate.

By default, the public availability calendar follows your booking rule. In **Advanced settings**, **Use a different rule for the public calendar display** lets you choose what appears booked separately. For example, you can show only confirmed sessions publicly while calendar appointments still hold their time. The public day overview and final time-slot checks use their respective rules. Event names and details stay private. Existing separate rules remain selected until you change them; unchecking the option makes the display follow your booking rule again. Save to apply changes.

The booking page leads with your session types, each as a card with its thumbnail photo, length, and optional price. Once a client picks the session they want, a compact availability calendar shows which days are open *for that type*: it already knows the type’s bookable weekdays, booking window, lead time, and per-day limit, so the client is never guessing dates. For types that publish times, tapping an open day shows the real open times (golden-hour types calculate them from the actual sunset or sunrise at your location for that exact date; studio types show your fixed hourly slots). Contact-first and all-day types take a date request instead of a time. And any client can switch to **Flexible dates** and pick a date range that could work (tap a start and an end date), or send the request with no dates at all, and the range they picked is recorded on the request.

The availability calendar shows which days are open, limited, or fully booked. It is private by design. It never shows who booked you, what the shoot is, or where it is. With Confirmed sessions only, it publishes sessions marked deposit received or confirmed. Calendar events uses busy events instead, unless you select a separate public display rule. You can embed on your own website (Squarespace, Wix, etc.) by pasting the one-line embed snippet from Booking setup (older iframe snippets keep working), or share the link directly. On a ShootCal Website you don't paste anything: the Availability section places the same embed script automatically. Your website embed opens the same session-type-first booking flow as your shared link.

Under **Put booking on your website**, choose **Light**, **Dark**, or **Match website**, then save the booking page. Light is the default. Choose separate **Light background** and **Dark background** colors, or reset either to its default. The light form has a soft shadow; the dark form has a thin border. Text and controls adjust to keep custom background colors readable. These settings apply on your own website and on ShootCal Websites.

Match website follows the appearance of the page containing the current embed script and updates without clearing a visitor's in-progress details. A booking page opened on its own follows the visitor's device appearance when Match website is selected. Older raw iframe embeds still work, but replace them with the current embed code to follow the containing website's appearance. The ShootCal website builder's Availability block links to these settings in a new tab, so you manage the form in one place.

By default, a submission does not book anything. It creates a **request** that lands in your Booking requests inbox (and emails you, unless you choose to handle requests only in the app). You review it and either Accept (which saves the confirmed ShootCal appointment right then) or Decline. Each session type has one of three booking modes: **Request first** (the default just described); **Instant book**, where the picked time is confirmed and added to your calendar immediately with no manual step; and **Contact first**, which takes a date request with no published times (a contact-first type can never instant-book).

A few built-in protections: a hidden anti-bot field, a 5-requests-per-hour-per-IP rate limit, and a re-check at accept time that the slot is still free so you never double-book.

## Booking links and compatibility routes

The app presents one booking-page experience. Behind it, existing routes remain compatible so previously shared links and calendar subscriptions keep working:

- **The availability calendar (read-only).** Served at `/embed/<token>` and rendered to standalone HTML. Its data source is a stored calendar feed file on disk, built from your ShootCal appointments. The embed reads that file directly: no database lookup for the events, and no live provider call when it renders. There is also a raw feed URL (the same file, served as a static `.ics`) for calendar subscriptions. When you have booking enabled, `/embed/<token>` serves the booking flow by default (it redirects into `/book` with embed styling); `?view=calendar` renders the classic grid, which is also what a booking-disabled feed always renders.
- **The booking page (interactive).** Served on `book.shootcal.com`: the short address is `book.shootcal.com/<name>`, and `book.shootcal.com/book/<name>` is the same page, with companion endpoints for a month’s open days per session type and a day’s open times, plus a submit endpoint. Older `shootcal.com/<name>` and `shootcal.com/book/<name>` links redirect there permanently, so nothing you already shared breaks. The month view is computed from the type’s rules plus the same published feed the calendar uses: advisory, with the real re-checks at day-pick and submit. The address ShootCal shows you follows your one account-wide **ShootCal URL**, which you manage in Settings and which is also used for your gallery and website addresses. An internal random token and any booking-only alias created before the account-wide URL continue to resolve as compatibility routes so already-shared links do not break; neither is a second editable public identity.

For older integrations that explicitly requested the classic calendar view, the compatibility renderer and the booking page remain connected: day cells are clickable when booking is enabled. Open days link straight to that date on the booking page; a fully booked day links with a flag so the booking page can say ‘this date is full, but if your dates are flexible I can try to fit you in.’

## Why the availability calendar can never leak client details

The privacy guarantee is enforced where the feed is built, not at display time. Two mechanisms:

1. **Only booked days are published.** A day is ‘booked’ only if its session’s deposit is received. That check reads the deposit marker stored on the ShootCal appointment. Personal events, tentative holds, and unpaid sessions never appear. (There is also an opt-in ‘all busy events’ mode for a brand-new user who hasn’t started marking deposits; even then no event text is included.) 2. **Each published event carries only timing.** Each event in the feed includes only its identifier and start/end times and a busy status. There is no title, location, description, attendee, or organizer.

This is belt-and-suspenders: before the file is written to disk, ShootCal scans the generated text for any of a list of forbidden properties (title, description, location, attendee, organizer, contact, url, and similar). If any is found, the build **fails closed** and the old file is left untouched. The event identifier is also sanitized of line breaks so a malformed id can’t smuggle a property line in. So even the feed that ships contains nothing but busy blocks.

## How a day is colored Open / Limited / Booked

The embed renders ONE calendar from an opaque busy feed that has no per-type information, so it can’t color per type. Instead it resolves a single per-day capacity equal to the MAX capacity across your bookable session types, and a day reads ‘Booked’ only when even the most permissive type is full. (The visible legend in the embed labels these states Available / Limited / Booked.) Concretely:

- A studio type’s ceiling is its back-to-back slot count derived from its fixed hours (open, close, session length, turnover); you never hand-count slots (‘Fill’).
- A sunset/sunrise type’s ceiling is the cascade maximum of six slots.
- A fixed-clock-time type is always 1.

Your per-day limit for a type (or the studio default when the type inherits) is clamped to that physical ceiling. The cap honors which types are actually bookable, using the same bookability rules as the booking page, so the calendar can’t advertise Open or Limited for a type the request page won’t book. If types exist but none are structured-bookable (for example only all-day weddings), the calendar colors booked-only (capacity 1).

## The day’s open times: golden-hour cascade vs studio grid

Both the slot picker and the submit path use the same slot-planning logic (the same logic runs in the native app and the web app), so the picker and the server agree exactly. By session-type mode:

- **sunset / sunrise**: ShootCal computes the actual sunset or sunrise time for that date at your stored latitude and longitude. It then packs sessions back from sunset (or forward from sunrise) in session-length plus break steps, routing AROUND your existing calendar events, up to six candidate slots. The first slot anchored at the sun event is flagged as prime (the ‘Golden hour’ tag on the page). This requires a location; with none, sun types yield no slots.
- **studio**: tiles that day's open-to-close hours in session-length steps plus turnover gaps; every tile is a slot, and a tile overlapping a busy event is flagged as already booked. The hours come from a date range with its own hours when one covers the date, then that weekday's different hours, then the type's main hours.
- **fixed**: a single clock time.
- **all-day**: produces no timed slots, but the type can still be offered on the booking page as a full-day date request (the contact-first flow, with flexible-date preferences).
- **manual / empty mode**: no structure, so nothing bookable.

An explicit **Block booking availability** choice on a Personal Event blocks its dates and times in either booking mode. New Personal Events default to allowing bookings. Every candidate is checked against your Primary Business Calendar using **What blocks online booking?**. **Calendar events** blocks timed appointments; **Confirmed sessions only** leaves unpaid or tentative appointments you create manually open. Accepted booking requests and instant bookings still hold their time before payment, so the public day and time pickers do not offer that slot again. Selected additional blocking calendars contribute their busy times independently. Personal event details never appear in the public booking page.

## The crucial distinction: public availability is capped, the manual picker is not

This is the heart of the ‘public vs manual’ difference. For a sunset/sunrise type, the full cascade can produce up to six candidate slots, but the PUBLIC booking page does not publish all of them. For sun types it figures out how many slots remain (your per-day limit minus what is already booked that day, and a deposit-paid session you scheduled by hand counts as booked too) and publishes only that many open slots. With the default per-day limit of one, the public page offers exactly ONE golden-hour slot (the prime time), even though the cascade physically fits more.

That cap is deliberate: it makes the public page match the day-full gate and the calendar’s per-day coloring. The full multi-slot cascade is the MANUAL tool: it’s there for you (in the app or manual entry) to stack several sessions into one golden hour when you choose to, but the public self-booking flow won’t oversell your evening. Studio and fixed types instead offer all their slots (a booked one is shown and flagged), because their per-slot availability already gates capacity.

Your per-day limit is enforced again at submit time: ShootCal counts the accepted bookings of that type on the day (in your calendar’s timezone) and the deposit-paid sessions already on your calendar, and takes whichever count is higher (an accepted booking is itself one of those paid events, so nothing is counted twice); a request over the limit is rejected as ‘day full’. Studio ‘Fill’ types leave the day-count uncapped and let per-slot availability do the gating.

## Request → review → accept (the default flow)

By default booking is request-mode and a public submission NEVER creates a calendar event. The submit step validates everything, then for request-mode stores a pending request with the picked start and end times. The slot is left OPEN while pending. It then best-effort emails you (the request is saved even if the email fails).

The pending request shows up in two places, both of which call the same accept/decline logic:

- **The magic-link page** in the notification email, with accept and decline buttons. This page is hardened against being embedded in a frame (it shows client personal information), so other sites cannot iframe it.
- **The Booking requests inbox** in the web app and the iPhone and iPad apps, which lists requests (pending first, soonest slot first) and offers the same accept and decline, plus replying to the client (prefilled from the type’s saved reply) and a decline-with-message option; on the web you can also ‘Accept with changes’ by adding the event yourself, and the request is recorded as booked. A request you never answered whose requested date has already passed is tagged **Not replied · Past date** and moves out of Pending into the Recently replied or declined group (it no longer counts toward the Requests badge); you can still reply, add it to the calendar if the shoot happened, or decline it to clear it. The Android app lists pending requests for reference; choose **Respond on ShootCal website** to reply, accept, or decline on the web.

Accept re-validates that the slot is still free, then creates the confirmed ShootCal appointment (the client's name, email, phone, and notes stay in ShootCal with the booking), and marks the request accepted. Declining can optionally send the client your saved decline note (with the client and session type filled in) before marking the request declined; either way nothing was ever booked, so there’s nothing to unwind. A declined request can be reopened to pending later (a sent decline email is not recalled on reopen).

## Instant mode, and where everything is stored

Instant mode is opt-in and resolved per session type (it reads the type’s booking mode, falling back to your global setting). For security it is ALWAYS derived from the resolved type, never from a field in the client’s submission, so a tampered request can’t flip a request-only type into a booking. In instant mode ShootCal claims the slot in its own database first (as accepted, with no appointment yet) inside an atomic database transaction that re-checks the per-day limit and slot overlap, THEN creates the ShootCal appointment and links it. If the appointment creation fails, the claim is deleted so the slot reopens.

Where data lives (server-side, scoped to your account). The main items:

- Your booking-page settings: which calendar, lead time, how far ahead bookings open, your per-day limit, which days and session types are bookable, the booking mode, blackout dates, your business name, and your after-booking redirect URL. Your account-wide ShootCal URL is managed separately in Settings. ShootCal also retains the booking page’s internal random token and, for an older account that used one, its legacy booking alias so existing links keep working; they are compatibility routes, not editable booking settings. (Client confirmation emails are a per-session-type rule, on by default, stored with your synced session types.)
- Every request and instant-book: its status (pending, accepted, declined, responded, or canceled), the slot times, the client’s name, email, phone, and notes, the request’s secret token, the linked appointment, decision and response timestamps, and any flexible-date preferences.
- A lightweight audit and rate-limit record per submission: which account it belongs to, the visitor’s IP hashed with the app’s secret key (never the raw IP), the client-supplied email (empty for demo and rate-limit-only rows), the slot start, and a timestamp. That IP hash is what enforces the per-hour-per-IP limit.
- Your synced session types and studio defaults (which override the legacy global rule settings), including each type’s booking rules, reply templates, and your decline reply.
- The availability feed file used by the embed.
- The optional studio logo shown atop the embed.
- Optional per-type cover photos, stored server-side and shown on the booking page.

## Anti-abuse, self-healing, and the reply tracking path

Several safeguards run on the public path:

- **Honeypot**: a hidden field a real person never sees. A bot that fills it gets a fake success and the submission is silently dropped (no stored request, no email, no calendar write).
- **Rate limit**: 5 requests per hour per IP, keyed on the visitor’s IP hashed with the app’s secret key (the IP comes from Cloudflare’s connecting-IP header, falling back to the raw connection address). It even logs a row for the public demo page (with an empty email) so the cap applies there too.
- **Demo page** (the [shootcal.com](http://shootcal.com) availability try-it flow): runs every validation for real but stores no request and sends no email, so it can’t be used as a mail relay.
- **Re-validation on accept/instant-book**: an atomic database transaction and overlap check recheck the slot before an accepted or instant booking is saved. A stale booking draft must be refreshed and reviewed before retrying.
- **Consistent gating**: availability checks saved ShootCal appointments and any selected external busy calendars. A saved cancellation releases the appointment’s local block; a connected calendar copy may still block until its cancellation syncs and availability refreshes. Schedule changes made directly in a connected Google Calendar or Outlook calendar sync back to ShootCal automatically.

Notifications: by default you’re emailed each request. A request notification can provide a private reply address that routes your answer back to the client through ShootCal. You can also set reply-mode to ‘app’, which sends no notification email and lets you handle requests in the inbox. See [How email works](/docs/app/how-email-works) for sending status and reply details.

## FAQ

### Can a member of the public ever see who I’m shooting, or what the shoot is, from my availability calendar?

No. The published feed only contains each event’s identifier, start and end times, and a busy status: no title, location, description, or attendees. A forbidden-property audit runs before the file is written and fails closed if any of those ever appear. The published busy dates follow your selected public-calendar display rule. With the confirmed-only rule, tentative appointments do not appear booked; event details stay private with either rule.

### If I have a personal appointment on my calendar, will it block a client from booking over it, even though it’s not published?

New **Personal Events** allow bookings by default. Turn on **Block booking availability** in the event editor to block those dates and times, including all-day and multi-day trips, without publishing the event title or details. Turn it off to allow bookings; paid and accepted bookings still keep their reservations.

Older Personal Events show **Existing booking rules** until you choose **Allow bookings** or **Block bookings**. Their previous behavior follows **What blocks online booking?**: **Calendar events** blocks busy timed appointments, while **Confirmed sessions only** leaves unpaid manually created appointments open. A different calendar can still block through **Booking availability** in the Calendar sidebar, independently of whether it is visible. Imported recurring schedules retain their existing rules and are managed in Google Calendar or Outlook.

### Does submitting the booking form put the event on my calendar automatically?

In the default request mode, no. The submission creates a pending request and emails you; the slot stays open. You Accept (which creates the event then, re-validating the slot is free) or Decline. Contact-first types work the same way, just without a published time: the client requests a date (with flexible-date preferences) and you follow up. Only if a session type is set to instant mode is the confirmed event created immediately, and that mode is resolved from the type on the server, never from the client’s request; a contact-first type can never instant-book.

### Why does my public golden-hour booking page show only one time, when my session can fit several back-to-back?

The cascade can fit up to six sun-anchored sessions, but the page caps what it PUBLISHES to your per-day limit minus what’s already booked that day. With the default limit of one, only the prime golden-hour slot is offered publicly. The full multi-slot cascade is the manual tool for you to stack sessions yourself; the public page is intentionally capped so it can’t oversell your evening, and so it matches the day-full gate and the calendar’s coloring. Raise the per-day limit on the type to publish more.

### What stops two people from booking the same slot at the same instant?

Both the instant-book path and the accept path do the overlap check and claim the slot in a single all-or-nothing step. The second accept waits its turn, sees the first’s now-accepted booking, and bails. One slot can never become two appointments. ShootCal trusts its own record of who’s booked here, because a connected calendar’s sync can lag a moment and a pending request isn’t booked yet.

### I deleted an accepted booking directly in my connected calendar. Will that slot stay blocked forever on my booking page?

Deleting a synced one-off appointment in Google Calendar or Outlook cancels it in ShootCal when the calendar refreshes and puts it in [Trash](/docs/app/calendar-events-and-quick-add#trash-and-restore) for 30 days. You can also cancel the booking directly in ShootCal. The saved cancellation clears its local availability block; a selected external calendar can still block the slot until its copy is canceled and availability refreshes. Restore the appointment from Trash if you want it back on the calendar.

### How is the per-day capacity decided for the single embedded calendar, given it has no per-type data?

The embed colors the one calendar by the MAX capacity across your bookable session types (a day is ‘open’ if ANY type has room). Studio capacity is derived from its hours grid, using the type's longest day when some days or date ranges have different hours; sun types use the cascade max of six, fixed types are one; your per-day limit (or studio default) is clamped to that physical ceiling. It also respects which types are actually bookable, mirroring the booking page, so it can’t show Open for a type the request page won’t fulfill.

### Is the public booking endpoint protected against spam and being used as a mail relay?

Yes, several ways. There’s a hidden honeypot field (a bot that fills it gets a fake success and the submission is dropped). There’s a 5-per-hour-per-IP rate limit keyed on the visitor’s IP hashed with the app’s secret key (the IP is taken from Cloudflare’s connecting-IP header, falling back to the raw connection address). Notification emails never go to the client-supplied address on a request (they go to you). A pending request books nothing and emails the client nothing. Only once a booking is actually confirmed (you accept it, or an instant-book type books it) does ShootCal email the client their confirmation, and only when that session type’s confirmation setting is on. The [shootcal.com](http://shootcal.com) demo availability page runs all checks but stores no request and sends no email, so it can’t relay mail either.

### Why can an older booking link differ from my ShootCal URL?

Your current public name is the single account-wide **ShootCal URL** you choose in Settings. ShootCal uses that name for the booking page, galleries, and website rather than giving the booking page another editable slug. Every booking page also has an internal random token, and an older account may retain a booking-only alias that it shared before the account-wide URL existed. Those older token and alias addresses still resolve to the same enabled booking page so saved bookmarks and links do not suddenly break, but they are compatibility routes: they are not additional names to manage. The address shown in the app follows your current ShootCal URL, as `book.shootcal.com/<your name>`.

### Can the availability calendar and booking page be embedded on Squarespace or Wix?

Yes. The snippet is now a single script tag that injects the frame and keeps it sized to the content (previously pasted iframe snippets keep working, since the embed still posts its height to the parent so those auto-size too). It’s edge-cached (10 minutes) and refreshed when your calendar changes. The embed opens the session-type-first booking flow. The booking page also allows framing, but the photographer-only magic-link review page is hard-blocked from framing because it shows client personal information.

### Can a client request flexible dates or a date range instead of picking a time?

Yes. Any client can switch the booking page to **Flexible dates**, tap a start and an end date to mark the range that could work, or send the request with no dates at all. The range they picked is recorded on the request, so when you review it you can offer a day that fits. Contact-first and all-day types (like weddings) always work this way: a date request with those same flexible-date preferences, rather than a published time. [← Back to Help Center](/)

### Can I set longer hours on Saturdays without changing my other days?

Yes, for a Studio hours session type. Edit the type, open **Advanced booking rules** and turn on **Different hours on some days**. Change Saturday's opening and closing times and leave the other days alone; they keep the type's main hours. Save the session type. Clients then see the longer list of Saturday times on your booking page.

### Can I open weekdays for a school break without changing my weekly schedule?

Yes. Edit the session type, open **Advanced booking rules**, turn on **Different schedule for certain dates** and add the break as a date range. Leave all seven days selected under **Days open during these dates**, or pick only the days you want. After the end date, the type goes back to its usual days on its own. Add the range to each session type you want to offer over the break. Blackout dates inside the range still stay closed.

---

### Discover more from ShootCal

Subscribe to get the latest posts sent to your email.
