openapi: 3.0.3
info:
  title: Health Export Pro — REST API Payload
  description: |
    Schema for the JSON payload that Health Export Pro sends to your server.

    Health Export Pro does **not** host an API — it acts as a client that POSTs
    health data to a server you control. This spec describes the request your
    server will receive so you can validate payloads, generate client stubs,
    or import into tools like Postman.
  version: "1.0.0"
  contact:
    name: Health Export Pro Support
    email: support@youngsoftware.org
  license:
    name: Proprietary
    url: https://healthexportpro.com/terms/

servers:
  - url: "{scheme}://{host}"
    description: Your receiver base URL
    variables:
      scheme:
        default: https
        enum: [https, http]
      host:
        default: your-server.example.com
        description: Hostname and optional port, e.g. api.example.com or 192.168.1.100:3000

paths:
  /api/health-data:
    post:
      operationId: receiveHealthData
      summary: Receive a health data export
      description: |
        The default endpoint path (`/api/health-data`) is configurable in the
        app's Settings screen. Your server should accept a POST at whatever
        path you configure and return any 2xx status.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/HealthDataPayload"
      responses:
        "200":
          description: Success — data accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "401":
          description: Unauthorized — check API key and auth type
        "413":
          description: Payload too large — increase your server's body size limit
      security:
        - bearerAuth: []
        - customHeader: []
        - {}

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: "Authorization: Bearer {api_key}"
    customHeader:
      type: apiKey
      in: header
      name: X-API-Key
      description: Custom header name and value (both configurable in app)

  schemas:
    HealthDataPayload:
      type: object
      required: [exportDate, startDate, endDate, syncSource, data]
      properties:
        exportDate:
          type: string
          format: date-time
          description: When the export was created
          example: "2026-02-26T12:00:00.000Z"
        startDate:
          type: string
          format: date-time
          description: Start of the exported date range
          example: "2026-02-25T00:00:00.000Z"
        endDate:
          type: string
          format: date-time
          description: End of the exported date range
          example: "2026-02-26T00:00:00.000Z"
        syncSource:
          type: string
          description: |
            How the export was triggered. Current values used by the app are
            `manual-upload`, `background-delivery`, and `widget`.
          example: manual-upload
        characteristics:
          $ref: "#/components/schemas/Characteristics"
        data:
          $ref: "#/components/schemas/HealthData"
        workoutRoutes:
          type: object
          description: GPS routes keyed by workout UUID
          additionalProperties:
            type: array
            items:
              $ref: "#/components/schemas/WorkoutRoute"

    Characteristics:
      type: object
      properties:
        biologicalSex:
          type: string
          enum: [male, female, other, notSet]
          description: User's biological sex from HealthKit

    HealthData:
      type: object
      description: |
        Health samples keyed by HealthKit type identifier. Quantity types
        (e.g. `HKQuantityTypeIdentifierHeartRate`) and category types
        (e.g. `HKCategoryTypeIdentifierSleepAnalysis`) are arrays of samples.
        Special sections use keys such as `workouts`, `medicationDoseEvents`,
        and `medications`.
      properties:
        workouts:
          type: array
          items:
            $ref: "#/components/schemas/WorkoutSample"
        medicationDoseEvents:
          type: array
          items:
            $ref: "#/components/schemas/MedicationDoseEvent"
        medications:
          type: array
          items:
            $ref: "#/components/schemas/MedicationDefinition"
      additionalProperties:
        type: array
        description: Array of quantity, category, correlation, ECG, audiogram, or state-of-mind samples for a given key
        items:
          $ref: "#/components/schemas/QuantitySample"

    QuantitySample:
      type: object
      required: [uuid, value, startDate, endDate]
      description: A quantity or category sample from HealthKit
      properties:
        uuid:
          type: string
          format: uuid
          description: HealthKit sample UUID
          example: "A1B2C3D4-E5F6-7890-ABCD-EF1234567890"
        value:
          type: number
          description: |
            Measured quantity (for quantity types) or integer category value
            (for category types like sleep analysis)
          example: 72
        unit:
          type: string
          description: |
            HealthKit unit string. Present for quantity types, absent for
            category types.
          example: "count/min"
        startDate:
          type: string
          format: date-time
          description: Sample start time
        endDate:
          type: string
          format: date-time
          description: Sample end time
        metadata:
          type: object
          description: HealthKit metadata dictionary (varies by sample)
          additionalProperties: true
        sourceRevision:
          $ref: "#/components/schemas/SourceRevision"
        device:
          $ref: "#/components/schemas/Device"

    WorkoutSample:
      type: object
      required: [uuid, workoutActivityType, durationSeconds, startDate, endDate]
      properties:
        uuid:
          type: string
          format: uuid
        workoutActivityType:
          type: integer
          description: HealthKit HKWorkoutActivityType raw value (e.g. 37 = running)
          example: 37
        durationSeconds:
          type: number
          description: Raw Apple Health workout duration in seconds
          example: 3600
        startDate:
          type: string
          format: date-time
        endDate:
          type: string
          format: date-time
        totalEnergyBurned:
          type: number
          description: Active calories in kcal
          example: 450.5
        totalDistance:
          type: number
          description: Distance value
          example: 5200
        totalDistanceUnit:
          type: string
          description: Distance unit
          example: "m"
        allStatistics:
          type: object
          description: Workout statistics keyed by HK type identifier
          additionalProperties: true
        events:
          type: array
          description: Pause, resume, and lap markers
          items:
            type: object
            additionalProperties: true
        activities:
          type: array
          description: Segmented workout activities
          items:
            type: object
            additionalProperties: true
        metadata:
          type: object
          additionalProperties: true

    MedicationDoseEvent:
      type: object
      required: [uuid, startDate, endDate]
      properties:
        uuid:
          type: string
          format: uuid
        medicationName:
          type: string
          description: Medication display name when available
          example: "Aspirin 81mg"
        medicationNickname:
          type: string
          description: Optional nickname from Apple Health
        scheduleType:
          type: integer
          description: HealthKit medication schedule type raw value
        logStatus:
          type: integer
          description: HealthKit medication log status raw value
        doseQuantity:
          type: number
          description: Dose quantity when available
        unit:
          type: string
          description: Dose unit
        startDate:
          type: string
          format: date-time
        endDate:
          type: string
          format: date-time
        metadata:
          type: object
          additionalProperties: true

    MedicationDefinition:
      type: object
      properties:
        nickname:
          type: string
        displayText:
          type: string
          example: "Aspirin 81mg"
        isArchived:
          type: boolean
        hasSchedule:
          type: boolean
        generalForm:
          type: string

    WorkoutRoute:
      type: object
      properties:
        locations:
          type: array
          items:
            $ref: "#/components/schemas/RouteLocation"

    RouteLocation:
      type: object
      properties:
        latitude:
          type: number
          example: 47.1234
        longitude:
          type: number
          example: 8.5678
        altitude:
          type: number
          description: Altitude in meters
          example: 450.0
        speed:
          type: number
          description: Speed in m/s
          example: 2.5
        course:
          type: number
          description: Direction of travel in degrees (0-360)
          example: 180.0
        date:
          type: string
          format: date-time
        horizontalAccuracy:
          type: number
          example: 5.0
        verticalAccuracy:
          type: number
          example: 3.0
        speedAccuracy:
          type: number
          example: 0.5
        distance:
          type: number
          description: Distance from previous point in meters
          example: 10.2

    SourceRevision:
      type: object
      properties:
        source:
          type: object
          properties:
            name:
              type: string
              example: "Apple Watch"
            bundleIdentifier:
              type: string
              example: "com.apple.health.123"
        version:
          type: string
          example: "11.0"
        operatingSystemVersion:
          type: string
          example: "11.0.0"
        productType:
          type: string
          example: "Watch7,3"

    Device:
      type: object
      properties:
        name:
          type: string
          example: "Apple Watch"
        manufacturer:
          type: string
          example: "Apple Inc."
        model:
          type: string
          example: "Watch"
        hardwareVersion:
          type: string
          example: "Watch7,3"
        softwareVersion:
          type: string
          example: "11.0"

    SuccessResponse:
      type: object
      description: |
        Optional response body. The app accepts any 2xx as success. If you
        return a count, the app displays it in the sync log.
      properties:
        ok:
          type: boolean
          example: true
        count:
          type: integer
          description: Total records stored
          example: 42
        inserted:
          type: object
          properties:
            measurements:
              type: integer
              example: 1250
            medications:
              type: integer
              example: 12
            workouts:
              type: integer
              example: 3
            workoutRoutes:
              type: integer
              example: 4821
