openapi: 3.0.3
info:
  title: 零感AI Text API
  version: 1.0.0
  description: >
    Partner API for high-volume paper text rewrite and AI-reduction callers.
    The public integration only needs target.platform; server-side strategy
    maps the platform to the matching 零感AI processing profile. Partner
    systems call text tasks with a ppai_ API key. ppacct_ account management
    credentials can create and disable ppai_ keys, but cannot call text
    transformation APIs. Pricing shown in the portal is a reference price;
    partners prepay quota and confirm final terms with customer service.
servers:
  - url: https://api.linggantext.com
    description: Production API gateway
security:
  - bearerAuth: []
paths:
  /:
    get:
      operationId: getLingganAiApiPortal
      summary: Open the 零感AI API portal and documentation entry.
      security: []
      responses:
        "200":
          description: HTML console page.
          content:
            text/html:
              schema:
                type: string
  /v1/health:
    get:
      operationId: getTextCapabilityGatewayHealth
      summary: Health check for the isolated public AI gateway process.
      security: []
      responses:
        "200":
          description: Gateway health snapshot.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HealthResponse"
  /v1/ready:
    get:
      operationId: getTextCapabilityReadiness
      summary: Readiness and overload protection status.
      description: Returns 200 when the Fastify process is ready and not under configured pressure.
      security: []
      responses:
        "200":
          description: API process is ready.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReadyResponse"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/platforms:
    get:
      operationId: listTextTransformationPlatforms
      summary: List available text transformation strategies.
      security: []
      responses:
        "200":
          description: Platform strategy list.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlatformList"
  /v1/overview:
    get:
      operationId: getLingganAiTextApiOverview
      summary: Get the public integration overview.
      description: Returns Base URL, credential types, public routes and the current capability matrix for portal pages and lightweight integration checks.
      security: []
      responses:
        "200":
          description: Public integration overview.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PublicOverview"
  /v1/openapi.yaml:
    get:
      operationId: getTextCapabilityOpenApiDocument
      summary: Fetch the canonical OpenAPI document.
      description: Serves this API contract as YAML so API reference tools can load it by URL.
      security: []
      responses:
        "200":
          description: OpenAPI YAML document.
          content:
            application/yaml:
              schema:
                type: string
  /v1/usage/preview:
    post:
      operationId: previewTextTransformationUsage
      summary: Preview character usage before creating a transformation.
      description: >
        Returns the same character-counting fields used by transformation billing.
        This endpoint does not call the model, create a task, or record usage.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UsagePreviewRequest"
            examples:
              chinese:
                summary: Preview Chinese/default billing characters.
                value:
                  input: "这是中文 English 123。"
                  target:
                    language: "zh"
      responses:
        "200":
          description: Character usage preview.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsagePreviewResponse"
        "400":
          $ref: "#/components/responses/InvalidRequest"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/ServerError"
  /v1/me:
    get:
      operationId: getCallerProfile
      summary: Validate the current API key and return caller quota and usage.
      responses:
        "200":
          description: Caller profile.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CallerProfileResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "429":
          $ref: "#/components/responses/RateLimited"
  /v1/text-transformations:
    post:
      operationId: createTextTransformation
      summary: Create a text transformation task.
      parameters:
        - $ref: "#/components/parameters/IdempotencyKey"
        - $ref: "#/components/parameters/RequestId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateTextTransformationRequest"
            examples:
              partnerPortalSync:
                summary: Sync AI-reduction request for a partner portal.
                value:
                  input: "This is the text to transform."
                  capability: "deai"
                  target:
                    platform: "cnki"
                    language: "zh"
                  mode: "sync"
                  metadata:
                    source: "partner-portal"
              partnerPortalAsync:
                summary: Async AI-reduction request for a partner portal.
                value:
                  input: "This is the text to transform."
                  capability: "deai"
                  target:
                    platform: "vip"
                    language: "zh"
                  mode: "async"
                  metadata:
                    source: "partner-portal"
      responses:
        "200":
          description: The sync transformation finished during the short server-side wait window.
          headers:
            x-request-id:
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TextTransformation"
        "202":
          description: The async transformation was queued, or a sync transformation is still running after the short wait window.
          headers:
            Location:
              schema:
                type: string
              description: Poll URL for the queued transformation.
            Retry-After:
              schema:
                type: integer
              description: Suggested poll delay in seconds.
            x-request-id:
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TextTransformation"
        "400":
          $ref: "#/components/responses/InvalidRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "429":
          $ref: "#/components/responses/RateLimited"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
        "500":
          $ref: "#/components/responses/ServerError"
  /v1/admin/api-keys:
    get:
      operationId: listAdminApiKeys
      summary: List API keys, quota and usage for the internal console.
      description: Requires TEXT_CAPABILITY_ADMIN_TOKEN.
      responses:
        "200":
          description: API key list.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CallerListResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    post:
      operationId: createAdminApiKey
      summary: Create a new API key in the writable key store.
      description: Requires TEXT_CAPABILITY_ADMIN_TOKEN and TEXT_CAPABILITY_API_KEYS_FILE.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateApiKeyRequest"
      responses:
        "201":
          description: API key created. The plaintext key is shown once.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateApiKeyResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "409":
          $ref: "#/components/responses/Conflict"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/admin/api-keys/{caller_id}/disable:
    post:
      operationId: disableAdminApiKey
      summary: Disable a caller API key.
      description: Requires TEXT_CAPABILITY_ADMIN_TOKEN and a writable key store.
      parameters:
        - name: caller_id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: API key disabled.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/admin/accounts:
    get:
      operationId: listAdminAccounts
      summary: List account management principals for the internal console.
      description: Requires TEXT_CAPABILITY_ADMIN_TOKEN.
      responses:
        "200":
          description: Account list.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AccountListResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    post:
      operationId: createAdminAccount
      summary: Create an account management credential.
      description: Requires TEXT_CAPABILITY_ADMIN_TOKEN and TEXT_CAPABILITY_API_KEYS_FILE. The returned management credential can manage ppai_ keys but cannot call text transformation APIs.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateAccountRequest"
      responses:
        "201":
          description: Account created. The plaintext management credential is shown once.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateAccountResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "409":
          $ref: "#/components/responses/Conflict"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/admin/audit:
    get:
      operationId: listAdminAuditEvents
      summary: List API key management audit events.
      description: Requires TEXT_CAPABILITY_ADMIN_TOKEN.
      responses:
        "200":
          description: Audit event list.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/admin/playground/text-transformations:
    post:
      operationId: createAdminPlaygroundTextTransformation
      summary: Run a server-side playground transformation for an existing caller.
      description: Requires TEXT_CAPABILITY_ADMIN_TOKEN. The browser does not need the caller API key plaintext.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - caller_id
                - input
                - target
              properties:
                caller_id:
                  type: string
                input:
                  type: string
                capability:
                  type: string
                  enum:
                    - rewrite
                    - deai
                    - rewrite_deai
                  default: deai
                target:
                  $ref: "#/components/schemas/TextTransformationTarget"
                mode:
                  type: string
                  enum:
                    - sync
                    - async
                  default: sync
      responses:
        "200":
          description: Playground transformation completed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TextTransformation"
        "202":
          description: Playground transformation queued or still running.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TextTransformation"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/session/bind:
    post:
      operationId: bindPortalAccountSession
      summary: Bind an account management credential for the portal.
      description: Uses a ppacct management credential. The credential can manage ppai_ keys but cannot call text transformations.
      responses:
        "200":
          description: Portal account profile.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PortalAccountResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/account:
    get:
      operationId: getPortalAccount
      summary: Get account quota, ppai_ keys and usage.
      responses:
        "200":
          description: Portal account profile.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PortalAccountResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/api-keys:
    get:
      operationId: listPortalApiKeys
      summary: List ppai_ keys for the bound account.
      responses:
        "200":
          description: Child API key list.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    post:
      operationId: createPortalApiKey
      summary: Create a ppai_ key under the bound account.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateApiKeyRequest"
      responses:
        "201":
          description: Child API key created. The plaintext key is shown once.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateApiKeyResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "409":
          $ref: "#/components/responses/Conflict"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/api-keys/{caller_id}/disable:
    post:
      operationId: disablePortalApiKey
      summary: Disable a ppai_ key under the bound account.
      parameters:
        - name: caller_id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Child API key disabled.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/usage/summary:
    get:
      operationId: getPortalUsageSummary
      summary: Get account-level and ppai_ usage summary.
      responses:
        "200":
          description: Portal usage summary.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/usage/events:
    get:
      operationId: listPortalUsageEvents
      summary: List recent successful usage events for the bound account.
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
            minimum: 1
            maximum: 200
      responses:
        "200":
          description: Portal usage event list.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/playground/text-transformations:
    post:
      operationId: createPortalPlaygroundTextTransformation
      summary: Run a server-side playground transformation using a ppai_ key id.
      description: Uses account management credential plus caller_id. The browser never needs to store the ppai_ plaintext.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - caller_id
                - input
                - capability
                - target
              properties:
                caller_id:
                  type: string
                input:
                  type: string
                capability:
                  type: string
                  enum:
                    - rewrite
                    - deai
                    - rewrite_deai
                target:
                  $ref: "#/components/schemas/TextTransformationTarget"
                mode:
                  type: string
                  enum:
                    - sync
                    - async
                  default: sync
      responses:
        "200":
          description: Portal playground transformation completed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TextTransformation"
        "202":
          description: Portal playground transformation queued or still running.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TextTransformation"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          $ref: "#/components/responses/NotFound"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
  /v1/portal/models:
    get:
      operationId: listPortalModels
      summary: List platform and capability matrix for the portal model marketplace.
      security: []
      responses:
        "200":
          description: Platform strategy list.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlatformList"
  /v1/text-transformations/{transformation_id}:
    get:
      operationId: getTextTransformation
      summary: Poll or fetch a text transformation.
      parameters:
        - name: transformation_id
          in: path
          required: true
          schema:
            type: string
        - $ref: "#/components/parameters/RequestId"
      responses:
        "200":
          description: Transformation status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TextTransformation"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/ServerError"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        minLength: 1
        maxLength: 128
      description: Stable caller-generated key for create retries.
    RequestId:
      name: x-request-id
      in: header
      required: false
      schema:
        type: string
        maxLength: 128
      description: Optional caller trace id echoed by the gateway.
  responses:
    InvalidRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Unauthorized:
      description: Missing or invalid bearer token.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Forbidden:
      description: Caller has no permission for the requested capability or target.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Conflict:
      description: Idempotency key conflicts with another payload.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    NotFound:
      description: The transformation was not found for this caller.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    RateLimited:
      description: Caller or source is rate limited.
      headers:
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    ServiceUnavailable:
      description: Capability is temporarily unavailable in this deployment, for example async mode without a worker queue or process pressure protection.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    ServerError:
      description: Internal server error.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
  schemas:
    HealthResponse:
      type: object
      required:
        - success
        - service
        - status
      properties:
        success:
          type: boolean
        service:
          type: string
          example: text-capability-service
        status:
          type: string
          example: ok
        time:
          type: string
          format: date-time
        textCapabilityApi:
          type: object
          additionalProperties: true
    ReadyResponse:
      type: object
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - ok
    PublicOverview:
      type: object
      properties:
        object:
          type: string
          enum:
            - linggan.text_api.overview
        name:
          type: string
          example: 零感AI
        base_url:
          type: string
          example: https://api.linggantext.com
        contact_email:
          type: string
          example: usw20020102@gmail.com
        access:
          type: object
          properties:
            method:
              type: string
              example: contact_customer_service
            note:
              type: string
              example: 联系客服，备注“申请密钥”。合作方预付开通额度，量大可优惠。
        pricing:
          type: object
          properties:
            type:
              type: string
              example: reference_price
            unit_price_cny:
              type: number
              example: 2
            unit_billable_chars:
              type: integer
              example: 1000
            note:
              type: string
        billing:
          type: object
          properties:
            billable_field:
              type: string
              example: billable_chars
            zh:
              type: string
            en:
              type: string
        auth:
          type: object
          properties:
            caller_api_key:
              type: object
              properties:
                prefix:
                  type: string
                  example: ppai_
                header:
                  type: string
                  example: Authorization: Bearer ppai_xxx
                used_for:
                  type: array
                  items:
                    type: string
            account_management_credential:
              type: object
              properties:
                prefix:
                  type: string
                  example: ppacct_
                header:
                  type: string
                  example: Authorization: Bearer ppacct_xxx
                used_for:
                  type: array
                  items:
                    type: string
        default_level:
          type: string
          example: L2
        default_capability:
          type: string
          example: deai
        capabilities:
          type: array
          items:
            type: string
        request_model:
          type: object
          properties:
            required:
              type: array
              items:
                type: string
            optional:
              type: array
              items:
                type: string
            note:
              type: string
        public_routes:
          type: array
          items:
            type: string
        platforms:
          type: array
          items:
            $ref: "#/components/schemas/PlatformMatrixItem"
    PlatformList:
      type: object
      required:
        - object
        - default_level
        - levels
        - platforms
        - data
      properties:
        object:
          type: string
          enum:
            - list
        default_level:
          type: string
          example: L2
        levels:
          type: array
          items:
            $ref: "#/components/schemas/CapabilityLevel"
        platforms:
          type: array
          items:
            $ref: "#/components/schemas/PlatformMatrixItem"
        data:
          type: array
          items:
            $ref: "#/components/schemas/PlatformStrategy"
    CapabilityLevel:
      type: object
      properties:
        id:
          type: string
          enum:
            - L1
            - L2
            - L3
            - L4
        label:
          type: string
        summary:
          type: string
        default:
          type: boolean
        badge:
          type: string
        recommended_for:
          type: array
          items:
            type: string
        warning:
          type: string
    PlatformMatrixItem:
      type: object
      properties:
        platform:
          type: string
        languages:
          type: array
          items:
            type: string
        levels:
          type: array
          items:
            type: object
            properties:
              level:
                type: string
              option:
                type: string
              language:
                type: string
              capabilities:
                type: array
                items:
                  type: string
              max_input_chars:
                type: integer
              permission_required:
                type: boolean
    PlatformStrategy:
      type: object
      properties:
        id:
          type: string
          example: cnki.l2.zh
        platform:
          type: string
          example: cnki
        level:
          type: string
          enum:
            - L1
            - L2
            - L3
            - L4
          example: L2
        option:
          type: string
          description: Legacy strategy option retained for compatibility.
          example: standard
        profileId:
          type: string
          nullable: true
          description: Internal AI Engine profile id when the public level maps to a concrete profile.
        postprocessPresetId:
          type: string
          nullable: true
          description: Optional internal postprocess preset override.
        language:
          type: string
          example: zh
        capabilities:
          type: array
          items:
            type: string
        version:
          type: string
        maxInputChars:
          type: integer
        permissionRequired:
          type: boolean
        levelProfile:
          type: object
          additionalProperties: true
        billing:
          type: object
          additionalProperties: true
    UsagePreviewRequest:
      type: object
      required:
        - input
      properties:
        input:
          type: string
          minLength: 1
          description: Raw text to count before submitting a transformation.
        target:
          type: object
          properties:
            language:
              type: string
              enum:
                - zh
                - en
              default: zh
        language:
          type: string
          deprecated: true
          description: Legacy shorthand. Prefer target.language.
    UsageMetrics:
      type: object
      properties:
        input_chars:
          type: integer
        normalized_chars:
          type: integer
        billable_chars:
          type: integer
        billing_language:
          type: string
        billing_mode:
          type: string
    UsagePreviewResponse:
      type: object
      required:
        - object
        - usage
      properties:
        object:
          type: string
          enum:
            - usage.preview
        target:
          type: object
          properties:
            language:
              type: string
        usage:
          $ref: "#/components/schemas/UsageMetrics"
        request_id:
          type: string
          nullable: true
    UsageSummary:
      type: object
      properties:
        caller_id:
          type: string
          nullable: true
        event_count:
          type: integer
        transformation_count:
          type: integer
        input_chars:
          type: integer
        normalized_chars:
          type: integer
        billable_chars:
          type: integer
        char_quota:
          type: integer
        remaining_chars:
          type: integer
          nullable: true
        first_event_at:
          type: string
          nullable: true
        last_event_at:
          type: string
          nullable: true
        account_id:
          type: string
          nullable: true
        api_key_count:
          type: integer
    Caller:
      type: object
      properties:
        id:
          type: string
        accountId:
          type: string
          nullable: true
        type:
          type: string
        status:
          type: string
          enum:
            - active
            - disabled
        source:
          type: string
        allowedCapabilities:
          type: array
          items:
            type: string
        allowedTargets:
          type: array
          items:
            type: string
        quotaMode:
          type: string
          enum:
            - observe_only
            - enforced
        charQuota:
          type: integer
        metadata:
          type: object
          additionalProperties: true
    Account:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
        status:
          type: string
          enum:
            - active
            - disabled
        source:
          type: string
        quotaMode:
          type: string
          enum:
            - observe_only
            - enforced
        charQuota:
          type: integer
        metadata:
          type: object
          additionalProperties: true
    PortalAccountResponse:
      type: object
      properties:
        object:
          type: string
          enum:
            - portal.account
        account:
          $ref: "#/components/schemas/Account"
        usage:
          $ref: "#/components/schemas/UsageSummary"
        api_keys:
          type: array
          items:
            allOf:
              - $ref: "#/components/schemas/Caller"
              - type: object
                properties:
                  usage:
                    $ref: "#/components/schemas/UsageSummary"
        request_id:
          type: string
    AccountListResponse:
      type: object
      properties:
        object:
          type: string
          enum:
            - list
        data:
          type: array
          items:
            $ref: "#/components/schemas/Account"
        request_id:
          type: string
    CallerProfileResponse:
      type: object
      properties:
        object:
          type: string
          enum:
            - caller.profile
        caller:
          $ref: "#/components/schemas/Caller"
        usage:
          $ref: "#/components/schemas/UsageSummary"
        request_id:
          type: string
    CallerListResponse:
      type: object
      properties:
        object:
          type: string
          enum:
            - list
        data:
          type: array
          items:
            allOf:
              - $ref: "#/components/schemas/Caller"
              - type: object
                properties:
                  usage:
                    $ref: "#/components/schemas/UsageSummary"
        request_id:
          type: string
    CreateApiKeyRequest:
      type: object
      required:
        - id
      properties:
        id:
          type: string
        source:
          type: string
        type:
          type: string
          default: partner
        status:
          type: string
          default: active
        allowedCapabilities:
          type: array
          items:
            type: string
        allowedTargets:
          type: array
          items:
            type: string
        quotaMode:
          type: string
          enum:
            - observe_only
            - enforced
          default: observe_only
        charQuota:
          type: integer
          default: 0
        metadata:
          type: object
          additionalProperties: true
    CreateAccountRequest:
      type: object
      required:
        - id
      properties:
        id:
          type: string
        source:
          type: string
        status:
          type: string
          default: active
        quotaMode:
          type: string
          enum:
            - observe_only
            - enforced
          default: observe_only
        charQuota:
          type: integer
          default: 0
        metadata:
          type: object
          additionalProperties: true
    CreateAccountResponse:
      type: object
      properties:
        object:
          type: string
          enum:
            - account.created
        plaintextManagementCredential:
          type: string
          description: Plaintext account management credential shown only once.
        storeOnlyOnce:
          type: boolean
        account:
          $ref: "#/components/schemas/Account"
        request_id:
          type: string
    CreateApiKeyResponse:
      type: object
      properties:
        object:
          type: string
          enum:
            - api_key.created
        plaintextApiKey:
          type: string
          description: Plaintext key shown only once.
        storeOnlyOnce:
          type: boolean
        caller:
          $ref: "#/components/schemas/Caller"
        request_id:
          type: string
    CreateTextTransformationRequest:
      type: object
      required:
        - input
        - target
      properties:
        input:
          type: string
          minLength: 1
          maxLength: 20000
          description: Raw text to transform.
        capability:
          type: string
          enum:
            - rewrite
            - deai
            - rewrite_deai
          default: deai
          description: Defaults to deai when omitted. Use rewrite or rewrite_deai only when explicitly needed.
        target:
          $ref: "#/components/schemas/TextTransformationTarget"
        mode:
          type: string
          enum:
            - sync
            - async
          default: sync
        metadata:
          type: object
          additionalProperties: true
          properties:
            source:
              type: string
              description: Bound caller source, for example partner-portal.
    TextTransformationTarget:
      type: object
      required:
        - platform
      properties:
        platform:
          type: string
          enum:
            - cnki
            - cnki-plus
            - vip
            - vip-plus
            - zhuque-ai
            - zhuque-ai-paper
            - zhuque-ai-daily
            - daya
            - gezida
            - wanfang
            - paperpass
            - paperpass-plus
            - paperyy
            - bigan
            - turnitin
        option:
          type: string
          deprecated: true
          description: Legacy compatibility field. Partner integrations should only pass target.platform.
          example: standard
        level:
          type: string
          enum:
            - L1
            - L2
            - L3
            - L4
          default: L2
          description: Advanced internal override. Partner integrations should omit it and only pass target.platform.
        language:
          type: string
          enum:
            - zh
            - en
          default: zh
    TextTransformation:
      type: object
      required:
        - id
        - object
        - status
      properties:
        id:
          type: string
          nullable: true
        object:
          type: string
          enum:
            - text.transformation
        created:
          type: integer
          nullable: true
          description: Unix epoch seconds.
        status:
          type: string
          enum:
            - queued
            - running
            - succeeded
            - failed
            - blocked
        capability:
          type: string
          nullable: true
        target:
          $ref: "#/components/schemas/TextTransformationTarget"
        output:
          type: object
          nullable: true
          properties:
            text:
              type: string
        usage:
          allOf:
            - $ref: "#/components/schemas/UsageMetrics"
          nullable: true
        error:
          $ref: "#/components/schemas/ErrorObject"
        request_id:
          type: string
          nullable: true
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          $ref: "#/components/schemas/ErrorObject"
        request_id:
          type: string
          nullable: true
    ErrorObject:
      type: object
      nullable: true
      properties:
        message:
          type: string
        type:
          type: string
          enum:
            - invalid_request_error
            - authentication_error
            - permission_error
            - not_found_error
            - conflict_error
            - rate_limit_error
            - quota_error
            - api_error
        param:
          type: string
          nullable: true
        code:
          type: string
          nullable: true
          enum:
            - missing_idempotency_key
            - missing_input
            - missing_capability
            - missing_target_platform
            - unsupported_level
            - unsupported_target_option
            - unsupported_capability
            - target_not_available
            - target_not_allowed
            - capability_not_allowed
            - input_too_large
            - invalid_api_key
            - invalid_admin_token
            - invalid_management_credential
            - caller_disabled
            - account_disabled
            - account_not_found
            - account_already_exists
            - api_key_not_found
            - caller_not_found
            - caller_already_exists
            - idempotency_conflict
            - quota_exceeded
            - rate_limit_exceeded
            - async_not_enabled
            - api_key_store_read_only
            - account_store_not_configured
            - account_store_read_only
            - admin_console_not_configured
            - caller_lookup_not_supported
            - transformation_not_found
            - execution_failed
            - internal_error
