> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qash.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# User login (deprecated)

> Exchange a Privy token for QASH access and refresh tokens.

<Warning>
  **Deprecated** — This endpoint requires partners to integrate the Privy SDK directly in their frontend or mobile app, which is not the recommended integration path.

  Use [Send login code](/api-reference/users/send-otp) and [Verify login code](/api-reference/users/verify-otp) instead — a backend-only email OTP login with no SDK dependency, entirely from your own servers.
</Warning>

<Note>
  Requires `X-Api-Key` and `X-Api-Secret` headers. See [Authentication](/api-reference/users/introduction#authentication) for details.
</Note>

Call this endpoint after the user authenticates in your app via **Privy** (email OTP, wallet, etc.). Pass the resulting `privyToken` to Qash to receive a QASH `accessToken` and `refreshToken`.

* If the user was pre-registered with `POST /users`, their Privy account is automatically linked on first login.
* The `accessToken` expires in \~24 hours (configurable server-side via `JWT_EXPIRES_IN`). Use `refreshToken` (valid 30 days) to obtain a new one.
* The `businessId` in the response is derived server-side from your API key — never send it from the client.
* `isNewUser: true` indicates this is the user's first login.


## OpenAPI

````yaml api-reference/openapi.json POST /api/v1/partner/auth/login
openapi: 3.1.0
info:
  title: QASH API
  description: >-
    QASH endpoints for exchange rates, cards, and partner-facing financial
    workflows.
  version: 1.0.0
servers:
  - url: https://api.qash.ai
    description: Partner API (Production)
  - url: https://staging.qash.ai
    description: Staging
  - url: https://app.qash.ai
    description: Production
security: []
tags:
  - name: Exchange rates
    description: Public endpoints for supported assets and TRM-based quotes.
  - name: Cards
    description: >-
      Authenticated partner endpoints for card state, controls, limits, and
      balances.
  - name: Users
    description: Admin endpoints for user provisioning and account management.
paths:
  /api/v1/partner/auth/login:
    post:
      tags:
        - Users
      summary: User login
      description: >-
        Deprecated. Requires integrating the Privy SDK directly in your app,
        which is no longer the recommended integration path. Use POST
        /api/v1/partner/auth/send and POST /api/v1/partner/auth/verify instead —
        a backend-only email OTP login that returns the same QASH access and
        refresh tokens without any client-side SDK dependency.
      operationId: partnerUserLogin
      requestBody:
        description: Privy token from the user's authentication session.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartnerLoginRequest'
            examples:
              default:
                summary: Privy token
                value:
                  privyToken: eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
      responses:
        '200':
          description: User authenticated successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerLoginResponse'
              examples:
                default:
                  summary: Successful login
                  value:
                    success: true
                    user:
                      id: 550e8400-e29b-41d4-a716-446655440000
                      email: user@example.com
                      status: active
                      userType: personal
                      roles: []
                      beta: false
                      delegated: false
                    accessToken: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
                    refreshToken: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
                    isNewUser: false
                    businessId: bp-uuid-del-partner
        '400':
          description: Missing or empty `privyToken`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                default:
                  value:
                    success: false
                    error: String must contain at least 1 character(s)
        '401':
          description: Invalid Privy token or invalid partner credentials.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                privyInvalid:
                  summary: Invalid Privy token
                  value:
                    success: false
                    error: Invalid Privy token
                partnerInvalid:
                  summary: Invalid partner credentials
                  value:
                    success: false
                    error: Invalid partner credentials
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                default:
                  value:
                    success: false
                    error: Failed to authenticate user
      deprecated: true
      security:
        - partnerApiKey: []
          partnerApiSecret: []
components:
  schemas:
    PartnerLoginRequest:
      type: object
      required:
        - privyToken
      properties:
        privyToken:
          type: string
          minLength: 1
          description: JWT issued by Privy after the user authenticates in your app.
          example: eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
    PartnerLoginResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        user:
          type: object
          properties:
            id:
              type: string
              format: uuid
            email:
              type: string
              format: email
            status:
              $ref: '#/components/schemas/UserStatus'
            userType:
              type: string
              enum:
                - personal
                - business
            roles:
              type: array
              items:
                type: string
            beta:
              type: boolean
            delegated:
              type: boolean
          required:
            - id
            - email
            - status
            - userType
            - roles
            - beta
            - delegated
        accessToken:
          type: string
          description: Short-lived JWT (~1 hour) for authenticated user requests.
        refreshToken:
          type: string
          description: Long-lived JWT (30 days) to obtain new access tokens.
        isNewUser:
          type: boolean
          description: '`true` if this is the user''s first login.'
        businessId:
          type: string
          format: uuid
          description: >-
            Business profile ID of the partner, derived server-side from the API
            key.
      required:
        - success
        - user
        - accessToken
        - refreshToken
        - isNewUser
        - businessId
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          description: Human-readable error message.
          example: Email is required
      required:
        - success
        - error
    UserStatus:
      type: string
      enum:
        - pending
        - active
        - suspended
        - banned
      description: Current lifecycle status of the user.
  securitySchemes:
    partnerApiKey:
      type: apiKey
      in: header
      name: X-Api-Key
      description: Partner API key. Generated from Qash Dashboard → Settings → API Keys.
    partnerApiSecret:
      type: apiKey
      in: header
      name: X-Api-Secret
      description: Partner API secret. Shown once at creation — store it securely.

````