openapi: 3.0.3
info:
  title: PUP - Order API v1
  description: >
    PUP is the universal player profile for padel. This API provides order management functionality 
    for purchasing rewards from the PUP marketplace.
  version: 1.0.0

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

x-tagGroups:
  - name: Order
    tags:
      - orders

tags:
  - name: orders
    x-displayName: "Orders"
    description: Operations related to reward purchases and order management

paths:
  /order/v1/orders:
    post:
      tags:
        - orders
      summary: Purchase a reward
      description: >
        Creates a new order for purchasing a reward from the marketplace. 
        The order will be created immediately with status 'pending_payment', 
        and payment will be processed asynchronously.
      operationId: createOrder
      security:
        - OAuth2:
            - urn:pup:order:manage
        - PAT: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderRequest'
      responses:
        '201':
          description: Order created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
        '400':
          description: Bad request - invalid input
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - invalid or missing JWT
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Reward not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Generic error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /order/v1/redemptions/authorize:
    post:
      tags:
        - orders
      summary: Authorize order redemption
      description: >
        Authorizes and processes order redemption by redemption code. 
        Only admins can authorize redemptions. This endpoint first checks 
        if the current user is authorized to perform the redemption, then 
        processes it if authorized.
      operationId: authorizeRedemption
      security:
        - OAuth2:
            - urn:pup:order.redemption:authorize
        - PAT: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthorizeRedemptionRequest'
      responses:
        '204':
          description: Order redeemed successfully
        '400':
          description: Bad request - order is not paid or cannot be redeemed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - invalid or missing JWT
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden - not authorized to redeem orders or order cannot be redeemed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Order not found - invalid redemption code
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Conflict - order already redeemed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Generic error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

components:
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          example: "An error message"
      description: Generic error response

    CreateOrderRequest:
      type: object
      required:
        - reward_id
      properties:
        reward_id:
          type: string
          description: The reward identifier to purchase
          example: 550e8400-e29b-41d4-a716-446655440000

    AuthorizeRedemptionRequest:
      type: object
      required:
        - redemption_code
      properties:
        redemption_code:
          type: string
          description: The redemption code from a paid order
          example: REDEMPTION-abc123xyz

    Order:
      type: object
      required:
        - order_id
        - user_id
        - reward_id
        - reward_title
        - price_amount
        - status
        - created_at
      properties:
        order_id:
          type: string
          description: Order identifier
          example: 7c9e6679-7425-40de-944b-e07fc1f90ae7
        user_id:
          type: string
          description: User identifier who placed the order
          example: 123e4567-e89b-12d3-a456-426614174000
        reward_id:
          type: string
          description: Reward identifier
          example: 550e8400-e29b-41d4-a716-446655440000
        reward_title:
          type: string
          description: Title of the purchased reward
          example: Premium Membership
        price_amount:
          type: integer
          description: Price in credits
          example: 1000
        status:
          type: string
          description: Current order status
          enum: [pending_payment, paid, payment_failed, cancelled, redeemed]
          example: paid
        transaction_id:
          type: string
          nullable: true
          description: Transaction ID (only present for paid orders)
          example: txn_abc123
        redemption_code:
          type: string
          nullable: true
          description: Redemption code (only present for paid orders)
          example: REDEMPTION-xyz789
        failure_reason:
          type: string
          nullable: true
          description: Reason for payment failure (only present for failed orders)
          example: Insufficient credits
        created_at:
          type: string
          format: date-time
          description: Order creation timestamp
          example: "2026-02-08T15:00:00Z"
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when order was completed (paid)
          example: "2026-02-08T15:01:00Z"
        redeemed_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when order was redeemed
          example: "2026-02-08T16:00:00Z"

    OrderResponse:
      type: object
      required:
        - order
      properties:
        order:
          $ref: '#/components/schemas/Order'

    SearchOrdersResponse:
      type: object
      required:
        - hits
        - meta
      properties:
        hits:
          type: array
          items:
            $ref: '#/components/schemas/Order'
        meta:
          $ref: '#/components/schemas/ResponseMetaMany'

    ResponseMetaMany:
      type: object
      required:
        - pagination
      properties:
        pagination:
          type: object
          required:
            - total
            - returned
            - offset
            - limit
          properties:
            total:
              type: integer
              description: Total number of matching records
              example: 145
            returned:
              type: integer
              description: Number of records actually returned in this response
              example: 20
            offset:
              type: integer
              description: Offset used in the request
              example: 0
            limit:
              type: integer
              description: Limit used in the request
              example: 20
            next:
              type: string
              nullable: true
              description: Relative path to next page of results
              example: /order/v1/orders?offset=20&limit=20
            previous:
              type: string
              nullable: true
              description: Relative path to previous page of results
              example: /order/v1/orders?offset=0&limit=20

  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://oauth2.gopup.app/oauth2/auth
          tokenUrl: https://oauth2.gopup.app/oauth2/token
          scopes:
            urn:pup:order:manage: Create and manage orders
            urn:pup:order:read: Read order information
            urn:pup:order.redemption:authorize: Authorize order redemptions (admin only)

    PAT:
      type: http
      scheme: bearer
      bearerFormat: PAT
      description: Personal Access Token
