Open Booking API 1.0

Draft Community Group Report

Latest editor's draft:
https://openactive.io/open-booking-api/EditorsDraft/
Editors:
Leigh Dodds (Open Data Institute)
Nick Evans (Open Data Institute)
Chris Thorpe
Repo:
We are on Github
Issues:
Report an issue
Version:

Abstract

This document specifies an HTTP API for placing bookings to participate in physical activities, either by attending events or through the use of leisure or sports facilities.

Status of This Document

This specification was published by the OpenActive Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

Contributions to this document are not only welcomed but are actively solicited and should be made via GitHub Issues and pull requests. The source code is available on GitHub.

Note

This document represents an early Editors Draft of the planned API design. It is likely to change between now and its final version. These early drafts are intended to help developers provide that feedback by developing proof-of-concept implementations. We encourage developers to explore this API and contribute to the development of the specification.

If you wish to make comments regarding this document, please send them to [email protected] (subscribe, archives).

1. Introduction

This section is non-normative.

The document is an output of the OpenActive Community Group. As part of the OpenActive initiative, the community group is developing standards that will promote the publication and use of open opportunity data in helping people to become more physically active.

The Community Group have already published specifications that define standard data models ([Modelling-Opportunity-Data]) and support the publication and harvesting of data in standard formats ([RPDE]).

This existing work helps increase the discovery of opportunities for people to be active. This specification builds on that work by defining an HTTP API that can be implemented by booking systems that are publishing opportunity data. By allowing third-party applications to place bookings in their systems, it becomes possible for more people to participate in events or make use of leisure and sporting facilities.

The specification defines the flow of HTTP requests and responses between the booking system (server) and the third-party application (client). This includes definitions of the overall application flow, detailed request and response formats and the potential error conditions that applications may encounter.

1.1 Scope and requirements

The current scope of the specification should conform to a set of use cases and requirements that have previously been identified and discussed with the OpenActive community.

The focus of the initial versions of this specification will be on the simplest use cases that will support making bookings on behalf of users. This core functionality includes:

A number of additional requirements that relate to the booking of events and facilities are currently out of scope:

It is possible that future versions of this specification may include support for these or other features. Revisions will be driven by the needs of the community.

1.1.1 Functionality that is out of scope

By design this specification will not define some types of functionality.

These have been declared as permanently out of scope because they are either adequately covered by existing specifications, or will be covered by future work of the OpenActive Community Group.

The functionality that is currrently defined as out of scope includes:

  • API authentication and security – while the specification recommends some best practices relating to authentication and security it does not mandate a specific means of securing an API. Implementers are free to choose the system that offers the best security for their platform and users
  • Payment processing – the design assumes that all payment handling will be carried out by the third-party application, in a separate payment flow. Booking systems and application developers are able to use the payment and reconciliation mechanisms that provide the best options for their customers
  • API business models – the design is agnostic to any business models that might govern the use of the API, e.g. revenue-sharing or transaction processing fees
  • Discovery – finding, filtering and searching for opportunity data. This specification assumes that the client and server applications have already shared data about the relevant opportunities. Additional functionality in this area will be addressed by future specifications from the Community Group

1.2 Audience

The document is primarily intended for the following audiences:

The following sections introduce terminology, concepts and requirements that underpin the design of the API. This content might also be useful for a wider audience, e.g. business analysts or product managers looking for a high-level overview of the API functionality.

2. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHOULD, and SHOULD NOT are to be interpreted as described in [RFC2119].

This specification makes use of the compact IRI Syntax; please refer to the Compact IRIs from [JSON-LD].

3. Typographical Conventions

The following typographic conventions are used in this specification:

markup
Markup (elements, attributes, properties), machine processable values (string, characters, media types), property name, or a file name is in a monospace font.
definition
A definition of a term, to be used elsewhere in this or other specifications, is in bold and italics.
hyperlink
A hyperlink is underlined and in blue.
[reference]
A document reference (normative or informative) is enclosed in square brackets and links to the references section.
Note

Notes are in light green boxes with a green left border and with a "Note" header in green. Notes are normative or informative depending on the whether they are in a normative or informative section, respectively.

Example 1
Examples are in light khaki boxes, with khaki left border, and with a
numbered "Example" header in khaki. Examples are always informative.
The content of the example is in monospace font and may be syntax colored.

4. Key Concepts

booking system
The platform or service that provides a server-side implementation of this API.
broker
The organisation or developer providing an application that allows customers to make bookings. Those applications will be clients of the API defined in this specification
confirmation
The process of contacting a customer following the placement of a successful order, e.g. to provide tickets, attendance details, etc. This specification does not define this process
customer
The user who places a booking using an application provided by a broker.
event
An Event is an opportunity to take part in a physical activity. Events take place at a specific location and at an agreed date and time.
facility
A sporting facility, e.g. a squash court, table tennis table or football pitch.
facilityuse
A FacilityUse is an generic opportunity to utilise the facilities of a seller in order to take part in a physical activity. FacilityUses are not scheduled, and their slots are an equivalent for an Event in being an opportunity which can be booked.
lease
A temporary reservation of a space at an event or for the use of a facility. Leases provide a limited time window during which a customer can place a booking and still be guaranteed a place at an event (or use of the facility).
offer
An Offer describes the terms under which a customer may participate in an event or use a facility.
opportunity
An opportunity is a generic term to describe an opportunity to be active. Currently an opportunity is either an Event (for scheduled events, such as a yoga class) or a Slot for a FacilityUse (for non-scheduled use of the facilities of a seller).
order
Describes the in-process or completed booking. An order may be made up of several order items. An order results in a customer having a confirmed reservation.
payment
The process of taking funds from a customer in order to place an order. Payment is managed between the customer and the broker.
reconciliation
The process by which brokers and booking systems confirm that payment(s) have been taken on behalf of customers, to ensure that money is appropriately exchanged between the brokers, booking systems and sellers. This specification does not define this process.
refund
The process of returning funds to a customer, e.g. if an order is cancelled. This specification does not define this process.
reservation
A reservation for a customer to attend an event or for the use of a facility. A reservation is created for every item in an order.
seller
The organisation providing access to events or use of facilities via a booking system. E.g. a leisure provider running yoga classes.
slot
A Slot is an opportunity to use a facility at a specific time and for a specified duration. A Slot is therefore a specific type of Event, although it has a more constrained set of properties.

5. Booking Flow

5.1 High-level summary of the API

This API defines a means for a booking system to expose an HTTP API that may be used by a broker to place bookings for opportunities on behalf of a customer. By exposing this API the booking system can support a seller in reaching a wider audience.

A broker provides customers with an application that helps them to discover opportunities to be physically active. The customer may then choose to make a booking to attend an event or to make use of a facility.

The broker will check the availability of the opportunity in order to check whether the customer can still attend. The broker will also present the customer with information about any costs associated with taking up the opportunity. This involves identifying the applicable offers and presenting them to the user. The customer should be made aware of any terms and conditions and any restrictions relating to age, gender or ability, as part of the process of proceeding to being in a position to make a booking.

If there is still availability and the customer is happy to accept an offer, then the customer can proceed to make a booking. The broker creates an order on behalf of the user.

Creating the order will also create a temporary lease that will reserve a space for the customer to take up the opportunity while the rest of the workflow completes.

If the offers for an event or use of a facility indicate that the user must pay, then the broker will take the customer through a separate payment workflow. This workflow is not defined by this specification.

Once payment has been completed, the broker will update the booking platform to indicate that payment has been taken. The booking process is then completed and the order is maked as completed.

The completion of the order will result in the lease being removed and a permanent reservation being created on behalf of the customer. The customer may receive confirmation from either the broker or booking system (or both) that provides details about how and when they can attend the event or use the booked facility.

Separately the broker and booking system will go through a reconciliation process to transfer funds or otherwise report on successful transactions. A customer might also cancel an order and will then receive a refund. The reconciliation processes is not defined by this specification. The details will depend on the business model and agreements in place between the broker and booking system. The cancellation workflow is defined in this specification in terms of the steps that the broker must undertake to provide the booking system with notification of the cancellation.

5.2 URLs used in the description of the API

The following sections contain URIs which are for guidance, and are used as examples only. For example, /events/452 is used to represent the canonical reference to the web representation of an Event with an id of 452. The URI could alternatively be /sessions/452 if session is the term used to describe the specific type of Event by a particular seller or booking system or by /slots/452 if dealing with a slot for use of a facility. All URIs should however be long lived identifiers and canonical and should not be recycled. Adherence to the workflows within this specification is required to develop a compliant booking system/broker implementation of this API and associated APIs such as RDPE in the Open Active ecosystem.

5.3 Workflow diagram

Flow diagram
Figure 1 Simple illustration of booking workflow

5.4 Sequence diagram

Sequence diagram
Figure 2 Sequence diagram showing API interactions

5.5 Step-by-step process description

The 1.0, and higher, versions of the Booking API supports single items per order and single payments per order. Future versions of the specification may support multiple items and multipart payments which are out of scope for the 1.0 release.

5.5.1 Complete transaction

  1. The broker requests details on a specific opportunity from the booking system (/events/452 in example) in order to discover available offers. These offers are subsequently presented to the customer.
  2. The customer chooses an bookable offer (see definition of a bookable event).
  3. If the offer for the opportunity is bookable, the broker makes a POST request to the orders endpoint (/orders in the examples) containing a Person object describing the customer, and information about the offer and opportunity selected. At a minimum, this Person object should contain the email address for the customer, and if possible the givenName and familyName. The booking system creates a timed lease on the space in the opportunity which is being booked. At this point the offer is deemed to be accepted and an order is created. The booking system sends a 201 status code, with a representation of the order in the body of the response, and with a Location header set containing the URI for the web representation of the created Order object.
  4. If there is a price for the offer, the broker takes payment from the customer via a third party payment provider.
  5. The broker notifies the seller of the payment by making a PATCH request to the specific order endpoint (/orders/123 in the example) of the booking system. This should include details of the paymentMethod and the paymentMethodId (commonly the last four digits of the card which can be used by the seller to identify the customer). The broker should store any details about the transaction which are needed for processing refunds or in the case of chargebacks. This is out of scope for the Booking API spec and is the responsibility of the broker.
  6. The booking system notifies the broker of a successful order completion by returning a response with a 200 status code and an object with an appropriate value for the confirmationCode field.

The broker is the entity initiating payment and as the merchant in the transaction is responsible for storing records of the payment transaction such as authorization codes. This is an implementation detail and is thus, out of scope for the Booking API and specification.

5.5.2 Cancelling a Lease

If the customer no longer wants to proceed with a particular offer, the lease for the space in the opportunity and the order may be cancelled by issuing a DELETE request to the specific order endpoint (/orders/123 in the example) of the booking system.

The booking system SHOULD release the space in the event and delete the underlying resource. Any subsequent requests to this resource should result in a 404 response.

5.5.3 Handling lease expiry

If the lease has expired during the payment process, the broker SHOULD check whether the opportunity is still bookable and if the selected offer is still available. If they are, the broker should create a new order using the workflow described above.

The booking system should respond to requests for orders with an expired lease with a 410 status code with an error specifying the errorType as https://openactive.io/errors/anonymous_lease_expired until the underlying order resource is removed.

5.6 Order cancellation and refunds

Since the broker is the party which initiates the third-party payment and is the entity which notifies the booking system of payment and creates the order on behalf of the customer, the broker is also the entity which handles refunds and cancellation. It should be noted that not all opportunities/offers are cancellable by the customer.

There are two distinct types of cancellation:

These two different types of cancellation have very different workflows which are outlined below.

5.6.1 Customer originated cancellation

The workflow to deal with the cancellation and refund of an order by the customer is described below. For clarity, it is assumed that the order being cancelled may be cancelled (see section around Cancellable offers/opportunities).

  1. The broker intiates a refund for the customer using the mechanisms provided by the third-party payment provider.

  2. The broker notifies the booking system of the cancellation by making a PATCH request to the specific order endpoint (/orders/123 in the example) of the booking system. The PATCH request body should contain an updated order item in the orderedItem property, with the orderItemStatus set to https://schema.org/OrderCancelled to indicate that the ordered item in the order is no longer required.

  3. The booking system responds to the broker with a representation of the order with the orderStatus property set to https://schema.org/OrderCancelled with a status of 200. The order is now deemed to be cancelled.

5.6.2 Booking system originated cancellation

The workflow to deal with the cancellation and refund of an order by the booking system is described below. Only the booking system can cancel orders relating to opportunities and offers which are not otherwise cancellable.

This is to be used in situations where the underlying opportunity/offer needs to be cancelled, thus necessitating the cancellation of a customer's order.

The mechanism for the booking system to notify the broker that an order is cancelled is through a webhook, where the booking system POSTs data relating to the orders which are cancelled to the broker. The booking system MUST only POST orders to a broker which have been initiated by that broker. No customer details should be transmitted in the POST to the webhook.

The process of registering webhooks by the broker with the booking system is out of scope for this specification. One possible addition in a later version of the Booking API specification is the extension of this mechanism to cover opportunities that are rescheduled.

  1. The POST sent by the booking system to the webhook receiver of the broker should contain an array of cancelled orders.

  2. The broker parses the array of cancelled orders and matches them to existing orders from customers.

  3. The broker refunds the customer and alerts them to the cancellation. It is good practice for the booking system to also notify the customer of the cancellation, where they can potentially provide more information about the rescheduling of the event.

  4. The broker then cancels the order as described in step 2 of the previous session by making a PATCH request to the CancelAction.

5.6.3 Definition of a 'cancellable' oppportunity/offer

In order to provide an excellent user experience for the customer, the booking system MUST provide information about its cancellation policy in its Terms and Conditions . To avoid disappointment by the customer, booking systems MUST also make it clear prior to entering the booking workflow, whether specific opportunities and offers are cancellable, and if required, what the cancellation window is. The broker must always display information relating to whether the opportunity/offer is cancellable and what the cancellation window is, before the user has created an order.

For an opportunity/offer to be cancellable it MUST:

  • contain an isCancellable boolean property set to 'true'

If the opportunity or offer contains a cancellationValidUntil datetime property, it MUST NOT have already been exceeded.

Different offers can potentially have different cancellation windows, or alternatively some offers may be cancellable, yet other offers on the same opportunity may not be cancellable. The data has been modelled to allow flexibility in business models for the booking system and the seller.

Cancellable opportunities/offers will result in orders which contain a CancelAction in their potentialAction property.

6. Common Requirements

This section defines some common functionality that applies to the design of the whole API.

6.1 Media types

Custom media types are used in this API to allow clients to choose the format of the data they receive.

Booking platforms MAY choose to support additional media types but MUST support the media type(s) defined by this specification.

Media types will conform to the following pattern:

application/vnd.openactive[.version]+json

The current media type is:

application/vnd.openactive.1.0+json

Brokers specifying a media type without a version, such as:

application/vnd.openactive+json

will recieve data in in the most current format which is 1.0.

If you are building an application as a broker and care about the stability of the response, or have a client application which is tied to a specific version you should always try to use a media type containing the version number.

Booking systems are not obliged to support previous versions of the specification, and so may not support a specific version number. We anticipate that when the Booking API reaches the stability of a 1.0 version that this advice may change.

6.2 Response formats

Requests and response documents exchanged via this API will all be valid [JSON-LD] documents.

The documents MUST include a [JSON-LD] context that refers to the [OpenActive-Vocabulary] as follows:

Example 2: minimal JSON-LD document
{
  "@context": "https://openactive.io/ns/oa.jsonld"
}

Unless otherwise specified the request and response documents MUST conform to the [Modelling-Opportunity-Data] data model.

6.3 URL discovery

The Booking API has been defined around the concept of URL discovery. This allows booking systems to create resource URLs which match their own terms for naming specific objects such as events and orders.

The URL for a specific action, such as for example providing payment details, may be discovered by parsing the actions defined in the potentialAction property of an object and constructing the appropriate URL from the urlTemplate property of the schema:EntryPoint object contained within the target property of the potentialAction required.

An example is below:

Example 3: Example of a potentialAction
"potentialAction": [
        {
          "type": "PayAction",
          "name": "Payment",
          "target": {
            "type": "EntryPoint",
            "urlTemplate": "https://example.com/orders",
            "encodingType": "application/vnd.openactive.v1.0+json",
            "httpMethod": "PATCH"
          }
        }
      ]

Since discovery of URLs is an implicit part of the specification, brokers SHOULD avoid hard-coding URLs for specific actions into their applications and client libraries. Brokers SHOULD use most applicable URL discovered at the point in the workflow they are currently in - e.g. not use a cached URL that has been previously successfully used. They should also not attempt to create URLs for a specific action based on patterns within previously used URLs.

It is the responsibility of booking platforms to advertise the URL for further activity in the booking workflow at the point of need. For example they MUST advertise the URL for order creation when a broker requests a specific opportunity resource and SHOULD advertise it in their RDPE feeds since both of these points within the booking workflow are places where a
customer may wish to check availability.

6.4 Error handling

Error responses MUST be served using an appropriate HTTP 4XX status code or HTTP 5XX status code.

All error responses from this API MUST be returned in a JSON-LD format using a content type of application/vnd.openactive.v1.0+json and include at least one Error object. The error handling has in the Booking API has been modelled closely on [RFC7807].

Example 4: Error response format
{
  "@context": "https://openactive.io/ns/oa.jsonld",
  "type": "Error",
  "errorType": "https://openactive.io/errors/incomplete_customer_details",
  "title": "Incomplete customer details",
  "details": "No customer details supplied",
  "status": 400,
  "instance": "/orders",
  "method": "POST"
}

6.4.1 Order creation : Incomplete customer details

Use cases:

  • if the email address of the customer is not supplied within a schema:Person object.

  • if the customer property supplied is not a valid schema:Person object.

errorType URI:

Status code: 400

6.4.2 Order creation : Incomplete broker details

Use cases:

  • if there is insuffficient detail in the schema:Organisation object describing the broker

  • if the broker property supplied is not a valid schema:Organisation object.

errorType URI:

Status code: 400

6.4.3 Order creation : Incomplete offer details

Use cases:

  • if there is no acceptedOffer property on the schema:OrderItem

  • if the acceptedOffer is not a URL which corresponds to an offer on the booking system

errorType URI:

Status code: 400

6.4.4 Order creation : Incomplete opportunity details

Use cases:

  • if there is no orderedItem property on the schema:OrderItem

  • if the orderedItem is not a URL which corresponds to an opportunity on the booking system

errorType URIs:

Status code: 400

6.4.5 Order creation : Unavailable offer

Use cases:

  • if the offer contained in the acceptedOffer property is not bookable

errorType URI:

Status code: 400

6.4.6 Order creation : Unavailable opportunity

Use cases:

  • if the opportunity contained in the orderedItem property is not bookable

errorType URIs:

Status code: 400

6.4.7 Order creation : Opportunity full

Use cases:

  • if there are no available spaces for the opportunity contained in the orderedItem property

errorType URIs:

Status code: 400

6.4.8 Order completion : Incomplete payment details

Use cases:

  • if the paymentMethod or paymentMethodId properties are missing or incorrect

errorType URI:

Status code: 400

6.4.9 Order completion : Anonymous lease expired

Use cases:

  • if broker did not supply payment details between the creation of the order and the expiration of the lease.

errorType URI:

Status code: 410

6.4.10 API authentication : Unauthenticated

Use cases:

  • if broker did not supply any form of authentication

errorType URI:

Status code: 403

6.4.11 API authentication : No API token provided

Use cases:

  • if broker did not supply an API key

errorType URI:

Status code: 403

6.4.12 API authentication : Invalid API token provided

Use cases:

  • if broker supplied an invalid API key, either malformed or expired

errorType URI:

Status code: 401

6.4.13 API authentication : Invalid authorization details provided

Use cases:

  • if broker supplied an invalid set of authorization details, either malformed or expired

errorType URI:

Status code: 401

6.4.14 Technical errors : Temporarily unable to create order

Use cases:

  • if booking platform is unable for technical reasons to create an order where the data provided to it is sufficient to allow it to do so

errorType URI:

Status code: 500

6.4.15 Technical errors : Temporarily unable to create order

Use cases:

  • if booking platform is unable for technical reasons to update an order where the data provided to it is sufficient to allow it to do so

errorType URI:

Status code: 500

6.4.16 Technical errors : Temporarily unable to delete order

Use cases:

  • if booking platform is unable for technical reasons to delete an order where the data provided to it is sufficient to allow it to do so

errorType URI:

Status code: 500

6.4.17 Generic errors : Unknown or incorrect offer

Use cases:

  • where a booking platform has no offer matching the one requested

errorType URI:

Status code: 404

6.4.18 Generic errors : Unknown or incorrect opportunity

Use cases:

  • where a booking platform has no opportunity matching the one requested

errorType URI:

Status code: 404

6.4.19 Generic errors : Unknown or incorrect order

Use cases:

  • where a booking platform has no order matching the one requested

errorType URI:

Status code: 404

6.4.20 Generic errors : Unknown or incorrect endpoint

Use cases:

  • where a booking platform has no endpoint matching the one requested

errorType URI:

Status code: 404

6.4.21 Generic errors : Not found

Use cases:

  • where a booking platform does not have the generic resource specified

errorType URI:

Status code: 404

6.4.22 Generic errors : Method not allowed

Use cases:

  • where a booking platform does not a speficic HTTP method for the endpoint requested with that specific HTTP verb

errorType URI:

Status code: 405

6.4.23 Generic errors : Gone

Use cases:

  • where an order has been cancelled and the underlying resources are marked for deletion

errorType URI:

Status code: 410

6.5 Security

All HTTP requests and responses SHOULD be secured using SSL.

6.6 Authentication

6.6.1 API level authentication

All of the API transactions described in this document SHOULD require authentication.

This standard does not mandate a particular authentication method, but recommendation is that implementers SHOULD consider using [OAuth2] as it is well-defined, widely supported and can be used in a variety of different application flows (e.g. via a Javascript web application or between servers).

Other server to server authentication mechanisms such as basic authentication, API key or bearer tokern based mechanisms are also appropriate.

One principle relating to authentication and the Booking API is that orders created by a specific broker SHOULD NOT be able to be changed by any other broker. It is the responsibility of the booking system to ensure that subsequent requests to an order should only be initiated by the broker which created the order.

6.6.2 Customer level authentication

Where necessary, OpenID Connect ([OpenIdConnect]) provides a standard way of verifying the identity of customer. It is a thin layer that sits atop OAuth2.

One principle relating to authentication and the Booking API is that orders created by a specific customer SHOULD NOT be able to be changed by any other customer. It is the responsibility of the booking system to ensure that subsequent requests to an order should only be initiated by the customer which created the order.

6.7 Delivery of Terms and Conditions and Privacy Policy

The broker should make the customer aware of and assent to any specific Terms and Conditions and Privacy Policy for using their service at the point of a customer signing up to the service and/or providing their contact details.

Since, during booking, the details of the customer are provided to the booking system and the seller, the broker should inform the customer of this any implications with resepct to GDPR and any other data protection legislation.

Specific Terms and Conditions/Privacy Policy for the booking service/seller and/or the opportynity/offer being taken MUST be made available using the privacyPolicy and termsAndConditions properties described in the example at the most appropriate level. If the properties are present at the opportunity level, they apply to all included opportunities and offers unless the properties are present at a lower level.

Example 5: Properties for Terms and Conditions and Privacy Policy
"privacyPolicy": {
      "type": "Terms",
      "url": "https://example.com/privacy-policy",
      "name": "Privacy Policy"
  },
  "termsAndConditions": {
      "type": "Terms",
      "url": "https://example.com/terms-and-conditions",
      "name": "Terms and Conditions"
  }

The URLs in the example are only illustrative.

7. Operations

7.1 Checking availability and offers

This specification assumes that a broker has already obtained opportunity data from a booking system that includes descriptions of events, facilities, slots etc. For example by harvesting data via an [RPDE] feed.

The availability of an event, or subEvent, or facility (either as a FacilityUse or Slot) may change at any time.

The offers available to a customer might also change over time and the data should be refreshed so that the most up-to-date representation of the live data is presented to the purchaser before booking.

A booking system MUST allow a broker to check the current state of events and/or facilities depending on what decide they expose from their platform.

7.1.1 Definition of a 'bookable' Event

An event is deemed to be 'bookable' if:

  • The event has not already occurred, i.e. the startDate (when expressed as a timedatestamp) and the endDate of the event has not been exceeded

  • The eventStatus of the event does not indicate that it has been cancelled or postponed

  • The remainingAttendeeCapacity of the event is greater than the number of places required

  • The potentialAction of the event contains one or more appropriate ReserveAction objects

  • There are one or more valid bookable offers for the event

  • The temporary lease on the space in the event (defined in orderLeaseDuration) has not expired before the payment is taken by the broker and the seller is notified by the broker that payment has taken place.

The customer may be ineligible to attend a 'bookable' event, but may book a space for someone else (e.g. a child) if:

  • The gender of the customer taking up the opportunity is incompatible with the genderRestriction of the event but the attendee is compatible

  • The age of the customer taking up the opportunity is incompatible with the ageRange of the event but the attendee is compatible

The event may also be deemed to be bookable if the event contains a deep link to a URL where the user can book the event independently, however this is out of scope for this API

The above set of restrictions are at the level of the event and the data contained within the content of the API returns.

On a booking system level, an event is 'bookable', mediated by a specific broker, if that broker has machine readable permission to access the relevant instance of the Booking API provided by the booking system via an API key or similar token.

For the purposes of this specification, the event is only bookable if the data describing the the event is published via a booking system which is compliant with and supports the Open Active Booking API.

7.1.2 Definition of a 'bookable' slot/facility use

A slot is essentially an event, and many of the above conditions apply, however some of the properties for a slot are different and as a consequence there are different criteria for it being bookable.

A slot is deemed to be 'bookable' if:

  • The slot has not already occurred, i.e. the startDate (when expressed as a timedatestamp) and endDate of the slot has not been exceeded

  • The remainingUses of the slot is greater than or equal to the number of slots required. For example if an independently organised badminton league requires four courts, the number of remainingUses should be 4 or higher.

  • There are one or more valid offers for the slot

  • The potentialAction of the slot contains one or more appropriate ReserveAction objects

There may be more restrictions placed by a seller on the booking of a slot for use of a facility. For example, it may be that one of the party must be over a certain age as a supervising adult if some of the party are minors. It is the responsibility of the booking platform to make the terms and conditions of booking available to the broker and it is the responsibility of the broker to ensure that the customer is aware of these conditions before entering the order workflow.

7.1.3 Checking availability and offers for an event or facility use slot

To check the availability of an opportunity a broker will issue a GET request to the URI specified in the id of the opportunity, having discovered it from the RDPE feed.

It is the responsibility of brokers to ensure that spaces within the opportunity are still available before proceeding with booking.

Example 6: Viewing event availability
GET /events/452 HTTP/1.1
Host: example.com
Date: Mon, 8 Oct 2018 20:50:35 GMT
Accept: application/vnd.openactive.v1.0+json
Example 7: Event response
HTTP/1.1 200 OK
Date: Mon, 8 Oct 2018 20:50:36 GMT
Content-Type: application/vnd.openactive.v1.0+json
Content-Length: ...


{
    "@context": "https://openactive.io/ns/oa.jsonld",
    "type": "Event",
    "identifier": 452,
    "id": "https://example.com/events/452",
    "name": "Speedball",
    "offers": [{
        "type": "Offer",
        "validThrough": "2018-10-29T11:00:00Z",
        "validFrom": "2018-10-01T11:00:00Z",
        "description": "Winger space for Speedball.",
        "id": "https://example.com/offers/1234",
        "name": "Speedball winger position",
        "price": 10.00,
        "priceCurrency": "GBP",
        "isCancellable": true,
        "cancellationValidUntil": "2018-10-28T11:00:00Z"
    }],
    "eventStatus": "https://schema.org/EventScheduled",
    "maximumAttendeeCapacity": 30,
    "remainingAttendeeCapacity": 20,
    "startDate": "2018-10-30T11:00:00Z",
    "endDate": "2018-10-30T12:00:00Z",
    "duration": "PT1H",
    "location": {},
    "potentialAction": [{
        "type": "ReserveAction",
        "name": "Book",
        "target": {
            "type": "EntryPoint",
            "urlTemplate": "https://example.com/orders",
            "encodingType": "application/vnd.openactive.v1.0+json",
            "httpMethod": "POST"
        }
    }],
    "privacyPolicy": {
        "type": "Terms",
        "url": "https://example.com/privacy-policy",
        "name": "Privacy Policy"
    },
    "termsAndConditions": {
        "type": "Terms",
        "url": "https://example.com/terms-and-conditions",
        "name": "Terms and Conditions"
    }
}

The booking system MUST ensure that the data presented to the broker in the remainingAttendeeCapacity property of the event is up to date and includes a combination of places already booked and places currently reserved by leases from in-progress orders.

Example 8: Viewing slot availability
GET /slots/324 HTTP/1.1
Host: example.com
Date: Mon, 8 Oct 2018 20:51:35 GMT
Accept: application/vnd.openactive.v1.0+json
Example 9: Slot response
HTTP/1.1 200 OK
Date: Mon, 8 Oct 2018 20:51:36 GMT
Content-Type: application/vnd.openactive.v1.0+json
Content-Length: ...


{
    "@context": "https://openactive.io/ns/oa.jsonld",
    "type": "Slot",
    "id": "http://www.example.org/slots/324",
    "identifier": 324,
    "facilityUse": "http://www.example.org/facility-use/1",
    "startDate": "2018-10-01T11:00:00Z",
    "duration": "PT30M",
    "remainingUses": 3,
    "maximumUses": 4,
    "offers": [{
        "type": "Offer",
        "name": "30 minute hire",
        "price": 15.00,
        "priceCurrency": "GBP"
    }],
  "potentialAction": [{
    "type": "ReserveAction",
    "name": "Book",
    "target": {
      "type": "EntryPoint",
      "urlTemplate": "https://example.com/orders",
      "encodingType": "application/vnd.openactive.v1.0+json",
      "httpMethod": "POST"
    }
  }]
}

The booking system MUST ensure that the data presented to the broker in the remainingUses property of the slot is up to date and includes a combination of places already booked and places currently reserved by leases from in-progress orders.

Example 10: Viewing slot availability via a facility use
GET /facility-use/1 HTTP/1.1
Host: example.com
Date: Mon, 8 Oct 2018 20:51:35 GMT
Accept: application/vnd.openactive.v1.0+json
Example 11: Facility use response
HTTP/1.1 200 OK
Date: Mon, 8 Oct 2018 20:51:36 GMT
Content-Type: application/vnd.openactive.v1.0+json
Content-Length: ...

{
    "@context": "https://www.openactive.io/ns/oa.jsonld",
    "type": "FacilityUse",
    "url": "http://www.example.org/facility-use/1",
    "name": "Example Leisure Centre Table Tennis",
    "description": "Table tennis tables are available to hire for thirty minute slots",
    "activity": "Table Tennis",
    "location": {
        "type": "Place",
        "name": "Example Leisure Centre",
        "address": {
            "type": "PostalAddress",
            "streetAddress": "1 High Street",
            "addressLocality": "Bristol",
            "postalCode": "BS1 4SD"
        }
    },
    "offers": [{
        "type": "Offer",
        "name": "30 minute hire",
        "price": 10.00,
        "priceCurrency": "GBP"
    }],
  "potentialAction": [{
    "type": "ReserveAction",
    "name": "Book",
    "target": {
      "type": "EntryPoint",
      "urlTemplate": "https://example.com/orders",
      "encodingType": "application/vnd.openactive.v1.0+json",
      "httpMethod": "POST"
    }
  }],
    "event": [{
            "type": "Slot",
            "id": "http://www.example.org/slots/123",
            "facilityUse": "http://www.example.org/facility-use/1",
            "startDate": "2018-03-01T10:00:00Z",
            "duration": "PT30M",
            "remainingUses": 0,
            "maximumUses": 4
        },
        {
            "type": "Slot",
            "id": "http://www.example.org/slots/234",
            "facilityUse": "http://www.example.org/facility-use/1",
            "startDate": "2018-03-01T11:00:00Z",
            "duration": "PT30M",
            "remainingUses": 3,
            "maximumUses": 4,
            "offers": [{
                "name": "30 minute hire",
                "price": 15.00,
                "priceCurrency": "GBP"
            }]
        }
    ]
}

7.1.4 Assembling a set of offers and presenting them to a customer

The broker MUST assemble a set of all applicable offers for an opportunity from the information supplied by the booking system. An applicable offer is an offer which is available for an opportunity which is bookable and for which the customer is eligible.

7.1.4.1 Collating offers for an event

In the case of the event having no subEvent the set of all applicable offers is simply the array of offers contained within the offers property.

In the case of an event containing sub-events within the subEvent property the set of all applicable offers should be compiled from the offers from the sub-event selected by the customer, augmented with any additional different offers contained in the parent super-event.

If the sub-event selected by the customer has no offers the set of all applicable offers will be compiled from the offers contained withinin the super-event.

The broker should then filter this set to provide a set of current offers which apply to the customer. This specification provides no guidance as to how the filtering should be performed.

The broker SHOULD however show all applicable offers to a customer, including information on pricing restrictions, unless the customer has only requested a subset in some form of preferences (e.g. only show adult classes and offers).

The customer selects one of these offers and when all pre-conditions have been met, the broker enters the order creation workflow on behalf of the customer.

7.1.4.2 Collating offers for the use of a facility

The process for building a set of all applicable offers is similar for facilities with the offers which are part of a specific slot having primacy over the more generic offers contained within aFacilityUse.

The booking system MUST ensure that the data presented to the broker in the remainingUses property in the slot is up to date and includes a combination of places already booked and places currently reserved by leases from in-progress orders. The booking system MUST also ensure that the hoursAvailable property on the FacilityUse is kept updated.

7.1.5 Obtaining a lease on a space within an opportunity

Orders SHOULD contain a orderLeaseDuration property. This property MUST contain an ISO 8601 formatted duration for the lease. The lease duration may also be advertised somewhere else to make it clear in advance, e.g. in docs/setup config, or as part of a potentialAction property.

(Note: In previous iterations of the Booking API specification, the lease was a property of an event. This has now been deprecated.)

The orderLeaseDuration property notifies the broker about the length of time for which a space will be reserved by the booking system whilst payment for the event is taken by the third-party payment system.

The default suggested lease duration is 15 minutes, but it is up to each booking plaftorm to define and advertise their own lease duration.

This lease is NOT designed as a pause for a shopping cart system (in addition shopping cart functionality is out of scope for v1.0 of this specification).

The broker MUST ensure that it has obtained all of the relevant details about a customer before getting to the point where it attempts to place an order. The lease is not designed as a pause in the process whilst a customer is registered by a broker.

The client may then present the updated availability and suitable offers to the customer.

7.2 Creating and updating orders

Booking systems MUST expose an orders endpoint, e.g. /orders to allow brokers to initiate the booking workflow.

Orders initiated by a specific broker SHOULD only be able to be updated by the same broker. For the purpose of creating and updating an order the only reliable mechanism for ensuring that the broker is the same across requests is via authentication/identification by API keys or Authoriztion headers. The broker property within the order is for information only.

It is the responsibility of the booking system to ensure that only the broker which created the order can update, complete and cancel an order.

7.2.1 Discovering the order endpoint

Booking systems MUST expose an orders endpoint, e.g. /orders to allow brokers to initiate and enter the booking workflow.

To initiate the booking workflow, the booking system must include a potentialAction field within each bookable opportunity. The potentialAction field MUST contain one or more objects of type ReserveAction.

These ReserveAction objects must contain a target field containing an EntryPoint object.

The EntryPoint object MUST state the url of the orders endpoint, and SHOULD contain the encodingType and the httpMethod which must be POST as a new order object will be created on successful invocation.

If the offer relates to a slot within a FacilityUse, the closest potentialAction property matching the type ReserveAction should be used.

An example is below:

Example 12: Example of a ReserveAction
"potentialAction": [
  {
    "type": "ReserveAction",
    "name": "Book",
    "target": {
      "type": "EntryPoint",
      "urlTemplate": "https://example.com/orders",
      "encodingType": "application/vnd.openactive.v1.0+json",
      "httpMethod": "POST"
    }
  }
]

7.2.2 Pre-conditions for creating an order

Before creating an order the broker MUST:

  • have obtained customer information
  • have determined that the opportunity is bookable (see sections on the definition of bookable for events and slots/facility uses)
  • have identified the selected offer
  • have prompted customer that they will enter a payment flow (no pre-emptive leasing)
  • have indicates that the customer's personal information is being submitted to third-party (the booking system and the seller) and made the customer aware of and assent to any legitimate privacy policy and terms and conditions
  • have already obtained permission to use API

Before creating an order the broker SHOULD:

  • have registered the customer (or have the customer's details to hand)
  • have identified the customer's preferred payment options

7.2.3 Creating a new order (/orders)

A POST request to the /orders endpoint of the booking system will result in server creating an new Order. A time limited lease will be created for spaces in the event referenced in the Order.

The broker property in the request body is to help the booking platform to clarify who is making request and to help them in situations such as queries to allow reconciliation of payments. It is not designed as any part of an authentication which should be performed outside of the JSON body of the request. No authentication tokens should be present within the broker property of the submitted JSON.

The broker property should be a well formed schema:Organisation object.

In the situation where a middleware to be used to handle access control for various brokers, independently of API key provisioning at the booking system level (which in some systems is a lengthly and time-consuming process), the broker property should contain the details of the end-user broker rather than the middleware.

To acheive compliance with Apple Pay, Google Pay and Google Reserve, the customer's telephone number, an optional field, should be supplied.

Example 13: Creating an order - request
POST /orders HTTP/1.1
Host: example.com
Date: Mon, 8 Oct 2018 20:52:35 GMT
Accept: application/vnd.openactive.v1.0+json

{
    "@context": "https://openactive.io/ns/oa.jsonld",
    "type": "Order",
    "broker": {
        "type": "Organization",
        "name": "MyFitnessApp",
        "url": "https://myfitnessapp.example.com"
    },
    "customer": {
        "type": "Person",
        "email": "[email protected]",
        "telephone": "020 811 8055",
        "givenName": "Geoff",
        "familyName": "Capes"
    },
    "acceptedOffer": [{
        "type": "Offer",
        "validThrough": "2018-10-29T11:00:00Z",
        "validFrom": "2018-10-01T11:00:00Z",
        "description": "Winger space for Speedball.",
        "id": "https://example.com/offers/1234",
        "itemOffered": {
            "type": "Event",
            "id": "https://example.com/events/123"
        },
        "name": "Speedball winger position",
        "price": 10.00,
        "priceCurrency": "GBP",
        "isCancellable": true,
        "cancellationValidUntil": "2018-10-28T11:00:00Z"
    }],
    "orderedItem": [{
        "orderQuantity": "1",
        "orderedItem": {
            "type": "Event",
            "id": "https://example.com/events/123"
        }
    }]
}

If successful the server will response with the location of a newly created Order resource:

Example 14: Creating an order - response
HTTP/1.1 201 Created
Date: Mon, 8 Oct 2018 20:52:36 GMT
Content-Type: application/vnd.openactive.v1.0+json
Location: /orders/890


{
    "@context": "https://openactive.io/ns/oa.jsonld",
    "type": "Order",
    "id": "https://example.com/orders/890",
    "acceptedOffer": [{
        "type": "Offer",
        "validThrough": "2018-10-29T11:00:00Z",
        "validFrom": "2018-10-01T11:00:00Z",
        "description": "Winger space for Speedball.",
        "id": "https://example.com/offers/1234",
        "itemOffered": {
            "type": "Event",
            "id": "https://example.com/events/123"
        },
        "name": "Speedball winger position",
        "price": 10.00,
        "priceCurrency": "GBP",
        "isCancellable": true,
        "cancellationValidUntil": "2018-10-28T11:00:00Z"
    }],
    "broker": {
        "type": "Organization",
        "name": "MyFitnessApp",
        "url": "https://myfitnessapp.example.com"
    },
    "customer": {
        "type": "Person",
        "email": "[email protected]",
        "telephone": "020 811 8055",
        "givenName": "Geoff",
        "familyName": "Capes"
    },
    "orderDate": "2018-10-08T20:52:36Z",
    "orderedItem": [{
        "type": "OrderItem",
        "orderQuantity": 1,
        "orderItemStatus": "https://schema.org/OrderPaymentDue",
        "orderedItem": {
            "type": "Event",
            "id": "https://example.com/events/123"
        }
    }],
    "orderLeaseDuration": "PT15M",
    "orderStatus": "https://schema.org/OrderPaymentDue",
    "partOfInvoice": {
        "type": "Invoice",
        "paymentStatus": "PaymentDue",
        "totalPaymentDue": {
            "type": "MonetaryAmount",
            "value": 10.00,
            "currency": "GBP"
        }
    },
    "paymentDueDate": "2018-10-08T21:07:36Z",
    "potentialAction": [{
        "type": "PayAction",
        "name": "Pay",
        "target": {
            "type": "EntryPoint",
            "urlTemplate": "https://example.com/orders/{order_id}",
            "encodingType": "application/vnd.openactive.v1.0+json",
            "httpMethod": "PATCH"
        }
    }]
}

7.2.4 Viewing an order (/orders/{orderId})

To get the latest state of an order, perform a GET request on its URI.

Example 15: Viewing an order - request
GET /orders/890 HTTP/1.1
Host: example.com
Date: Mon, 8 Oct 2018 20:53:35 GMT
Accept: application/vnd.openactive.v1.0+json
Example 16: Viewing an order - response
HTTP/1.1 200 Created
Date: Mon, 8 Oct 2018 20:53:36 GMT
Content-Type: application/vnd.openactive.v1.0+json
Content-Length: ...

{
    "@context": "https://openactive.io/ns/oa.jsonld",
    "type": "Order",
    "id": "https://example.com/orders/890",
    "acceptedOffer": [{
        "type": "Offer",
        "validThrough": "2018-10-29T11:00:00Z",
        "validFrom": "2018-10-01T11:00:00Z",
        "description": "Winger space for Speedball.",
        "id": "https://example.com/offers/1234",
        "itemOffered": {
            "type": "Event",
            "id": "https://example.com/events/123"
        },
        "name": "Speedball winger position",
        "price": 10.00,
        "priceCurrency": "GBP",
        "isCancellable": true,
        "cancellationValidUntil": "2018-10-28T11:00:00Z"
    }],
    "broker": {
        "type": "Organization",
        "name": "MyFitnessApp",
        "url": "https://myfitnessapp.example.com"
    },
    "customer": {
        "type": "Person",
        "email": "[email protected]",
        "telephone": "020 811 8055",
        "givenName": "Geoff",
        "familyName": "Capes"
    },
    "orderDate": "2018-10-08T20:52:36Z",
    "orderedItem": [{
        "type": "OrderItem",
        "orderQuantity": 1,
        "orderItemStatus": "https://schema.org/OrderPaymentDue",
        "orderedItem": {
            "type": "Event",
            "id": "https://example.com/events/123"
        }
    }],
    "orderLeaseDuration": "PT15M",
    "orderStatus": "https://schema.org/OrderPaymentDue",
    "partOfInvoice": {
        "type": "Invoice",
        "paymentStatus": "PaymentDue",
        "totalPaymentDue": {
            "type": "MonetaryAmount",
            "value": 10.00,
            "currency": "GBP"
        }
    },
    "paymentDueDate": "2018-10-08T21:07:36Z",
    "potentialAction": [{
            "type": "PayAction",
            "name": "Pay",
            "target": {
                "type": "EntryPoint",
                "urlTemplate": "https://example.com/orders/{order_id}",
                "encodingType": "application/vnd.openactive.v1.0+json",
                "httpMethod": "PATCH"
            }
        }
    ]
}

Note: The paymentDueDate is set by the date and time of the order and the orderLeaseDuration.

7.2.5 Deleting an order (/orders/{orderId})

A DELETE request to an Order URI will delete the order. Deletion may only be used in the specific case for cancelling an order and the associated lease on a space in an event if the customer no longer wishes to take up the opportunity.

A DELETE request MUST NOT be used to cancel an existing completed order as part of a refund/cancellation workflow. An appropriate approach for that is defined elsewhere.

7.2.6 Completing an order (/orders/{orderId})

An order is completed by the broker submitting notification that the customer has made a payment via a third-party payment gateway.

An order is not considered complete until payment has occurred.

Brokers MUST update the booking system to indicate that payment has been taken.

Once the booking system is content with the payments, it then sets the orderStatus property of the Order to https://schema.org/OrderDelivered and returns a representation of the completed order with a 200 status code.

Example 17: Completing an order - request
PATCH /orders/123 HTTP/1.1
Host: example.com
Date: Mon, 8 Oct 2018 20:56:35 GMT
Accept: application/vnd.openactive.v1.0+json

{
    "type": "Order",
    "payments": [{
        "type": "Payment",
        "paymentMethod": "https://purl.org/goodrelations/v1#PaymentMethodCreditCard",
        "paymentMethodId": "3204",
        "totalPaidToProvider": {
            "type": "MonetaryAmount",
            "value": 10.00,
            "currency": "GBP"
        }
    }]
}
Example 18: Completing an order - response
HTTP/1.1 200 OK
Date: Mon, 8 Oct 2018 20:56:36 GMT
Content-Type: application/vnd.openactive.v1.0+json
Content-Length: ...


{
    "@context": "https://openactive.io/ns/oa.jsonld",
    "type": "Order",
    "id": "https://example.com/orders/890",
    "acceptedOffer": [{
        "type": "Offer",
        "validThrough": "2018-10-29T11:00:00Z",
        "validFrom": "2018-10-01T11:00:00Z",
        "description": "Winger space for Speedball.",
        "id": "https://example.com/offers/1234",
        "itemOffered": {
            "type": "Event",
            "id": "https://example.com/events/123"
        },
        "name": "Speedball winger position",
        "price": 10.00,
        "priceCurrency": "GBP",
        "isCancellable": true,
        "cancellationValidUntil": "2018-10-28T11:00:00Z"
    }],
    "broker": {
        "type": "Organization",
        "name": "MyFitnessApp",
        "url": "https://myfitnessapp.example.com"
    },
    "customer": {
        "type": "Person",
        "email": "[email protected]",
        "telephone": "020 811 8055",
        "givenName": "Geoff",
        "familyName": "Capes"
    },
    "orderDate": "2018-10-08T20:52:36Z",
    "orderedItem": [{
        "type": "OrderItem",
        "orderQuantity": 1,
        "orderItemStatus": "https://schema.org/OrderDelivered",
        "orderedItem": {
            "type": "Event",
            "id": "https://example.com/events/123"
        }
    }],
    "orderStatus": "https://schema.org/OrderDelivered",
    "partOfInvoice": {
        "type": "Invoice",
        "paymentStatus": "PaymentComplete",
        "totalPaymentDue": {
            "type": "MonetaryAmount",
            "value": 10.00,
            "currency": "GBP"
        }
    },
    "payments": [{
        "type": "Payment",
        "paymentMethod": "https://purl.org/goodrelations/v1#PaymentMethodCreditCard",
        "paymentMethodId": "3204",
        "totalPaidToProvider": {
            "type": "MonetaryAmount",
            "value": 10.00,
            "currency": "GBP"
        },
        "paymentDate": "2018-10-08T20:56:36Z"
    }],
    "potentialAction": [{
        "type": "CancelAction",
        "name": "Cancel",
        "target": {
            "type": "EntryPoint",
            "urlTemplate": "https://example.com/orders/{order_id}",
            "encodingType": "application/vnd.openactive.v1.0+json",
            "httpMethod": "PATCH"
        }
    }]
}

Note: If the record had been retrieved after the expiry of the cancellation window, the CancelAction would be omitted.

7.3 Ordering a place at a free event/ordering a free slot

Free opportunities MUST follow the same workflow as paid opportunities. A free event or slot is technically a free offer on a space for an opportunity. There MUST be at least one offer with a price property of 0.00. For free Offers publishers MAY leave out the priceCurrency. If a priceCurrency is not available then brokers SHOULD display a suitable default currency when displaying a zero price.

The order workflow MUST be followed as described for offers with a payment. The PATCH to the URL defined in PayAction should follow the example shown below.

Orders for a free place at an opportunity are the only current scenario in the Booking API specification where a Payment object has paymentMethod and paymentMethodId as optional properties.

Example 19: Completing an free order with a payment of 0.00 - request
PATCH /orders/123 HTTP/1.1
Host: example.com
Date: Mon, 8 Oct 2018 20:51:35 GMT
Accept: application/vnd.openactive.v1.0+json

{
  "type": "Order",
  "payments": [{
    "type": "Payment",
    "totalPaidToProvider": {
      "type": "MonetaryAmount",
      "value": 0.00,
      "currency": "GBP"
    }
  }]
}

7.4 Leases and the orderLeaseDuration property

If the lease expires during payment, the broker MAY delete the order (if the booking system has not already done so, returning a response with a 410 status code).

The broker should then create a new order for the customer in order to generate a new lease.

Before creating a new order, the broker MUST check the opportunity and offers to ensure that a space still exists within the opportunity and that the offer selected by the customer is still valid.

If no space exists or the offer is now invalid, the customer should be refunded if payment has been taken.

7.5 The state transitions during the order process

  1. An order object is created by a broker invoking the orders endpoint with a POST request containing details of the broker (represented as a schema:Organisation), customer (represented as a schema:Person) and details of the selected event and offer as components of a schema:OrderItem object. The booking system returns a representation of the order object to the broker in a response with a 201 status and the URL for the object in the Location header. The orderStatus of the order at this point in the flow should be https://schema.org/OrderPaymentDue
  2. Concurrently the booking system also creates a lease for a space in the event for the customer for the duration specified in the orderLeaseDuration property of the event.
  3. The broker directs the customer into the flow of the third-party payment provider.
  4. If the customer successfully completes the payment within the duration of the lease, the broker sends notification of the payment with a PATCH request to the specific order end point (/orders/123 in the examples) with details of the payment in the paymentMethod and paymentMethodId properties. At this point the order is deemed to be completed. The orderStatus property should be currently set to https://schema.org/OrderDelivered and the confirmationNumber property set to an appropriate unique value by the booking system. At this point in the flow, the order is deemed to be complete.

If the lease expires before the payment is made, the order should either be deleted by the broker or be deleted by the booking system at some point after expiry. The orderStatus property should be set to https://schema.org/OrderCancelled to indicate that the order cannot proceed to completion.

7.6 Actions which occur after order completion: confirmations and refunds

Both the broker and booking system may need to take further actions after completing an order. This section describes some potential interactions.

7.6.1 Supplying a confirmation to the customer

The broker SHOULD provide the customer with confirmation of a successful payment having been made through the third-party system and that the order has been completed successfully. The broker will have access to a completed order which will contain a confirmationCode property.

The booking system may also provide the customer with a confirmation that the space at the opportunity has been booked on their behalf.

7.6.2 Refunding a customer and cancelling an order

Refunds and cancellations are a responsibility of the broker who is the party in the system in a position to process a refund for the customer with the third-party payments system.

The broker should initiate a refund with the third-party payment provider. The refund process should be considered to be asynchronous for the purposes of this specification.

After initiating a refund, the broker should cancel the order by submitting a PATCH request to the URL defined in the CancelAction prescribed in the potentialAction property of the order response.

The process of cancellation is documented in Section 5.6

7.7 Customers

7.7.1 Creation of customers on the booking system

In this current iteration of the Booking API specification, the programmatic creation of customers on the booking system by the broker is considered to be out of scope.

7.7.2 Viewing a customer's previously placed orders

A server MUST provide endpoints to allow brokers to retrieve information about previously placed orders. In future versions of the specification, endpoints may be provided which permit a broker to see all orders created by a customer. In this current implementation, if the broker wishes to present a view of all orders for a customer, it should keep an internal record.

7.7.3 Deletion of personal data of the customer if the order is not completed

If an order is not completed, the booking system SHOULD delete all personal information of the customer provided to it as part of the order creation process.

8. Future versions of this API

Some of the patterns within version 1.0, for example the PATCHing of an order resource to provide a payment and using PATCH to change the status of an orderItem to cancel an order provide the groundwork for known requirements such as multiple order items (shopping carts), cancellation of individual order items and also multipart payments.

Both orderItems and payments are modelled as collections to support extension of the version 1.0 specification towards multipart orders and payments without breaking changes in the Order model for subsequent versions.

The new models for Payment and for Error enhance the Open Active model specification to make it more transactional when used as part of the Booking API.

The currently known requirements not satisfied in version 1.0 are:

We have not yet decided what the priorities are, or whether all of these requirements are in scope for version 1.0 and would encourage people to shape future iterations of the specification by becoming involved in the communities associated with Open Active and the open specification.

In a future version, it is imagined that an API method describing the service, and including such things as the links to Privacy Policy, Terms and Conditions and the target for a ReserveAction could be used to reduce data duplication.

At the moment there is no provision for a customer to cancel an order after the cancellation window, yet they may wish to do this out of politeness, even though no refund is possible, with the benefit that their place may be taken by another participant.

9. New Open Active models defined in the 1.0 Booking API specification

These models are not yet reflected in the current version (2.0) of the Open Active Modelling Specification.

9.1 Error

Property Status Notes
errorType REQUIRED A URI providing an enumeration value for the type of error.
title REQUIRED A human readable reason for the error.
detail RECOMMENDED A human readable description of the error.
instance REQUIRED The requested URL.
method RECOMMENDED The method of the request (e.g. GET).
status OPTIONAL An integer representing the HTTP status code.
invalid-params OPTIONAL An array of invalid parameters, if appropriate.
requestId OPTIONAL Used by technical support for diagnostics purposes.

9.2 Payment

Property Status Notes
paymentMethod REQUIRED A URI providing an enumeration value for the type of payment method used.
paymentMethodId REQUIRED A string identifier for the method of payment used (e.g. the last 4 digits of the credit card).
totalPaidToProvider REQUIRED A schema:MonetaryAmount object deining the total amount paid.
confirmationNumber OPTIONAL A string identifier to confirm that a payment has been recorded by the booking system.
paymentDate OPTIONAL The date and time that payment has been recorded by the booking system, expressed as an ISO 8601 DateTime.

9.3 Acknowledgements

This section is non-normative.

The editors thank all members of the OpenActive Community Group for their contributions.

A. References

A.1 Normative references

[JSON-LD]
JSON-LD 1.0. W3C. W3C Recommendation. URL: https://www.w3.org/TR/json-ld/
[Modelling-Opportunity-Data]
Modelling Opportunity Data. OpenActive Community Group. URL: https://openactive.io/modelling-opportunity-data/
[OpenActive-Vocabulary]
OpenActive Vocabulary. OpenActive Community Group. URL: https://openactive.io/ns/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: https://tools.ietf.org/html/rfc3986
[RFC7231]
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. R. Fielding, Ed.; J. Reschke, Ed.. IETF. June 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7231
[RFC7807]
Problem Details for HTTP APIs. M. Nottingham; E. Wilde. IETF. March 2016. Proposed Standard. URL: https://tools.ietf.org/html/rfc7807

A.2 Informative references

[OAuth2]
OAuth 2.0. URL: https://oauth.net/2/
[OpenIdConnect]
OpenID Connect. URL: https://openid.net/connect/
[reference]
Reference not found.
[RPDE]
Realtime Paged Data Exchange. OpenActive Community Group. URL: https://openactive.io/realtime-paged-data-exchange/