Zum Hauptinhalt springen
Was this helpful?

Pool Booking API

Pool Allocation Contracts

Configure interchangeable resource pools, submit requested quantities, and predict quote snapshots exactly

This page collects the pool-booking rules that are otherwise spread across the resource-type DTOs, reservation writes, public booking service, and pricing service.

bookingMode awarerequestedQuantity awareOrganisation public bookingServer-derived pricing

Core Field Semantics

FieldMeaningImportant rule
bookingModeHow the resource type may be booked.SINGLE_RESOURCE, POOL, or BOTH.
quantityCapacity requested within each assigned concrete resource.Pool allocation currently requires quantity = 1.
requestedQuantityNumber of concrete resources the allocator should assign.Defaults to 1 when omitted.
resourceCountNumber of resources actually assigned to the reservation.Used in pricing snapshots.
resourceIdsExplicit concrete resource selection.All ids must belong to one resource type.

bookingMode values

  • SINGLE_RESOURCE: rejects requestedQuantity > 1
  • POOL: allows abstract resource-type booking and automatic allocation
  • BOTH: allows either explicit resource ids or abstract pool allocation

Configure The Resource Type

Pool behavior starts at POST /api/resource-types and PATCH /api/resource-types/:id.

Relevant fields:

  • bookingMode
  • pricingEnabled
  • paymentRequired
  • priceAmount
  • priceCurrency
  • minBookingDuration
  • bufferTime

Example:

curl -X POST "$PRIMECAL_API/api/resource-types" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Archery lane",
"bookingMode": "POOL",
"minBookingDuration": 60,
"bufferTime": 15,
"pricingEnabled": true,
"paymentRequired": true,
"priceAmount": 1999,
"priceCurrency": "usd"
}'

Internal Reservation Payloads

Use POST /api/reservations with resourceTypeId plus requestedQuantity when the client wants automatic allocation.

Automatic pool allocation

{
"resourceTypeId": 3,
"requestedQuantity": 2,
"startTime": "2026-07-01T09:00:00.000Z",
"endTime": "2026-07-01T10:00:00.000Z",
"notes": "Need two adjacent lanes"
}

Behavior:

  • allocator loads active resources of that type in deterministic order
  • each candidate is inspected for reservation and blocking-calendar conflicts
  • the first requestedQuantity available resources are assigned

Explicit multi-resource selection

{
"resourceTypeId": 3,
"resourceIds": [5, 6],
"startTime": "2026-07-01T09:00:00.000Z",
"endTime": "2026-07-01T10:00:00.000Z"
}

Behavior:

  • requestedQuantity is derived from the number of explicit resourceIds when omitted
  • all selected resources must belong to the same resource type
  • quantity > 1 is rejected when more than one concrete resource is selected

Update limitation

PATCH /api/reservations/:id currently rejects changing requestedQuantity. Reallocation is not supported as part of the update flow yet.

Public Booking Payloads

Organisation booking catalogue

GET /api/public/booking/organisations/:slug

Resource types expose pool-relevant fields directly:

{
"resourceTypes": [
{
"id": 31,
"name": "Signature massage",
"bookingMode": "POOL",
"pricingEnabled": true,
"paymentRequired": true,
"paymentAvailable": true,
"priceAmount": 12500,
"priceCurrency": "eur"
}
]
}

Aggregated availability for pool booking

GET /api/public/booking/organisations/:slug/availability

Query:

  • date: required YYYY-MM-DD
  • resourceTypeId: required positive int
  • resourceId: optional for specific-resource mode
  • requestedQuantity: optional positive int

When no resourceId is provided, PrimeCal returns aggregated slots:

{
"mode": "any",
"resourceType": {
"id": 31,
"bookingMode": "POOL"
},
"resources": [
{ "id": 41, "name": "Room A", "capacity": 1 },
{ "id": 42, "name": "Room B", "capacity": 1 }
],
"slots": [
{
"startTime": "2026-07-01T09:00:00.000Z",
"endTime": "2026-07-01T10:30:00.000Z",
"available": true,
"availableQuantity": 2,
"resourceIds": [41, 42]
}
]
}

availableQuantity is the number of currently assignable resources for that slot, not an arbitrary client-side counter.

Organisation public reserve payload

POST /api/public/booking/organisations/:slug/reserve

{
"resourceTypeId": 3,
"requestedQuantity": 2,
"quantity": 1,
"startTime": "2026-07-01T09:00:00.000Z",
"endTime": "2026-07-01T10:00:00.000Z",
"customerName": "Ada Lovelace",
"customerEmail": "ada@example.com",
"customerPhone": "+3612345678"
}

Representative response:

{
"reservationId": 77,
"resourceTypeId": 3,
"requestedQuantity": 2,
"assignedResourceIds": [5, 6],
"assignedResources": [
{ "id": 5, "name": "Lane 1" },
{ "id": 6, "name": "Lane 2" }
],
"status": "pending_payment",
"paymentStatus": "pending",
"requiresPayment": true,
"quotedAmount": 3998,
"quotedCurrency": "usd"
}

Legacy token route limitation

POST /api/public/booking/:token/reserve stays single-resource only. requestedQuantity > 1 is rejected for token routes.

Pricing Mathematics

The pricing service currently computes the reservation snapshot as:

quotedUnitAmount = priceAmount
quotedTotalAmount = round_half_even(priceAmount * resourceCount * durationHours)
quotedCurrency = normalized lowercase Stripe currency

Important details:

  • resourceCount is the assigned resource count, which matches requestedQuantity for a successful pool allocation
  • durationHours is calculated from endTime - startTime using arbitrary precision decimal arithmetic

MCP Pool Tools

PrimeCal also exposes pool-booking operations through MCP for agent workflows.

check_pool_capacity

Accepted fields:

  • poolId or resourceTypeId
  • startTime
  • endTime
  • requestedQuantity or quantity
  • userTimezone

Representative response fields:

  • canAccommodate
  • availableResourceCount
  • availableQuantity
  • nextAvailableSlot

simulate_pool_pricing

Accepted fields:

  • poolId or resourceTypeId
  • requestedQuantity or quantity
  • startTime and endTime, or durationHours
  • userTimezone

Representative response fields:

  • quotedUnitAmount
  • quotedTotalAmount
  • quotedCurrency
  • totalPrice
  • requiredDeposit

When a dedicated deposit configuration is not present on the resource type, the tool returns a zero-value requiredDeposit in the quote currency.

  • when pricingEnabled is false, the quote is forced to 0 / 0 / null
  • paymentRequired mirrors the resource type and is snapshotted onto the reservation as paymentRequiredSnapshot

Example:

InputValue
priceAmount12500
resourceCount2
durationHours1.5

Result:

FieldValue
quotedUnitAmount12500
quotedTotalAmount37500
quotedCurrencyeur

Errors and Edge Cases

Pool capacity conflict

If PrimeCal cannot allocate enough free resources, the allocator throws a conflict payload like:

{
"errorCode": "POOL_CAPACITY_CONFLICT",
"message": "Concurrent capacity conflict.",
"availableResourceCount": 1,
"requestedQuantity": 2,
"partialAllocationBlocked": true
}

Other common validation failures

  • requestedQuantity < 1: 400
  • SINGLE_RESOURCE with requestedQuantity > 1: 400
  • selected resources from multiple resource types: 400
  • public token route with requestedQuantity > 1: 400
  • requestedQuantity greater than the pool size: 400

Screenshot And MCP Targets

Use these exact placeholder paths in docs automation and manual MCP evidence:

SurfaceFile
User guide admin statedocs/assets/user-guide/enterprise-reservation-system/admin-resource-type-booking-mode-pool.png
User guide public availabilitydocs/assets/user-guide/enterprise-reservation-system/customer-pool-booking-availability-grid.png
User guide public payment stepdocs/assets/user-guide/enterprise-reservation-system/customer-pool-booking-payment-step.png
MCP availability evidencedocs/assets/agents/enterprise-reservations/mcp-pool-availability-response.png
MCP create evidencedocs/assets/agents/enterprise-reservations/mcp-pool-booking-create-response.png