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

# Enable trading

> Check that wallet delegation is in place and return its status. Delegation itself is granted in the app. On older accounts, also credits any pending welcome airdrop.



## OpenAPI

````yaml POST /v1/wallet/enable-trading
openapi: 3.0.3
info:
  title: Totalis RFQ API
  version: 2.1.0
  description: >-
    Public REST surface for the Totalis parlay RFQ platform, a decentralized
    request-for-quote marketplace for parlay bets across Kalshi and Polymarket,
    with on-chain Solana vault settlement.


    **Wire format**: snake_case JSON. All successful responses are wrapped in `{
    "data": ... }`; list endpoints add `meta` with cursor-based pagination.
    Errors use a `{ "error": { code, message, details? } }` envelope.


    **Authentication**: programmatic clients send `X-API-Key`; the web dashboard
    uses Privy JWTs (`Authorization: Bearer ...`). Any authenticated user can
    both place parlays and quote as a market maker. There is no separate MM
    role. Admin endpoints are out of scope for this public reference.


    **Rate limiting**: three buckets. Authenticated routes share one per-account
    bucket of 300 req/min (100 without a key). Public market reads (`/markets`,
    `/v1/markets`) are a separate per-IP bucket of 100 req/min that an API key
    does not raise. Quote service routes (`/v1/quote-requests`,
    `/v1/cashout-requests`, `/v1/mm/quote-requests`, `/v1/mm/cashout-requests`)
    have their own per-IP limit, 300 req/min by default. Responses include
    `X-RateLimit-*` headers. Request body limit: 256KB.


    **Pagination**: list endpoints use opaque cursor pagination. Pass
    `meta.cursor` from the previous response as `?cursor=...` to fetch the next
    page; do not parse or construct cursors client-side.
servers:
  - url: https://api.totalis.trade
    description: Production
security:
  - ApiKey: []
tags:
  - name: Markets
    description: Cached Kalshi and Polymarket market data.
  - name: User
    description: User profile, wallet, and devnet helpers.
  - name: API Keys
    description: Manage programmatic access keys for the authenticated user.
paths:
  /v1/wallet/enable-trading:
    post:
      tags:
        - User
      summary: Confirm TEE wallet delegation AND drain any pending welcome airdrop
      description: |
        Two responsibilities, kept in one round-trip so the frontend can
        render a single combined success toast:

        1. **Delegation status.** Confirms whether the embedded wallet
           is currently delegated to our key quorum. The actual
           delegation is a USER-SIDE action (frontend `addSigners()`);
           this endpoint only reads the current state. It does NOT
           perform the delegation itself.
        2. **Pending welcome-airdrop drain.** Under the deferred-airdrop
           flow, the welcome airdrop amount is staged at
           approval time. This endpoint atomically claims that amount,
           mints the USDC from treasury to the canonical wallet, and
           clears the staged amount. Idempotent: a second call after a
           successful drain returns `airdrop: null` (nothing left to
           drain) without re-minting. On mint failure, the pending
           amount is restored so the user can retry on their next call.
      operationId: enableTrading
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    allOf:
                      - $ref: '#/components/schemas/DelegationStatus'
                      - type: object
                        properties:
                          airdrop:
                            allOf:
                              - $ref: '#/components/schemas/AirdropDrainOutcome'
                            nullable: true
                            description: |
                              Outcome of the pending-airdrop drain.
                              `null` when nothing was staged for this
                              user (most common: pre-approval, or
                              already drained on a prior call). See
                              `AirdropDrainOutcome` for the non-null
                              shape.
        '401':
          $ref: '#/components/responses/Unauthorized'
      security:
        - PrivyJWT: []
        - ApiKey: []
components:
  schemas:
    DelegationStatus:
      type: object
      properties:
        ready:
          type: boolean
          description: True if a wallet is linked and delegation can proceed
        delegated:
          type: boolean
          description: True if TEE wallet delegation is active (server can sign)
        address:
          type: string
          description: Solana wallet address (base58). Empty string if no wallet linked.
        wallet_id:
          type: string
          description: Privy embedded wallet ID (used for delegation API calls)
    AirdropDrainOutcome:
      type: object
      description: |
        Outcome of the pending-airdrop drain performed by
        `POST /v1/wallet/enable-trading`. Narrower than
        `AirdropOutcome`. There is no `pending` field because the drain
        is the terminal step (either the mint landed or it didn't; the
        amount is never left in a staged state by this endpoint).
        `{ success: true, amount }` means the staged amount minted
        successfully on-chain. `{ success: false, amount }` means the mint
        attempt failed and the pending amount has been restored; the
        user can retry on their next call.
      required:
        - success
        - amount
      properties:
        success:
          type: boolean
        amount:
          type: number
          description: USDC amount (whole dollars)
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/ErrorBody'
    ErrorBody:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          enum:
            - VALIDATION_ERROR
            - UNAUTHORIZED
            - FORBIDDEN
            - NOT_FOUND
            - CONFLICT
            - RATE_LIMITED
            - PAYLOAD_TOO_LARGE
            - INTERNAL_ERROR
            - SERVICE_UNAVAILABLE
          description: Machine-readable error code.
        message:
          type: string
          description: Human-readable error message.
        details:
          type: object
          description: Additional error context.
        retry_after:
          type: integer
          nullable: true
          description: Seconds until retry; set on 429 responses.
  responses:
    Unauthorized:
      description: Missing or invalid authentication
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: UNAUTHORIZED
              message: Missing or invalid authentication
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        Programmatic API key. Sent as `X-API-Key: <key>`. Generate one from the
        Totalis dashboard. The WebSocket takes no header; send the key in the
        auth message instead.
    PrivyJWT:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Privy JWT issued to the web dashboard. Sent as `Authorization: Bearer
        <jwt>`. The Privy session signer underpins all wallet-signed actions.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.