---
openapi: 3.0.1
info:
  title: API V1
  version: v1
paths:
  "/nhsapi/v1/Auth":
    post:
      summary: Login
      tags:
      - Authentication
      description: Authenticate with email and password to obtain access and refresh
        tokens
      parameters: []
      responses:
        '200':
          description: successful authentication
          content:
            application/json:
              examples:
                successful_login:
                  value:
                    success: true
                    data:
                      token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHRlcm5hbF9hY2NvdW50X2lkIjoxLCJleHAiOjE3MDQ0NjgwMDB9.abc123
                      refresh_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHRlcm5hbF9hY2NvdW50X2lkIjoxLCJleHAiOjE3MDUwNzI4MDB9.def456
                      account:
                        id: 1
                        email: test@example.com
                        name: Test API Account
                        organisation_id: 1
                        permissions:
                          worker_basic_read: true
                          worker_advanced_read: false
                          shift_basic_read: true
                          shift_advanced_read: true
                          create_shifts: true
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      token:
                        type: string
                        description: JWT access token for API authentication
                        example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                      refresh_token:
                        type: string
                        description: JWT refresh token for obtaining new access tokens
                        example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                      account:
                        type: object
                        properties:
                          id:
                            type: integer
                            example: 1
                          email:
                            type: string
                            example: test@example.com
                          name:
                            type: string
                            example: Test API Account
                          organisation_id:
                            type: integer
                            example: 1
                          permissions:
                            type: object
                            properties:
                              worker_basic_read:
                                type: boolean
                                description: Permission to read basic worker information
                                example: true
                              worker_advanced_read:
                                type: boolean
                                description: Permission to read advanced worker information
                                example: false
                              shift_basic_read:
                                type: boolean
                                description: Permission to read basic shift information
                                example: true
                              shift_advanced_read:
                                type: boolean
                                description: Permission to read advanced shift information
                                example: true
                              create_shifts:
                                type: boolean
                                description: Permission to create shifts/vacancies
                                example: true
        '401':
          description: missing credentials
          content:
            application/json:
              examples:
                invalid_credentials:
                  value:
                    success: false
                    error:
                      code: INVALID_CREDENTIALS
                      message: Invalid email or password
                missing_credentials:
                  value:
                    success: false
                    error:
                      code: INVALID_CREDENTIALS
                      message: Invalid email or password
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Error code
                        example: INVALID_CREDENTIALS
                      message:
                        type: string
                        description: Error message
                        example: Invalid email or password
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                auth:
                  type: object
                  properties:
                    email:
                      type: string
                      format: email
                      description: The email address of the external account
                      example: test@example.com
                    password:
                      type: string
                      format: password
                      description: The password for the external account
                      example: SecurePassword123!
                  required:
                  - email
                  - password
              required:
              - auth
  "/nhsapi/v1/Auth/refresh":
    post:
      summary: Refresh token
      tags:
      - Authentication
      description: Use a refresh token to obtain new access and refresh tokens
      parameters: []
      responses:
        '200':
          description: token refreshed successfully
          content:
            application/json:
              examples:
                successful_refresh:
                  value:
                    success: true
                    data:
                      token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHRlcm5hbF9hY2NvdW50X2lkIjoxLCJleHAiOjE3MDQ0NjgwMDB9.xyz789
                      refresh_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHRlcm5hbF9hY2NvdW50X2lkIjoxLCJleHAiOjE3MDUwNzI4MDB9.uvw456
                      account:
                        id: 1
                        email: test@example.com
                        name: Test API Account
                        organisation_id: 1
                        permissions:
                          worker_basic_read: true
                          worker_advanced_read: false
                          shift_basic_read: true
                          shift_advanced_read: true
                          create_shifts: true
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      token:
                        type: string
                        description: New JWT access token
                        example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                      refresh_token:
                        type: string
                        description: New JWT refresh token
                        example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                      account:
                        type: object
                        properties:
                          id:
                            type: integer
                            example: 1
                          email:
                            type: string
                            example: test@example.com
                          name:
                            type: string
                            example: Test API Account
                          organisation_id:
                            type: integer
                            example: 1
                          permissions:
                            type: object
                            properties:
                              worker_basic_read:
                                type: boolean
                                example: true
                              worker_advanced_read:
                                type: boolean
                                example: false
                              shift_basic_read:
                                type: boolean
                                example: true
                              shift_advanced_read:
                                type: boolean
                                example: true
                              create_shifts:
                                type: boolean
                                example: true
        '401':
          description: invalid refresh token
          content:
            application/json:
              examples:
                invalid_refresh_token:
                  value:
                    success: false
                    error:
                      code: INVALID_REFRESH_TOKEN
                      message: Invalid or expired refresh token
                expired_token:
                  value:
                    success: false
                    error:
                      code: TOKEN_EXPIRED
                      message: Refresh token has expired
                invalid_token_format:
                  value:
                    success: false
                    error:
                      code: INVALID_TOKEN
                      message: Invalid token format
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Error code
                        enum:
                        - INVALID_REFRESH_TOKEN
                        - TOKEN_EXPIRED
                        - INVALID_TOKEN
                        example: INVALID_REFRESH_TOKEN
                      message:
                        type: string
                        description: Error message
                        example: Invalid or expired refresh token
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                refresh_token:
                  type: string
                  description: The refresh token obtained from login
                  example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
              required:
              - refresh_token
  "/nhsapi/v1/Booking":
    post:
      summary: Create a booking
      tags:
      - Booking
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '201':
          description: booking created
          content:
            application/json:
              examples:
                booking:
                  value:
                    id: 9b6c2c7e-5e7a-4e86-8c1e-8c1e4e86c7e5
                    resourceType: Booking
                    meta:
                      profile: https://api.patchwork.health/Booking
                    status: confirmed
                    organization:
                    - type: Organization
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test Hospital NHS API
                      coding:
                        code: '1'
                    - type: Department
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test A&E Department
                      coding:
                        code: '1'
                    - type: Site
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test Site NHS API
                      coding:
                        code: '1'
                    Worker:
                      workerReference:
                        identifier:
                          value: '123456'
                        display: John Smith
                    costCentre: validcostcentre
                    basedOn:
                      type: Vacancy
                      system: Patchwork
                      reference: some-vacancy-id
        '400':
          description: bad request
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type:
                  - integer
                  - string
                  description: Shift ID
                Worker:
                  type: object
                  properties:
                    workerReference:
                      type: object
                      properties:
                        identifier:
                          type: object
                          properties:
                            value:
                              type: string
                              description: ESR number
                        display:
                          type: string
                          description: Full name
        required: true
  "/nhsapi/v1/Booking/{id}":
    get:
      summary: Retrieve a booking
      tags:
      - Booking
      parameters:
      - name: id
        in: path
        description: Booking ID
        required: true
        schema:
          type:
          - integer
          - string
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: booking retrieved
          content:
            application/json:
              examples:
                booking:
                  value:
                    id: "./spec/swagger/nhs-v1/booking_spec.rb[1:2:1:1]"
                    resourceType: Booking
                    meta:
                      profile: https://api.patchwork.health/Booking
                    status: confirmed
                    organization:
                    - type: Organization
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test Hospital NHS API
                      coding:
                        code: '1'
                    - type: Department
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test A&E Department
                      coding:
                        code: '1'
                    - type: Site
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test Site NHS API
                      coding:
                        code: '1'
                    Worker:
                      workerReference:
                        identifier:
                          value: '123456'
                        display: John Smith
                    costCentre: validcostcentre
                    basedOn:
                      type: Vacancy
                      system: Patchwork
                      reference: some-vacancy-id
              schema:
                type: object
                properties:
                  id:
                    type:
                    - integer
                    - string
                    example: 9b6c2c7e-5e7a-4e86-8c1e-8c1e4e86c7e5
                  resourceType:
                    type: string
                    example: Booking
                  meta:
                    type: object
                    properties:
                      profile:
                        type: string
                        example: https://api.patchwork.health/Booking
                  status:
                    type: string
                    example: confirmed
                  organization:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                          example: Organization
                        identifier:
                          type: object
                          properties:
                            system:
                              type: string
                              example: Patchwork
                            value:
                              type: string
                              example: '1'
                        display:
                          type: string
                          example: Unique Test Hospital NHS API
                        coding:
                          type: object
                          properties:
                            code:
                              type: string
                              example: '1'
                  Worker:
                    type: object
                    properties:
                      workerReference:
                        type: object
                        properties:
                          identifier:
                            type: object
                            properties:
                              value:
                                type: string
                                example: '123456'
                          display:
                            type: string
                            example: John Smith
                  costCentre:
                    type: string
                    example: validcostcentre
                  basedOn:
                    type: object
                    properties:
                      type:
                        type: string
                        example: Vacancy
                      system:
                        type: string
                        example: Patchwork
                      reference:
                        type: string
                        example: some-vacancy-id
        '404':
          description: shift not booked
    delete:
      summary: Delete a booking
      tags:
      - Booking
      parameters:
      - name: id
        in: path
        description: Booking ID
        required: true
        schema:
          type:
          - integer
          - string
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: booking cancelled
          content:
            application/json:
              examples:
                booking:
                  value:
                    id: "./spec/swagger/nhs-v1/booking_spec.rb[1:2:2:1]"
                    resourceType: Booking
                    meta:
                      profile: https://api.patchwork.health/Booking
                    status: cancelled
        '404':
          description: not found
        '400':
          description: bad request
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                cancellationReason:
                  type: object
                  properties:
                    system:
                      type: string
                      example: https://api.patchwork.health/fhir/CancellationReason
                    code:
                      type: string
                      example: staff_unavailability
                    display:
                      type: string
                      example: Staff unavailability
  "/nhsapi/v1/Vacancy":
    post:
      summary: Create a vacancy
      tags:
      - Vacancy
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '201':
          description: vacancy created
          content:
            application/json:
              examples:
                vacancy:
                  value:
                    id: "./spec/swagger/nhs-v1/vacancy_spec.rb[1:1:1:1]"
                    resourceType: Vacancy
                    meta:
                      profile: https://api.patchwork.health/Vacancy
                    status: requested
        '400':
          description: bad request
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                resourceType:
                  type: string
                  example: Vacancy
                meta:
                  type: object
                  properties:
                    profile:
                      type: string
                      example: https://api.patchwork.health/Booking
                status:
                  type: string
                  example: requested
                organization:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        example: Organisation
                        description: Type of organization (Organisation, Department,
                          or Site)
                        enum:
                        - Organisation
                        - Department
                        - Site
                      identifier:
                        type: object
                        properties:
                          system:
                            type: string
                            example: Patchwork
                          value:
                            type: string
                            example: '1'
                        required:
                        - system
                        - value
                      display:
                        type: string
                        example: Unique Test Hospital NHS API
                      coding:
                        type: object
                        properties:
                          code:
                            type: string
                            example: '1'
                        required:
                        - code
                    required:
                    - type
                    - identifier
                    - display
                    - coding
                  description: Array of organization elements. Must include Organisation,
                    Department, and Site.
                  minItems: 3
                  uniqueItems: true
                  example:
                  - type: Organization
                    identifier:
                      system: Patchwork
                      value: '1'
                    display: Test Organization
                    coding:
                      code: '1'
                  - type: Department
                    identifier:
                      system: Patchwork
                      value: '2'
                    display: Test Department
                    coding:
                      code: '2'
                  - type: Site
                    identifier:
                      system: Patchwork
                      value: '3'
                    display: Test Site
                    coding:
                      code: '3'
                  additionalProperties: false
                notes:
                  type: array
                  description: Optional notes for the vacancy
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        enum:
                        - admin
                        - worker
                        description: 'Type of note: "admin" for administrative notes,
                          "worker" for worker-facing notes'
                      text:
                        type: string
                        description: Content of the note
                    required:
                    - type
                    - text
                  example:
                  - type: admin
                    text: Administrative note visible to staff only
                  - type: worker
                    text: Note visible to workers
                costCentre:
                  type: string
                  example: validcostcentre
                qualifications:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        example: grade
                        description: Type of qualification
                      code:
                        type: object
                        properties:
                          coding:
                            type: array
                            items:
                              type: object
                              properties:
                                system:
                                  type: string
                                  example: https://api.patchwork.health/fhir/Grade
                                code:
                                  type: string
                                  example: '1'
                                display:
                                  type: string
                                  example: Foundation Year 1
                                  description: Grade title that will be used to find
                                    the Grade record
                              required:
                              - system
                              - code
                              - display
                        required:
                        - coding
                      priority:
                        type: string
                        example: '1'
                        description: Priority of the qualification (higher number
                          means higher priority)
                    required:
                    - type
                    - code
                    - priority
                  example:
                  - type: grade
                    code:
                      coding:
                      - system: https://api.patchwork.health/fhir/Grade
                        code: '1'
                        display: Foundation Year 1
                    priority: '1'
                reasonCode:
                  type: object
                  properties:
                    coding:
                      type: array
                      items:
                        type: object
                        properties:
                          system:
                            type: string
                            example: Patchwork
                          code:
                            type: string
                            example: '1'
                          display:
                            type: string
                            example: Sickness
                        required:
                        - code
                        - display
                  required:
                  - coding
                plannedTime:
                  type: object
                  properties:
                    timing:
                      type: array
                      items:
                        type: object
                        properties:
                          boundsPeriod:
                            type: object
                            properties:
                              start:
                                type: string
                                format: date-time
                              end:
                                type: string
                                format: date-time
                            required:
                            - start
                            - end
                          servicePeriod:
                            type: object
                            properties:
                              start:
                                type: string
                                example: '10:00:00'
                              end:
                                type: string
                                example: '18:00:00'
                            required:
                            - start
                            - end
                        required:
                        - boundsPeriod
                        - servicePeriod
                  required:
                  - timing
                source:
                  type: object
                  properties:
                    id:
                      type: string
                      example: patchwork
                trigerredBy:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                        example: Test User
                      type:
                        type: string
                        example: confirmedBy
                      date:
                        type: string
                        format: date-time
              required:
              - resourceType
              - qualifications
              - plannedTime
              - organization
        required: true
  "/nhsapi/v1/Vacancy/{id}":
    get:
      summary: Retrieve a vacancy
      tags:
      - Vacancy
      parameters:
      - name: id
        in: path
        description: Vacancy ID
        required: true
        schema:
          type:
          - integer
          - string
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: vacancy retrieved
          content:
            application/json:
              examples:
                vacancy:
                  value:
                    id: "./spec/swagger/nhs-v1/vacancy_spec.rb[1:2:1:1]"
                    resourceType: Vacancy
                    meta:
                      profile: https://api.patchwork.health/Vacancy
                    status: requested
                    organization:
                    - type: Organization
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test Hospital NHS API
                      coding:
                        code: '1'
                    - type: Department
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test A&E Department
                      coding:
                        code: '1'
                    - type: Site
                      identifier:
                        system: Patchwork
                        value: '1'
                      display: Unique Test Site NHS API
                      coding:
                        code: '1'
              schema:
                type: object
                properties:
                  id:
                    type:
                    - integer
                    - string
                    example: a0521313-606c-456a-887f-bad4758bbbf4
                  resourceType:
                    type: string
                    example: Vacancy
                  meta:
                    type: object
                    properties:
                      profile:
                        type: string
                        example: https://api.patchwork.health/Vacancy
                  status:
                    type: string
                    example: requested
                  organization:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                          example: Organization
                        identifier:
                          type: object
                          properties:
                            system:
                              type: string
                              example: Patchwork
                            value:
                              type: string
                              example: '1'
                        display:
                          type: string
                          example: Unique Test Hospital NHS API
                        coding:
                          type: object
                          properties:
                            code:
                              type: string
                              example: '1'
                  notes:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                          example: admin
                          enum:
                          - admin
                          - worker
                        text:
                          type: string
                          example: Administrative note text
        '404':
          description: vacancy not found
    put:
      summary: Update a vacancy
      tags:
      - Vacancy
      parameters:
      - name: id
        in: path
        description: Vacancy ID
        required: true
        schema:
          type:
          - integer
          - string
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: vacancy updated
          content:
            application/json:
              examples:
                vacancy:
                  value:
                    id: "./spec/swagger/nhs-v1/vacancy_spec.rb[1:2:2:1]"
                    resourceType: Vacancy
                    meta:
                      profile: https://api.patchwork.health/Vacancy
                    status: updated
        '400':
          description: bad request
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                  description: Updated status
                resourceType:
                  type: string
                plannedTime:
                  type: object
                  properties:
                    timing:
                      type: array
                      items:
                        type: object
                        properties:
                          boundsPeriod:
                            type: object
                            properties:
                              start:
                                type: string
                                format: date-time
                              end:
                                type: string
                                format: date-time
                            required:
                            - start
                            - end
                          servicePeriod:
                            type: object
                            properties:
                              start:
                                type: string
                                example: '10:00:00'
                              end:
                                type: string
                                example: '18:00:00'
                            required:
                            - start
                            - end
                        required:
                        - boundsPeriod
                        - servicePeriod
                  required:
                  - timing
                qualifications:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        example: grade
                        description: Type of qualification
                      code:
                        type: object
                        properties:
                          coding:
                            type: array
                            items:
                              type: object
                              properties:
                                system:
                                  type: string
                                  example: https://api.patchwork.health/fhir/Grade
                                code:
                                  type: string
                                  example: '1'
                                display:
                                  type: string
                                  example: Foundation Year 1
                                  description: Grade title that will be used to find
                                    the Grade record
                              required:
                              - system
                              - code
                              - display
                        required:
                        - coding
                      priority:
                        type: string
                        example: '1'
                        description: Priority of the qualification (higher number
                          means higher priority)
                    required:
                    - type
                    - code
                    - priority
                  example:
                  - type: grade
                    code:
                      coding:
                      - system: https://api.patchwork.health/fhir/Grade
                        code: '1'
                        display: Foundation Year 1
                    priority: '1'
                organization:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        example: Organisation
                        description: Type of organization (Organization, Department,
                          or Site)
                        enum:
                        - Organization
                        - Department
                        - Site
                      identifier:
                        type: object
                        properties:
                          system:
                            type: string
                            example: Patchwork
                          value:
                            type: string
                            example: '1'
                        required:
                        - system
                        - value
                      display:
                        type: string
                        example: Unique Test Hospital NHS API
                        description: Display name of the organization
                      coding:
                        type: object
                        properties:
                          code:
                            type: string
                            example: '1'
                        required:
                        - code
                    required:
                    - type
                    - identifier
                    - display
                    - coding
                  description: Array of organization elements. Must include Organisation,
                    Department, and Site.
                  minItems: 3
                  uniqueItems: true
                  example:
                  - type: Organization
                    identifier:
                      system: Patchwork
                      value: '1'
                    display: Test Organization
                    coding:
                      code: '1'
                  - type: Department
                    identifier:
                      system: Patchwork
                      value: '2'
                    display: Test Department
                    coding:
                      code: '2'
                  - type: Site
                    identifier:
                      system: Patchwork
                      value: '3'
                    display: Test Site
                    coding:
                      code: '3'
                costCentre:
                  type: string
                  example: validcostcentre
                  description: Cost centre code
                reasonCode:
                  type: object
                  properties:
                    coding:
                      type: array
                      items:
                        type: object
                        properties:
                          system:
                            type: string
                            example: Patchwork
                          code:
                            type: string
                            example: '1'
                          display:
                            type: string
                            example: Sickness
                        required:
                        - code
                        - display
                  required:
                  - coding
                notes:
                  type: array
                  description: Optional notes for the vacancy
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        enum:
                        - admin
                        - worker
                        example: admin
                      text:
                        type: string
                        example: Note content
                    required:
                    - type
                    - text
              required:
              - resourceType
        required: true
    delete:
      summary: Delete a vacancy
      tags:
      - Vacancy
      parameters:
      - name: id
        in: path
        description: Vacancy ID
        required: true
        schema:
          type:
          - integer
          - string
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: vacancy revoked
          content:
            application/json:
              examples:
                vacancy:
                  value:
                    id: "./spec/swagger/nhs-v1/vacancy_spec.rb[1:2:3:1]"
                    resourceType: Vacancy
                    meta:
                      profile: https://api.patchwork.health/Vacancy
                    status: revoked
        '400':
          description: bad request
  "/nhsapi/v1/Webhooks":
    get:
      summary: List all webhooks
      tags:
      - Webhooks
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: webhooks listed
          content:
            application/json:
              examples:
                webhooks:
                  value:
                    webhooks:
                    - id: 1
                      event_types:
                      - booking_created
                      - booking_cancelled
                      url: https://example.com/webhook
                      active: true
                      retry_config:
                        max_attempts: 6
                        backoff_base: 3
                        max_delay: 300
                      headers: {}
                      last_triggered_at:
                      last_success_at:
                      failure_count: 0
                      created_at: '2024-01-01T00:00:00Z'
                      updated_at: '2024-01-01T00:00:00Z'
              schema:
                type: object
                properties:
                  webhooks:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        event_types:
                          type: array
                          items:
                            type: string
                          example:
                          - booking_created
                          - booking_cancelled
                        url:
                          type: string
                          example: https://example.com/webhook
                        active:
                          type: boolean
                          example: true
                        retry_config:
                          type: object
                          properties:
                            max_attempts:
                              type: integer
                              example: 6
                            backoff_base:
                              type: integer
                              example: 3
                            max_delay:
                              type: integer
                              example: 300
                        headers:
                          type: object
                          example: {}
                        last_triggered_at:
                          type: string
                          format: date-time
                          nullable: true
                        last_success_at:
                          type: string
                          format: date-time
                          nullable: true
                        failure_count:
                          type: integer
                          example: 0
                        created_at:
                          type: string
                          format: date-time
                        updated_at:
                          type: string
                          format: date-time
    post:
      summary: Create a webhook
      tags:
      - Webhooks
      description: |-
        Create a new webhook webhook. When triggered, webhooks will include:
        - `X-Signature` header: HMAC-SHA256 signature in format `sha256=<hex_digest>`
        - `X-Timestamp` header: Unix timestamp when the signature was generated
        - `Content-Type: application/json` header

        The signature is calculated as: `HMAC-SHA256(secret, timestamp + '.' + canonical_json_body)`

        JSON payloads are canonicalized (keys sorted alphabetically, whitespace removed) before signing.
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '201':
          description: webhook created
          content:
            application/json:
              examples:
                webhook:
                  value:
                    webhook:
                      id: 1
                      event_types:
                      - booking_created
                      - booking_cancelled
                      url: https://example.com/webhook
                      active: true
                      retry_config:
                        max_attempts: 6
                        backoff_base: 3
                        max_delay: 300
                      headers:
                        X-Custom-Header: value
                      hmac_secret: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
                      last_triggered_at:
                      last_success_at:
                      failure_count: 0
                      created_at: '2024-01-01T00:00:00Z'
                      updated_at: '2024-01-01T00:00:00Z'
              schema:
                type: object
                properties:
                  webhook:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      event_types:
                        type: array
                        items:
                          type: string
                        example:
                        - booking_created
                        - booking_cancelled
                      url:
                        type: string
                        example: https://example.com/webhook
                      active:
                        type: boolean
                        example: true
                      retry_config:
                        type: object
                        properties:
                          max_attempts:
                            type: integer
                            example: 6
                          backoff_base:
                            type: integer
                            example: 3
                          max_delay:
                            type: integer
                            example: 300
                      headers:
                        type: object
                      hmac_secret:
                        type: string
                        description: The HMAC secret (only shown on creation)
                        example: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
                      last_triggered_at:
                        type: string
                        format: date-time
                        nullable: true
                      last_success_at:
                        type: string
                        format: date-time
                        nullable: true
                      failure_count:
                        type: integer
                        example: 0
                      created_at:
                        type: string
                        format: date-time
                      updated_at:
                        type: string
                        format: date-time
        '422':
          description: invalid request
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                webhook:
                  type: object
                  properties:
                    url:
                      type: string
                      format: uri
                      description: The URL to send webhook notifications to
                      example: https://example.com/webhook
                    event_types:
                      type: array
                      items:
                        type: string
                        enum:
                        - booking_created
                        - booking_cancelled
                        - vacancy_created
                        - vacancy_updated
                        - vacancy_cancelled
                        - shift_updated
                      description: Event types to subscribe to
                      example:
                      - booking_created
                      - booking_cancelled
                    active:
                      type: boolean
                      description: Whether the webhook is active
                      example: true
                    hmac_secret:
                      type: string
                      description: HMAC secret used to sign webhook requests (min
                        32 chars). Used to generate X-Signature header. If not provided,
                        will be auto-generated
                      example: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
                    retry_config:
                      type: object
                      properties:
                        max_attempts:
                          type: integer
                          description: Maximum retry attempts
                          example: 6
                        backoff_base:
                          type: integer
                          description: Exponential backoff base
                          example: 3
                        max_delay:
                          type: integer
                          description: Maximum delay between retries in seconds
                          example: 300
                    headers:
                      type: object
                      description: Custom headers to include in webhook requests
                      example:
                        X-Custom-Header: value
                  required:
                  - url
                  - event_types
              required:
              - webhook
  "/nhsapi/v1/Webhooks/{id}":
    parameters:
    - name: id
      in: path
      description: Webhook ID
      required: true
      schema:
        type: integer
    get:
      summary: Show a webhook
      tags:
      - Webhooks
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: webhook found
          content:
            application/json:
              examples:
                webhook:
                  value:
                    webhook:
                      id: 1
                      event_types:
                      - booking_created
                      - booking_cancelled
                      url: https://example.com/webhook
                      active: true
                      retry_config:
                        max_attempts: 6
                        backoff_base: 3
                        max_delay: 300
                      headers: {}
                      hmac_secret: a1b2c3d4****************************e1f2
                      last_triggered_at:
                      last_success_at:
                      failure_count: 0
                      created_at: '2024-01-01T00:00:00Z'
                      updated_at: '2024-01-01T00:00:00Z'
              schema:
                type: object
                properties:
                  webhook:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      event_types:
                        type: array
                        items:
                          type: string
                        example:
                        - booking_created
                        - booking_cancelled
                      url:
                        type: string
                        example: https://example.com/webhook
                      active:
                        type: boolean
                        example: true
                      retry_config:
                        type: object
                        properties:
                          max_attempts:
                            type: integer
                            example: 6
                          backoff_base:
                            type: integer
                            example: 3
                          max_delay:
                            type: integer
                            example: 300
                      headers:
                        type: object
                      hmac_secret:
                        type: string
                        description: Masked HMAC secret
                        example: a1b2c3d4****************************e1f2
                      last_triggered_at:
                        type: string
                        format: date-time
                        nullable: true
                      last_success_at:
                        type: string
                        format: date-time
                        nullable: true
                      failure_count:
                        type: integer
                        example: 0
                      created_at:
                        type: string
                        format: date-time
                      updated_at:
                        type: string
                        format: date-time
        '404':
          description: webhook not found
    put:
      summary: Update a webhook
      tags:
      - Webhooks
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: webhook updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  webhook:
                    type: object
                    properties:
                      id:
                        type: integer
                      event_types:
                        type: array
                        items:
                          type: string
                      url:
                        type: string
                      active:
                        type: boolean
                      retry_config:
                        type: object
                      headers:
                        type: object
                      last_triggered_at:
                        type: string
                        format: date-time
                        nullable: true
                      last_success_at:
                        type: string
                        format: date-time
                        nullable: true
                      failure_count:
                        type: integer
                      created_at:
                        type: string
                        format: date-time
                      updated_at:
                        type: string
                        format: date-time
        '422':
          description: invalid request
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                webhook:
                  type: object
                  properties:
                    url:
                      type: string
                      format: uri
                      example: https://example.com/webhook
                    event_types:
                      type: array
                      items:
                        type: string
                        enum:
                        - booking_created
                        - booking_cancelled
                        - vacancy_created
                        - vacancy_updated
                        - vacancy_cancelled
                        - shift_updated
                    active:
                      type: boolean
                    retry_config:
                      type: object
                      properties:
                        max_attempts:
                          type: integer
                        backoff_base:
                          type: integer
                        max_delay:
                          type: integer
                    headers:
                      type: object
              required:
              - webhook
    delete:
      summary: Delete a webhook
      tags:
      - Webhooks
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '204':
          description: webhook deleted
        '404':
          description: webhook not found
  "/nhsapi/v1/Webhooks/{id}/attempts":
    parameters:
    - name: id
      in: path
      description: Webhook ID
      required: true
      schema:
        type: integer
    get:
      summary: List webhook attempts
      tags:
      - Webhooks
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      - name: success
        in: query
        description: Filter by success status (true/false)
        required: false
        schema:
          type: string
      - name: page
        in: query
        description: Page number
        required: false
        schema:
          type: integer
      - name: per_page
        in: query
        description: Items per page (default 100)
        required: false
        schema:
          type: integer
      responses:
        '200':
          description: attempts listed
          content:
            application/json:
              examples:
                attempts:
                  value:
                    attempts:
                    - id: 1
                      event_data:
                        event_type: booking_created
                        booking_id: 123
                      status_code: 200
                      response_body: OK
                      error_message:
                      success: true
                      attempted_at: '2024-01-01T00:00:00Z'
                    meta:
                      total: 1
                      page: 1
                      per_page: 100
              schema:
                type: object
                properties:
                  attempts:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        event_data:
                          type: object
                          description: The event data that was sent
                          example:
                            event_type: booking_created
                            booking_id: 123
                        status_code:
                          type: integer
                          example: 200
                        response_body:
                          type: string
                          example: OK
                        error_message:
                          type: string
                          nullable: true
                        success:
                          type: boolean
                          example: true
                        attempted_at:
                          type: string
                          format: date-time
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                        example: 50
                      page:
                        type: integer
                        example: 1
                      per_page:
                        type: integer
                        example: 100
        '404':
          description: webhook not found
  "/nhsapi/v1/Webhooks/{id}/test":
    parameters:
    - name: id
      in: path
      description: Webhook ID
      required: true
      schema:
        type: integer
    post:
      summary: Test a webhook
      tags:
      - Webhooks
      description: |-
        Send a test webhook to the configured URL. The test webhook will include:
        - `X-Signature` header with HMAC-SHA256 signature
        - `X-Timestamp` header with Unix timestamp
        - Test event data with event_type: 'test'

        This allows you to verify your webhook endpoint is correctly configured.
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: test result
          content:
            application/json:
              examples:
                test_success:
                  value:
                    success: true
                    status_code: 200
                    body: OK
                    error:
                test_failure:
                  value:
                    success: false
                    status_code: 500
                    body: Internal Server Error
                    error: Internal Server Error
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Whether the test was successful
                    example: true
                  status_code:
                    type: integer
                    description: HTTP status code received
                    example: 200
                  body:
                    type: string
                    description: Response body received
                    example: OK
                  error:
                    type: string
                    nullable: true
                    description: Error message if test failed
        '404':
          description: webhook not found
  "/nhsapi/v1/Webhooks/{id}/regenerate_secret":
    parameters:
    - name: id
      in: path
      description: Webhook ID
      required: true
      schema:
        type: integer
    post:
      summary: Regenerate HMAC secret
      tags:
      - Webhooks
      parameters:
      - name: X-External-Account-Token
        in: header
        description: External account token for authentication
        schema:
          type: string
      responses:
        '200':
          description: secret regenerated
          content:
            application/json:
              examples:
                secret_regenerated:
                  value:
                    id: 1
                    hmac_secret: new_secret_at_least_32_characters_long_for_security
                    notice: HMAC secret regenerated. Store it securely. It will not
                      be shown again in full.
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    example: 1
                  hmac_secret:
                    type: string
                    description: The new HMAC secret
                    example: new_secret_at_least_32_characters_long_for_security
                  notice:
                    type: string
                    example: HMAC secret regenerated. Store it securely. It will not
                      be shown again in full.
        '404':
          description: webhook not found
        '422':
          description: invalid secret
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                hmac_secret:
                  type: string
                  description: Optional new HMAC secret (min 32 chars). If not provided,
                    will be auto-generated
                  example: new_secret_at_least_32_characters_long_for_security
servers:
- url: https://{defaultHost}
  variables:
    defaultHost:
      default: www.example.com
components:
  securitySchemes:
    externalAccountToken:
      type: apiKey
      name: X-External-Account-Token
      in: header
