Booking rules are how you express “who can book what, when, at what price.” Every resource has a default rule (any member, any time, the flat hourly rate); you layer additional rules on top for tier gating, blackouts, member-only periods, and surge pricing.
This guide is conceptual — we don't walk through a specific UI. The conceptis what generalises across the rule builder, the API, and the bulk importer. Once you understand the model, the surface you build it from doesn't matter.
All examples are demo content. Pricing in JSON snippets is in NZD for readability — your rules use whatever currency you set at workspace level.
Section 1
Per-tier rules, blackouts, member-only resources
The three shapes that cover ~90% of operator needs
Most operators only ever need three rule shapes. We've seen rule builders that ship with 20 — and operators only ever use these three. Build for the common case first.
1. Per-tier pricing
Charge members different rates depending on their tier. Free tier pays a guest rate, paid tier gets included hours, premium tier gets unlimited access. Always evaluated as an override on the resource's default rate.
2. Blackouts
Block bookings for a window. Examples: building closed for a public holiday, room reserved for staff training, weekly cleaning slot. Blackouts are hard: the room is simply not bookable. They take precedence over every other rule.
3. Member-only resources
Restrict a resource so it's only visible to active members. Guest bookings via the public URL never see member-only resources. Useful for premium spaces (recording studios, the “quiet” floor) that you want to reserve as part of the membership value.
Section 2
Rule builder walkthrough
Abstract concept · same shape across UI / API / bulk import
Whatever surface you build rules from, they all serialise to the same JSON shape under the hood. The shape is intentionally narrow — five top-level fields, no surprises.
The fields
scope. Which resources this rule applies to. Either a singleresource_id, an array of ids, or"*"for all-resources.actor. Who the rule targets. Tier id, member id, the string"guest", or"*"for everyone.time.When it's active. ISO 8601 ranges, recurring cron-like windows (“mon-fri 09:00-17:00”), or specific dates.effect. What happens.allow,deny,price,require_approval.priority. Integer 0–100. Higher wins. Defaults explained in the conflicts section.
See /v2/preview/app/settings for where you configure global workspace defaults that interact with per-resource rules.
Section 3
Four example rules
Copy-pasteable JSON · representative shapes
Four real-shape examples — change the ids and you can paste these into the bulk import endpoint as-is.
Example 1 — Premium tier gets 50% off the boardroom
{
"id": "rule_demo_premium_boardroom_50",
"scope": { "resource_id": "res_boardroom_demo" },
"actor": { "tier_id": "tier_premium" },
"time": "*",
"effect": {
"type": "price",
"amount_cents": 2250,
"currency": "NZD",
"per": "hour"
},
"priority": 50
}Example 2 — All resources closed for the Anzac Day public holiday
{
"id": "rule_demo_anzac_2026",
"scope": "*",
"actor": "*",
"time": {
"start": "2026-04-25T00:00:00+12:00",
"end": "2026-04-26T00:00:00+12:00"
},
"effect": { "type": "deny", "reason": "Anzac Day — building closed" },
"priority": 90
}Example 3 — Recording studio is members-only on weeknights
{
"id": "rule_demo_studio_member_only_weeknights",
"scope": { "resource_id": "res_studio_demo" },
"actor": "guest",
"time": "mon-fri 17:00-22:00 Pacific/Auckland",
"effect": { "type": "deny", "reason": "Members only after-hours" },
"priority": 60
}Example 4 — Free-tier members pay a guest-equivalent rate on weekends
{
"id": "rule_demo_free_tier_weekend_surcharge",
"scope": { "resource_id": "res_boardroom_demo" },
"actor": { "tier_id": "tier_free" },
"time": "sat,sun Pacific/Auckland",
"effect": {
"type": "price",
"amount_cents": 5500,
"currency": "NZD",
"per": "hour",
"label": "Weekend rate"
},
"priority": 40
}Section 4
Conflict resolution
Priority wins · then specificity · then most-recent
Two rules can apply to the same booking attempt. The resolver picks one. The order is deterministic — if the input doesn't change, the output doesn't either.
The resolution order
- Higher
prioritywins. Blackouts default to 90, member-only to 60, price overrides to 40. You can override. - Tie-break on specificity. A rule scoped to a single
resource_idbeats"*". A rule scoped to a single member beats one scoped to a tier. - Tie-break on recency. The most recently created rule wins. Surface which rule fired in the booking detail view so operators can see which one applied.
Worst-case behaviour
If two rules tie on all three criteria (priority + specificity + recency, which is impossible without manual id forging), the resolver picks the rule with the lexicographically earlier id. We surface a console warning when this happens.
Section 5
Overrides (front-desk + automatic surge)
Manual + automatic escape hatches · always audit-logged
Rules cover the steady-state. Overrides cover the exception. Two flavours: a manual override that staff can apply at the front desk, and an automatic override that responds to demand.
Front-desk override
Front-desk staff can override a deny or a blackout for the next 24 hours, with a reason. The override is logged and notifies the operator-owner via a digest email.
POST /v1/bookings/{booking_id}/override
{
"reason": "Vendor onsite for elevator maintenance — using boardroom as staging",
"valid_until": "2026-05-23T18:00:00Z",
"scope": "this_booking_only"
}Automatic surge
Workspace-wide, optional. When occupancy crosses 85%, surge pricing applies the next slot a guest tries to book. Surge is a percentage multiplier on the base rate (configurable, default 1.5x), capped at 2x. Surge never applies to existing members — only to new guest bookings.
settings_audit_log with the actor, timestamp, and reason. Reviewable from Settings → Audit log. Useful when a member complains about a rate that “wasn't there yesterday”. Next steps
Rules dialled in. What now?
- Stripe Connect
Once your rules generate a price, this is how the money flows.
- Webhooks
booking.created / booking.confirmed fire when rules approve a booking.
- API authentication
Scripting rules from the API requires a scoped key with rules:write.
- Quickstart
Start from zero — sign up, connect Stripe, take your first booking.