payload-reservepayload-reserve

Configuration

Full reference for all payloadReserve() plugin options.

Full reference for all payloadReserve() plugin options.

All options are optional — the plugin works with sensible defaults.

Full Config Example

import { payloadReserve } from 'payload-reserve'
import type { ReservationPluginConfig } from 'payload-reserve'

payloadReserve({
  // Disable the plugin entirely while keeping the config type-safe
  disabled: false,

  // Admin group label for all reservation collections
  adminGroup: 'Reservations',

  // Minutes of buffer between reservations when a service has none defined
  defaultBufferTime: 0,

  // Minimum hours of notice required before a cancellation is allowed
  cancellationNoticePeriod: 24,

  // Extend an existing auth collection instead of creating a standalone Customers collection.
  // The named collection must exist in your Payload config before the plugin runs.
  userCollection: 'users',

  // Override collection slugs
  slugs: {
    services: 'services',
    resources: 'resources',
    schedules: 'schedules',
    reservations: 'reservations',
    customers: 'customers',
    media: 'media',
  },

  // Override access control per collection
  access: {
    services: {
      read: () => true,
      create: ({ req }) => !!req.user,
      update: ({ req }) => !!req.user,
      delete: ({ req }) => !!req.user,
    },
    resources: { read: () => true },
    schedules: { read: () => true },
    reservations: { create: () => true },
    customers: { create: () => true },
  },

  // Configurable status machine
  statusMachine: {
    statuses: ['pending', 'confirmed', 'completed', 'cancelled', 'no-show'],
    defaultStatus: 'pending',
    terminalStatuses: ['completed', 'cancelled', 'no-show'],
    blockingStatuses: ['pending', 'confirmed'],
    transitions: {
      pending: ['confirmed', 'cancelled'],
      confirmed: ['completed', 'cancelled', 'no-show'],
      completed: [],
      cancelled: [],
      'no-show': [],
    },
  },

  // Plugin hook callbacks — see /hooks-api
  hooks: {
    afterBookingCreate: [
      async ({ doc, req }) => {
        // Send confirmation email, etc.
      },
    ],
  },

  // Extra fields appended to the Reservations collection
  extraReservationFields: [
    { name: 'paymentReminderSent', type: 'checkbox', defaultValue: false },
  ],

  // Allow bookings without a customer account (per-service override available)
  allowGuestBooking: false,

  // Customize the option list for Resource.resourceType (first entry is the field default).
  // Passing an empty array throws at init.
  resourceTypes: ['staff', 'equipment', 'room'],

  // Customize the option list for Schedule.exceptions[].type.
  // Passing an empty array throws at init.
  leaveTypes: ['vacation', 'sick', 'personal', 'closure', 'other'],

  // Resource-owner multi-tenancy (opt-in). Adds an owner relationship to Resources
  // (and optionally Services) so owners only see their own records.
  resourceOwnerMode: {
    // Roles that bypass ownership scoping and see all records.
    // Default: anyone whose req.user.collection is the admin collection.
    adminRoles: ['admin'],
    // Also add an owner field to Services (default: false — Services are platform-managed).
    ownedServices: false,
    // Field name for the owner relationship on Resources (default: 'owner').
    ownerField: 'owner',
    // Collection the owner field relates to. Defaults to staffProvisioning.userCollection
    // when set, otherwise slugs.customers. Set this when owners live in a different
    // collection than your customers.
    ownerCollection: 'users',
  },

  // Auto-provision a Resource for staff-role users (opt-in; REQUIRES resourceOwnerMode).
  // On user create/update, a paired Resource owned by that user is created (idempotent).
  staffProvisioning: {
    // Role value(s) that mark a user as staff. Required, must be non-empty.
    staffRoles: ['stylist', 'therapist'],
    // Auth collection holding staff users. Defaults to top-level userCollection.
    userCollection: 'users',
    // Field on the user holding the role (default: 'role').
    roleField: 'role',
    // resourceType stamped on the provisioned Resource (default: 'staff'; must be a valid resourceType).
    resourceType: 'staff',
    // User field copied into Resource.name (default: 'name', falls back to email).
    nameFrom: 'name',
    // Escape hatch to stamp tenant IDs / custom fields before the Resource is saved.
    beforeCreate: ({ data, req, user }) => data,
  },
})

staffProvisioning requires resourceOwnerMode. Configuring staffProvisioning without resourceOwnerMode throws at init. staffProvisioning.staffRoles must be a non-empty array, and staffProvisioning.userCollection is required when the top-level userCollection is unset. The provisioned Resource is created by impersonating the staff user (so owner is always that user), is idempotent (deduped by owner), is non-blocking (failures are logged, not thrown), and is never auto-deleted on demotion.

Defaults Table

OptionTypeDefaultDescription
disabledbooleanfalseDisable plugin functionality
adminGroupstring'Reservations'Admin panel group label
defaultBufferTimenumber0Default buffer between bookings (minutes)
cancellationNoticePeriodnumber24Minimum hours notice for cancellation
userCollectionstringundefinedExisting auth collection slug to extend
slugs.servicesstring'services'Services collection slug
slugs.resourcesstring'resources'Resources collection slug
slugs.schedulesstring'schedules'Schedules collection slug
slugs.reservationsstring'reservations'Reservations collection slug
slugs.customersstring'customers'Customers collection slug
slugs.mediastring'media'Media collection slug (used by image fields)
statusMachinePartial<StatusMachineConfig>Default 5-status machineCustom status machine (validated at init)
hooksReservationPluginHooks{}Plugin hook callbacks
extraReservationFieldsField[][]Extra Payload fields appended to the Reservations collection
allowGuestBookingbooleanfalseAllow bookings without a customer account (per-service override available)
resourceTypesstring[]['staff', 'equipment', 'room']Option list for Resource.resourceType; first entry is the field default. Empty array throws
leaveTypesstring[]['vacation', 'sick', 'personal', 'closure', 'other']Option list for Schedule.exceptions[].type. Empty array throws
resourceOwnerModeResourceOwnerModeConfigundefinedOpt-in resource-owner multi-tenancy (see sub-options below)
resourceOwnerMode.adminRolesstring[][]Roles that bypass ownership scoping; falls back to admin-collection check
resourceOwnerMode.ownedServicesbooleanfalseAlso add an owner field to Services
resourceOwnerMode.ownerFieldstring'owner'Owner relationship field name on Resources
resourceOwnerMode.ownerCollectionstringstaffProvisioning.userCollection ?? slugs.customersCollection the owner field relates to
staffProvisioningStaffProvisioningConfigundefinedOpt-in staff auto-provisioning; requires resourceOwnerMode
staffProvisioning.staffRolesstring[]— (required, non-empty)Role value(s) marking a user as staff
staffProvisioning.userCollectionstringtop-level userCollectionAuth collection holding staff users (required if top-level userCollection unset)
staffProvisioning.roleFieldstring'role'User field holding the role
staffProvisioning.resourceTypestring'staff'resourceType stamped on the Resource (must be a valid resourceType)
staffProvisioning.nameFromstring'name'User field copied into Resource.name (falls back to email)
staffProvisioning.beforeCreatefunctionundefinedStamp tenant/custom fields onto the Resource before create

Vocabularies: resourceTypes (default ['staff', 'equipment', 'room']) and leaveTypes (default ['vacation', 'sick', 'personal', 'closure', 'other']) customize the option lists for Resource.resourceType and Schedule.exceptions[].type. See Staff Scheduling.

Internationalization

The plugin's admin strings are translatable and ship in 12 languages. Translations are not a plugin option — they merge into Payload's own i18n config (your translations take precedence), so you override strings or add languages through buildConfig({ i18n }). See Internationalization.

Edit on GitHub

On this page