openapi: 3.1.0
info:
  title: Taiga Partner API
  version: 1.0.0
  summary: Partner-facing API for onboarding providers and submitting therapy sessions for billing.
  description: >
    The Taiga Partner API lets therapy platforms onboard providers, submit
    sessions for billing, and monitor claim status. All endpoints are scoped to
    the authenticated partner organization.
servers:
  - url: https://api.usetaiga.com
    description: Production
tags:
  - name: Providers
    description: Onboard and update partner-owned providers and practices.
  - name: Payers
    description: Search insurance payers for autocomplete and payer IDs.
  - name: Sessions
    description: Submit, list, inspect, and update partner-owned sessions.
security:
  - BearerAuth: []
paths:
  /api/v1/partner/providers:
    post:
      tags:
        - Providers
      operationId: onboardProvider
      summary: Onboard a provider
      description: >
        Registers a provider and practice for the authenticated partner
        organization. The call is idempotent within a partner organization.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OnboardProviderRequest'
            examples:
              default:
                value:
                  provider:
                    firstName: Jane
                    lastName: Smith
                    npi: "1234567890"
                    taxonomyCode: 103T00000X
                    specialty: Clinical Psychologist
                    credentials: PhD
                  practice:
                    name: Smith Therapy Associates
                    taxId: "123456789"
                    address:
                      street: 100 Main Street
                      line2: Suite 200
                      city: New York
                      state: NY
                      zip: "10001"
                    phone: "2125551234"
                    contactName: Jane Smith
      responses:
        '201':
          description: Provider and practice created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProviderMutationResponse'
        '200':
          description: Provider already exists for this partner.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProviderMutationResponse'
        '400':
          description: Missing or invalid required fields.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Provider NPI is already registered to another partner organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/partner/payers/search:
    get:
      tags:
        - Payers
      operationId: searchPayers
      summary: Search payers
      description: >
        Searches insurance payers for autocomplete. Use the returned
        `payerName` as the insurance carrier name and send `payerId` alongside
        it when available.
      parameters:
        - $ref: '#/components/parameters/PayerSearchQuery'
      responses:
        '200':
          description: Matching payers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PayerSearchResponse'
        '400':
          description: Missing or invalid query.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Upstream payer search failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/partner/providers/{npi}:
    patch:
      tags:
        - Providers
      operationId: updateProvider
      summary: Update a provider
      description: >
        Updates an existing partner-owned provider and/or practice. Only fields
        included in the request body are changed.
      parameters:
        - $ref: '#/components/parameters/NpiPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProviderRequest'
            examples:
              default:
                value:
                  provider:
                    credentials: PsyD
                  practice:
                    phone: "2125559999"
                    address:
                      street: 200 New Street, Suite 300
                      city: New York
                      state: NY
                      zip: "10002"
      responses:
        '200':
          description: Provider and/or practice updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProviderMutationResponse'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Provider not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Provider belongs to a different partner organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/partner/sessions:
    get:
      tags:
        - Sessions
      operationId: listSessions
      summary: List sessions
      description: Lists sessions for the authenticated partner organization.
      parameters:
        - $ref: '#/components/parameters/LimitQuery'
        - $ref: '#/components/parameters/PageTokenQuery'
        - $ref: '#/components/parameters/StatusQuery'
        - $ref: '#/components/parameters/ProviderNpiQuery'
        - $ref: '#/components/parameters/PatientNameQuery'
        - $ref: '#/components/parameters/DateFromQuery'
        - $ref: '#/components/parameters/DateToQuery'
        - $ref: '#/components/parameters/ExternalSessionIdQuery'
      responses:
        '200':
          description: Session list.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionListResponse'
        '400':
          description: Invalid query parameters or pagination cursor.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ErrorResponse'
                  - $ref: '#/components/schemas/ValidationErrorResponse'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      tags:
        - Sessions
      operationId: submitSession
      summary: Submit a session
      description: >
        Submits a therapy session for billing. You must provide one of:
        `session.noteText`, `session.diagnosisCodes + session.procedureCodes`,
        or `session.diagnosisCodes + session.durationMinutes`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubmitSessionRequest'
            examples:
              diagnosisAndDuration:
                value:
                  externalSessionId: your-internal-session-id
                  patient:
                    firstName: Sarah
                    lastName: Johnson
                    dateOfBirth: "1988-05-15"
                    gender: F
                    address:
                      street: 2222 Random St
                      city: New York
                      state: NY
                      zip: "10001"
                    insurance:
                      memberId: MEM-2026-0042
                      payerName: Cigna
                  providerNpi: "1234567890"
                  session:
                    dateOfService: "2026-04-01"
                    placeOfService: telehealth
                    durationMinutes: 45
                    diagnosisCodes:
                      - code: F32.1
                        description: Major depressive disorder, single episode, moderate
      responses:
        '201':
          description: Session accepted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmitSessionResponse'
        '400':
          description: Invalid payload.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Provider NPI not found for this partner organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Duplicate external session ID for this partner.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DuplicateSessionErrorResponse'
  /api/v1/partner/sessions/{sessionId}:
    get:
      tags:
        - Sessions
      operationId: getSession
      summary: Get session status
      description: Returns partner-safe session, claim, and timeline details.
      parameters:
        - $ref: '#/components/parameters/SessionIdPath'
      responses:
        '200':
          description: Session detail.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionDetailResponse'
        '400':
          description: Invalid session ID.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Session not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      tags:
        - Sessions
      operationId: updateSession
      summary: Update a session
      description: >
        Updates patient demographics, insurance details, or codes on an
        existing session before claim submission. Replacing diagnosis or
        procedure codes overwrites all existing codes of that type.
      parameters:
        - $ref: '#/components/parameters/SessionIdPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSessionRequest'
            examples:
              default:
                value:
                  patient:
                    insurance:
                      memberId: MEM-2026-CORRECTED
                      groupNumber: "7778888"
                  session:
                    diagnosisCodes:
                      - code: F32.1
                        description: Major depressive disorder, single episode, moderate
                      - code: F41.1
                        description: Generalized anxiety disorder
      responses:
        '200':
          description: Session updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateSessionResponse'
        '400':
          description: Invalid session ID.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Session not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Session is already submitted and can no longer be modified.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >
        Send your partner API key as `Authorization: Bearer tga_live_...`.
  parameters:
    NpiPath:
      name: npi
      in: path
      required: true
      schema:
        type: string
      description: Provider NPI.
    SessionIdPath:
      name: sessionId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Taiga session identifier returned at submission time.
    LimitQuery:
      name: limit
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 25
    PageTokenQuery:
      name: pageToken
      in: query
      schema:
        type: string
      description: Opaque pagination cursor returned as `nextPageToken`.
    StatusQuery:
      name: status
      in: query
      schema:
        $ref: '#/components/schemas/PartnerSessionStatus'
    ProviderNpiQuery:
      name: providerNpi
      in: query
      schema:
        type: string
    PatientNameQuery:
      name: patientName
      in: query
      schema:
        type: string
    DateFromQuery:
      name: dateFrom
      in: query
      schema:
        type: string
        format: date
    DateToQuery:
      name: dateTo
      in: query
      schema:
        type: string
        format: date
    ExternalSessionIdQuery:
      name: externalSessionId
      in: query
      schema:
        type: string
    PayerSearchQuery:
      name: q
      in: query
      required: true
      schema:
        type: string
        minLength: 2
      description: Search text for the payer/carrier name.
  schemas:
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
    ValidationIssue:
      type: object
      required:
        - message
        - path
      properties:
        path:
          type: string
        message:
          type: string
    ValidationErrorResponse:
      type: object
      required:
        - error
        - issues
      properties:
        error:
          type: string
          enum:
            - Validation failed
        issues:
          type: array
          items:
            $ref: '#/components/schemas/ValidationIssue'
    DuplicateSessionErrorResponse:
      type: object
      required:
        - error
        - sessionId
      properties:
        error:
          type: string
        sessionId:
          type: string
    PayerSearchItem:
      type: object
      required:
        - payerId
        - payerName
        - avatarUrl
      properties:
        payerId:
          type: string
          description: Payer's electronic ID.
        payerName:
          type: string
          description: Insurance carrier name, not the plan/product name.
        avatarUrl:
          type:
            - string
            - 'null'
    PayerSearchResponse:
      type: object
      required:
        - payers
      properties:
        payers:
          type: array
          items:
            $ref: '#/components/schemas/PayerSearchItem'
    ProviderInput:
      type: object
      required:
        - firstName
        - lastName
        - npi
      properties:
        firstName:
          type: string
        lastName:
          type: string
        npi:
          type: string
        taxonomyCode:
          type: string
        specialty:
          type: string
        credentials:
          type: string
    PracticeAddressInput:
      type: object
      required:
        - street
        - city
        - state
        - zip
      properties:
        street:
          type: string
        line2:
          type: string
          description: Apartment, suite, unit, floor, or similar secondary designator.
        city:
          type: string
        state:
          type: string
          minLength: 2
          maxLength: 2
        zip:
          type: string
    PracticeInput:
      type: object
      required:
        - name
        - taxId
        - address
      properties:
        name:
          type: string
        npi:
          type: string
        taxId:
          type: string
        taxonomyCode:
          type: string
        address:
          $ref: '#/components/schemas/PracticeAddressInput'
        phone:
          type: string
        contactName:
          type: string
    OnboardProviderRequest:
      type: object
      required:
        - provider
        - practice
      properties:
        provider:
          $ref: '#/components/schemas/ProviderInput'
        practice:
          $ref: '#/components/schemas/PracticeInput'
    UpdateProviderFields:
      type: object
      properties:
        taxonomyCode:
          type: string
        specialty:
          type: string
        credentials:
          type: string
    UpdatePracticeFields:
      type: object
      properties:
        name:
          type: string
        npi:
          type: string
        taxId:
          type: string
        taxonomyCode:
          type: string
        address:
          $ref: '#/components/schemas/PartialPracticeAddressInput'
        phone:
          type: string
        contactName:
          type: string
    PartialPracticeAddressInput:
      type: object
      properties:
        street:
          type: string
        line2:
          type: string
          description: Apartment, suite, unit, floor, or similar secondary designator.
        city:
          type: string
        state:
          type: string
          minLength: 2
          maxLength: 2
        zip:
          type: string
    UpdateProviderRequest:
      type: object
      properties:
        provider:
          $ref: '#/components/schemas/UpdateProviderFields'
        practice:
          $ref: '#/components/schemas/UpdatePracticeFields'
    ProviderMutationResponse:
      type: object
      required:
        - providerId
        - practiceId
        - providerNpi
        - practiceName
        - status
      properties:
        providerId:
          type: string
        practiceId:
          type: string
        providerNpi:
          type: string
        practiceName:
          type: string
        status:
          type: string
          enum:
            - created
            - already_exists
            - updated
    PatientAddress:
      type: object
      required:
        - street
        - city
        - state
        - zip
      properties:
        street:
          type: string
        line2:
          type: string
          description: Apartment, suite, unit, floor, or similar secondary designator.
        city:
          type: string
        state:
          type: string
        zip:
          type: string
    PatientInsurance:
      type: object
      required:
        - memberId
        - payerName
      properties:
        memberId:
          type: string
          description: Insurance member ID from the patient's card.
        payerName:
          type: string
          description: Insurance carrier/payer name, not the plan/product name.
        payerId:
          type: string
          description: Payer's electronic ID for routing.
        groupNumber:
          type: string
          description: Insurance group number from the patient's card.
    SessionPatient:
      type: object
      required:
        - firstName
        - lastName
        - dateOfBirth
        - gender
        - address
        - insurance
      properties:
        firstName:
          type: string
        lastName:
          type: string
        dateOfBirth:
          type: string
          format: date
        gender:
          $ref: '#/components/schemas/PatientGender'
        address:
          $ref: '#/components/schemas/PatientAddress'
        insurance:
          $ref: '#/components/schemas/PatientInsurance'
    CodeEntry:
      type: object
      required:
        - code
      properties:
        code:
          type: string
        description:
          type: string
        modifier:
          type: string
    SubmitSessionData:
      type: object
      required:
        - dateOfService
      properties:
        dateOfService:
          type: string
          format: date
        placeOfService:
          $ref: '#/components/schemas/SessionPlaceOfService'
        durationMinutes:
          type: number
        noteText:
          type: string
        diagnosisCodes:
          type: array
          items:
            $ref: '#/components/schemas/CodeEntry'
        procedureCodes:
          type: array
          items:
            $ref: '#/components/schemas/CodeEntry'
    SubmitSessionRequest:
      type: object
      required:
        - patient
        - providerNpi
        - session
      properties:
        externalSessionId:
          type: string
        patient:
          $ref: '#/components/schemas/SessionPatient'
        providerNpi:
          type: string
          description: Provider NPI from the onboarding step.
        session:
          $ref: '#/components/schemas/SubmitSessionData'
    SubmitSessionResponse:
      type: object
      required:
        - sessionId
        - status
        - message
      properties:
        sessionId:
          type: string
        externalSessionId:
          type:
            - string
            - 'null'
        status:
          type: string
          enum:
            - processing
        message:
          type: string
    PartnerSessionStatus:
      type: string
      enum:
        - processing
        - submitted
        - accepted
        - rejected
        - denied
        - paid
    SessionSummaryPatient:
      type: object
      required:
        - firstName
        - lastName
        - fullName
        - dateOfBirth
        - memberId
      properties:
        firstName:
          type:
            - string
            - 'null'
        lastName:
          type:
            - string
            - 'null'
        fullName:
          type:
            - string
            - 'null'
        dateOfBirth:
          type:
            - string
            - 'null'
          format: date
        memberId:
          type:
            - string
            - 'null'
    SessionSummaryPayer:
      type: object
      properties:
        payerName:
          type:
            - string
            - 'null'
        payerId:
          type:
            - string
            - 'null'
        groupNumber:
          type:
            - string
            - 'null'
    SessionSummaryProvider:
      type: object
      required:
        - providerId
        - firstName
        - lastName
        - fullName
        - npi
      properties:
        providerId:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        fullName:
          type:
            - string
            - 'null'
        npi:
          type:
            - string
            - 'null'
        credentials:
          type:
            - string
            - 'null'
        specialty:
          type:
            - string
            - 'null'
    ClaimSummary:
      type:
        - object
        - 'null'
      properties:
        claimId:
          type: string
        status:
          type:
            - string
            - 'null'
        submittedAt:
          type:
            - string
            - 'null'
          format: date-time
        lastUpdated:
          type:
            - string
            - 'null'
          format: date-time
        patientControlNumber:
          type:
            - string
            - 'null'
        payerClaimControlNumber:
          type:
            - string
            - 'null'
        submissionMode:
          type:
            - string
            - 'null'
    SessionListItem:
      type: object
      required:
        - sessionId
        - status
        - dateOfService
        - createdAt
        - updatedAt
        - patient
        - payer
        - provider
        - claim
      properties:
        sessionId:
          type: string
        externalSessionId:
          type:
            - string
            - 'null'
        status:
          $ref: '#/components/schemas/PartnerSessionStatus'
        dateOfService:
          type: string
          format: date
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        patient:
          $ref: '#/components/schemas/SessionSummaryPatient'
        payer:
          $ref: '#/components/schemas/SessionSummaryPayer'
        provider:
          $ref: '#/components/schemas/SessionSummaryProvider'
        claim:
          $ref: '#/components/schemas/ClaimSummary'
    SessionListResponse:
      type: object
      required:
        - items
        - nextPageToken
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/SessionListItem'
        nextPageToken:
          type:
            - string
            - 'null'
    SessionEvent:
      type: object
      required:
        - type
        - timestamp
      properties:
        type:
          type: string
        timestamp:
          type: string
          format: date-time
    TimelineEvent:
      type: object
      required:
        - type
        - timestamp
        - summary
      properties:
        type:
          type: string
        status:
          type:
            - string
            - 'null'
        summary:
          type: string
        timestamp:
          type: string
          format: date-time
    SessionDetailResponse:
      allOf:
        - $ref: '#/components/schemas/SessionListItem'
        - type: object
          required:
            - message
            - patientName
            - events
            - timeline
          properties:
            message:
              type: string
            patientName:
              type:
                - string
                - 'null'
            events:
              type: array
              items:
                $ref: '#/components/schemas/SessionEvent'
            timeline:
              type: array
              items:
                $ref: '#/components/schemas/TimelineEvent'
    UpdatePatientAddress:
      type: object
      properties:
        street:
          type: string
        line2:
          type: string
          description: Apartment, suite, unit, floor, or similar secondary designator.
        city:
          type: string
        state:
          type: string
        zip:
          type: string
    UpdatePatientInsurance:
      type: object
      properties:
        memberId:
          type: string
        payerName:
          type: string
        payerId:
          type: string
        groupNumber:
          type: string
    UpdateSessionPatient:
      type: object
      properties:
        firstName:
          type: string
        lastName:
          type: string
        dateOfBirth:
          type: string
          format: date
        gender:
          $ref: '#/components/schemas/PatientGender'
        address:
          $ref: '#/components/schemas/UpdatePatientAddress'
        insurance:
          $ref: '#/components/schemas/UpdatePatientInsurance'
    UpdateSessionData:
      type: object
      properties:
        dateOfService:
          type: string
          format: date
        placeOfService:
          $ref: '#/components/schemas/SessionPlaceOfService'
        diagnosisCodes:
          type: array
          items:
            $ref: '#/components/schemas/CodeEntry'
        procedureCodes:
          type: array
          items:
            $ref: '#/components/schemas/CodeEntry'
    UpdateSessionRequest:
      type: object
      properties:
        patient:
          $ref: '#/components/schemas/UpdateSessionPatient'
        session:
          $ref: '#/components/schemas/UpdateSessionData'
    UpdateSessionResponse:
      type: object
      required:
        - sessionId
        - status
        - message
      properties:
        sessionId:
          type: string
        status:
          type: string
          enum:
            - updated
        message:
          type: string
    PatientGender:
      type: string
      enum:
        - M
        - F
        - U
    SessionPlaceOfService:
      type: string
      enum:
        - office
        - telehealth
