openapi: 3.0.3
info:
  title: PUP - Integration API v1
  description: >
    PUP is the universal player profile for padel. This API provides third-party integration connection and lifecycle management functionality.
  version: 1.0.0

servers:
  - url: https://api.gopup.app
    description: Development server

x-tagGroups:
  - name: Integration
    tags:
      - integrations

tags:
  - name: integrations
    x-displayName: "Integrations"
    description: Operations related to 3rd party integration connection and lifecycle

security:
  - OAuth2:
      - urn:pup:integration:read
  - PAT: []

paths:
  /integration/v1/workspaces/{workspace_id}/integrations:
    post:
      tags:
        - integrations
      operationId: connectIntegration
      summary: Connect a new integration
      description: Initiates a new third-party integration connection for a workspace using provider credentials and optional configuration.
      security:
        - OAuth2:
            - urn:pup:integration:manage
        - PAT: []
      parameters:
        - name: workspace_id
          in: path
          required: true
          description: Workspace (Club) ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConnectIntegrationRequest'
      responses:
        '201':
          description: Integration connection initiated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConnectIntegrationResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

    get:
      tags:
        - integrations
      operationId: listIntegrations
      summary: List integrations for a workspace
      description: Returns a list of third-party integrations configured for a workspace.
      security:
        - OAuth2:
            - urn:pup:integration:read
        - OAuth2:
            - urn:pup:integration:manage
        - PAT: []
      parameters:
        - name: workspace_id
          in: path
          required: true
          description: Workspace (Club) ID
          schema:
            type: string
        - name: status
          in: query
          required: false
          description: Filter by connection status
          schema:
            type: string
            enum:
              - connecting
              - connected
              - degraded
              - error
              - disconnected
        - name: provider
          in: query
          required: false
          description: Filter by integration provider
          schema:
            type: string
            enum:
              - playtomic
              - lightspeed_k_series
      responses:
        '200':
          description: List of integrations
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListIntegrationsResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /integration/v1/workspaces/{workspace_id}/integrations/{integration_id}:
    get:
      tags:
        - integrations
      operationId: getIntegration
      summary: Get integration details
      description: Returns full details for a third-party integration by ID.
      security:
        - OAuth2:
            - urn:pup:integration:read
        - OAuth2:
            - urn:pup:integration:manage
        - PAT: []
      parameters:
        - name: workspace_id
          in: path
          required: true
          description: Workspace (Club) ID
          schema:
            type: string
        - name: integration_id
          in: path
          required: true
          description: Integration ID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Integration details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetIntegrationResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Integration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /integration/v1/workspaces/{workspace_id}/integrations/{integration_id}/reconnect:
    post:
      tags:
        - integrations
      operationId: reconnectIntegration
      summary: Reconnect an integration with fresh credentials
      description: Re-initiates connection handshake for an existing integration using updated credentials.
      security:
        - OAuth2:
            - urn:pup:integration:manage
        - PAT: []
      parameters:
        - name: workspace_id
          in: path
          required: true
          description: Workspace (Club) ID
          schema:
            type: string
        - name: integration_id
          in: path
          required: true
          description: Integration ID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReconnectIntegrationRequest'
      responses:
        '204':
          description: Integration reconnection initiated
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Integration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /integration/v1/workspaces/{workspace_id}/integrations/{integration_id}/disconnect:
    post:
      tags:
        - integrations
      operationId: disconnectIntegration
      summary: Disconnect an integration
      description: Disconnects and severs an active integration connection.
      security:
        - OAuth2:
            - urn:pup:integration:manage
        - PAT: []
      parameters:
        - name: workspace_id
          in: path
          required: true
          description: Workspace (Club) ID
          schema:
            type: string
        - name: integration_id
          in: path
          required: true
          description: Integration ID
          schema:
            type: string
            format: uuid
      responses:
        '204':
          description: Integration disconnected successfully
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Integration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /integration/v1/workspaces/{workspace_id}/integrations/{integration_id}/config:
    patch:
      tags:
        - integrations
      operationId: updateIntegrationConfig
      summary: Update integration configuration
      description: Updates non-secret configuration parameters for an integration.
      security:
        - OAuth2:
            - urn:pup:integration:manage
        - PAT: []
      parameters:
        - name: workspace_id
          in: path
          required: true
          description: Workspace (Club) ID
          schema:
            type: string
        - name: integration_id
          in: path
          required: true
          description: Integration ID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateIntegrationConfigRequest'
      responses:
        '204':
          description: Integration configuration updated
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Integration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

components:
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://auth.gopup.app/oauth2/auth
          tokenUrl: https://auth.gopup.app/oauth2/token
          scopes:
            urn:pup:integration:read: Read integration state and configurations
            urn:pup:integration:manage: Connect, manage, and disconnect integrations
    PAT:
      type: http
      scheme: bearer
      bearerFormat: PAT
      description: Personal Access Token

  schemas:
    ConnectionMethod:
      type: string
      enum:
        - credentials
        - oauth2
      description: How the integration connects

    PlaytomicConfig:
      type: object
      properties:
        venue_id:
          type: string
          nullable: true
          description: Optional venue ID

    LightspeedKSeriesConfig:
      type: object
      properties:
        pup_cents_per_currency_unit:
          type: string
          nullable: true
          description: Number of PUP cents rewarded per currency unit

    ConnectIntegrationRequest:
      oneOf:
        - $ref: '#/components/schemas/ConnectPlaytomicIntegrationRequest'
        - $ref: '#/components/schemas/ConnectLightspeedKSeriesIntegrationRequest'
      discriminator:
        propertyName: provider
        mapping:
          playtomic: '#/components/schemas/ConnectPlaytomicIntegrationRequest'
          lightspeed_k_series: '#/components/schemas/ConnectLightspeedKSeriesIntegrationRequest'

    ConnectPlaytomicIntegrationRequest:
      type: object
      required:
        - provider
        - client_id
        - client_secret
      properties:
        provider:
          type: string
          enum:
            - playtomic
        client_id:
          type: string
          minLength: 1
        client_secret:
          type: string
          minLength: 1
        venue_id:
          type: string
          nullable: true
          description: Optional Playtomic venue ID

    ConnectLightspeedKSeriesIntegrationRequest:
      type: object
      required:
        - provider
        - client_id
        - client_secret
      properties:
        provider:
          type: string
          enum:
            - lightspeed_k_series
        client_id:
          type: string
          minLength: 1
        client_secret:
          type: string
          minLength: 1
        pup_cents_per_currency_unit:
          type: string
          nullable: true
          description: Number of PUP cents rewarded per currency unit

    ConnectIntegrationResponse:
      type: object
      required:
        - integration_id
      properties:
        integration_id:
          type: string
          format: uuid
        authorization_url:
          type: string
          nullable: true
          description: OAuth authorization URL if connection method is OAuth2

    ReconnectIntegrationRequest:
      oneOf:
        - $ref: '#/components/schemas/ReconnectPlaytomicIntegrationRequest'
        - $ref: '#/components/schemas/ReconnectLightspeedKSeriesIntegrationRequest'
      discriminator:
        propertyName: provider
        mapping:
          playtomic: '#/components/schemas/ReconnectPlaytomicIntegrationRequest'
          lightspeed_k_series: '#/components/schemas/ReconnectLightspeedKSeriesIntegrationRequest'

    ReconnectPlaytomicIntegrationRequest:
      type: object
      required:
        - provider
        - client_id
        - client_secret
      properties:
        provider:
          type: string
          enum:
            - playtomic
        client_id:
          type: string
          minLength: 1
        client_secret:
          type: string
          minLength: 1

    ReconnectLightspeedKSeriesIntegrationRequest:
      type: object
      required:
        - provider
        - client_id
        - client_secret
      properties:
        provider:
          type: string
          enum:
            - lightspeed_k_series
        client_id:
          type: string
          minLength: 1
        client_secret:
          type: string
          minLength: 1

    UpdateIntegrationConfigRequest:
      oneOf:
        - $ref: '#/components/schemas/UpdatePlaytomicConfigRequest'
        - $ref: '#/components/schemas/UpdateLightspeedKSeriesConfigRequest'
      discriminator:
        propertyName: provider
        mapping:
          playtomic: '#/components/schemas/UpdatePlaytomicConfigRequest'
          lightspeed_k_series: '#/components/schemas/UpdateLightspeedKSeriesConfigRequest'

    UpdatePlaytomicConfigRequest:
      type: object
      required:
        - provider
      properties:
        provider:
          type: string
          enum:
            - playtomic
        venue_id:
          type: string
          nullable: true
          description: Optional Playtomic venue ID

    UpdateLightspeedKSeriesConfigRequest:
      type: object
      required:
        - provider
      properties:
        provider:
          type: string
          enum:
            - lightspeed_k_series
        pup_cents_per_currency_unit:
          type: string
          nullable: true
          description: Number of PUP cents rewarded per currency unit

    GetIntegrationResponse:
      type: object
      required:
        - integration
      properties:
        integration:
          $ref: '#/components/schemas/Integration'

    ListIntegrationsResponse:
      type: object
      required:
        - hits
      properties:
        hits:
          type: array
          items:
            $ref: '#/components/schemas/Integration'

    IntegrationStatus:
      type: string
      enum:
        - connecting
        - connected
        - degraded
        - error
        - disconnected

    PlaytomicIntegration:
      type: object
      required:
        - id
        - workspace_id
        - provider
        - status
        - connection_method
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
        workspace_id:
          type: string
        provider:
          type: string
          enum:
            - playtomic
        status:
          $ref: '#/components/schemas/IntegrationStatus'
        connection_method:
          $ref: '#/components/schemas/ConnectionMethod'
        degraded_reason:
          type: string
          nullable: true
        error_reason:
          type: string
          nullable: true
        config:
          $ref: '#/components/schemas/PlaytomicConfig'
        connected_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    LightspeedKSeriesIntegration:
      type: object
      required:
        - id
        - workspace_id
        - provider
        - status
        - connection_method
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
        workspace_id:
          type: string
        provider:
          type: string
          enum:
            - lightspeed_k_series
        status:
          $ref: '#/components/schemas/IntegrationStatus'
        connection_method:
          $ref: '#/components/schemas/ConnectionMethod'
        degraded_reason:
          type: string
          nullable: true
        error_reason:
          type: string
          nullable: true
        config:
          $ref: '#/components/schemas/LightspeedKSeriesConfig'
        connected_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    Integration:
      oneOf:
        - $ref: '#/components/schemas/PlaytomicIntegration'
        - $ref: '#/components/schemas/LightspeedKSeriesIntegration'
      discriminator:
        propertyName: provider
        mapping:
          playtomic: '#/components/schemas/PlaytomicIntegration'
          lightspeed_k_series: '#/components/schemas/LightspeedKSeriesIntegration'

    Error:
      type: object
      required:
        - error
        - code
      properties:
        error:
          type: string
          example: "An error message"
        code:
          type: string
          enum:
            - MALFORMED_REQUEST
            - INVALID_INPUT
            - UNAUTHORIZED
            - INSUFFICIENT_SCOPE
            - ACCESS_DENIED
            - RESOURCE_NOT_FOUND
            - RESOURCE_EXISTS
            - CONFLICT
            - ACTION_BLOCKED
            - INTERNAL_ERROR
