Booking Items

Booking items represent the programmes, courses, or events that users can apply to. The API exposes a resolved view of booking items with their merged option tree, workflows, eligibility rules, and audit history.

Retrieving a booking item

A booking item can be retrieved using its id:

>>> response = requests.get(
...     'https://api.kaizenep.com/v2/booking-items/effa9413-ee11-49a2-9e36-98397b878c2a',
...     params={'includeParts': 'all'},
...     headers=headers
... )
>>> response.json()
{
    "_id": "effa9413-ee11-49a2-9e36-98397b878c2a",
    "name": "Clinical Skills Exam",
    "state": "published",
    "securityContext": {
        "roles": []
    },
    "option": {
        "id": "effa9413-ee11-49a2-9e36-98397b878c2a",
        "title": "Clinical Skills Exam",
        "bookableType": "cover",
        "path": ["effa9413-ee11-49a2-9e36-98397b878c2a"],
        "breadcrumbs": [
            {"id": "effa9413-ee11-49a2-9e36-98397b878c2a", "title": "Clinical Skills Exam"}
        ],
        "state": {"id": "published", "name": "Published"},
        "capacities": {"availableCapacity": 10},
        "pricing": {"price": 100.0, "currency": "CAD", "method": ["1868df13-..."]},
        "metadata": [{"key": "EXAM_CODE", "value": "CSE-2026-01"}],
        "summary": {
            "price": {"min": 100.0, "max": 100.0, "currency": "CAD"},
            "bookingDates": {},
            "bookingWindow": {},
            "openOptions": 2
        },
        "workflowId": "w-446gsumpbi",
        "eligibilityId": "cb6239c9958fbdfc3d2a3b1c9027bd07",
        "options": [
            {
                "id": "5e89a487-8e09-4bef-95e9-38162fd8de3b",
                "title": "Clinical Skills Exam - Session 1",
                "bookableType": "bookable",
                "path": ["effa9413-...", "5e89a487-..."],
                "state": {"id": "published", "name": "Published"},
                "pricing": {"price": 100.0, "currency": "CAD"},
                "workflowId": "w-446gsumpbi",
                "eligibilityId": "cb6239c9958fbdfc3d2a3b1c9027bd07",
                "options": []
            },
            ...
        ]
    },
    "workflows": [...],
    "eligibilities": [...],
    "metadata": [{"key": "EXAM_CODE", "value": "CSE-2026-01"}],
    "summary": {...},
    "auditLog": [
        {
            "_id": "935bb253-01d1-4287-a319-5a4a393b3e98",
            "date": "2026-05-14T09:23:34.527385+00:00",
            "action": "booking_item_edit",
            "actor": "exam.admin"
        },
        ...
    ]
}

The response includes several sections that can be individually controlled using the includeParts query parameter.

includeParts

The content of the response can be controlled by the includeParts parameter. Pass a comma-separated list of parts to include:

  • all — Includes everything listed below

  • options — The merged option tree (sessions resolved with inherited properties)

  • workflows — Full workflow definitions (states, transitions, actions, guards)

  • eligibilities — Eligibility rule sets used across the option tree

  • metadata — Key/value metadata attached to the booking item

  • summary — A summary of the root option (pricing range, dates, open options count)

  • auditlog — Audit log of actions performed on the booking item

If includeParts is omitted, all parts are returned by default.

# Fetch only the option tree and metadata
>>> response = requests.get(
...     'https://api.kaizenep.com/v2/booking-items/<id>',
...     params={'includeParts': 'options,metadata'},
...     headers=headers
... )

Response structure

Base fields (always present)

These fields are always returned regardless of includeParts:

Field

Type

Description

_id

string

Unique identifier of the booking item

name

string

Display name of the booking item

state

string

Current state (e.g. published, draft)

securityContext

object

Roles required to access this item

Option tree (options part)

The option field contains the root of the resolved option tree. Each node represents a session (option) with its properties inherited and merged from parent nodes.

Key fields on each option node:

Field

Type

Description

id

string

Option identifier

title

string

Resolved display title

bookableType

string

Either cover (non-bookable container) or bookable

path

array

Ordered list of ancestor IDs from root to this node

breadcrumbs

array

List of {id, title} objects for navigation

state

object

{id, name} — current workflow state

capacities

object

Available capacity information

pricing

object

Price, currency, and payment method references

workflowId

string

Reference to the workflow definition in the workflows array

eligibilityId

string

Hash reference to the eligibility rule in the eligibilities array

options

array

Child option nodes (recursive tree structure)

Note

The form and eligibility objects are stripped from the option tree in the list response for performance. Use the individual option endpoint to retrieve full details including form fields and eligibility rules.

Workflows (workflows part)

An array of workflow definitions referenced by workflowId in the option tree. Each workflow describes how a booking progresses through states, what form fields are available at each stage, and what transitions (actions) are possible.

Structure overview:

{
    "id": "w-446gsumpbi",
    "name": "Clinical Skills Exam Workflow",
    "form": {
        "id": "w-446gsumpbi",
        "name": "Clinical Skills Exam Workflow",
        "initial": {
            "state": "ws-ri2663t3f2",
            "roles": ["org_medschool:candidate"],
            "actions": []
        },
        "states": [...],
        "transitions": [...],
        "fields": [...]
    }
}

Workflow states

Each state defines which roles can see/edit which fields and which transitions are available:

{
    "id": "ws-ri2663t3f2",
    "name": "DRAFT",
    "roles": [
        {
            "role": "org_medschool:candidate",
            "group": {
                "wff-ztm8jbzujd": "edit",
                "wff-zo35g8ebeo": "edit",
                "wff-5sx7numpou": "view"
            },
            "transitions": ["wt-ac4dfrszrx"],
            "canDelete": false
        },
        {
            "role": "org_medschool:exam-admin",
            "group": {"wff-ztm8jbzujd": "view"},
            "transitions": [],
            "canDelete": false
        }
    ]
}

Field

Type

Description

id

string

State identifier (referenced by transitions)

name

string

Display name of the state (e.g. DRAFT, SUBMITTED, PAID)

roles

array

Per-role permissions for this state

roles[].role

string

Role identifier (e.g. org_medschool:candidate, org_medschool:exam-admin)

roles[].group

object

Field permissions — maps field ID → "edit" or "view"

roles[].transitions

array

Transition IDs this role is allowed to trigger from this state

roles[].canDelete

boolean

Whether this role can delete the booking in this state

Workflow transitions

Transitions define how a booking moves from one state to another, including validation, required actions, and guards:

{
    "id": "wt-ac4dfrszrx",
    "name": "Submit booking",
    "sources": ["ws-ri2663t3f2"],
    "destination": "ws-uhth56zgsh",
    "actions": [
        {
            "action": "fill_in_fields",
            "data": {
                "fields": [
                    {"id": "wff-zo35g8ebeo", "required": true},
                    {"id": "wff-5mdi71hykg", "required": true}
                ]
            }
        },
        {"action": "collect_payment", "data": {}},
        {"action": "reserve_seat", "data": {"ttl": "10"}},
        {"action": "confirm_booking", "data": {}}
    ],
    "guards": [
        {
            "guard": "field_guard",
            "data": {
                "field": "wff-zo35g8ebeo",
                "op": "has_all",
                "value": ["23d6iwmewja"]
            }
        }
    ],
    "message": "",
    "allowInvalidForm": false,
    "autoTransition": false,
    "requireConfirmation": false
}

Field

Type

Description

id

string

Transition identifier

name

string

Display name (e.g. “Submit”, “Retract”, “Approve”)

sources

array

State IDs from which this transition can be triggered

destination

string

Target state ID after the transition completes

actions

array

Ordered list of actions executed during the transition

guards

array

Conditions that must be met before the transition is allowed

message

string

Optional message displayed to the user during transition

allowInvalidForm

boolean

If true, transition is allowed even if required fields are incomplete

autoTransition

boolean

If true, transition fires automatically when conditions are met

requireConfirmation

boolean

If true, user must confirm before the transition executes

Common transition actions:

  • fill_in_fields — Requires specified fields to be filled (with optional required flag)

  • collect_payment — Triggers payment collection

  • reserve_seat — Reserves capacity with a TTL (time-to-live in minutes)

  • confirm_booking — Marks the booking as confirmed

  • refund_payments — Issues refunds with configurable refund options (full, partial, custom)

Guards:

Guards prevent a transition from being triggered unless conditions are met:

  • field_guard — Checks a field value (operators: has_all, has_any, equals, etc.)

Workflow form fields

The fields array defines all form fields available in the workflow:

[
    {
        "id": "wff-ztm8jbzujd",
        "fieldType": "string",
        "type": "field",
        "options": {
            "required": true,
            "label": "Candidate full name",
            "meta": {}
        },
        "validators": [],
        "asyncValidators": []
    },
    {
        "id": "wff-zo35g8ebeo",
        "fieldType": "select",
        "type": "field",
        "options": {
            "required": false,
            "label": "Assessment track",
            "meta": {},
            "categories": [
                {"_id": "23d6iwmewja", "name": "General medicine"},
                {"_id": "k1b3us34lvj", "name": "Emergency medicine"}
            ]
        },
        "validators": [],
        "asyncValidators": []
    }
]

Field

Type

Description

id

string

Field identifier (referenced in state group permissions and transition actions)

fieldType

string

Input type: string, text, number, select, date, file, etc.

type

string

Always "field" for form fields

options.required

boolean

Whether the field is required by default

options.label

string

Display label for the field

options.categories

array

For select fields: available choices with _id and name

validators

array

Synchronous validation rules

asyncValidators

array

Asynchronous validation rules (e.g. server-side checks)

Eligibilities (eligibilities part)

An array of eligibility rule sets referenced by eligibilityId in the option tree. The rules field is returned as a parsed JSON object (not a string):

[
    {
        "id": "32e2693e-4984-442f-97d7-12ed31c747c3",
        "name": "Exam registration eligibility",
        "rules": {
            "op": "and",
            "description": "Clinical Skills Exam eligibility",
            "affirmative": true,
            "args": [
                {
                    "op": "hasRole",
                    "description": "Must hold candidate role",
                    "affirmative": true,
                    "options": {"roles": ["org_medschool:candidate"]}
                },
                {
                    "op": "hasRelation",
                    "description": "Must be linked to candidate cohort",
                    "affirmative": true,
                    "options": {
                        "relation": "9c595151-...",
                        "relationCategories": ["454462fd-..."]
                    }
                },
                {
                    "op": "hasEvent",
                    "description": "Must have completed prerequisite event in range",
                    "affirmative": true,
                    "options": {
                        "start": "2026-04-01",
                        "end": "2026-05-16"
                    }
                }
            ]
        }
    }
]

The rules tree is a recursive structure of logical operators:

Field

Type

Description

op

string

Operator: and, or, or a condition like hasRole, hasRelation, hasEvent

description

string

Human-readable description of the rule

affirmative

boolean

If false, the rule is negated

args

array

Child rules (for and/or operators)

options

object

Condition-specific parameters (for leaf operators)

Metadata (metadata part)

Key/value pairs attached to the booking item:

[
    {"key": "EXAM_CODE", "value": "CSE-2026-01"}
]

Summary (summary part)

A summarised view of the root option, useful for listing pages:

{
    "price": {"min": 100.0, "max": 100.0, "currency": "CAD"},
    "bookingDates": {},
    "bookingWindow": {},
    "openOptions": 2
}

Audit log (auditlog part)

A chronological list of actions performed on the booking item, sorted by date (oldest first):

[
    {
        "_id": "a1b2c3d4-...",
        "date": "2026-05-14T09:23:34.527385+00:00",
        "action": "booking_item_edit",
        "actor": "exam.admin",
        "source": "web"
    }
]

Each entry contains:

Field

Type

Description

_id

string

Audit log entry identifier

date

string

ISO 8601 timestamp of the action

action

string

Action type (e.g. booking_item_edit, booking_item_create)

actor

string

User who performed the action

user

string

Target user (if applicable)

masquerade

string

Original actor if action was performed via masquerade

source

string

Source of the action (e.g. web, api)

extra

object

Additional context data specific to the action

Retrieving a single option

Individual options can be retrieved with full details (including form fields and eligibility rules that are stripped from the tree response):

>>> response = requests.get(
...     'https://api.kaizenep.com/v2/booking-items/<booking_item_id>/options/<option_id>',
...     headers=headers
... )
>>> response.json()
{
    "id": "5e89a487-8e09-4bef-95e9-38162fd8de3b",
    "title": "Clinical Skills Exam - Session 1",
    "bookableType": "bookable",
    "state": {"id": "published", "name": "Published"},
    "pricing": {"price": 100.0, "currency": "CAD"},
    "form": {
        "id": "w-446gsumpbi",
        "fields": [...]
    },
    "eligibility": {
        "rules": "{...}",
        "hash": "cb6239c9958fbdfc3d2a3b1c9027bd07"
    },
    "workflow": {
        "id": "w-446gsumpbi",
        "state": "draft",
        "name": "Clinical Skills Exam Workflow"
    },
    "options": []
}

This endpoint returns the full option data including form and eligibility which are not present in the tree view.