openapi: "3.0.3"

info:
  title: SentryAgent.ai — Tier Management
  version: 1.0.0
  description: |
    Tier status and upgrade endpoints for the SentryAgent.ai AgentIdP platform.

    The tier system defines per-organization limits on agents, tokens, and API calls.

    **All endpoints require a valid Bearer JWT.**

    **Available tiers:**
    | Tier | Max Agents | Max Tokens/Month | Rate Limit |
    |------|-----------|-----------------|------------|
    | `free` | 100 | 10,000 | 100 req/min |
    | `pro` | 1,000 | 100,000 | 1,000 req/min |
    | `enterprise` | unlimited | unlimited | custom |

servers:
  - url: http://localhost:3000/api/v1
    description: Local development server
  - url: https://api.sentryagent.ai/v1
    description: Production server

tags:
  - name: Tiers
    description: Tier status and upgrade management

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        JWT access token obtained via `POST /token`.
        Include as `Authorization: Bearer <token>`.

  schemas:
    PlanTier:
      type: string
      enum:
        - free
        - pro
        - enterprise
      description: Current subscription plan tier.
      example: free

    TierLimits:
      type: object
      description: Hard limits defined by the current tier.
      required:
        - maxAgents
        - maxTokensPerMonth
        - rateLimitPerMinute
      properties:
        maxAgents:
          type: integer
          description: Maximum number of agents allowed for this organization.
          example: 100
        maxTokensPerMonth:
          type: integer
          description: Maximum OAuth 2.0 token requests per calendar month.
          example: 10000
        rateLimitPerMinute:
          type: integer
          description: Maximum API requests per minute.
          example: 100

    TierUsage:
      type: object
      description: Live usage counters for the current billing period.
      required:
        - agentsRegistered
        - tokensThisMonth
        - requestsThisMinute
      properties:
        agentsRegistered:
          type: integer
          description: Current number of active (non-decommissioned) agents.
          minimum: 0
          example: 47
        tokensThisMonth:
          type: integer
          description: Total OAuth 2.0 tokens issued in the current calendar month.
          minimum: 0
          example: 3214
        requestsThisMinute:
          type: integer
          description: API requests in the current rate-limit window.
          minimum: 0
          example: 12

    TierStatus:
      type: object
      description: Full tier status response — current tier, plan limits, and live usage.
      required:
        - organizationId
        - tier
        - limits
        - usage
      properties:
        organizationId:
          type: string
          format: uuid
          description: Organization the tier status applies to.
          example: "org-1234-5678-abcd-ef01"
        tier:
          $ref: '#/components/schemas/PlanTier'
        limits:
          $ref: '#/components/schemas/TierLimits'
        usage:
          $ref: '#/components/schemas/TierUsage'
        billingPeriodStart:
          type: string
          format: date
          description: First day of the current billing period (UTC).
          example: "2026-04-01"
        billingPeriodEnd:
          type: string
          format: date
          description: Last day of the current billing period (UTC).
          example: "2026-04-30"

    TierUpgradeRequest:
      type: object
      description: Request body for initiating a tier upgrade.
      required:
        - targetTier
      properties:
        targetTier:
          type: string
          enum:
            - pro
            - enterprise
          description: |
            The target plan tier to upgrade to.
            Downgrading is not permitted via this endpoint.
          example: "pro"
        successUrl:
          type: string
          format: uri
          description: |
            URL to redirect to after successful payment.
            Defaults to the platform dashboard when omitted.
          example: "https://my-app.example.com/dashboard?upgrade=success"
        cancelUrl:
          type: string
          format: uri
          description: |
            URL to redirect to if the user cancels checkout.
            Defaults to the platform dashboard when omitted.
          example: "https://my-app.example.com/dashboard?upgrade=cancel"

    TierUpgradeResponse:
      type: object
      description: Stripe Checkout URL to initiate the tier upgrade payment flow.
      required:
        - checkoutUrl
        - targetTier
      properties:
        checkoutUrl:
          type: string
          format: uri
          description: |
            Stripe-hosted Checkout page URL.
            Redirect the authenticated user to this URL to complete payment.
          example: "https://checkout.stripe.com/pay/cs_test_abcdef1234567890"
        targetTier:
          $ref: '#/components/schemas/PlanTier'

    ErrorResponse:
      type: object
      description: Standard error response envelope.
      required:
        - code
        - message
      properties:
        code:
          type: string
          example: "UNAUTHORIZED"
        message:
          type: string
          example: "A valid Bearer token is required to access this resource."
        details:
          type: object
          additionalProperties: true

  responses:
    Unauthorized:
      description: Missing or invalid Bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: "UNAUTHORIZED"
            message: "A valid Bearer token is required to access this resource."

    Forbidden:
      description: Valid token but insufficient permissions.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: "FORBIDDEN"
            message: "You do not have permission to perform this action."

    InternalServerError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: "INTERNAL_SERVER_ERROR"
            message: "An unexpected error occurred. Please try again later."

security:
  - BearerAuth: []

paths:
  /tiers/status:
    get:
      operationId: getTierStatus
      tags:
        - Tiers
      summary: Get current tier status
      description: |
        Returns the current tier, plan limits, and live usage counters for the
        authenticated organization.

        The organization ID is derived from the `organization_id` claim in the
        Bearer JWT — no explicit organization ID is required in the request.

        Use this endpoint to:
        - Display the current plan in your dashboard
        - Check remaining quota before performing bulk operations
        - Determine whether an upgrade is needed
      responses:
        '200':
          description: Tier status returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TierStatus'
              example:
                organizationId: "org-1234-5678-abcd-ef01"
                tier: "free"
                limits:
                  maxAgents: 100
                  maxTokensPerMonth: 10000
                  rateLimitPerMinute: 100
                usage:
                  agentsRegistered: 47
                  tokensThisMonth: 3214
                  requestsThisMinute: 12
                billingPeriodStart: "2026-04-01"
                billingPeriodEnd: "2026-04-30"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /tiers/upgrade:
    post:
      operationId: initiateTierUpgrade
      tags:
        - Tiers
      summary: Initiate a tier upgrade via Stripe
      description: |
        Initiates a Stripe Checkout Session for upgrading the organization's plan tier.

        The returned `checkoutUrl` is a Stripe-hosted payment page.
        Redirect the authenticated user to this URL to complete the upgrade payment.

        After successful payment, Stripe notifies the platform via the
        `POST /billing/webhook` endpoint, which activates the new tier automatically.

        **Constraints:**
        - Only upgrades are supported (free → pro, free → enterprise, pro → enterprise).
        - Attempting to "upgrade" to the current or lower tier returns `400`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TierUpgradeRequest'
            example:
              targetTier: "pro"
              successUrl: "https://my-app.example.com/dashboard?upgrade=success"
              cancelUrl: "https://my-app.example.com/dashboard?upgrade=cancel"
      responses:
        '201':
          description: Stripe Checkout Session created successfully. Redirect user to checkoutUrl.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TierUpgradeResponse'
              example:
                checkoutUrl: "https://checkout.stripe.com/pay/cs_test_abcdef1234567890"
                targetTier: "pro"
        '400':
          description: Invalid upgrade request — already on target tier or attempting a downgrade.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                alreadyOnTier:
                  summary: Already on target tier
                  value:
                    code: "ALREADY_ON_TIER"
                    message: "Your organization is already on the 'pro' tier."
                invalidDowngrade:
                  summary: Downgrade not permitted
                  value:
                    code: "DOWNGRADE_NOT_PERMITTED"
                    message: "Downgrading tiers is not supported via this endpoint."
                missingOrgId:
                  summary: Missing organization_id in token
                  value:
                    code: "VALIDATION_ERROR"
                    message: "organization_id is required in token."
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          description: Unexpected error or Stripe API failure.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: "STRIPE_ERROR"
                message: "Failed to create Stripe Checkout Session. Please try again."
