openapi: 3.1.0
info:
  title: SuperPenguin FOCUS AI Provider Profile
  version: 0.1.0
  summary: Export AI usage and provider-billed costs to authorized FinOps clients.
  description: |
    A narrow, provider-implementable API profile based on FOCUS 1.4 semantics.
    Implementing this API does not by itself imply full FOCUS conformance.
servers:
  - url: https://api.provider.example
    description: Replace with the provider API origin.
tags:
  - name: FinOps
security:
  - bearerAuth: []
  - oauth2:
      - billing.account.read
      - billing.usage.read
paths:
  /v1/finops/capabilities:
    get:
      operationId: getFinOpsCapabilities
      tags: [FinOps]
      summary: Describe export capabilities for the authorized account.
      responses:
        "200":
          description: Account-specific provider capabilities.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Capabilities"
              examples:
                complete:
                  $ref: "#/components/examples/CapabilitiesExample"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
  /v1/finops/usage:
    get:
      operationId: listFinOpsUsage
      tags: [FinOps]
      summary: Export complete metered usage over a half-open UTC window.
      security:
        - bearerAuth: []
        - oauth2:
            - billing.usage.read
      parameters:
        - $ref: "#/components/parameters/Start"
        - $ref: "#/components/parameters/End"
        - $ref: "#/components/parameters/Granularity"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Cursor"
      responses:
        "200":
          description: One page of usage meter records.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsagePage"
              examples:
                firstPage:
                  $ref: "#/components/examples/UsagePageExample"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
  /v1/finops/costs:
    get:
      operationId: listFinOpsCosts
      tags: [FinOps]
      summary: Export provider-reported billed costs over a half-open UTC window.
      security:
        - bearerAuth: []
        - oauth2:
            - billing.cost.read
      parameters:
        - $ref: "#/components/parameters/Start"
        - $ref: "#/components/parameters/End"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Cursor"
      responses:
        "200":
          description: One page of billed-cost records.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CostPage"
              examples:
                firstPage:
                  $ref: "#/components/examples/CostPageExample"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: opaque
      description: Dedicated read-only token bound to the customer billing account.
    oauth2:
      type: oauth2
      description: OAuth 2.0 Authorization Code with PKCE S256 and refresh tokens.
      flows:
        authorizationCode:
          authorizationUrl: https://provider.example/oauth/authorize
          tokenUrl: https://provider.example/oauth/token
          refreshUrl: https://provider.example/oauth/token
          scopes:
            billing.account.read: Read billing account identity and capabilities.
            billing.usage.read: Read metered usage.
            billing.cost.read: Read billed costs.
  parameters:
    Start:
      name: start
      in: query
      required: true
      description: Inclusive UTC window start.
      schema:
        type: string
        format: date-time
    End:
      name: end
      in: query
      required: true
      description: Exclusive UTC window end.
      schema:
        type: string
        format: date-time
    Granularity:
      name: granularity
      in: query
      required: true
      description: Requested native usage bucket width.
      schema:
        $ref: "#/components/schemas/Granularity"
    Limit:
      name: limit
      in: query
      required: false
      description: Maximum records in this page.
      schema:
        type: integer
        minimum: 1
        maximum: 1000
        default: 1000
    Cursor:
      name: cursor
      in: query
      required: false
      description: Opaque cursor returned by the previous page.
      schema:
        type: string
        minLength: 1
  responses:
    BadRequest:
      description: Invalid query or unsupported capability.
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
    Unauthorized:
      description: Missing or invalid credential.
      headers:
        WWW-Authenticate:
          schema:
            type: string
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
    Forbidden:
      description: Valid credential without the required scope or account access.
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
    RateLimited:
      description: Provider rate limit exceeded.
      headers:
        Retry-After:
          required: true
          schema:
            type: string
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/Problem"
  schemas:
    Granularity:
      type: string
      enum: [1h, 1d]
    DecimalString:
      type: string
      pattern: "^-?(0|[1-9][0-9]*)(\\.[0-9]+)?$"
      examples: ["1250000", "1.250000"]
    UsageType:
      type: string
      enum:
        - input_tokens
        - output_tokens
        - cache_read_tokens
        - cache_write_5m_tokens
        - cache_write_1h_tokens
        - input_audio_tokens
        - output_audio_tokens
        - requests
        - audio_seconds
        - characters
        - events
        - session_minutes
        - credits
    Dimension:
      type: string
      enum:
        - model
        - project
        - workspace
        - api_key
        - service_tier
        - workload_type
        - upstream_provider
    AuthorizationMethod:
      type: string
      enum:
        - scoped_bearer_token
        - oauth2_authorization_code
    DatasetCapabilities:
      type: object
      additionalProperties: false
      required:
        - endpoint
        - granularities
        - retention_days
        - maximum_window_days
        - dimensions
      properties:
        endpoint:
          type: string
          pattern: "^/v[0-9]+/"
        granularities:
          type: array
          minItems: 1
          uniqueItems: true
          items:
            $ref: "#/components/schemas/Granularity"
        retention_days:
          type: integer
          minimum: 1
        maximum_window_days:
          type: integer
          minimum: 1
        freshness_lag_minutes:
          type: integer
          minimum: 0
        settlement_lag_hours:
          type: integer
          minimum: 0
        dimensions:
          type: array
          uniqueItems: true
          items:
            $ref: "#/components/schemas/Dimension"
        currencies:
          type: array
          uniqueItems: true
          items:
            type: string
            pattern: "^[A-Z]{3}$"
    Capabilities:
      type: object
      additionalProperties: false
      required:
        - profile_version
        - focus_version
        - provider
        - authorization_methods
        - datasets
      properties:
        profile_version:
          type: string
          const: "0.1"
        focus_version:
          type: string
          const: "1.4"
        provider:
          type: string
          minLength: 1
        authorization_methods:
          type: array
          minItems: 1
          uniqueItems: true
          items:
            $ref: "#/components/schemas/AuthorizationMethod"
        protected_resource_metadata_url:
          type: [string, "null"]
          format: uri
        datasets:
          type: object
          additionalProperties: false
          required: [usage]
          properties:
            usage:
              $ref: "#/components/schemas/DatasetCapabilities"
            costs:
              $ref: "#/components/schemas/DatasetCapabilities"
    CommonRecord:
      type: object
      required:
        - x_RecordId
        - x_RecordUpdatedAt
        - x_Granularity
        - ChargePeriodStart
        - ChargePeriodEnd
        - ServiceProviderName
        - ServiceCategory
        - ServiceName
      properties:
        x_RecordId:
          type: string
          minLength: 1
        x_RecordUpdatedAt:
          type: string
          format: date-time
        x_Granularity:
          $ref: "#/components/schemas/Granularity"
        ChargePeriodStart:
          type: string
          format: date-time
        ChargePeriodEnd:
          type: string
          format: date-time
        ServiceProviderName:
          type: string
          minLength: 1
        ServiceCategory:
          type: string
          const: AI and Machine Learning
        ServiceSubcategory:
          type: [string, "null"]
        ServiceName:
          type: string
          minLength: 1
        SkuId:
          type: [string, "null"]
        SkuMeter:
          type: [string, "null"]
        x_ModelId:
          type: [string, "null"]
        x_ProjectId:
          type: [string, "null"]
        x_WorkspaceId:
          type: [string, "null"]
        x_ApiKeyId:
          type: [string, "null"]
        x_ServiceTier:
          type: [string, "null"]
        x_WorkloadType:
          type: [string, "null"]
        x_UpstreamProvider:
          type: [string, "null"]
    UsageRecord:
      allOf:
        - $ref: "#/components/schemas/CommonRecord"
        - type: object
          required:
            - SkuId
            - SkuMeter
            - ConsumedQuantity
            - ConsumedUnit
            - x_UsageType
          properties:
            SkuId:
              type: string
              minLength: 1
            SkuMeter:
              type: string
              minLength: 1
            ConsumedQuantity:
              $ref: "#/components/schemas/DecimalString"
            ConsumedUnit:
              type: string
              minLength: 1
            x_UsageType:
              oneOf:
                - $ref: "#/components/schemas/UsageType"
                - type: string
                  pattern: "^x_[A-Za-z0-9_]+$"
    CostRecord:
      allOf:
        - $ref: "#/components/schemas/CommonRecord"
        - type: object
          required:
            - BillingPeriodStart
            - BillingPeriodEnd
            - InvoiceIssuerName
            - ChargeCategory
            - ChargeDescription
            - BillingCurrency
            - BilledCost
            - EffectiveCost
            - x_CostStatus
          properties:
            BillingPeriodStart:
              type: string
              format: date-time
            BillingPeriodEnd:
              type: string
              format: date-time
            InvoiceIssuerName:
              type: string
              minLength: 1
            InvoiceId:
              type: [string, "null"]
            ChargeCategory:
              type: string
              enum: [Usage, Purchase, Tax, Credit, Adjustment]
            ChargeClass:
              type: [string, "null"]
            ChargeDescription:
              type: string
            BillingCurrency:
              type: string
              pattern: "^[A-Z]{3}$"
            BilledCost:
              $ref: "#/components/schemas/DecimalString"
            EffectiveCost:
              $ref: "#/components/schemas/DecimalString"
            PricingCurrency:
              type: [string, "null"]
              pattern: "^[A-Z]{3}$"
            PricingCurrencyBilledCost:
              oneOf:
                - $ref: "#/components/schemas/DecimalString"
                - type: "null"
            x_CostStatus:
              type: string
              enum: [provisional, final]
            x_UsageType:
              type: [string, "null"]
            x_CorrectsRecordId:
              type: [string, "null"]
    UsagePage:
      type: object
      additionalProperties: false
      required: [data, next_cursor, as_of, available_through]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/UsageRecord"
        next_cursor:
          type: [string, "null"]
        as_of:
          type: string
          format: date-time
        available_through:
          type: string
          format: date-time
    CostPage:
      type: object
      additionalProperties: false
      required: [data, next_cursor, as_of, available_through]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/CostRecord"
        next_cursor:
          type: [string, "null"]
        as_of:
          type: string
          format: date-time
        available_through:
          type: string
          format: date-time
    Problem:
      type: object
      required: [type, title, status]
      properties:
        type:
          type: string
          format: uri-reference
        title:
          type: string
        status:
          type: integer
          minimum: 400
          maximum: 599
        detail:
          type: string
        instance:
          type: string
          format: uri-reference
  examples:
    CapabilitiesExample:
      value:
        profile_version: "0.1"
        focus_version: "1.4"
        provider: Example Inference
        authorization_methods:
          - scoped_bearer_token
          - oauth2_authorization_code
        protected_resource_metadata_url: https://api.provider.example/.well-known/oauth-protected-resource
        datasets:
          usage:
            endpoint: /v1/finops/usage
            granularities: [1h, 1d]
            retention_days: 90
            maximum_window_days: 7
            freshness_lag_minutes: 15
            dimensions: [model, project, api_key, service_tier]
            currencies: [USD]
          costs:
            endpoint: /v1/finops/costs
            granularities: [1d]
            retention_days: 365
            maximum_window_days: 31
            settlement_lag_hours: 24
            dimensions: [model, project]
            currencies: [USD]
    UsagePageExample:
      value:
        data:
          - x_RecordId: usage_20260701_model-x_input
            x_RecordUpdatedAt: "2026-07-02T01:05:00Z"
            x_Granularity: 1h
            ChargePeriodStart: "2026-07-01T00:00:00Z"
            ChargePeriodEnd: "2026-07-01T01:00:00Z"
            ServiceProviderName: Example Inference
            ServiceCategory: AI and Machine Learning
            ServiceSubcategory: Generative AI
            ServiceName: Inference API
            SkuId: model-x:input
            SkuMeter: Input Tokens
            ConsumedQuantity: "1250000"
            ConsumedUnit: tokens
            x_UsageType: input_tokens
            x_ModelId: model-x
            x_ProjectId: project_123
            x_ApiKeyId: key_456
            x_ServiceTier: standard
        next_cursor: eyJvZmZzZXQiOjF9
        as_of: "2026-07-02T01:05:00Z"
        available_through: "2026-07-02T01:00:00Z"
    CostPageExample:
      value:
        data:
          - x_RecordId: cost_20260701_model-x_input
            x_RecordUpdatedAt: "2026-07-03T03:00:00Z"
            x_Granularity: 1d
            BillingPeriodStart: "2026-07-01T00:00:00Z"
            BillingPeriodEnd: "2026-08-01T00:00:00Z"
            ChargePeriodStart: "2026-07-01T00:00:00Z"
            ChargePeriodEnd: "2026-07-02T00:00:00Z"
            ServiceProviderName: Example Inference
            ServiceCategory: AI and Machine Learning
            ServiceSubcategory: Generative AI
            ServiceName: Inference API
            InvoiceIssuerName: Example Inference
            ChargeCategory: Usage
            ChargeClass: null
            ChargeDescription: Model X input tokens
            BillingCurrency: USD
            BilledCost: "1.250000"
            EffectiveCost: "1.250000"
            SkuId: model-x:input
            SkuMeter: Input Tokens
            x_CostStatus: final
            x_UsageType: input_tokens
            x_ModelId: model-x
            x_ProjectId: project_123
        next_cursor: null
        as_of: "2026-07-03T03:00:00Z"
        available_through: "2026-07-02T00:00:00Z"
