openapi: 3.1.0
info:
  title: Baltique OS Native Mobile API
  version: 1.0.0
  description: >-
    JSON API for the native Baltique OS staff application. It is independent
    from the WWW rendering layer. High-risk clinical actions remain explicit,
    online and audited.
servers:
  - url: https://baltique.pl/api/mobile/v1
security:
  - bearerAuth: []
tags:
  - name: Authentication
  - name: Workspace
  - name: Patients
  - name: Work Queue
  - name: Cases
  - name: Surgery day
  - name: PACU
  - name: Laboratory
  - name: Communication
  - name: Notifications
paths:
  /health:
    get:
      security: []
      responses:
        '200': { description: API health }
  /auth/login:
    post:
      security: []
      tags: [Authentication]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password, device]
              properties:
                email: { type: string, format: email }
                password: { type: string, format: password }
                device: { $ref: '#/components/schemas/Device' }
      responses:
        '201': { description: Session created }
        '401': { description: Invalid credentials }
        '429': { description: Login rate limited }
  /auth/refresh:
    post:
      security: []
      tags: [Authentication]
      responses:
        '200': { description: Rotated access and refresh tokens }
  /auth/logout:
    post:
      tags: [Authentication]
      responses:
        '200': { description: Session revoked }
  /me/bootstrap:
    get:
      tags: [Workspace]
      responses:
        '200': { description: Current user, role, capabilities, sites and dashboard }
  /sites:
    get:
      tags: [Workspace]
      responses:
        '200': { description: Sites visible to the current user }
  /sites/context:
    put:
      tags: [Workspace]
      responses:
        '200': { description: Active site context changed }
  /dashboard:
    get:
      tags: [Workspace]
      responses:
        '200': { description: Role-specific operational summary }
  /patients:
    get:
      tags: [Patients]
      parameters:
        - { name: q, in: query, schema: { type: string } }
        - { name: page, in: query, schema: { type: integer, minimum: 1 } }
      responses:
        '200': { description: Site-scoped patient list }
    post:
      tags: [Patients]
      parameters:
        - { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
      responses:
        '201': { description: Patient created after explicit staff confirmation }
  /patients/{id}:
    get:
      tags: [Patients]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: Patient detail } }
    patch:
      tags: [Patients]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: Patient contact/language/address updated } }
  /intake/document:
    post:
      tags: [Patients]
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required: [file]
              properties: { file: { type: string, format: binary } }
      responses: { '201': { description: OCR session created and extracted } }
  /intake/camera:
    post:
      tags: [Patients]
      responses: { '201': { description: Camera capture stored and extracted } }
  /intake/{id}/confirm:
    post:
      tags: [Patients]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '201': { description: Patient created from reviewed OCR proposal } }
  /work-items:
    get:
      tags: [Work Queue]
      responses: { '200': { description: Role and site scoped work queue } }
  /work-items/{id}:
    patch:
      tags: [Work Queue]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: Work item status changed and audited } }
  /cases:
    get:
      tags: [Cases]
      responses: { '200': { description: Case Spine list } }
  /cases/{id}:
    get:
      tags: [Cases]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: Case detail with tasks and events } }
  /schedule:
    get:
      tags: [Workspace]
      responses: { '200': { description: Calendar range } }
  /or-day:
    get:
      tags: [Surgery day]
      responses: { '200': { description: Surgery day board and canonical events } }
  /or-events:
    post:
      tags: [Surgery day]
      responses: { '201': { description: Explicit observed OR event recorded } }
  /pacu:
    get:
      tags: [PACU]
      responses: { '200': { description: Active PACU episodes } }
  /pacu/{id}:
    patch:
      tags: [PACU]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: PACU/discharge state updated } }
  /aftercare:
    get:
      tags: [PACU]
      responses: { '200': { description: Active aftercare episodes } }
  /labs:
    get:
      tags: [Laboratory]
      responses: { '200': { description: Governed pre-op laboratory reviews } }
  /labs/{id}:
    get:
      tags: [Laboratory]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: Analysis, evidence and patient draft } }
  /labs/{id}/decision:
    post:
      tags: [Laboratory]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: Explicit surgeon/anesthesiologist decision } }
  /communications:
    get:
      tags: [Communication]
      responses: { '200': { description: Communication Hub threads } }
  /communications/{id}:
    get:
      tags: [Communication]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '200': { description: Thread messages } }
  /communications/{id}/drafts:
    post:
      tags: [Communication]
      parameters: [ { $ref: '#/components/parameters/Id' } ]
      responses: { '201': { description: Draft created; never auto-sent } }
  /inventory:
    get:
      tags: [Workspace]
      responses: { '200': { description: Available canonical inventory data } }
  /notifications:
    get:
      tags: [Notifications]
      responses: { '200': { description: Secure in-app notifications } }
  /devices/push:
    put:
      tags: [Notifications]
      responses: { '200': { description: Device push token registered encrypted at rest } }
  /search:
    get:
      tags: [Workspace]
      responses: { '200': { description: Role/site scoped search } }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: opaque
  parameters:
    Id:
      name: id
      in: path
      required: true
      schema: { type: integer, minimum: 1 }
  schemas:
    Device:
      type: object
      required: [uid, platform]
      properties:
        uid: { type: string, maxLength: 120 }
        platform: { type: string, enum: [ios, android] }
        app_version: { type: string }
        build_number: { type: string }
        os_version: { type: string }
        manufacturer: { type: string }
        model: { type: string }
        locale: { type: string }
        timezone: { type: string }
