openapi: 3.1.0
info:
  title: Nextvisit API
  description: API for the Nextvisit Clinical Documentation platform for developers
  version: 1.0.0
  termsOfService: https://nextvisit.app/terms-of-service/
  contact:
    name: Nextvisit Support
    email: hello@nextvisit.ai
  license:
    name: Proprietary
    url: https://nextvisit.app/terms-of-service/
servers:
  - url: https://nextvisit.app/api
    description: Production API
  - url: https://ea.nextvisit.app/api
    description: Beta API
tags:
  - name: Tokens
    description: >-
      User token management endpoints for secure access to the Nextvisit
      platform. Includes login, logout, and token management operations.
  - name: Users
    description: >-
      User account management including profile updates, permission settings,
      role assignments, and practice affiliations.
  - name: Progress Notes
    description: >-
      Clinical progress note management including creating, updating,
      retrieving, and signing notes with associated transcriptions and analyses.
  - name: Billing
    description: >-
      Billing and subscription management including plans, usage tracking, and
      cost estimates.
  - name: Transcription
    description: >-
      Audio transcription services including file upload transcription and
      temporary API tokens for client-side transcription.
  - name: Patients
    description: >-
      Patient management including creating, updating, retrieving, and searching
      patient records within your team.
paths:
  /user:
    get:
      summary: Get authenticated user
      description: Retrieves the currently authenticated user's details
      operationId: getAuthenticatedUser
      tags:
        - Users
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
              examples:
                default:
                  $ref: '#/components/examples/UserExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/auth/tokens:
    post:
      summary: Create a new access token
      description: >-
        Authenticates a user and issues a new access token. When API token
        verification is enabled (server configuration), users with enhanced
        security (2FA enabled or linked social providers like Google/Apple) must
        complete additional verification. Users with 2FA provide their
        authenticator code via `two_factor_code`. Users with linked social
        providers (without 2FA) receive a 6-digit OTP via email and provide it
        via `otp_code`.
      operationId: apiCreateToken
      tags:
        - Tokens
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
            examples:
              standard:
                $ref: '#/components/examples/LoginRequestExample'
              with_2fa:
                $ref: '#/components/examples/LoginRequestWith2FAExample'
              with_otp:
                $ref: '#/components/examples/LoginRequestWithOTPExample'
      responses:
        '200':
          description: Token successfully created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponse'
              examples:
                default:
                  $ref: '#/components/examples/TokenResponseExample'
        '403':
          description: Verification required - user must provide 2FA code or email OTP
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationRequiredResponse'
              examples:
                two_factor:
                  $ref: '#/components/examples/VerificationRequiredTwoFactorExample'
                email_otp:
                  $ref: '#/components/examples/VerificationRequiredEmailOTPExample'
        '422':
          $ref: '#/components/responses/Unprocessable'
    get:
      summary: List all access tokens
      description: Returns a list of the authenticated user's access tokens
      operationId: apiListTokens
      tags:
        - Tokens
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of tokens
          content:
            application/json:
              schema:
                type: object
                properties:
                  tokens:
                    type: array
                    items:
                      $ref: '#/components/schemas/TokenInfo'
              examples:
                default:
                  $ref: '#/components/examples/TokensListExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/auth/tokens/current:
    delete:
      summary: Revoke current token
      description: Revokes the current access token used for authentication
      operationId: apiRevokeCurrentToken
      tags:
        - Tokens
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Token successfully revoked
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Status message
                    example: Token revoked
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/auth/tokens/{id}:
    parameters:
      - $ref: '#/components/parameters/TokenId'
    delete:
      summary: Revoke specific token
      description: Revokes a specific access token by ID
      operationId: apiRevokeToken
      tags:
        - Tokens
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Token successfully revoked
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Status message
                    example: Token revoked
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/auth/google:
    post:
      summary: Authenticate with Google
      description: >-
        Authenticates a user using a Google ID token obtained from Google
        Sign-In (OAuth 2.0). This endpoint supports tokens from web
        applications, Chrome extensions, iOS apps, and Android apps. If the user
        doesn't exist, a new account is automatically created.
      operationId: apiGoogleAuth
      tags:
        - Tokens
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GoogleAuthRequest'
            examples:
              default:
                $ref: '#/components/examples/GoogleAuthRequestExample'
      responses:
        '200':
          description: Authentication successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GoogleAuthResponse'
              examples:
                existing_user:
                  $ref: '#/components/examples/GoogleAuthResponseExample'
                new_user:
                  $ref: '#/components/examples/GoogleAuthNewUserResponseExample'
        '422':
          description: Invalid Google ID token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: The given data was invalid.
                errors:
                  id_token:
                    - The provided Google ID token is invalid.
  /v1/progress-notes:
    get:
      summary: List progress notes
      description: Returns a paginated list of progress notes with optional filtering
      operationId: listProgressNotes
      tags:
        - Progress Notes
      security:
        - bearerAuth: []
      parameters:
        - name: patient_id
          in: query
          description: Filter notes by patient ID
          required: false
          schema:
            type: integer
        - name: per_page
          in: query
          description: Number of items per page (1-100)
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 15
        - name: sort_by
          in: query
          description: Sort order for results
          required: false
          schema:
            type: string
            enum:
              - latest
              - oldest
            default: latest
      responses:
        '200':
          description: List of progress notes
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ProgressNote'
                  links:
                    type: object
                    description: Pagination links
                  meta:
                    type: object
                    description: Pagination metadata
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Forbidden - User does not have permission to access these progress
            notes
    post:
      summary: Create a new progress note
      description: >-
        Creates a new progress note either with an audio file or as a text-only
        note
      operationId: createProgressNote
      tags:
        - Progress Notes
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              oneOf:
                - type: object
                  properties:
                    name:
                      type: string
                      description: Name or title of the progress note
                      maxLength: 255
                      example: Follow-up Visit - Jane Doe
                    patient_id:
                      type: integer
                      description: ID of the associated patient (optional)
                      example: 123
                    file:
                      type: string
                      format: binary
                      description: Audio file of the encounter
                    model_id:
                      type: integer
                      description: ID of the prompt/template to use (optional)
                      default: 1
                      example: 1
                    context:
                      type: string
                      description: Additional context information for the note (optional)
                      example: Patient reports improved sleep quality
                  required:
                    - name
                    - file
                - type: object
                  properties:
                    name:
                      type: string
                      description: Name or title of the progress note
                      maxLength: 170
                      example: Follow-up Visit - Jane Doe
                    note:
                      type: string
                      description: Text content of the note
                      minLength: 120
                      maxLength: 40000
                      example: >-
                        Patient presents for follow-up visit. Reports
                        improvement in symptoms since last visit. Sleep quality
                        has improved with current medication regimen. No adverse
                        effects reported.
                    model_id:
                      type: integer
                      description: ID of the prompt/template to use
                      example: 1
                    patient_id:
                      type: integer
                      description: ID of the associated patient (optional)
                      example: 123
                    context:
                      type: string
                      description: Additional context information for the note (optional)
                      example: Patient reports improved sleep quality
                    documents:
                      type: array
                      description: Array of document IDs to link to this note (optional)
                      items:
                        type: integer
                  required:
                    - name
                    - note
                    - model_id
      responses:
        '201':
          description: Progress note created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressNote'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Forbidden - User does not have permission to create notes for this
            patient
        '422':
          $ref: '#/components/responses/ValidationError'
  /v1/progress-notes/{id}:
    parameters:
      - name: id
        in: path
        description: Progress note unique identifier
        required: true
        schema:
          type: integer
    get:
      summary: Get a specific progress note
      description: Returns a single progress note by ID
      operationId: getProgressNote
      tags:
        - Progress Notes
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Progress note details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressNote'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Forbidden - User does not have permission to access this progress
            note
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      summary: Update a progress note
      description: Updates an existing progress note
      operationId: updateProgressNote
      tags:
        - Progress Notes
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: Name or title of the progress note
                  example: Follow-up Visit - Jane Doe
                transcription:
                  type: string
                  description: Transcribed content of the audio recording
                  example: Patient reports improvement in symptoms since last visit.
                analysis:
                  type: string
                  description: AI-generated analysis of the transcription
                  example: >-
                    Patient presents with improved symptoms. Continue current
                    treatment plan.
      responses:
        '200':
          description: Progress note updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressNote'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Forbidden - User does not have permission to modify this progress
            note
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
    delete:
      summary: Delete a progress note
      description: Deletes a progress note and its associated files
      operationId: deleteProgressNote
      tags:
        - Progress Notes
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Progress note deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Progress note deleted successfully
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Forbidden - User does not have permission to delete this progress
            note
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/progress-notes/{id}/sign:
    parameters:
      - name: id
        in: path
        description: Progress note unique identifier
        required: true
        schema:
          type: integer
    put:
      summary: Sign a progress note
      description: Marks a progress note as reviewed and signed
      operationId: signProgressNote
      tags:
        - Progress Notes
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Progress note signed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressNote'
        '400':
          description: >-
            Bad request - Cannot sign a note without completed transcription and
            analysis
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: >-
                      Cannot sign a progress note that does not have complete
                      transcription and analysis
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Forbidden - User does not have permission to sign this progress note
        '404':
          $ref: '#/components/responses/NotFound'
  /v1/progress-notes/{id}/audio-url:
    parameters:
      - name: id
        in: path
        description: Progress note unique identifier
        required: true
        schema:
          type: integer
    get:
      summary: Get audio file URL
      description: Returns a temporary signed URL to access the audio file
      operationId: getProgressNoteAudioUrl
      tags:
        - Progress Notes
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Audio URL generated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    description: Temporary URL to access the audio file
                    example: >-
                      https://storage.nextvisit.app/encounters/abc123.mp3?token=xyz
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Forbidden - User does not have permission to access this audio file
        '404':
          description: Not found - Progress note or audio file not found
  /v1/billing/plans:
    get:
      summary: List available billing plans
      description: >-
        Returns a list of all visible billing plans with their pricing and
        features
      operationId: listBillingPlans
      tags:
        - Billing
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of available billing plans
          content:
            application/json:
              schema:
                type: object
                properties:
                  plans:
                    type: array
                    items:
                      $ref: '#/components/schemas/BillingPlan'
              examples:
                default:
                  $ref: '#/components/examples/BillingPlansExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/billing/estimate:
    get:
      summary: Get billing cost estimate
      description: >-
        Returns an estimate of the current billing costs based on the number of
        users in the team
      operationId: getBillingEstimate
      tags:
        - Billing
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Billing cost estimate
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingEstimate'
              examples:
                default:
                  $ref: '#/components/examples/BillingEstimateExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/billing/usage/{module}:
    parameters:
      - name: module
        in: path
        description: The billing module to get usage for (e.g., 'notes')
        required: true
        schema:
          type: string
          example: notes
    get:
      summary: Get billing usage statistics
      description: >-
        Returns usage statistics for the current billing period including
        encounters, peer reviews, and documents
      operationId: getBillingUsage
      tags:
        - Billing
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Usage statistics for the current billing period
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingUsage'
              examples:
                default:
                  $ref: '#/components/examples/BillingUsageExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /v1/transcribe/file:
    post:
      summary: Transcribe audio file
      description: >-
        Uploads an audio file and returns the transcribed text using AI-powered
        speech recognition
      operationId: transcribeFile
      tags:
        - Transcription
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: >-
                    Audio file to transcribe. Supported formats: mp3, mp4, m4a,
                    wav, ogg, webm, flac, aac, pcm, opus. Maximum size: 200MB
              required:
                - file
      responses:
        '200':
          description: Transcription completed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptionResponse'
              examples:
                success:
                  $ref: '#/components/examples/TranscriptionSuccessExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Forbidden - User does not have a paid plan
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptionResponse'
              example:
                status: error
                success: false
                message: You must have a paid plan to use this feature.
                text: null
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          description: >-
            Too many requests - Rate limit exceeded (120 requests per 60
            seconds)
  /v1/transcribe/token:
    get:
      summary: Get temporary transcription token
      description: >-
        Returns a temporary speech-to-text API token for client-side websocket
        audio transcription. The token is short-lived and should be used
        immediately. Requires a paid plan.
      operationId: getTranscriptionToken
      tags:
        - Transcription
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Token retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptionTokenResponse'
              examples:
                success:
                  $ref: '#/components/examples/TranscriptionTokenSuccessExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Forbidden - User does not have a paid plan
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptionTokenResponse'
              example:
                success: false
                message: You must have a paid plan to use this feature.
                token: null
        '429':
          description: >-
            Too many requests - Rate limit exceeded (120 requests per 60
            seconds)
  /v1/patients:
    get:
      summary: List patients
      description: >-
        Returns a paginated list of patients for the current team with optional
        filtering, sorting, and includes
      operationId: listPatients
      tags:
        - Patients
      security:
        - bearerAuth: []
      parameters:
        - name: per_page
          in: query
          description: Number of items per page
          required: false
          schema:
            type: integer
            default: 50
        - name: sort
          in: query
          description: Sort field. Prefix with - for descending order (e.g., -created_at)
          required: false
          schema:
            type: string
            enum:
              - id
              - '-id'
              - first_name
              - '-first_name'
              - last_name
              - '-last_name'
              - date_of_birth
              - '-date_of_birth'
              - created_at
              - '-created_at'
              - updated_at
              - '-updated_at'
            default: '-created_at'
        - name: filter[first_name]
          in: query
          description: Filter by first name
          required: false
          schema:
            type: string
        - name: filter[last_name]
          in: query
          description: Filter by last name
          required: false
          schema:
            type: string
        - name: filter[date_of_birth]
          in: query
          description: Filter by date of birth
          required: false
          schema:
            type: string
            format: date
        - name: filter[trashed]
          in: query
          description: Include soft-deleted patients (with, only, or omit for none)
          required: false
          schema:
            type: string
            enum:
              - with
              - only
        - name: include
          in: query
          description: Comma-separated list of relationships to include
          required: false
          schema:
            type: string
            example: user,team,encounters,demographics
      responses:
        '200':
          description: List of patients
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PatientFull'
                  links:
                    type: object
                    description: Pagination links
                  meta:
                    type: object
                    description: Pagination metadata
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      summary: Create a patient
      description: Creates a new patient record for the current team
      operationId: createPatient
      tags:
        - Patients
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatientCreateRequest'
            examples:
              default:
                $ref: '#/components/examples/PatientCreateExample'
      responses:
        '200':
          description: Patient created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PatientFull'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/ValidationError'
        '500':
          description: Server error - Failed to create patient
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Failed to create patient
                  error:
                    type: string
                    example: Database connection error
  /v1/patients/{id}:
    parameters:
      - name: id
        in: path
        description: Patient unique identifier
        required: true
        schema:
          type: integer
    get:
      summary: Get a patient
      description: >-
        Returns a single patient by ID with related data including encounters
        and timeline events
      operationId: getPatient
      tags:
        - Patients
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Patient details
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PatientFull'
              examples:
                default:
                  $ref: '#/components/examples/PatientFullExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      summary: Update a patient
      description: Updates an existing patient record
      operationId: updatePatient
      tags:
        - Patients
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatientUpdateRequest'
      responses:
        '200':
          description: Patient updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PatientFull'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationError'
        '500':
          description: Server error - Failed to update patient
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Failed to update patient
                  error:
                    type: string
                    example: Database connection error
    delete:
      summary: Delete a patient
      description: Soft deletes a patient record
      operationId: deletePatient
      tags:
        - Patients
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Patient deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Patient deleted successfully
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: Server error - Failed to delete patient
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Failed to delete patient
                  error:
                    type: string
                    example: Database connection error
  /v1/patients/search:
    get:
      summary: Search patients
      description: >-
        Full-text search across all patients in the current team using
        Meilisearch
      operationId: searchPatients
      tags:
        - Patients
      security:
        - bearerAuth: []
      parameters:
        - name: query
          in: query
          description: Search query string
          required: true
          schema:
            type: string
            minLength: 1
        - name: per_page
          in: query
          description: Number of results per page (1-100)
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - name: sort_by
          in: query
          description: Sort order by updated_at
          required: false
          schema:
            type: string
            enum:
              - asc
              - desc
            default: desc
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PatientFull'
                  links:
                    type: object
                    description: Pagination links
                  meta:
                    type: object
                    description: Pagination metadata
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/ValidationError'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
  schemas:
    ProgressNote:
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: Unique identifier for the progress note
          example: 123
        name:
          type: string
          description: Name or title of the progress note
          example: Follow-up Visit - Jane Doe
        transcription:
          type: string
          description: Transcribed content of the audio recording
          example: Patient reports improvement in symptoms since last visit...
        analysis:
          type: string
          description: AI-generated analysis of the transcription
          example: Patient's condition has improved with current treatment regimen...
        template:
          type: object
          properties:
            id:
              type: integer
              description: Template ID used for this note
              example: 5
            name:
              type: string
              description: Name of the template
              example: Standard Follow-up
            description:
              type: string
              description: Description of the template
              example: Standard template for routine follow-up visits
        patient:
          allOf:
            - $ref: '#/components/schemas/PatientFull'
          description: Associated patient information
        audio:
          type: object
          properties:
            duration:
              type: number
              description: Duration of the audio in seconds
              example: 480
            bitrate:
              type: integer
              description: Bitrate of the audio file
              example: 128000
            size:
              type: integer
              description: Size of the audio file in bytes
              example: 7680000
            uploaded_at:
              type: string
              format: date-time
              description: When the audio was uploaded
              example: '2023-04-10T15:30:00Z'
            expires_at:
              type: string
              format: date-time
              description: When the audio file will expire
              example: '2023-05-10T15:30:00Z'
            file_url:
              type: string
              description: Temporary URL to access the audio file
              example: https://storage.nextvisit.app/encounters/abc123.mp3?token=xyz
        has:
          type: object
          properties:
            content:
              type: boolean
              description: Whether analysis has been completed
              example: true
            transcription:
              type: boolean
              description: Whether transcription has been completed
              example: true
            signed:
              type: boolean
              description: Whether the note has been reviewed and signed
              example: false
        team_id:
          type: integer
          description: ID of the team this note belongs to
          example: 5
        user_id:
          type: integer
          description: ID of the user who created this note
          example: 42
        user:
          allOf:
            - $ref: '#/components/schemas/User'
          description: Information about the user who created the note
        transcription_started_at:
          type: string
          format: date-time
          description: When transcription process started
          example: '2023-04-10T15:35:00Z'
        transcription_completed_at:
          type: string
          format: date-time
          description: When transcription was completed
          example: '2023-04-10T15:40:00Z'
        analysis_started_at:
          type: string
          format: date-time
          description: When analysis process started
          example: '2023-04-10T15:40:00Z'
        analysis_completed_at:
          type: string
          format: date-time
          description: When analysis was completed
          example: '2023-04-10T15:45:00Z'
        error_state:
          type:
            - string
            - 'null'
          description: Any error state during processing
          example: null
        created_at:
          type: string
          format: date-time
          description: When the progress note was created
          example: '2023-04-10T15:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the progress note was last updated
          example: '2023-04-10T15:45:00Z'
      required:
        - id
        - name
        - team_id
        - user_id
        - created_at
        - updated_at
    User:
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: Unique identifier for the user
          example: 12345
        name:
          type: string
          description: Full name of the user
          example: Dr. Sarah Johnson
        email:
          type: string
          format: email
          description: Email address of the user
          example: sarah.johnson@nextvisit.ai
        created_at:
          type: string
          format: date-time
          description: Timestamp when the user was created
          example: '2023-03-15T09:12:34Z'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the user was last updated
          example: '2023-05-22T14:07:53Z'
      required:
        - id
        - name
        - email
        - created_at
        - updated_at
    LoginRequest:
      type: object
      properties:
        email:
          type: string
          format: email
          description: User's email address
          example: user@nextvisit.app
        password:
          type: string
          format: password
          description: User's password
          example: secureP@ssw0rd!
        device_name:
          type: string
          description: Name of the device requesting the token
          example: iPhone 14 Pro
        two_factor_code:
          type: string
          description: >-
            TOTP code from authenticator app (required for users with 2FA
            enabled when API token verification is active). Recovery codes can
            also be used.
          example: '123456'
        otp_code:
          type: string
          description: >-
            6-digit verification code sent via email (required for users with
            linked social providers when API token verification is active)
          example: '123456'
      required:
        - email
        - password
        - device_name
    GoogleAuthRequest:
      type: object
      description: Request payload for Google Sign-In authentication
      properties:
        id_token:
          type: string
          description: Google ID token obtained from Google Sign-In SDK or OAuth 2.0 flow
          example: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
        device_name:
          type: string
          description: Name of the device or application requesting the token
          maxLength: 255
          example: Chrome Extension
      required:
        - id_token
        - device_name
    GoogleAuthResponse:
      type: object
      description: Response from successful Google authentication
      properties:
        status:
          type: string
          description: Status of the authentication request
          example: success
        token:
          type: string
          description: Authentication token value
          example: nv-sk-2|4qrD6iCn5FYhHyrdVX1IE4kk6RWg091WpboNklOC
        token_id:
          type: integer
          description: Unique identifier for the token
          example: 123
        user:
          type: object
          properties:
            id:
              type: integer
              description: User ID
              example: 1
            name:
              type: string
              description: User's full name
              example: John Doe
            current_team_id:
              type: integer
              description: ID of the user's current team
              example: 5
            email:
              type: string
              description: User's email address
              example: john.doe@example.com
        team:
          type: object
          properties:
            id:
              type: integer
              description: Team ID
              example: 5
            name:
              type: string
              description: Team name
              example: Medical Practice
        is_new_user:
          type: boolean
          description: >-
            Indicates if a new user account was created during this
            authentication
          example: false
      required:
        - status
        - token
        - token_id
        - user
        - team
        - is_new_user
    TokenResponse:
      type: object
      properties:
        status:
          type: string
          description: Status of the token request
          example: success
        token:
          type: string
          description: Authentication token value
          example: nv-sk-2|4qrD6iCn5FYhHyrdVX1IE4kk6RWg091WpboNklOC
        token_id:
          type: integer
          description: Unique identifier for the token
          example: 123
        user:
          type: object
          description: Basic information about the authenticated user
          properties:
            id:
              type: integer
              description: User's unique identifier
              example: 1
            name:
              type: string
              description: User's full name
              example: John Doe
            current_team_id:
              type: integer
              description: ID of the user's current team
              example: 5
            email:
              type: string
              format: email
              description: User's email address
              example: john.doe@example.com
        team:
          type: object
          description: Basic information about the user's current team
          properties:
            id:
              type: integer
              description: Team's unique identifier
              example: 5
            name:
              type: string
              description: Name of the team
              example: Medical Practice
      required:
        - status
        - token
        - token_id
        - user
        - team
    TokenInfo:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the token
          example: 123
        name:
          type: string
          description: Name of the device or application the token was created for
          example: iPhone 14 Pro
        created_at:
          type: string
          format: date-time
          description: When the token was created
          example: '2023-01-01T12:00:00.000000Z'
        last_used_at:
          type: string
          format: date-time
          description: When the token was last used
          example: '2023-01-02T14:30:00.000000Z'
      required:
        - id
        - name
        - created_at
    VerificationRequiredResponse:
      type: object
      description: >-
        Response indicating that additional verification is required to complete
        token generation
      properties:
        status:
          type: string
          description: Status indicating verification is required
          enum:
            - verification_required
          example: verification_required
        verification_type:
          type: string
          description: Type of verification required
          enum:
            - two_factor
            - email_otp
          example: two_factor
        message:
          type: string
          description: Human-readable message explaining what is required
          example: Please provide your two-factor authentication code.
      required:
        - status
        - verification_type
        - message
    BillingPlan:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the plan
          example: 1
        name:
          type: string
          description: Display name of the plan
          example: Pro
        slug:
          type: string
          description: URL-friendly identifier for the plan
          example: pro
        price:
          type: number
          description: Price of the plan per user
          example: 199
        price_prefix:
          type: string
          description: Currency symbol or prefix for price display
          example: $
        price_suffix:
          type: string
          description: Suffix for price display (e.g., per month)
          example: /user/month
        description:
          type: string
          description: Short description of the plan
          example: For growing practices
        features:
          type: array
          description: List of features included in the plan
          items:
            type: string
          example:
            - Unlimited notes
            - Priority support
            - Custom templates
      required:
        - id
        - name
        - slug
        - price
    BillingEstimate:
      type: object
      properties:
        users:
          type: integer
          description: Total number of users in the team and child teams
          example: 5
        total:
          type: number
          description: Total estimated cost
          example: 995
        total_formatted:
          type: string
          description: Formatted total cost with currency symbol
          example: $995.00
        renewal_date:
          type: string
          description: Next billing renewal date
          example: February 16th, 2026
      required:
        - users
        - total
        - total_formatted
        - renewal_date
    BillingUsage:
      type: object
      properties:
        plan:
          type: object
          description: Current subscription plan details
          properties:
            name:
              type: string
              description: Name of the subscribed plan
              example: pro
            status:
              type: string
              description: Current subscription status
              enum:
                - active
                - past_due
                - canceled
                - incomplete
                - incomplete_expired
                - trialing
                - paused
              example: active
            ends_at:
              type:
                - string
                - 'null'
              format: date
              description: Date when the subscription ends (if canceled)
              example: null
            active:
              type: boolean
              description: Whether the subscription is currently active
              example: true
            past_due:
              type: boolean
              description: Whether the subscription has past due payments
              example: false
            trial:
              type: object
              properties:
                has_expired_trial:
                  type: boolean
                  description: Whether the user had a trial that has expired
                  example: false
                on_trial:
                  type: boolean
                  description: Whether the user is currently on a trial
                  example: false
                trial_ends_at:
                  type:
                    - string
                    - 'null'
                  format: date
                  description: Date when the trial ends
                  example: null
        usage:
          type: object
          description: Usage statistics for the current billing period
          properties:
            used:
              type: number
              description: Total usage count (weighted sum of all items)
              example: 125
            peer_reviews:
              type: string
              description: Weighted count of peer reviews (0.25 per review)
              example: '25.00'
            encounters:
              type: string
              description: Count of encounters (1.0 per encounter)
              example: '75.00'
            documents:
              type: string
              description: Weighted count of documents (0.5 per document)
              example: '25.00'
            period_start:
              type: string
              description: Start date of the current billing period
              example: Jan 1st, 2026
            period_end:
              type: string
              description: End date of the current billing period
              example: Jan 31st, 2026
            resets_at:
              type: string
              format: date
              description: Date when usage resets
              example: '2026-01-31'
            limit:
              type: integer
              description: Maximum allowed usage for the current plan
              example: 1000
            updated:
              type: string
              description: Timestamp when usage was last calculated
              example: Jan 16 2026 10:30 AM
      required:
        - plan
        - usage
    TranscriptionResponse:
      type: object
      properties:
        status:
          type: string
          description: Status of the transcription request
          enum:
            - success
            - error
          example: success
        success:
          type: boolean
          description: Whether the transcription was successful
          example: true
        message:
          type: string
          description: Human-readable status message
          example: File uploaded successfully.
        text:
          type:
            - string
            - 'null'
          description: The transcribed text from the audio file
          example: >-
            Patient reports improvement in symptoms since last visit. Sleep
            quality has improved with the current medication regimen.
      required:
        - status
        - success
        - message
    TranscriptionTokenResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Whether the token was retrieved successfully
          example: true
        message:
          type: string
          description: Human-readable status message
          example: Token retrieved successfully.
        token:
          type:
            - string
            - 'null'
          description: Temporary API token for client-side transcription
          example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
      required:
        - success
        - message
    PatientFull:
      type: object
      properties:
        id:
          type: integer
          description: Unique identifier for the patient
          example: 789
        uuid:
          type: string
          format: uuid
          description: UUID for the patient
          example: 550e8400-e29b-41d4-a716-446655440000
        first_name:
          type: string
          description: Patient's first name
          example: Jane
        middle_name:
          type:
            - string
            - 'null'
          description: Patient's middle name
          example: Marie
        last_name:
          type: string
          description: Patient's last name
          example: Doe
        gender:
          type:
            - string
            - 'null'
          description: Patient's gender (when demographics are loaded)
          example: female
        date_of_birth:
          type: string
          format: date
          description: Patient's date of birth
          example: '1985-03-15'
        notes:
          type:
            - string
            - 'null'
          description: Clinical notes about the patient
          example: Patient has a history of anxiety. Prefers afternoon appointments.
        latest_medications:
          type: array
          description: List of current medications (when loaded)
          items:
            type: string
          example:
            - Sertraline 50mg
            - Lorazepam 0.5mg PRN
        user:
          allOf:
            - $ref: '#/components/schemas/User'
          description: User who created the patient (when loaded)
        timeline:
          type: array
          description: Patient timeline events (when loaded)
          items:
            type: object
        encounters:
          type: array
          description: Recent encounters/progress notes (when loaded)
          items:
            $ref: '#/components/schemas/ProgressNote'
        meta:
          type:
            - object
            - 'null'
          description: Additional metadata
          additionalProperties: true
        created_at:
          type: string
          format: date-time
          description: When the patient was created
          example: '2024-01-15T10:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the patient was last updated
          example: '2024-06-20T14:45:00Z'
      required:
        - id
        - uuid
        - first_name
        - last_name
        - date_of_birth
        - created_at
        - updated_at
    PatientCreateRequest:
      type: object
      properties:
        first_name:
          type: string
          description: Patient's first name
          maxLength: 255
          example: Jane
        middle_name:
          type:
            - string
            - 'null'
          description: Patient's middle name
          maxLength: 255
          example: Marie
        last_name:
          type: string
          description: Patient's last name
          maxLength: 255
          example: Doe
        date_of_birth:
          type: string
          format: date
          description: Patient's date of birth (must be before today)
          example: '1985-03-15'
        notes:
          type:
            - string
            - 'null'
          description: Clinical notes about the patient
          example: New patient referral from Dr. Smith
        allergies:
          type:
            - string
            - 'null'
          description: Known allergies
          example: Penicillin, Sulfa drugs
        insurance:
          type:
            - string
            - 'null'
          description: Insurance information
          example: Blue Cross Blue Shield
        meta:
          type:
            - object
            - 'null'
          description: Additional metadata
          additionalProperties: true
      required:
        - first_name
        - last_name
        - date_of_birth
    PatientUpdateRequest:
      type: object
      properties:
        first_name:
          type: string
          description: Patient's first name
          maxLength: 255
          example: Jane
        middle_name:
          type:
            - string
            - 'null'
          description: Patient's middle name
          maxLength: 255
          example: Marie
        last_name:
          type: string
          description: Patient's last name
          maxLength: 255
          example: Doe
        date_of_birth:
          type: string
          format: date
          description: Patient's date of birth (must be before today)
          example: '1985-03-15'
        notes:
          type:
            - string
            - 'null'
          description: Clinical notes about the patient
          example: Updated contact information
        allergies:
          type:
            - string
            - 'null'
          description: Known allergies
          example: Penicillin, Sulfa drugs
        meta:
          type:
            - object
            - 'null'
          description: Additional metadata
          additionalProperties: true
    Error:
      type: object
      properties:
        message:
          type: string
          description: Error message
          example: Validation failed
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          description: Detailed validation errors by field
          example:
            email:
              - The email must be a valid email address
              - The email has already been taken
            password:
              - The password must be at least 8 characters
            template_name:
              - This field is required
      required:
        - message
  parameters:
    TokenId:
      name: id
      in: path
      description: Identifier for a token
      required: true
      schema:
        type: integer
        format: int64
  responses:
    Unauthorized:
      description: Unauthorized access
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: Unauthorized
    Unprocessable:
      description: Unprocessable entity
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: The provided credentials are incorrect.
            errors:
              email:
                - The provided credentials are incorrect.
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: Resource not found
    ValidationError:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: The given data was invalid
            errors:
              name:
                - The name field is required
              content:
                - The content must be at least 10 characters
  examples:
    UserExample:
      value:
        id: 1
        name: John Doe
        email: john.doe@example.com
        created_at: '2023-01-15T08:30:00Z'
        updated_at: '2023-01-15T08:30:00Z'
    LoginRequestExample:
      summary: Standard login request
      value:
        email: john.doe@example.com
        password: securepassword123
        device_name: iPhone 14 Pro
    LoginRequestWith2FAExample:
      summary: Login with two-factor authentication code
      value:
        email: john.doe@example.com
        password: securepassword123
        device_name: iPhone 14 Pro
        two_factor_code: '123456'
    LoginRequestWithOTPExample:
      summary: Login with email OTP verification code
      value:
        email: john.doe@example.com
        password: securepassword123
        device_name: iPhone 14 Pro
        otp_code: '123456'
    VerificationRequiredTwoFactorExample:
      summary: Two-factor verification required
      value:
        status: verification_required
        verification_type: two_factor
        message: Please provide your two-factor authentication code.
    VerificationRequiredEmailOTPExample:
      summary: Email OTP verification required
      value:
        status: verification_required
        verification_type: email_otp
        message: A verification code has been sent to your email.
    GoogleAuthRequestExample:
      summary: Google Sign-In authentication request
      value:
        id_token: >-
          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiMTIzNDU2Nzg5MC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImF1ZCI6IjEyMzQ1Njc4OTAuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMjM0NTY3ODkwIiwiZW1haWwiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiSm9obiBEb2UiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EvZGVmYXVsdC11c2VyPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6IkRvZSIsImxvY2FsZSI6ImVuIiwiaWF0IjoxNjE2MjM5MDIyLCJleHAiOjE2MTYyNDI2MjJ9.signature
        device_name: Chrome Extension
    GoogleAuthResponseExample:
      summary: Successful authentication for existing user
      value:
        status: success
        token: nv-sk-2|4qrD6iCn5FYhHyrdVX1IE4kk6RWg091WpboNklOC
        token_id: 123
        user:
          id: 1
          name: John Doe
          current_team_id: 5
          email: john.doe@example.com
        team:
          id: 5
          name: Medical Practice
        is_new_user: false
    GoogleAuthNewUserResponseExample:
      summary: Successful authentication with new user creation
      value:
        status: success
        token: nv-sk-2|4qrD6iCn5FYhHyrdVX1IE4kk6RWg091WpboNklOC
        token_id: 124
        user:
          id: 42
          name: Jane Smith
          current_team_id: 10
          email: jane.smith@example.com
        team:
          id: 10
          name: Jane Smith's Team
        is_new_user: true
    TokenResponseExample:
      value:
        status: success
        token: nv-sk-2|4qrD6iCn5FYhHyrdVX1IE4kk6RWg091WpboNklOC
        token_id: 123
        user:
          id: 1
          name: John Doe
          current_team_id: 5
          email: john.doe@example.com
        team:
          id: 5
          name: Medical Practice
    TokensListExample:
      value:
        tokens:
          - id: 123
            name: iPhone 14 Pro
            created_at: '2023-01-01T12:00:00.000000Z'
            last_used_at: '2023-01-02T14:30:00.000000Z'
          - id: 124
            name: MacBook Pro
            created_at: '2023-01-10T09:15:00.000000Z'
            last_used_at: '2023-01-10T15:22:00.000000Z'
    BillingPlansExample:
      value:
        plans:
          - id: 1
            name: Starter
            slug: starter
            price: 99
            price_prefix: $
            price_suffix: /user/month
            description: For individual practitioners
            features:
              - 50 notes per month
              - Basic support
              - Standard templates
          - id: 2
            name: Pro
            slug: pro
            price: 199
            price_prefix: $
            price_suffix: /user/month
            description: For growing practices
            features:
              - 1000 notes per month
              - Priority support
              - Custom templates
              - Team management
          - id: 3
            name: Enterprise
            slug: enterprise
            price: 299
            price_prefix: $
            price_suffix: /user/month
            description: For large organizations
            features:
              - Unlimited notes
              - Dedicated support
              - Custom integrations
              - SSO
              - Advanced analytics
    BillingEstimateExample:
      value:
        users: 5
        total: 995
        total_formatted: $995.00
        renewal_date: February 16th, 2026
    BillingUsageExample:
      value:
        plan:
          name: pro
          status: active
          ends_at: null
          active: true
          past_due: false
          trial:
            has_expired_trial: false
            on_trial: false
            trial_ends_at: null
        usage:
          used: 125
          peer_reviews: '25.00'
          encounters: '75.00'
          documents: '25.00'
          period_start: Jan 1st, 2026
          period_end: Jan 31st, 2026
          resets_at: '2026-01-31'
          limit: 1000
          updated: Jan 16 2026 10:30 AM
    TranscriptionSuccessExample:
      value:
        status: success
        success: true
        message: File uploaded successfully.
        text: >-
          Patient reports improvement in symptoms since last visit. Sleep
          quality has improved with the current medication regimen. No side
          effects noted. Will continue current treatment plan and follow up in
          four weeks.
    TranscriptionTokenSuccessExample:
      value:
        success: true
        message: Token retrieved successfully.
        token: >-
          eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    PatientCreateExample:
      value:
        first_name: Jane
        middle_name: Marie
        last_name: Doe
        date_of_birth: '1985-03-15'
        notes: >-
          New patient referral from Dr. Smith. History of anxiety and
          depression.
        allergies: Penicillin, Sulfa drugs
        insurance: Blue Cross Blue Shield
    PatientFullExample:
      value:
        data:
          id: 789
          uuid: 550e8400-e29b-41d4-a716-446655440000
          first_name: Jane
          middle_name: Marie
          last_name: Doe
          gender: female
          date_of_birth: '1985-03-15'
          notes: Patient has a history of anxiety. Prefers afternoon appointments.
          latest_medications:
            - Sertraline 50mg daily
            - Lorazepam 0.5mg PRN
          user:
            id: 42
            name: Dr. Sarah Johnson
            email: sarah.johnson@nextvisit.ai
            created_at: '2023-03-15T09:12:34Z'
            updated_at: '2024-05-22T14:07:53Z'
          encounters:
            - id: 123
              name: Follow-up Visit
              team_id: 5
              user_id: 42
              created_at: '2024-06-15T14:30:00Z'
              updated_at: '2024-06-15T15:45:00Z'
          meta:
            preferred_contact: email
            emergency_contact: John Doe (555) 123-4567
          created_at: '2024-01-15T10:30:00Z'
          updated_at: '2024-06-20T14:45:00Z'
