Availo is built to be extended. This is the same hook layer that Availo Pro itself uses — nothing is private API.
Actions
Fired on the booking lifecycle. Handlers receive the booking as an associative array (the database row) and the EventType object.
// A booking was created (confirmed, or pending under approval mode).
do_action( 'availo_booking_created', array $booking, EventType $event, string $raw_token );
// A pending booking was approved (Pro). Sends the confirmation email + .ics.
do_action( 'availo_booking_approved', array $booking, ?EventType $event );
// A booking was cancelled (by invitee, admin, or a declined request).
do_action( 'availo_booking_cancelled', array $booking, ?EventType $event );
// A booking was rescheduled — a new booking is created, the old one marked.
do_action( 'availo_booking_rescheduled', array $new_booking, array $old_booking, EventType $event, string $raw_token );
// A reminder is due for a confirmed, upcoming booking.
do_action( 'availo_booking_reminder', array $booking, ?EventType $event );
$raw_token is the unhashed manage token, available only at creation time — use it to build a manage URL with \Availo\Frontend\BookingPageRouter::manage_url( $raw_token ).
Example — post to Slack on every booking:
add_action( 'availo_booking_created', function ( $booking, $event ) {
if ( 'confirmed' !== $booking['status'] ) {
return;
}
wp_remote_post( 'https://hooks.slack.com/services/XXX', array(
'body' => wp_json_encode( array(
'text' => sprintf( 'New booking: %s with %s', $event->title, $booking['invitee_name'] ),
) ),
) );
}, 10, 2 );
Filters
// Modify a booking row before it is inserted (runs inside the per-host lock,
// after availability validation). Pro uses this for approval status, host
// assignment, and attaching Zoom/Meet links.
apply_filters( 'availo_booking_data', array $data, EventType $event, DateTimeImmutable $start );
// Adjust the slot-engine configuration before slots are computed. Add busy
// intervals here to block time from external sources.
apply_filters( 'availo_slot_config', array $config, EventType $event );
// Filter the computed availability. Receives the range so you can compute
// additional hosts' availability for the same window.
apply_filters( 'availo_available_slots', array $slots, EventType $event,
DateTimeImmutable $range_start, DateTimeImmutable $range_end,
DateTimeZone $invitee_tz, DateTimeImmutable $now );
// Add row actions (e.g. Approve/Decline) to bookings in the admin list.
apply_filters( 'availo_booking_row_actions', array $actions, array $item );
// Return false to suppress the confirmation/notification emails for a booking
// (reminders and integrations still run).
apply_filters( 'availo_send_booking_emails', bool $send, array $booking, EventType $event );
// Customize email bodies before merge tags are applied.
apply_filters( 'availo_email_confirmation_body', string $body, array $booking, EventType $event );
apply_filters( 'availo_email_pending_body', string $body, array $booking, EventType $event );
apply_filters( 'availo_email_reminder_body', string $body, array $booking, ?EventType $event );
Example — block time from an external source:
add_filter( 'availo_slot_config', function ( $config, $event ) {
$config['busy'][] = array(
'start' => new DateTimeImmutable( '2026-08-01 09:00:00', new DateTimeZone( 'UTC' ) ),
'end' => new DateTimeImmutable( '2026-08-01 12:00:00', new DateTimeZone( 'UTC' ) ),
'event_type_id' => 0, // 0 = external; never counts toward the daily cap.
);
return $config;
}, 10, 2 );
The slot engine
The core availability calculation lives in \Availo\Core\SlotEngine. It’s pure PHP with no WordPress dependencies — given a configuration array, a date range, and a time zone, it returns available start times grouped by day. All arithmetic is in UTC using IANA time zones, so daylight-saving transitions are handled correctly.
\Availo\Core\Availability::slots_for_range() is the WordPress-aware wrapper that assembles the config from an event type, its schedule, and existing bookings, then applies the filters above.
REST API
The booking widget talks to a public REST namespace, availo/v1:
| Route | Method | Purpose |
|---|---|---|
/slots | GET | Available slots for an event type and month |
/bookings | POST | Create a booking |
/bookings/{token} | GET | Fetch a booking by its manage token |
/bookings/{token}/cancel | POST | Cancel a booking |
/bookings/{token}/reschedule | POST | Reschedule a booking |
/bookings/{token}/ics | GET | Download the .ics for a booking |
These power the front-end widget. The manage routes are authenticated by the 256-bit token in the URL; creation is rate-limited and protected against spam.
Webhook payload
(Pro.) Each webhook delivery is an HTTP POST with a JSON body:
{
"event": "booking.created",
"created_at": "2026-07-13T09:00:00+00:00",
"data": {
"booking_id": 123,
"status": "confirmed",
"start_utc": "2026-07-20 14:00:00",
"end_utc": "2026-07-20 14:30:00",
"invitee_name": "Jane Cooper",
"invitee_email": "jane@example.com",
"invitee_timezone": "America/New_York",
"location": "https://zoom.us/j/…",
"source": "web",
"event_type": { "id": 5, "title": "Discovery Call", "slug": "discovery-call" },
"manage_url": "https://yoursite.com/schedule/manage/…/"
}
}
When a secret is configured, verify the X-Availo-Signature header — sha256=<HMAC-SHA256 of the raw request body, keyed with your secret>.
Capabilities
| Capability | Granted to | Controls |
|---|---|---|
availo_view_bookings | Admin, Host | Access to the bookings, calendar, add-booking screens |
availo_manage_availability | Admin, Host | Editing availability |
availo_manage_others_bookings | Admin only | Seeing/managing every host’s bookings |
edit_availo_events (+ related) | Admin, Host | Managing event types |
The Availo Host role (availo_host) bundles the host capabilities.
Data storage
- Event types are a custom post type (
availo_event); their settings are post meta. - Bookings, booking meta, schedules, schedule rules, and schedule overrides are custom database tables (prefixed
availo_), designed for fast date-range queries and safe concurrent booking.
Manage tokens are stored hashed; personal data lives only in the booking tables, giving a single place for the GDPR tools to operate.