Scheduling

Booking requests, custom booking pages and the booking key

Take booking requests without a time, replace the standard booking page with your own HTML and CSS, and let any website send bookings for an Event Type with its publishable booking key.

An Event Type can ask the booker for a time, or take a request without a time that you answer later. It can show Agaro's standard booking page, or a page you write yourself in HTML and CSS. Either way Agaro checks every booking and sends the emails. Separately, a booking key lets any other website send bookings for the same Event Type.

All three live in the Event Type editor under Booking experience, Booking page. The section follows the Appearance tab's access, and the booking key also needs the private links control of Privacy and security.

Ask for a time

Ask for a time is on for every Event Type until you change it. With it on, bookers choose one of your free times, as always.

Turn it off and select Save changes, and the booking page shows only the details form: the booker's name, email, phone, notes, guests and your custom questions. No calendar is read and no time is shown. Each submit is recorded as a booking request with the status Requested.

A request keeps every rule that does not need a time: required questions, email verification when the Event Type asks for it, guests, the location choice, and the booking rate limits. Each submit is a request of its own, so a booker who sends the form twice appears twice; a retry of the same submit returns the first. A request takes no seat, counts toward no booking limit, gets no reminder and puts nothing on any calendar.

The booker gets a receipt saying you will get back to them with a time. You get an email with their details and a link to answer the request.

Some Event Types always ask for a time, and the switch stays on for them:

Event TypeWhy
Paid bookingsThe payment is for a time that is held
SeatsSeveral bookers share one time
RecurringThe series repeats a time
Round robin, collective or managedHosts are matched to the time

If an Event Type with the switch off later becomes one of these, its booking page asks for a time again.

Answer a request

Open Scheduling. Requests without a time are listed above the calendar, never on it, with the booker's name, email and the time the request arrived. Select Answer to see the details and answers, then:

  • Confirm with a time: pick one of the Event Type's free times. Agaro checks the time again when you confirm, exactly as it checks a booking (seats, buffers, your busy time, notice and limits). The request becomes a confirmed booking: it goes on your calendar, the booker is emailed the time, their guests are invited and reminders are set.
  • Decline: the booker is sent a polite note that you cannot take the request, with your reason when you give one.
  • Convert to lead: creates a lead in the CRM from the booker's details, notes and answers, through the Leads module's own create rules. The lead's notes name the request's reference. It is offered only when your workspace has the Leads module and you may create leads, and not when a lead with the booker's email already exists (then Open lead opens it). The request stays open, so you can still confirm or decline it.

Answering a request needs the same access as approving a booking.

Choose the booking page

Under Booking page choose one of:

ChoiceWhat bookers see at /e/<workspace-slug>/<event-type-slug>
Agaro booking pageThe calendar, the times and the form, in your Appearance design
Custom HTML and CSSYour own page. Agaro fills in the times and takes the booking

Select Save changes to publish the choice. Switching back to the Agaro page keeps your HTML and CSS, so you can switch again later.

Write a custom page

With Custom HTML and CSS chosen, the section shows an HTML box and a CSS box side by side, and the live preview beside the settings shows your unsaved page.

To begin, choose a template under Start from a template. Both ask for the booker's name, email, phone, a note and each custom question of the booking form:

  • Details and time carries the time picker placeholder, where Agaro draws the available times.
  • Details form asks for no time. It is offered when Ask for a time is off.

A template replaces what is in both boxes; nothing is published until you save.

Paste only what goes inside the page: no html, head or body tags, and put styles in the CSS box. The HTML can be up to 64,000 characters and the CSS up to 32,000.

Fields your page must carry

Each input names what it carries with a data-agaro-field attribute. The section's Fields your page must carry table lists the fields for your Event Type, including one for each custom question.

AttributeWhat it carriesNeeded
data-agaro-field="name"The booker's nameRequired
data-agaro-field="email"Their email addressRequired
data-agaro-field="phone"Their phone numberOptional
data-agaro-field="notes"A note for youOptional
data-agaro-slotsWhere Agaro draws the available times as buttonsRequired while the Event Type asks for a time, or the time field below
data-agaro-field="time"A select or hidden input for the time, instead of the buttonsRequired while the Event Type asks for a time, or the buttons above
data-agaro-field="duration"A select of the Event Type's lengths, when it has more than oneOptional
data-agaro-field="location"A select of its locations, when it has more than oneOptional
data-agaro-field="attendeeLocation"Where to meet, when the booker chooses the placeOptional
data-agaro-field="guests"Guest emails, separated by commasOptional
data-agaro-field="answers.<question key>"The answer to one custom questionRequired when the question is

A checkbox question carries the attribute on each checkbox; every ticked value is sent. Agaro fills an empty select for the time, duration or location with the Event Type's own choices.

These parts are optional:

AttributeUse
data-agaro-formThe form Agaro sends. Without it, the first form on the page
data-agaro-error="<field>"Shows the error for one field, for example data-agaro-error="email"
data-agaro-error="form"Shows an error about the whole booking
data-agaro-successShown once the booking is made; the form is hidden
data-agaro-referenceFilled with the booking reference
data-agaro-booked-timeFilled with the booked day and time

The time buttons carry the classes agaro-slot, agaro-slot-day, agaro-slot-day-label and agaro-slot-times, and the chosen button has aria-pressed="true", so your CSS can style them.

What Agaro checks when you save

Save changes refuses a custom page, and says why under the boxes, when:

  • it carries a script, frame, plugin, or style, meta, link or base element;
  • it carries an event handler attribute (such as onclick), a javascript: link, a form action or a link target;
  • it carries a password field (a booking page never asks for a password);
  • its CSS contains a <, an @import, or expression, behavior or binding values;
  • it lacks the form, the name or email field, the time, or a required question's field.

The same notes appear while you type, so you can fix them before saving.

A saved page can also stop fitting the Event Type later: a required question added to the booking form, or Ask for a time turned back on (or kept on because the Event Type now takes payment, has seats, repeats, or is a round robin, collective or managed event). Until the page carries the new field, bookers see the Agaro booking page instead, so nobody meets a form that cannot book. The section says so beside the notes.

How the page is kept safe

Your page never runs on Agaro's own address with the visitor's session. It is served in a sandboxed frame with its own isolated origin and a strict content security policy: it cannot read Agaro cookies or storage, reach the page around it, make network requests, submit forms elsewhere or load frames and plugins. The only script in it is Agaro's, which sends the form to the booking page around the frame; that page books through the same action as the standard page. The markup is cleaned again each time the page is served.

The frame shows your page only inside your Agaro booking page: opened on its own, or framed by any other website, it shows nothing. Above it the booking page names your brand and says Agaro hosts it. Links in your page open in a new tab, so the booking page is never replaced. When the booking page itself is embedded in another website, a custom page offers a link that opens it in its own tab instead of the frame.

What a booking runs

A booking from a custom page follows exactly the rules of the standard page: the offered time is checked again when the booking is made, seats and booking limits apply, required questions must be answered, guests are checked, and paid Event Types go to checkout. When the Event Type requires a verified email, Agaro asks for the code in its own dialog before booking.

Errors from Agaro appear in your form: a field's error in its data-agaro-error element, anything else in data-agaro-error="form", or at the top of the form when you have none.

The booking key

A booking key lets any website send bookings for this one Event Type to Agaro. Under Booking key, select Create booking key.

The key looks like pk_book_.... It is safe to put in a web page: it can only create bookings for this Event Type, under the same rules as the booking page, and it cannot read bookings or reach anything else. Never put a secret API key in a web page.

  • Rotate key replaces the key at once. Websites using the old key stop taking bookings until you paste the new one.
  • Revoke key removes it. Every website using it is refused from then on. Bookings already made are kept.
  • Allowed websites limits which websites may use the key from a browser. Enter one address per line, such as https://www.example.com, and select Save websites. Leave it empty to allow any website.

The section shows an HTML form example and a Fetch example, ready to copy with your key. Both read the booking's status: they say the booking is made only when it is confirmed, say the request was received when the host confirms bookings (pending) or when there is no time yet (requested), and send the booker to checkout for a paid Event Type (awaiting_payment).

An Event Type that requires a verified email cannot take bookings through the key yet: a website has no way to verify the booker's email, so those bookings are refused. The Booking key section warns you when this applies. Use your Agaro booking page for such an Event Type, or turn off email verification under Privacy and security.

Send a booking

Send a POST to /api/public/event-bookings on your Agaro address with the key and the booking, as JSON or as form data:

js
const attempt = crypto.randomUUID();
const response = await fetch("https://erp.agaro.ai/api/public/event-bookings", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Agaro-Booking-Key": "pk_book_...",
    "Idempotency-Key": attempt,
  },
  body: JSON.stringify({
    time: "2026-11-10T14:00:00.000Z",
    name: "Sara Ahmed",
    email: "[email protected]",
    phone: "+1 555 0100",
    answers: { company_size: "11-50" },
  }),
});
FieldMeaning
keyThe booking key, in the body or in the X-Agaro-Booking-Key header
name, emailRequired
phone, notesOptional
timeThe UTC start, one of the offered times. Required while the Event Type asks for a time; ignored when it takes requests without one
durationMinutes; the Event Type's length when left out
location, attendeeLocationA location id, and the booker's own place when the location asks for one
answers{ "<question key>": value }, a list for a checkbox question; in form data, answers.<question key> fields
guestsA list, or one string of emails separated by commas
timeZoneThe booker's time zone, for their emails
emailVerificationReceiptNot yet available to websites; an Event Type that requires a verified email refuses key bookings

Send the same Idempotency-Key again when you retry after a network error; the retry returns the same booking rather than a second one.

A successful booking answers 201 with booking.reference, booking.status (confirmed, pending when the host confirms bookings, awaiting_payment with a checkoutUrl for a paid Event Type, or requested for a request without a time), the start and end (both null for a request), and the booker's manage link (none for a request). A retry that returns an existing booking carries no manage link: the link is given only to the submit that made the booking, which also emails it to the booker.

Errors answer with error.code, error.message and fieldErrors under the names you sent:

Statuserror.codeMeaning
401invalid_keyThe key is unknown, rotated or revoked
403origin_not_allowedThe website is not in Allowed websites
409time_unavailableThe time is no longer offered; read the times again
413, 415, 400payload_too_large, unsupported_media_type, invalid_requestThe request could not be read; a body may be up to 32 KB
422validation_failedFix the fields named in fieldErrors
429rate_limitedToo many attempts from this address or for this email

Read the offered times

GET /api/public/event-bookings/slots?key=pk_book_... answers the offered UTC start times for the next 30 days, and askForTime: false with no times for an Event Type that takes requests without a time. Add from, to (ISO dates) and duration (minutes) to choose others. The booking checks the time again, so a listed time can still be taken by someone else first.

Server to server

A server that holds a real API key can also book through the authenticated /api/v1 layer, with POST /api/v1/event-booking-public/bookPublicEventSlot and the workspace and Event Type slugs. Keep that API key on the server; a web page only ever carries the publishable booking key.

Limits

Requests are limited per address, per address and Event Type (shared with the booking page), and per booker email. Event Types that require a verified email do not take key bookings yet; the Agaro page and custom pages ask for the code themselves.

Troubleshooting

Save says the page needs fields

Add the named attributes. For the time, add data-agaro-slots where the times should appear, or a field with data-agaro-field="time", or turn Ask for a time off to take requests without a time.

The Ask for a time switch cannot be turned off

The Event Type takes payment, has seats, repeats, or is a round robin, collective or managed event. Those always ask for a time.

Save says to remove an element or attribute

Delete it from the HTML. Agaro adds its own booking script, so the page needs none of its own; put styles in the CSS box.

A website gets origin_not_allowed

Add the website's exact address, such as https://www.example.com, under Allowed websites, or clear the list to allow any website.

A website stopped taking bookings

The key may have been rotated or revoked. Copy the current key from Booking key into the website.