ITB - Online appointment booking service
1.0.0 - Initial Release

ITB - Online appointment booking service, published by Service Well AB. This guide is not an authorized publication; it is the continuous build for version 1.0.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/servicewell/servicewell.fhir.wof-portal/ and changes regularly. See the Directory of published versions

Getting Started - Using the WOF Portal ITB FHIR API

This guide is written for customers/partners who want to integrate with the WOF Portal ITB, which exposes a FHIR-based API.

Scope & user journey

This section describes an example booking journey for a consumer-facing application using the Public API. The exact user interface, data-loading strategy, and order of steps are determined by the implementer.

For example, some consumers may load clinics, treatments, and practitioners progressively as the patient makes selections, while others may preload this information using available API operations such as $get-offer-context. The API supports different implementation patterns.

1. Select clinic and/or treatment
The booking journey typically starts with the patient selecting a clinic, a treatment, or both. Clinics and treatments can be used as filters for each other, and the order in which they are presented is up to the implementer.

A consumer may, for example:

  • present clinics first and then filter available treatments,
  • present treatments first and then filter available clinics,
  • allow the patient to refine both selections gradually.

The patient should be able to view enough information to make a choice, such as clinic name and address, or treatment name, duration, and description.

2. Optional promo or campaign code
If the booking flow supports campaign or promo codes, the implementer may use such a code to filter, highlight, or preselect relevant clinics or treatments.

How the code is handled in the user interface is implementation-specific. For example, it may be:

  • entered manually by the patient,
  • provided through a campaign link,
  • applied automatically by the consumer system.

If an invalid code is used, the consumer should present an appropriate error message or fallback behavior.

3. Select practitioner
Before searching for available appointment slots, the consumer needs to have practitioner information available for the selected clinic and treatment combination. This information may already have been loaded earlier in the flow (for example through $get-offers-context), or it may be loaded at this stage.

In the current API version, practitioner selection is required when retrieving availability through $find. This means that if the consumer wants to show available slots across multiple practitioners, the consumer currently needs to query availability separately for each relevant practitioner.

4. Select date and time
Available dates and time slots are retrieved based on the selected clinic, treatment, and practitioner.

Because availability is currently fetched per practitioner, consumers who want to present a broader availability view across multiple practitioners need to collect the results from multiple practitioner-specific queries and present them in a suitable way.

For example, a consumer may:

  • show available time slots grouped by practitioner, allowing the patient to select from each practitioner's availability, or
  • combine the returned results into a list of unique time slots and then let the patient choose among the practitioners available at that time.

The exact presentation is implementation-specific.

5. Review and confirm booking
Before creating the booking, it is advisable to present the patient with a summary of the selected booking details, such as clinic, treatment, practitioner, and appointment time.

The exact confirmation flow is implementation-specific, but may include actions such as:

  • accepting terms and conditions,
  • choosing whether to receive a confirmation message, if supported,
  • identifying the patient using BankID or another supported authentication method.

6. Booking confirmation
After the booking is completed, a confirmation page is shown. If the patient selected SMS confirmation, a message is sent to the phone number registered with the clinic. From the confirmation page, the patient can continue to My bookings.

7. View and manage bookings
Viewing and managing bookings is a separate flow from the booking creation journey. A consumer may provide a view such as "My bookings", where the patient can see existing or upcoming appointments.

Depending on the implementation and the clinic's rules, the patient may also be allowed to reschedule or cancel an existing booking.

<size:24>Example</size>ExamplePatient booking journeyPatientITBAuthEHRPatientportalPatientPatientITBITBAuthAuthEHREHRPatientportalPatientportal1. Select clinic and/or treatment (implementation-defined order)alt[Clinic first]Select clinic filterGet matching treatmentsTreatments[Treatment first]Select treatment filterGet matching clinicsClinics[Progressive refinement]Refine clinic + treatment filtersRefresh filtered clinics/treatmentsUpdated filtered options2. Optional promo/campaign codealt[Manual code entry]Enter promo code[Campaign link / auto-applied code]Read code from URL/system contextApply/validate campaign codeFilter/highlight context OR invalid code3. Select practitionerGet practitioners for selected clinic+treatmentPractitioner listSelect practitioner4. Select date and timeloop[Per relevant practitioner]Find availability ($find)Proposed appointment timesalt[Grouped by practitioner]Show slots per practitioner[Aggregated time view]Show unique times with available practitionersSelect appointment time5. Review and confirm bookingShow summary (clinic, treatment, practitioner, time)Accept terms and continueopt[Patient identification]Authenticate (BankID or equivalent)Auth OK6. Booking confirmationCreate booking ($book)Booking savedBooking confirmation7. View and manage bookings (separate flow)Open "My bookings"Get existing/upcoming bookingsBookingsShow bookingsopt[Allowed by clinic rules + implementation]Request reschedule/cancelUpdate bookingBooking updatedUpdate result

Authentication and security

To use the Public API, the consumer must be provided with the relevant environment-specific connection and security details, such as:

  • FHIR Base URL for sandbox and production
  • API key for sandbox and production
  • any applicable network or security constraints, such as IP allowlisting (not currently needed)

For API key provisioning and related access information, contact Service Well support.

The API supports two authorization contexts:

  • system-authenticated access, where the consumer integration acts on its own behalf
  • patient-authenticated access, where the consumer acts on behalf of an authenticated patient

Accordingly, API endpoints are divided into two categories:

  • system-authenticated endpoints, which require system-level authorization
  • patient-authenticated endpoints, which require patient authentication and patient context

System tokens and patient tokens are separate access tokens issued through different authentication flows and representing different identities:

  • a system token represents the consumer integration
  • a patient token represents the authenticated patient

At the same time, endpoint access is governed by granted scopes. Depending on the scopes granted during patient authentication, a patient token may also authorize operations that are otherwise available with a system token. For this reason, some endpoints may be callable with either token, provided that the required scopes are present.

Even so, the recommended token choice remains scenario-dependent:

  • use a system token for integration-level access when no patient context is needed
  • use a patient token when acting on behalf of an authenticated patient

System tokens may also be preferable for non-interactive backend usage, for example because they typically have a longer lifetime than patient tokens.

Each endpoint must be called with an access token that provides the required scopes and, where applicable, patient context.

System authentication

System authentication is used for API operations where the consumer integration accesses the API on its own behalf.

To obtain a system token, call the system token endpoint using the assigned API key:

POST //1.0/R4/auth/system-token
X-ApiKey: <API_KEY>

If the request is successful, the API returns a system token. This token is then used when calling system-authenticated endpoints.

Example:

Authorization: Bearer <SYSTEM_ACCESS_TOKEN>

The system token represents the consumer integration and is intended for integration-level access where patient context is not required.

Patient authentication

Patient authentication is based on OpenID Connect (OIDC).

For endpoints that require patient authentication, the consumer must authenticate the patient through the configured OIDC flow and obtain a patient access token from the identity provider.

To support patient sign-in, the consumer must be configured with the required OIDC settings, including:

  • OIDC issuer URL
  • client_id
  • client_secret, where applicable for confidential clients
  • registered redirect_uri values, provided by the consumer and registered by Service Well
  • required scopes to request during authentication.

Available scopes:

  • patient/Patient.read
  • patient/Appointment.read
  • patient/Appointment.write
  • patient/$book.write
  • system/Organization.read
  • system/HealthcareService.read
  • system/PractitionerRole.read
  • system/ActivityDefinition.read
  • system/$find.read
  • system/$get-offers-context.read

Requied scopes:

  • openid
  • wof-profile
  • PortalAccess

The consumer must also understand how patient context is established after authentication. Depending on the implementation, this may be provided either:

  • directly in token claims, such as a patient identifier
  • through a dedicated endpoint, for example a patient-style endpoint

Although the same client configuration may support both system authentication and patient authentication, these flows produce different tokens for different authorization contexts.

Patient-authorized calls

When a patient signs in successfully through OIDC, the consumer receives a patient access token representing the authenticated patient.

This token is used when calling patient-authenticated API endpoints.

Example:

Authorization: Bearer <PATIENT_ACCESS_TOKEN>

The patient token authorizes access to patient-specific data and operations. Depending on the scopes granted during login, it may also authorize certain operations that are otherwise available using a system token.

Summary

In summary:

  • the API key is used to obtain a system token for the consumer integration
  • the system token represents the consumer integration and is typically used for system-authenticated endpoints
  • the patient token is obtained through OIDC login and represents the authenticated patient
  • endpoint access depends on the scopes granted to the presented token
  • a patient token can, if granted sufficient scopes, also be accepted for operations that do not require a system context

The recommended usage is therefore:

  • use a system token for integration-level access without patient context
  • use a patient token when acting on behalf of a signed-in patient

Portal defined interactions

OperationDefinition Description
Book / Modify / Cancel Appointment

Creates, modifies, or cancels an Appointment based on the supplied Appointment resource.

This operation corresponds to the IHE ITI Scheduling $book operation and:

  • CREATES a new Appointment when a new, schedulable Appointment is supplied
  • MODIFIES an existing Appointment when an updated Appointment is supplied
  • CANCELS an existing Appointment when a cancellation Appointment is supplied

On success, the operation returns the finalized Appointment in an IHE Scheduled Availability Bundle.

Find Appointments (Available Slots)

Finds available appointment opportunities (slots) and returns them as proposed Appointments.

This operation corresponds to the IHE ITI Scheduling $find operation and returns a Bundle of Appointment resources conforming to the IHE Scheduled Availability Bundle profile.

$getOffersContext — Booking Content Context

$get-offers-context is a read-oriented FHIR operation designed to let a frontend quickly populate booking content so a patient can choose what to book and with whom/where — without needing multiple round-trips.
It may include ActivityDefinitionPortal, HealthcareServicePortal, PractitionerRolePortal and OfferPortal.
It MUST NOT include Schedule, Slot, or bookable time slots.

This operation returns a profiled Bundle that may include:

  • ActivityDefinitionPortal (what is being offered)
  • HealthcareServicePortal (where / which clinic service offers it)
  • PractitionerRolePortal (who can perform it)
  • Offer resources (a lightweight “relation + settings” object)

The response is intentionally shaped for fast content rendering, not for scheduling.

Simple (unordered)flow explanation:

  • Get booking context ($getOffersContext)
    Consumer client loads the booking context needed to drive the bookingflow. The request can be altered to include services, where it can be booked, by which practitioner and the relationship between them.

  • Find available times ($find)
    The consumer client request available appointments whithin the specified search criterias and time frame options in a given time range and receives proposed appointments. In the current API version, availability is retrieved per practitioner, so practitioner information must be available before calling $find. This is aligned with the IHE "Find Potential Appointments" interaction.

  • Book an appointment ($book create)
    After the patient selects a proposed time (appointment), the consumer application submits a $book request to create the booking. In this implementation, the request must always contain the full Appointment resource representing the appointment to be booked.

  • Modify an appointment ($book modify)
    The same $book operation is also used to modify an existing appointment. In this case, the consumer application submits the full Appointment resource for the existing booking, updated with the intended changes, such as a new time or practitioner. On success, the API returns the updated appointment. This matches the IHE model where $book can be triggered to modify an already booked appointment.

  • Cancel an appointment ($book cancel)
    If the patient cancels an appointment, the same $book operation is also used to cancel an existing appointment. To cancel a booking, the consumer application submits the full Appointment resource for the existing booking with the appropriate cancellation status set. On success, the API returns the cancelled appointment. In IHE Scheduling, cancellation is one of the defined trigger cases for $book, rather than a separate operation.

  • Error handling
    If something fails in $find or $book and a request cannot be fullfilled, the API returns an OperationOutcome with error details.

NOTE* For $book, a successful response returns a Bundle containing a single Appointment resource and may also include an OperationOutcome with supplemental information. An unsuccessful $book response returns only an OperationOutcome in the response Bundle.


ITB Conformance resources

This section describes the contract model behind the API and how to use it when building an online booking website.

Recommended way to read and use them:

  1. Start with CapabilityStatement to understand what is supported in this environment (interactions, search capabilities, and published operations).
  2. Continue with OperationDefinitions to implement operation workflows correctly, including request parameters, response shape, and error outcomes.
  3. Use profile and extension artifacts as your payload rulebook for request/response validation and UI mapping.
  4. Use logical models as semantic guidance when mapping business concepts in your frontend/backend.
  5. Use NamingSystem to handle identifiers correctly (system|value) in search, filtering, and matching.
  6. Use examples as implementation guidance and test fixtures, not as the source of truth.

How to interpret priority:

  • Treat CapabilityStatement + OperationDefinition as runtime truth.
  • Treat StructureDefinition as data truth.
  • Treat examples as guidance.

You'll find the complete list of resources and can read more in the Artifacts section