openapi: 3.1.0
info:
  title: Nuora Health API
  version: 1.0.0
  description: |
    Nuora Health is a UK-based pharmacy platform offering 9 clinical services.
    AI agents can discover services, check eligibility, book consultations, and
    manage patient notifications.

    GPhC Registered (#1039035) | CQC Registered (#1-1997598861)
    Area served: England and Wales
  contact:
    name: Nuora Support
    email: support@nuorahealth.com
    url: https://nuorahealth.com
  license:
    name: Proprietary

servers:
  - url: https://nuorahealth.com/api/v1
    description: Production

security: []

paths:
  /services:
    get:
      operationId: listServices
      summary: List all available pharmacy services
      description: Returns all 9 clinical services with pricing, eligibility info, and booking URLs. No authentication required.
      tags: [Services]
      responses:
        '200':
          description: Service catalog
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceCatalogResponse'
              example:
                services:
                  - slug: weight
                    name: Weight Loss
                    category: Endocrinology
                    description: "Lose Weight. Love Life. — UK's premier medical weight management program."
                    pricing:
                      headline: "£189 all-inclusive per month"
                      from_price: 189
                      currency: GBP
                    eligibility_url: /api/v1/eligibility/check
                    booking_url: /api/v1/bookings
                    nhs_funded: false
                    area_served: [England, Wales]
                provider:
                  name: NUORA
                  legal_name: NUORA LTD
                  url: https://nuorahealth.com
                  gphc_number: "1039035"
                  cqc_registration: "1-1997598861"
                _links:
                  self: /api/v1/services
                  openapi: /openapi.yaml
                  agent_card: /.well-known/agent.json

  /services/{slug}:
    get:
      operationId: getServiceDetails
      summary: Get detailed information about a specific service
      description: Returns comprehensive service details including eligibility criteria, pricing tiers, process steps, demographics, and NHS comparison data.
      tags: [Services]
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
            enum: [weight, mens-ed, hair, hrt, sexual, derm, allergy, vape, longevity]
          description: Service identifier
      responses:
        '200':
          description: Service details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceDetailResponse'
        '404':
          description: Service not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /eligibility/check:
    post:
      operationId: checkEligibility
      summary: Check patient eligibility for a service
      description: |
        Basic eligibility screening. No authentication required. Does not store PHI.
        For weight loss: checks age (18+) and BMI thresholds (27 with comorbidities, 30 without).
      tags: [Clinical]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EligibilityCheckRequest'
            example:
              service_slug: weight
              patient_age: 35
              answers:
                bmi: 32
      responses:
        '200':
          description: Eligibility result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EligibilityCheckResponse'
              example:
                eligible: true
                outcome: green
                reasons: ["Patient appears eligible for Weight Loss"]
                next_steps: ["Proceed to full clinical assessment", "Book a pharmacist consultation"]
                service:
                  name: Weight Loss
                  slug: weight
                _links:
                  booking: /api/v1/bookings
                  service_detail: /api/v1/services/weight
        '404':
          $ref: '#/components/responses/NotFound'

  /bookings:
    post:
      operationId: createBooking
      summary: Book a pharmacist consultation
      description: Schedule a video consultation. Requires API key with write:bookings scope. Patient consent is mandatory.
      tags: [Bookings]
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateBookingRequest'
            example:
              service_slug: weight
              patient:
                name: Jane Smith
                phone: "+447700900123"
                email: jane@example.com
              preferred_time: "2026-02-14T10:00:00Z"
              consent: true
      responses:
        '201':
          description: Booking created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BookingResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /bookings/{id}:
    get:
      operationId: getBookingStatus
      summary: Check booking status
      description: Retrieve the current status of a booking. Requires API key with write:bookings scope.
      tags: [Bookings]
      security:
        - ApiKeyAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Booking details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BookingDetailResponse'
        '404':
          $ref: '#/components/responses/NotFound'

  /notifications:
    post:
      operationId: createNotification
      summary: Send a patient notification
      description: Queue a notification to a patient via SMS, WhatsApp, or email. Requires API key with write:notifications scope. Patient must exist in the system.
      tags: [Notifications]
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateNotificationRequest'
      responses:
        '201':
          description: Notification queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationResponse'
        '404':
          description: Patient not found

  /auth/register:
    post:
      operationId: registerApiKey
      summary: Register for an API key
      description: Create an API key for accessing authenticated endpoints. Key is shown once — store it securely.
      tags: [Authentication]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterKeyRequest'
            example:
              name: My AI Agent
              email: developer@example.com
              scopes: [read:services, write:bookings]
      responses:
        '201':
          description: API key created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegisterKeyResponse'

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Nuora-API-Key
      description: "API key prefixed with nuora_pk_. Register at POST /auth/register."

  responses:
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Insufficient scope
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
      required: [error]

    ServiceCatalogResponse:
      type: object
      properties:
        services:
          type: array
          items:
            $ref: '#/components/schemas/ServiceSummary'
        provider:
          $ref: '#/components/schemas/Provider'
        _links:
          type: object
          properties:
            self:
              type: string
            openapi:
              type: string
            agent_card:
              type: string

    ServiceSummary:
      type: object
      properties:
        slug:
          type: string
        name:
          type: string
        category:
          type: string
        description:
          type: string
        pricing:
          type: object
          properties:
            headline:
              type: string
            from_price:
              type: number
            currency:
              type: string
        eligibility_url:
          type: string
        booking_url:
          type: string
        nhs_funded:
          type: boolean
        area_served:
          type: array
          items:
            type: string

    ServiceDetailResponse:
      type: object
      properties:
        slug:
          type: string
        name:
          type: string
        category:
          type: string
        description:
          type: string
        tagline:
          type: string
        eligibility:
          type: object
          properties:
            summary:
              type: string
            criteria:
              type: array
              items:
                type: string
            min_age:
              type: integer
            assessment_url:
              type: string
        pricing:
          type: object
          properties:
            headline:
              type: string
            tiers:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                  price:
                    type: number
                  currency:
                    type: string
                  unit:
                    type: string
                  description:
                    type: string
            currency:
              type: string
        process:
          type: array
          items:
            type: object
            properties:
              step:
                type: integer
              title:
                type: string
              description:
                type: string
              time:
                type: string
        demographics:
          type: object
          nullable: true
          properties:
            primary_age:
              type: string
            primary_gender:
              type: string
        nhs_comparison:
          type: object
          nullable: true
          properties:
            gp_wait_time:
              type: string
            our_response_time:
              type: string
            nhs_available:
              type: boolean
        advantages:
          type: array
          items:
            type: string
        actions:
          type: object
          properties:
            start_assessment:
              $ref: '#/components/schemas/Action'
            book_consultation:
              $ref: '#/components/schemas/Action'
        _links:
          type: object

    Action:
      type: object
      properties:
        label:
          type: string
        url:
          type: string

    Provider:
      type: object
      properties:
        name:
          type: string
        legal_name:
          type: string
        url:
          type: string
        gphc_number:
          type: string
        cqc_registration:
          type: string

    EligibilityCheckRequest:
      type: object
      required: [service_slug]
      properties:
        service_slug:
          type: string
          description: Service to check eligibility for
          enum: [weight, mens-ed, hair, hrt, sexual, derm, allergy, vape, longevity]
        patient_age:
          type: integer
          minimum: 0
          maximum: 150
        answers:
          type: object
          description: Service-specific answers (e.g. bmi for weight loss)

    EligibilityCheckResponse:
      type: object
      properties:
        eligible:
          type: boolean
        outcome:
          type: string
          enum: [green, amber, red]
        reasons:
          type: array
          items:
            type: string
        next_steps:
          type: array
          items:
            type: string
        service:
          type: object
          properties:
            name:
              type: string
            slug:
              type: string
        _links:
          type: object

    CreateBookingRequest:
      type: object
      required: [service_slug, patient, consent]
      properties:
        service_slug:
          type: string
        patient:
          type: object
          required: [name, phone]
          properties:
            name:
              type: string
            phone:
              type: string
            email:
              type: string
              format: email
        preferred_time:
          type: string
          format: date-time
        notes:
          type: string
          maxLength: 2000
        consent:
          type: boolean
          description: Must be true. Patient consent for booking.
          const: true

    BookingResponse:
      type: object
      properties:
        booking_id:
          type: string
        status:
          type: string
        service:
          type: object
          properties:
            name:
              type: string
            slug:
              type: string
        datetime:
          type: string
        _links:
          type: object

    BookingDetailResponse:
      type: object
      properties:
        booking_id:
          type: string
        status:
          type: string
        service_code:
          type: string
        patient_name:
          type: string
          x-phi: true
        datetime:
          type: string
        pharmacist_name:
          type: string
        video_link:
          type: string
        created_at:
          type: string
        _links:
          type: object

    CreateNotificationRequest:
      type: object
      required: [patient_phone, message, channel]
      properties:
        patient_phone:
          type: string
          x-phi: true
        message:
          type: string
          maxLength: 1000
        channel:
          type: string
          enum: [sms, whatsapp, email]
        priority:
          type: string
          enum: [low, normal, high]
          default: normal

    NotificationResponse:
      type: object
      properties:
        notification_id:
          type: string
        status:
          type: string
        channel:
          type: string

    RegisterKeyRequest:
      type: object
      required: [name, email]
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        scopes:
          type: array
          items:
            type: string
            enum: [read:services, write:bookings, write:notifications]

    RegisterKeyResponse:
      type: object
      properties:
        key_id:
          type: string
        api_key:
          type: string
          description: Store securely. Shown once only.
        scopes:
          type: array
          items:
            type: string
        rate_limit_tier:
          type: string
        message:
          type: string
        usage:
          type: object
          properties:
            header:
              type: string
            bearer:
              type: string

tags:
  - name: Services
    description: Browse and discover pharmacy services
  - name: Clinical
    description: Clinical workflows (eligibility, prescriptions)
  - name: Bookings
    description: Schedule and manage consultations
  - name: Notifications
    description: Patient communication
  - name: Authentication
    description: API key management
