Skip to content
Browse docs

Actions, filters and integration surfaces

The stable hooks to build on, the theme-support flags, and the REST surfaces to know about.

The curated integration surface: the hooks that are stable and intended for third-party use. (The full internal hook list is larger; building on undocumented internals is at your own risk across updates.)

Domain actions

Fired by the plugin's services after the database transaction commits, so a listener can safely read the state the event describes, send external notifications, or sync a CRM without racing the write:

ActionFires after
dsb_order_bookings_confirmedan order's bookings confirm
dsb_order_faileda failed order releases its holds
dsb_order_bookings_endeda refund, cancellation or late failure cancels an order's bookings
dsb_booking_cancelledany booking cancellation (member or club path)
dsb_booking_refundedstaff record a refund
dsb_absence_reported / dsb_absence_reversedan expected absence is set or undone
dsb_credit_issued / dsb_credit_redeemed / dsb_credit_adjusted / dsb_credit_expiredthe corresponding credit ledger event
dsb_manual_booking_createda staff-built booking is saved
dsb_session_change_recordeda session change affecting booked members is flagged (note: when flagged, not when the notice is sent)
dsb_account_converted / dsb_conversion_requested / dsb_conversion_request_completed / dsb_conversion_request_declinedthe account-conversion lifecycle
dsb_member_registeredpublic registration succeeds

Filters

FilterAdjusts
dsb_manual_hold_minuteshow long pending manual bookings hold places (default 48 hours, floor 1 hour)
dsb_class_durationsthe durations offered on the timetable form (defaults to the setting)
dsb_register_profile_cardsthe protected-profile popup's cards: add cards or remap fields per site
dsb_wizard_takes_over_pagereturn false to render the first-login wizard inside the theme layout instead of full-window
dsb_bypass_front_page_templatereturn false if your theme handles the booking-page-as-front-page case itself
dsb_notice_channelroute a notice to inline, toast or popup presentation
dsb_root_align_classthe alignment class on the booking flow's root element (default 'alignwide', the block theme's wide width); return 'alignfull' for edge-to-edge or an empty string for a classic layout
dsb_booking_add_vetolets an extension refuse an add-to-basket with its own customer-facing message: return a WP_Error (default null allows). Runs on the single add path shared by the JS and no-JS flows, before the capacity hold, so a refused add never occupies a place
dsb_checkout_credit_allowedwhether account credit may be applied to the current cart at all (default true). Returning false zeroes the applied amount, stops auto-apply and hides the checkout credit box together
dsb_credit_issue_scopethe scope stamped on compensation credit (default '', ordinary club credit). Returning a payout recipient name makes the lot spendable only on that recipient's classes
dsb_checkout_credit_scopethe scope of the current basket (default ''). Checkout, auto-apply and redemption only ever see lots of the matching scope, and the scope is stamped on the order so later refunds restore credit into the right pot
dsb_credit_admin_scopesthe recipient pots staff may issue credit into on the admin Credit screen (default none, so no selector is shown)

The last four exist for site-specific payment-routing addons (classes whose payments go directly to a recipient, with credit kept honest per pot); without such an addon they never change anything. The club-owner view is in How booking credit works.

Theme support flags

Some branding settings only make sense when the theme renders the relevant chrome, so themes opt in rather than the plugin hard-coding theme names:

add_theme_support( 'dsb-header-background' );
add_theme_support( 'dsb-body-background' );
add_theme_support( 'dsb-login-panel-image' );
add_theme_support( 'dsb-student-profile' );

Each unlocks its Branding & vocabulary field and its helper (dsb_header_background_colour(), dsb_body_background_colour(), dsb_login_panel_image_url()); the last enables the My Account student-profile tab for themes that define the profile fields. Helpers return an empty string when the flag is absent. Any theme, fork or rebrand unlocks them the same way.

The public timetable feed (the one REST route meant for you)

GET /wp-json/dsbook/v1/timetable is the exception to the build-on-hooks-not-routes advice below: an unauthenticated, read-only route designed for external consumption, typically a club's separate marketing site rendering the current timetable. The club-owner view is Publishing your timetable on another website; the contract:

  • Opt-in and off by default, gated on the Public timetable feed setting (Tempo → Settings → Timetable). While off, the route stays registered and answers 403 with error code dsb_timetable_feed_disabled naming the setting, deliberately not a 404 that would read as a broken install. Unlicensed sites answer 402 like the rest of the namespace.
  • Optional term parameter; 0 (the default) resolves to the current term, or the next to start between terms.
  • The payload carries the resolved term's dates, half-term break and exclusions, the current-and-upcoming term list, and every active schedule for the term: day, time, class name, age group, location, and teacher display names. Entries closed to online booking are included with online_open: false, so your front end can badge invitation-only classes instead of hiding them.
  • Never in the payload: pricing, capacity or remaining places, staff notes, or any teacher data beyond display names. Nothing about students exists anywhere near this route.
  • Extra sessions (staff-created dated one-offs) are deliberately excluded; the feed's shape is weekly slots.
  • Responses send Cache-Control: public, max-age=300, so a plain fetch on the consuming site inherits five-minute caching; there's no need to hammer it per page view.

REST, for awareness

The plugin also runs authenticated REST routes for its own front ends: customer flow routes, register routes (capability-gated, with protected-profile fetches PIN-window-checked and audited), wizard routes, and the admin calendar's session feed (admin-only, capability-gated). Those exist to serve the plugin's own screens, and their contracts can evolve with it; build integrations on the domain actions and template functions above in preference to calling them directly. On locked (unlicensed) sites the namespace answers 402 across the board.

Two WooCommerce notes

  • Checkout Block only: classic woocommerce_checkout_* hooks don't fire; use woocommerce_store_api_* and read state from the order.
  • Booking metadata rides on order line items with hidden machine keys and visible Student / Package / Sessions rows, so order-based integrations (accounting exports, CRM sync) can read what a line was for without touching Tempo's tables.
Was this helpful?

Still stuck?

Most questions are answered in a minute here. When they aren't, a real person replies.

Tempo customers Send us the question through the support form. The person who built it reads every message. Contact support
Not a customer yet? Demos, pricing and anything pre-sales. Ask before you buy. Ask a pre-sales question