openapi: 3.0.3
info:
  title: SerperMatrix API
  version: 1.0.0
  description: REST API (DRF + Djoser + SimpleJWT).
paths:
  /api/v1/api-keys/:
    get:
      operationId: api_keys_list
      summary: List my API keys
      parameters:
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      tags:
      - api-keys
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAPIKeyListList'
          description: ''
    post:
      operationId: api_keys_create
      summary: Create API key
      tags:
      - api-keys
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/APIKeyCreate'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/APIKeyCreate'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/APIKeyCreate'
      security:
      - jwtAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyCreate'
          description: ''
  /api/v1/api-keys/{id}/:
    get:
      operationId: api_keys_retrieve
      summary: Retrieve API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - api-keys
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyList'
          description: ''
    put:
      operationId: api_keys_update
      summary: Rename API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - api-keys
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/APIKeyPartialUpdate'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/APIKeyPartialUpdate'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/APIKeyPartialUpdate'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyPartialUpdate'
          description: ''
    patch:
      operationId: api_keys_partial_update
      summary: Rename API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - api-keys
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedAPIKeyPartialUpdate'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedAPIKeyPartialUpdate'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedAPIKeyPartialUpdate'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyPartialUpdate'
          description: ''
    delete:
      operationId: api_keys_destroy
      summary: Revoke API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - api-keys
      security:
      - jwtAuth: []
      responses:
        '204':
          description: No response body
  /api/v1/api-keys/{id}/reset/:
    post:
      operationId: api_keys_reset_create
      description: Revokes the key and creates a new one with the same name.
      summary: Reset API key
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - api-keys
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/APIKeyList'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/APIKeyList'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/APIKeyList'
      security:
      - jwtAuth: []
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyCreatedResponse'
          description: ''
  /api/v1/api-keys/{id}/reveal/:
    post:
      operationId: api_keys_reveal_create
      description: Returns the full secret for keys created with encrypted storage.
        Legacy keys without stored ciphertext must be reset.
      summary: Reveal API key secret
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - api-keys
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/APIKeyList'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/APIKeyList'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/APIKeyList'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIKeyRevealResponse'
          description: ''
  /api/v1/auth/jwt/create/:
    post:
      operationId: auth_jwt_create_create
      description: Credential login; response body tokens + HttpOnly cookies (dual
        mode).
      tags:
      - auth
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenObtainPair'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenObtainPair'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TokenObtainPair'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenObtainPair'
          description: ''
  /api/v1/auth/jwt/refresh/:
    post:
      operationId: auth_jwt_refresh_create
      description: Rotate access token; accepts refresh in body or ``refresh`` cookie.
      tags:
      - auth
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRefresh'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenRefresh'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TokenRefresh'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenRefresh'
          description: ''
  /api/v1/auth/jwt/verify/:
    post:
      operationId: auth_jwt_verify_create
      description: |-
        Takes a token and indicates if it is valid.  This view provides no
        information about a token's fitness for a particular use.
      tags:
      - auth
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenVerify'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenVerify'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TokenVerify'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenVerify'
          description: ''
  /api/v1/auth/logout/:
    post:
      operationId: auth_logout_create
      summary: Logout (clear JWT cookies)
      tags:
      - auth
      security:
      - jwtAuth: []
      responses:
        '204':
          description: Cookies cleared.
  /api/v1/auth/resend-activation/:
    post:
      operationId: auth_resend_activation_create
      summary: Resend activation email
      tags:
      - auth
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ResendActivationRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ResendActivationRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ResendActivationRequest'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '204':
          description: Activation email queued.
        '400':
          description: Missing email, unknown user, or already active.
        '403':
          description: Account locked.
        '429':
          description: Too many resend attempts.
  /api/v1/billing/checkout/confirm/:
    post:
      operationId: billing_checkout_confirm_create
      description: Verifies a transaction directly against the Paddle API and grants
        credits + records a local Transaction if it is paid. Idempotent. This is the
        reliability fallback so credit-granting does not depend solely on a webhook
        arriving.
      summary: Confirm a Paddle transaction (server-side reconciliation)
      tags:
      - billing
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmTransaction'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ConfirmTransaction'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ConfirmTransaction'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingStatus'
          description: ''
  /api/v1/billing/checkout/create-transaction/:
    post:
      operationId: billing_checkout_create_transaction_create
      description: Creates a Paddle transaction for a specific plan and returns the
        transaction ID.
      summary: Create Paddle Transaction
      tags:
      - billing
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PurchaseRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PurchaseRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PurchaseRequest'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaddleCheckoutResponse'
          description: ''
  /api/v1/billing/status/:
    get:
      operationId: billing_status_list
      description: Authenticated billing status for checkout result polling.
      summary: Get current billing status
      tags:
      - billing
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/BillingStatus'
          description: ''
  /api/v1/chat/:
    post:
      operationId: chat_create
      description: |-
        POST /api/v1/chat — proxy chat completions through OpenRouter with
        credit billing, A/B testing, and dual logging.
      tags:
      - Chat
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ChatCompletionRequest'
        required: true
      security:
      - jwtAuth: []
      - ApiKeyAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatCompletionResponse'
          description: ''
        '400':
          description: Invalid request payload
        '402':
          description: Insufficient credits
        '502':
          description: Upstream API error
  /api/v1/logs:
    get:
      operationId: logs_list
      description: 'Dashboard activity: search/scrape request history with optional
        download.'
      summary: List my API activity logs
      parameters:
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      tags:
      - logs
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedAPILogListList'
          description: ''
  /api/v1/logs/{id}:
    get:
      operationId: logs_retrieve
      description: 'Dashboard activity: search/scrape request history with optional
        download.'
      summary: Retrieve a log entry (includes response body)
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - logs
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APILogDetail'
          description: ''
  /api/v1/logs/{id}/download:
    get:
      operationId: logs_download_retrieve
      description: 'Dashboard activity: search/scrape request history with optional
        download.'
      summary: Download stored response as file
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - logs
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
                description: Unspecified response body
          description: ''
        '404':
          description: No response body
  /api/v1/logs/stats:
    get:
      operationId: logs_stats_retrieve
      description: |-
        Time-bucketed usage for the Usage dashboard chart.

        Query params:
          * ``period``          — ``1d`` | ``7d`` | ``30d`` (default ``7d``);
                                  ignored when explicit custom dates are given.
          * ``created_after`` / ``created_before`` (or ``date_from`` /
            ``date_to``) — ISO dates for a custom range (override ``period``).
          * ``endpoint``        — ``search`` | ``scrape`` | ``chat`` (``any``/
                                  omitted = all).
          * ``api_key_prefix``  — single key prefix (``any``/omitted = all).

        Returns continuous daily buckets (missing days zero-filled) so the
        chart renders an unbroken series::

            {period, start, end, total_credits, total_requests,
             data: [{date, credits, requests}, ...]}
      tags:
      - logs
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APILogList'
          description: ''
  /api/v1/o/{provider}/:
    get:
      operationId: o_retrieve
      description: OAuth redirect flow; issues JWT + sets cookies on success.
      parameters:
      - in: path
        name: provider
        schema:
          type: string
          pattern: ^\S+$
        required: true
      tags:
      - o
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProviderAuth'
          description: ''
    post:
      operationId: o_create
      description: OAuth redirect flow; issues JWT + sets cookies on success.
      parameters:
      - in: path
        name: provider
        schema:
          type: string
          pattern: ^\S+$
        required: true
      tags:
      - o
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProviderAuth'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ProviderAuth'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ProviderAuth'
      security:
      - jwtAuth: []
      - {}
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProviderAuth'
          description: ''
  /api/v1/plans/:
    get:
      operationId: plans_list
      description: Public, read-only plan catalog. Purchases go through ``CheckoutViewSet``.
      summary: List pricing plans
      parameters:
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      tags:
      - plans
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedPlanList'
          description: ''
  /api/v1/plans/{id}/:
    get:
      operationId: plans_retrieve
      description: Public, read-only plan catalog. Purchases go through ``CheckoutViewSet``.
      summary: Retrieve a plan
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - plans
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Plan'
          description: ''
  /api/v1/profile/:
    get:
      operationId: profile_retrieve
      description: Returns the current user's profile, active plan, credit balances,
        and billing cycle expiration date.
      summary: Get Profile & Credit Usage
      tags:
      - profile
      security:
      - ApiKeyAuth: []
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgrammaticProfile'
          description: ''
  /api/v1/scrape:
    post:
      operationId: scrape_create
      description: POST /scrape — forwards to ``SERPERMATRIX_SCRAPE_BASE_URL``.
      summary: Scrape a URL (configured upstream)
      tags:
      - scrape
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ScrapeRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ScrapeRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ScrapeRequest'
        required: true
      security:
      - ApiKeyAuth: []
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '400':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '402':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '502':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '503':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
  /api/v1/search:
    post:
      operationId: search_create
      description: POST /search — Unified search with ``sources``.
      summary: Search the web across one or more sources
      tags:
      - search
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SearchRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SearchRequest'
        required: true
      security:
      - ApiKeyAuth: []
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '400':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '402':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
        '502':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: ''
  /api/v1/transactions/:
    get:
      operationId: transactions_list
      description: Current user's transaction history.
      summary: List my billing transactions
      parameters:
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      tags:
      - transactions
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTransactionList'
          description: ''
  /api/v1/transactions/{id}/:
    get:
      operationId: transactions_retrieve
      description: Current user's transaction history.
      summary: Retrieve a transaction
      parameters:
      - in: path
        name: id
        schema:
          type: string
          pattern: ^[0-9]+$
        required: true
      tags:
      - transactions
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transaction'
          description: ''
  /api/v1/users/:
    get:
      operationId: users_list
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      parameters:
      - name: page
        required: false
        in: query
        description: A page number within the paginated result set.
        schema:
          type: integer
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedUserList'
          description: ''
    post:
      operationId: users_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCreatePasswordRetype'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/UserCreatePasswordRetype'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/UserCreatePasswordRetype'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserCreatePasswordRetype'
          description: ''
  /api/v1/users/{id}/:
    get:
      operationId: users_retrieve
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this user account.
        required: true
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    put:
      operationId: users_update
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this user account.
        required: true
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/User'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/User'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    patch:
      operationId: users_partial_update
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this user account.
        required: true
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedUser'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedUser'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedUser'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    delete:
      operationId: users_destroy
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: A unique integer value identifying this user account.
        required: true
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '204':
          description: No response body
  /api/v1/users/activation/:
    post:
      operationId: users_activation_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Activation'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/Activation'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/Activation'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Activation'
          description: ''
  /api/v1/users/me/:
    get:
      operationId: users_me_retrieve
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    put:
      operationId: users_me_update
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/User'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/User'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    patch:
      operationId: users_me_partial_update
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedUser'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedUser'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedUser'
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
          description: ''
    delete:
      operationId: users_me_destroy
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      security:
      - jwtAuth: []
      responses:
        '204':
          description: No response body
  /api/v1/users/resend_activation/:
    post:
      operationId: users_resend_activation_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendEmailReset'
          description: ''
  /api/v1/users/reset_email/:
    post:
      operationId: users_reset_email_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendEmailReset'
          description: ''
  /api/v1/users/reset_email_confirm/:
    post:
      operationId: users_reset_email_confirm_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UsernameResetConfirm'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/UsernameResetConfirm'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/UsernameResetConfirm'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsernameResetConfirm'
          description: ''
  /api/v1/users/reset_password/:
    post:
      operationId: users_reset_password_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SendEmailReset'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendEmailReset'
          description: ''
  /api/v1/users/reset_password_confirm/:
    post:
      operationId: users_reset_password_confirm_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PasswordResetConfirmRetype'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PasswordResetConfirmRetype'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PasswordResetConfirmRetype'
        required: true
      security:
      - jwtAuth: []
      - {}
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PasswordResetConfirmRetype'
          description: ''
  /api/v1/users/set_email/:
    post:
      operationId: users_set_email_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SetUsername'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SetUsername'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SetUsername'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SetUsername'
          description: ''
  /api/v1/users/set_password/:
    post:
      operationId: users_set_password_create
      description: |-
        Djoser user endpoints (registration, activation, ``me``, CRUD for staff).

        Sensitive anonymous actions use ``ScopedRateThrottle`` scopes from settings.
      tags:
      - users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SetPassword'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SetPassword'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SetPassword'
        required: true
      security:
      - jwtAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SetPassword'
          description: ''
components:
  schemas:
    APIKeyCreate:
      type: object
      properties:
        name:
          type: string
          default: Default
          maxLength: 100
    APIKeyCreatedResponse:
      type: object
      description: Returned once after create or reset.
      properties:
        id:
          type: integer
        name:
          type: string
        prefix:
          type: string
        key:
          type: string
          description: Full secret; store once; never shown again.
        created_at:
          type: string
          format: date-time
        detail:
          type: string
      required:
      - created_at
      - detail
      - id
      - key
      - name
      - prefix
    APIKeyList:
      type: object
      description: List/retrieve — never exposes the secret; only prefix + metadata.
      properties:
        id:
          type: integer
          readOnly: true
        name:
          type: string
          readOnly: true
        prefix:
          type: string
          readOnly: true
        is_active:
          type: boolean
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
        last_used_at:
          type: string
          format: date-time
          readOnly: true
          nullable: true
        total_requests:
          type: integer
          readOnly: true
      required:
      - created_at
      - id
      - is_active
      - last_used_at
      - name
      - prefix
      - total_requests
    APIKeyPartialUpdate:
      type: object
      description: Rename an active key (``PATCH``).
      properties:
        name:
          type: string
          maxLength: 100
    APIKeyRevealResponse:
      type: object
      description: Full secret for an active key (owner only, via ``POST …/reveal/``).
      properties:
        key:
          type: string
      required:
      - key
    APILogDetail:
      type: object
      properties:
        id:
          type: integer
          readOnly: true
        endpoint:
          type: string
          maxLength: 50
        query:
          type: string
          maxLength: 500
        status_code:
          type: integer
          maximum: 2147483647
          minimum: -2147483648
        credits_used:
          type: integer
          maximum: 2147483647
          minimum: -2147483648
        response_time_ms:
          type: integer
          maximum: 2147483647
          minimum: -2147483648
        cached:
          type: boolean
        content_format:
          $ref: '#/components/schemas/ContentFormatEnum'
        api_key_prefix:
          type: string
          maxLength: 12
        created_at:
          type: string
          format: date-time
          readOnly: true
        response_body:
          type: string
      required:
      - created_at
      - endpoint
      - id
    APILogList:
      type: object
      description: List activity without full response body (use retrieve or download).
      properties:
        id:
          type: integer
          readOnly: true
        endpoint:
          type: string
          maxLength: 50
        query:
          type: string
          maxLength: 500
        status_code:
          type: integer
          maximum: 2147483647
          minimum: -2147483648
        credits_used:
          type: integer
          maximum: 2147483647
          minimum: -2147483648
        response_time_ms:
          type: integer
          maximum: 2147483647
          minimum: -2147483648
        cached:
          type: boolean
        content_format:
          $ref: '#/components/schemas/ContentFormatEnum'
        api_key_prefix:
          type: string
          maxLength: 12
        created_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - created_at
      - endpoint
      - id
    Activation:
      type: object
      properties:
        uid:
          type: string
        token:
          type: string
      required:
      - token
      - uid
    BillingIntervalEnum:
      enum:
      - monthly
      - yearly
      type: string
      description: |-
        * `monthly` - monthly
        * `yearly` - yearly
    BillingStatus:
      type: object
      description: Compact authenticated billing status for post-checkout polling.
      properties:
        plan_slug:
          type: string
          nullable: true
        plan_name:
          type: string
          nullable: true
        plan_credits:
          type: integer
        extra_credits:
          type: integer
        current_cycle_end:
          type: string
          format: date-time
          nullable: true
        paid_through:
          type: string
          format: date-time
          nullable: true
        subscription_status:
          type: string
          nullable: true
        billing_cycle:
          type: string
          nullable: true
      required:
      - billing_cycle
      - current_cycle_end
      - extra_credits
      - paid_through
      - plan_credits
      - plan_name
      - plan_slug
      - subscription_status
    ChatCompletionRequest:
      type: object
      properties:
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
          description: List of message objects with 'role' and 'content'.
          maxItems: 100
          minItems: 1
        temperature:
          type: number
          format: double
          maximum: 2.0
          minimum: 0.0
          default: 0.7
        max_tokens:
          type: integer
          maximum: 16384
          minimum: 1
          default: 4096
      required:
      - messages
    ChatCompletionResponse:
      type: object
      description: White-label completion envelope returned to callers on success.
      properties:
        id:
          type: string
          description: SerperMatrix completion ID
        object:
          type: string
          default: chat.completion
        model:
          type: string
          description: Public model identifier (always serpermatrix/chat)
        choices:
          type: array
          items:
            type: object
            additionalProperties: {}
        usage:
          $ref: '#/components/schemas/Usage'
      required:
      - choices
      - id
      - model
      - usage
    ConfirmTransaction:
      type: object
      description: Body for ``POST …/billing/checkout/confirm/`` (server-side reconciliation).
      properties:
        transaction_id:
          type: string
      required:
      - transaction_id
    ContentFormatEnum:
      enum:
      - json
      - markdown
      - text
      type: string
      description: |-
        * `json` - JSON
        * `markdown` - Markdown
        * `text` - Text
    FormatsEnum:
      enum:
      - json
      - markdown
      - text
      type: string
      description: |-
        * `json` - json
        * `markdown` - markdown
        * `text` - text
    Message:
      type: object
      properties:
        role:
          $ref: '#/components/schemas/RoleEnum'
        content:
          type: string
          maxLength: 50000
      required:
      - content
      - role
    PaddleCheckoutResponse:
      type: object
      description: Returns transaction_id, client_token, and environment to Nuxt.js.
      properties:
        transaction_id:
          type: string
        client_token:
          type: string
        environment:
          type: string
      required:
      - client_token
      - environment
      - transaction_id
    PaginatedAPIKeyListList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/APIKeyList'
    PaginatedAPILogListList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/APILogList'
    PaginatedPlanList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/Plan'
    PaginatedTransactionList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/Transaction'
    PaginatedUserList:
      type: object
      required:
      - count
      - results
      properties:
        count:
          type: integer
          example: 123
        next:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=4
        previous:
          type: string
          nullable: true
          format: uri
          example: http://api.example.org/accounts/?page=2
        results:
          type: array
          items:
            $ref: '#/components/schemas/User'
    PasswordResetConfirmRetype:
      type: object
      properties:
        uid:
          type: string
        token:
          type: string
        new_password:
          type: string
        re_new_password:
          type: string
      required:
      - new_password
      - re_new_password
      - token
      - uid
    PatchedAPIKeyPartialUpdate:
      type: object
      description: Rename an active key (``PATCH``).
      properties:
        name:
          type: string
          maxLength: 100
    PatchedUser:
      type: object
      description: |-
        Read/write profile fields for authenticated users and ``/users/me/``.

        Extends Djoser's serializer so email change + re-activation behavior stays
        consistent with ``SEND_ACTIVATION_EMAIL``.
      properties:
        first_name:
          type: string
          maxLength: 255
        last_name:
          type: string
          maxLength: 255
        id:
          type: integer
          readOnly: true
        email:
          type: string
          format: email
          readOnly: true
    Plan:
      type: object
      description: Public catalog fields (no internal-only data).
      properties:
        id:
          type: integer
          readOnly: true
        name:
          type: string
          readOnly: true
        slug:
          type: string
          readOnly: true
          pattern: ^[-a-zA-Z0-9_]+$
        price:
          type: string
          format: decimal
          pattern: ^-?\d{0,8}(?:\.\d{0,2})?$
          readOnly: true
        yearly_price:
          type: string
          format: decimal
          pattern: ^-?\d{0,8}(?:\.\d{0,2})?$
          readOnly: true
        credits:
          type: integer
          readOnly: true
        description:
          type: string
          readOnly: true
        requests_per_minute:
          type: integer
          readOnly: true
        features:
          readOnly: true
          description: List of feature strings for the pricing card.
        is_active:
          type: boolean
          readOnly: true
        is_featured:
          type: boolean
          readOnly: true
        order:
          type: integer
          readOnly: true
        price_per_credit:
          type: number
          format: double
          readOnly: true
        paddle_price_id_monthly:
          type: string
          readOnly: true
        paddle_price_id_yearly:
          type: string
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - created_at
      - credits
      - description
      - features
      - id
      - is_active
      - is_featured
      - name
      - order
      - paddle_price_id_monthly
      - paddle_price_id_yearly
      - price
      - price_per_credit
      - requests_per_minute
      - slug
      - yearly_price
    ProgrammaticProfile:
      type: object
      properties:
        email:
          type: string
          format: email
        company_name:
          type: string
        plan_name:
          type: string
          nullable: true
        plan_credits_remaining:
          type: integer
        extra_credits_remaining:
          type: integer
        total_credits_remaining:
          type: integer
        credits_used_this_cycle:
          type: integer
        cycle_end_date:
          type: string
          format: date-time
      required:
      - company_name
      - credits_used_this_cycle
      - cycle_end_date
      - email
      - extra_credits_remaining
      - plan_credits_remaining
      - plan_name
      - total_credits_remaining
    ProviderAuth:
      type: object
      properties:
        access:
          type: string
          readOnly: true
        refresh:
          type: string
          readOnly: true
        user:
          type: string
          readOnly: true
      required:
      - access
      - refresh
      - user
    PurchaseRequest:
      type: object
      description: Body for ``POST …/billing/checkout/create-transaction/``.
      properties:
        plan_id:
          type: integer
        billing_interval:
          allOf:
          - $ref: '#/components/schemas/BillingIntervalEnum'
          default: monthly
      required:
      - plan_id
    ResendActivationRequest:
      type: object
      properties:
        email:
          type: string
          format: email
      required:
      - email
    RoleEnum:
      enum:
      - user
      - assistant
      - system
      type: string
      description: |-
        * `user` - user
        * `assistant` - assistant
        * `system` - system
    ScrapeRequest:
      type: object
      properties:
        url:
          type: string
          format: uri
          maxLength: 500
        formats:
          type: array
          items:
            $ref: '#/components/schemas/FormatsEnum'
          description: Output formats to include in the response (e.g. ["markdown"]).
          minItems: 1
        use_cache:
          type: boolean
          default: true
          description: If true, returns a cached response if available (up to 24 hours
            old). If false, forces a fresh scrape.
      required:
      - formats
      - url
    SearchRequest:
      type: object
      properties:
        query:
          type: string
          description: The search query you want to execute.
          maxLength: 500
        sources:
          type: array
          items:
            $ref: '#/components/schemas/SourcesEnum'
          default:
          - web
          description: Search source types to query. Defaults to ["web"].
        limit:
          type: integer
          maximum: 100
          minimum: 1
          description: Maximum number of results to return per source.
        page:
          type: integer
          minimum: 1
          description: Page number.
        country:
          type: string
          description: Geographic location (country code, e.g. 'us').
        lang:
          type: string
          description: Host language (e.g. 'en').
        location:
          type: string
          description: Location string (e.g. 'New York, United States').
        tbs:
          type: string
          description: Time period or custom filters (e.g. 'qdr:d').
        autocorrect:
          type: boolean
          description: Enable or disable autocorrect.
        use_cache:
          type: boolean
          default: true
          description: If true, returns a cached response if available (up to 1 hour
            old). If false, forces a fresh search.
      required:
      - query
    SendEmailReset:
      type: object
      properties:
        email:
          type: string
          format: email
      required:
      - email
    SetPassword:
      type: object
      properties:
        new_password:
          type: string
        current_password:
          type: string
      required:
      - current_password
      - new_password
    SetUsername:
      type: object
      properties:
        current_password:
          type: string
        new_email:
          type: string
          format: email
          title: Email
          maxLength: 255
      required:
      - current_password
      - new_email
    SourcesEnum:
      enum:
      - web
      - news
      - images
      - places
      - shopping
      - videos
      - scholar
      - patents
      - autocomplete
      type: string
      description: |-
        * `web` - web
        * `news` - news
        * `images` - images
        * `places` - places
        * `shopping` - shopping
        * `videos` - videos
        * `scholar` - scholar
        * `patents` - patents
        * `autocomplete` - autocomplete
    StatusEnum:
      enum:
      - pending
      - completed
      - failed
      - refunded
      type: string
      description: |-
        * `pending` - Pending
        * `completed` - Completed
        * `failed` - Failed
        * `refunded` - Refunded
    TokenObtainPair:
      type: object
      properties:
        email:
          type: string
          writeOnly: true
        password:
          type: string
          writeOnly: true
        access:
          type: string
          readOnly: true
        refresh:
          type: string
          readOnly: true
      required:
      - access
      - email
      - password
      - refresh
    TokenRefresh:
      type: object
      properties:
        access:
          type: string
          readOnly: true
        refresh:
          type: string
          writeOnly: true
      required:
      - access
      - refresh
    TokenVerify:
      type: object
      properties:
        token:
          type: string
          writeOnly: true
      required:
      - token
    Transaction:
      type: object
      description: User's purchase / credit-grant history.
      properties:
        id:
          type: integer
          readOnly: true
        plan:
          type: integer
          readOnly: true
          nullable: true
        plan_name:
          type: string
          readOnly: true
          nullable: true
        plan_slug:
          type: string
          readOnly: true
          nullable: true
        amount:
          type: string
          format: decimal
          pattern: ^-?\d{0,8}(?:\.\d{0,2})?$
          readOnly: true
        credits_added:
          type: integer
          readOnly: true
        status:
          allOf:
          - $ref: '#/components/schemas/StatusEnum'
          readOnly: true
        reference:
          type: string
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
      required:
      - amount
      - created_at
      - credits_added
      - id
      - plan
      - plan_name
      - plan_slug
      - reference
      - status
    Usage:
      type: object
      properties:
        prompt_tokens:
          type: integer
        completion_tokens:
          type: integer
        total_tokens:
          type: integer
        credits_used:
          type: integer
        credits_remaining:
          type: integer
      required:
      - completion_tokens
      - credits_remaining
      - credits_used
      - prompt_tokens
      - total_tokens
    User:
      type: object
      description: |-
        Read/write profile fields for authenticated users and ``/users/me/``.

        Extends Djoser's serializer so email change + re-activation behavior stays
        consistent with ``SEND_ACTIVATION_EMAIL``.
      properties:
        first_name:
          type: string
          maxLength: 255
        last_name:
          type: string
          maxLength: 255
        id:
          type: integer
          readOnly: true
        email:
          type: string
          format: email
          readOnly: true
      required:
      - email
      - first_name
      - id
      - last_name
    UserCreatePasswordRetype:
      type: object
      description: |-
        Registration payload: email, password, re_password, and required user fields.

        Delegates creation to ``User.objects.create_user`` (trial subscription logic
        lives in ``UserAccountManager``). Password strength is validated in Djoser's
        base ``UserCreateSerializer``.
      properties:
        first_name:
          type: string
          maxLength: 255
        last_name:
          type: string
          maxLength: 255
        email:
          type: string
          format: email
          maxLength: 255
        id:
          type: integer
          readOnly: true
        password:
          type: string
          writeOnly: true
        re_password:
          type: string
      required:
      - email
      - first_name
      - id
      - last_name
      - password
      - re_password
    UsernameResetConfirm:
      type: object
      properties:
        new_email:
          type: string
          format: email
          title: Email
          maxLength: 255
      required:
      - new_email
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
      description: Enter your API key here
    jwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
