Skip to main content

Current Approach: Polling

Scheduling in ESUS stays in sync by polling the Slot search endpoint. Push notifications via Subscription are not active yet (see below); today the supported way to detect availability changes is to poll Slots periodically.

Remember that Slot search only supports schedule (exact Schedule UUID), status, start (exact day, no prefixes), and service-type. There is no date parameter, no _sort, and no schedule.actor chaining.

# Free slots for a schedule (resolve the practitioner's Schedule id first)
curl "https://api.esus.health/fhir/Slot?schedule=aa11bb22-cc33-dd44-ee55-ff6677889900&status=free&_count=10" \
  -H "Authorization: Bearer YOUR_TOKEN"

Free Slots for a Day

curl "https://api.esus.health/fhir/Slot?schedule=aa11bb22-cc33-dd44-ee55-ff6677889900&status=free&start=2026-04-21" \
  -H "Authorization: Bearer YOUR_TOKEN"

Since there is no _sort on Slot, order the results by start on the client side to find the nearest one.

Subscription (Push) — NOT active yet

You can register a Subscription resource (CRUD works), but notification delivery is not implemented: the dispatcher that would send the webhooks is not wired to any resource change, and the Slot module fires no notifications. Registering a Subscription today delivers nothing. Use polling.

# Create works, but no notifications will be delivered yet
curl -X POST https://api.esus.health/fhir/Subscription \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "status": "active",
    "reason": "Slot availability",
    "criteria": "Slot",
    "channel": {
      "type": "rest-hook",
      "endpoint": "https://your-app.example.com/webhooks/slots",
      "payload": "application/fhir+json"
    }
  }'

Notes on the intended behavior (for when it is activated), which differs from standard FHIR:

  • criteria is matched by resource type only (the part before the ?). The criteria’s query parameters are ignored — there is no search-based filtering. For example, "Slot?schedule=..." would match any Slot, not only those on that schedule.
  • The delivered payload would not be a FHIR Bundle of type: notification, but a custom JSON object: { subscriptionId, resourceType, resource, timestamp }.

Overbooking and Conflict Handling

There is no _conflictDetection parameter. Conflict handling in $book is purely status-based: the slot must be free. If the slot is not free (for example already busy), $book returns ValidationError with HTTP 400, not 409. No booking path returns 409.

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "error",
    "code": "invalid",
    "diagnostics": "Slot is not available (status: busy)"
  }]
}

The Slot.overbooked boolean exists as a descriptive field, but $book does not evaluate it: a booking is rejected whenever the slot is not free, regardless of overbooked. If your application wants to allow overbooking, that is your business logic’s responsibility (e.g. keep the slot free, or manage overlapping appointments outside of $book).