openapi: 3.0.3
info:
  title: Stock Events Account API
  version: 1.0.0
  description: |
    REST API for Stock Events account automation.

    ## Authentication

    Send a Stock Events API key with every protected request in the `Authorization` header:

    ```http
    Authorization: Bearer se_live_...
    ```

    API keys are created and revoked in the web app under Settings > Data > API Keys. The raw key is shown only once when it is created. Store it securely and revoke it if it is exposed.

    Account automation API access requires an active Pro subscription. API keys remain attached to your account, but requests are rejected while Pro access is inactive.

    The OpenAPI document is public and does not require authentication. Do not send API keys as query parameters or request bodies.

    ```bash
    curl -H "Authorization: Bearer $STOCK_EVENTS_API_KEY" \
      https://stockevents.app/api/v1/watchlists
    ```

    Common authentication failures:

    - `401 Unauthorized`: missing, invalid, or revoked API key.
    - `403 Forbidden`: account does not currently have Pro access.
servers:
  - url: https://stockevents.app/api/v1

paths:
  /openapi.yaml:
    get:
      operationId: GetOpenapiYaml
      summary: Get OpenAPI document
      responses:
        '200':
          description: OpenAPI document
          content:
            application/yaml:
              schema:
                type: string

  /watchlists:
    get:
      operationId: ListWatchlists
      summary: List watchlists
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: Watchlists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchlistListResponse'
        default:
          $ref: '#/components/responses/Error'
    post:
      operationId: CreateWatchlist
      summary: Create watchlist
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WatchlistCreateRequest'
      responses:
        '201':
          description: Created watchlist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchlistResponse'
        default:
          $ref: '#/components/responses/Error'

  /watchlists/{watchlistId}:
    get:
      operationId: GetWatchlist
      summary: Get watchlist
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
      responses:
        '200':
          description: Watchlist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchlistResponse'
        default:
          $ref: '#/components/responses/Error'
    patch:
      operationId: PatchWatchlist
      summary: Update watchlist
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WatchlistPatchRequest'
      responses:
        '200':
          description: Updated watchlist
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchlistResponse'
        default:
          $ref: '#/components/responses/Error'

  /watchlists/{watchlistId}/symbols:
    get:
      operationId: ListWatchlistSymbols
      summary: List watchlist symbols
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
      responses:
        '200':
          description: Watchlist symbols
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSymbolListResponse'
        default:
          $ref: '#/components/responses/Error'
    post:
      operationId: CreateWatchlistSymbol
      summary: Add symbol to watchlist
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserSymbolCreateRequest'
      responses:
        '201':
          description: Created watchlist symbol
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSymbolResponse'
        default:
          $ref: '#/components/responses/Error'

  /watchlists/{watchlistId}/symbols/{symbol}:
    patch:
      operationId: PatchWatchlistSymbol
      summary: Update watchlist symbol
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
        - $ref: '#/components/parameters/symbol'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserSymbolPatchRequest'
      responses:
        '200':
          description: Updated watchlist symbol
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserSymbolResponse'
        default:
          $ref: '#/components/responses/Error'
    delete:
      operationId: DeleteWatchlistSymbol
      summary: Delete watchlist symbol
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
        - $ref: '#/components/parameters/symbol'
      responses:
        '204':
          description: Deleted watchlist symbol
        default:
          $ref: '#/components/responses/Error'

  /transactions:
    get:
      operationId: ListTransactions
      summary: List transactions
      security:
        - ApiKeyAuth: []
      parameters:
        - name: watchlistId
          in: query
          schema:
            type: string
        - name: symbol
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Transactions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionListResponse'
        default:
          $ref: '#/components/responses/Error'
    post:
      operationId: CreateTransaction
      summary: Create transaction
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransactionCreateRequest'
      responses:
        '201':
          description: Created transaction
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionResponse'
        default:
          $ref: '#/components/responses/Error'

  /transactions/{transactionId}:
    get:
      operationId: GetTransaction
      summary: Get transaction
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/transactionId'
      responses:
        '200':
          description: Transaction
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionResponse'
        default:
          $ref: '#/components/responses/Error'
    patch:
      operationId: PatchTransaction
      summary: Update transaction
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/transactionId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransactionPatchRequest'
      responses:
        '200':
          description: Updated transaction
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionResponse'
        default:
          $ref: '#/components/responses/Error'
    delete:
      operationId: DeleteTransaction
      summary: Delete transaction
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/transactionId'
      responses:
        '204':
          description: Deleted transaction
        default:
          $ref: '#/components/responses/Error'

  /watchlists/{watchlistId}/holdings:
    get:
      operationId: GetHoldingsView
      summary: Get holdings view
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
        - $ref: '#/components/parameters/currency'
        - $ref: '#/components/parameters/lang'
        - $ref: '#/components/parameters/timezone'
        - name: withChart
          in: query
          schema:
            type: boolean
            default: false
        - name: withMarketValue
          in: query
          schema:
            type: boolean
            default: true
        - name: dateFrom
          in: query
          schema:
            type: string
            format: date-time
        - name: plMethod
          in: query
          schema:
            type: string
        - name: chartMode
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Holdings view
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HoldingsView'
        default:
          $ref: '#/components/responses/Error'

  /watchlists/{watchlistId}/dividends:
    get:
      operationId: GetDividendsView
      summary: Get dividends view
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/watchlistId'
        - $ref: '#/components/parameters/lang'
        - name: year
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Dividends view
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DividendsView'
        default:
          $ref: '#/components/responses/Error'

components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer

  parameters:
    watchlistId:
      name: watchlistId
      in: path
      required: true
      schema:
        type: string
    transactionId:
      name: transactionId
      in: path
      required: true
      schema:
        type: string
    symbol:
      name: symbol
      in: path
      required: true
      schema:
        type: string
    currency:
      name: currency
      in: query
      required: false
      schema:
        type: string
    lang:
      name: lang
      in: query
      required: false
      schema:
        type: string
    timezone:
      name: timezone
      in: query
      required: false
      schema:
        type: string

  responses:
    Error:
      description: Error response
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

  schemas:
    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          $ref: '#/components/schemas/ApiError'

    ApiError:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
        message:
          type: string

    Watchlist:
      type: object
      required: [id, name, share, inCombinedView, isDeleted]
      properties:
        id:
          type: string
        name:
          type: string
        color:
          type: string
          nullable: true
        sort:
          type: string
        customSortOrder:
          type: array
          items:
            type: string
        share:
          type: boolean
        inCombinedView:
          type: boolean
        goalDividends:
          type: number
          format: double
        goalHoldings:
          type: number
          format: double
        horizonAnnualContribution:
          type: number
          format: double
        horizonDividendGrowthRate:
          type: number
          format: double
        horizonStockGrowthRate:
          type: number
          format: double
        horizonMaxYield:
          type: number
          format: double
        currency:
          type: string
        brokerageAccountId:
          type: string
        isDeleted:
          type: boolean

    WatchlistCreateRequest:
      type: object
      required: [name]
      properties:
        name:
          type: string
        color:
          type: string
          nullable: true
        sort:
          type: string
        customSortOrder:
          type: array
          items:
            type: string
        share:
          type: boolean
        inCombinedView:
          type: boolean
        goalDividends:
          type: number
          format: double
        goalHoldings:
          type: number
          format: double
        horizonAnnualContribution:
          type: number
          format: double
        horizonDividendGrowthRate:
          type: number
          format: double
        horizonStockGrowthRate:
          type: number
          format: double
        horizonMaxYield:
          type: number
          format: double
        currency:
          type: string

    WatchlistPatchRequest:
      type: object
      properties:
        name:
          type: string
        color:
          type: string
          nullable: true
        sort:
          type: string
        customSortOrder:
          type: array
          items:
            type: string
        share:
          type: boolean
        inCombinedView:
          type: boolean
        goalDividends:
          type: number
          format: double
        goalHoldings:
          type: number
          format: double
        horizonAnnualContribution:
          type: number
          format: double
        horizonDividendGrowthRate:
          type: number
          format: double
        horizonStockGrowthRate:
          type: number
          format: double
        horizonMaxYield:
          type: number
          format: double
        currency:
          type: string

    WatchlistResponse:
      type: object
      required: [data]
      properties:
        data:
          $ref: '#/components/schemas/Watchlist'

    WatchlistListResponse:
      type: object
      required: [data]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Watchlist'

    UserSymbol:
      type: object
      required: [watchlistId, symbol, isDeleted]
      properties:
        watchlistId:
          type: string
        symbol:
          type: string
        shares:
          type: number
          format: double
          nullable: true
        shareMode:
          type: string
        avgCost:
          type: number
          format: double
        avgCostCurrency:
          type: string
        dripActive:
          type: boolean
        dripOnlyWhole:
          type: boolean
        dividendsToCash:
          type: boolean
        dividendTax:
          type: number
          format: double
        isDeleted:
          type: boolean

    UserSymbolCreateRequest:
      type: object
      required: [symbol]
      properties:
        symbol:
          type: string
        shares:
          type: number
          format: double
          nullable: true
        shareMode:
          type: string
        avgCost:
          type: number
          format: double
        avgCostCurrency:
          type: string
        dripActive:
          type: boolean
        dripOnlyWhole:
          type: boolean
        dividendsToCash:
          type: boolean
        dividendTax:
          type: number
          format: double

    UserSymbolPatchRequest:
      type: object
      properties:
        symbol:
          type: string
        shares:
          type: number
          format: double
          nullable: true
        shareMode:
          type: string
        avgCost:
          type: number
          format: double
        avgCostCurrency:
          type: string
        dripActive:
          type: boolean
        dripOnlyWhole:
          type: boolean
        dividendsToCash:
          type: boolean
        dividendTax:
          type: number
          format: double

    UserSymbolResponse:
      type: object
      required: [data]
      properties:
        data:
          $ref: '#/components/schemas/UserSymbol'

    UserSymbolListResponse:
      type: object
      required: [data]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/UserSymbol'

    Transaction:
      type: object
      required: [id, watchlistId, symbol, date, isDeleted]
      properties:
        id:
          type: string
        watchlistId:
          type: string
        symbol:
          type: string
        date:
          type: string
          format: date-time
        change:
          type: number
          format: double
        price:
          type: number
          format: double
        priceCurrency:
          type: string
        toCash:
          type: boolean
        feesPercent:
          type: number
          format: double
        feesAmount:
          type: number
          format: double
        feesCurrency:
          type: string
        notes:
          type: string
        type:
          type: string
        isDeleted:
          type: boolean
        lastChange:
          type: string
          format: date-time
          nullable: true

    TransactionCreateRequest:
      type: object
      required: [watchlistId, symbol]
      properties:
        watchlistId:
          type: string
        symbol:
          type: string
        date:
          type: string
          format: date-time
        change:
          type: number
          format: double
        price:
          type: number
          format: double
        priceCurrency:
          type: string
        toCash:
          type: boolean
        feesPercent:
          type: number
          format: double
        feesAmount:
          type: number
          format: double
        feesCurrency:
          type: string
        notes:
          type: string
        type:
          type: string

    TransactionPatchRequest:
      type: object
      properties:
        watchlistId:
          type: string
        symbol:
          type: string
        date:
          type: string
          format: date-time
        change:
          type: number
          format: double
        price:
          type: number
          format: double
        priceCurrency:
          type: string
        toCash:
          type: boolean
        feesPercent:
          type: number
          format: double
        feesAmount:
          type: number
          format: double
        feesCurrency:
          type: string
        notes:
          type: string
        type:
          type: string

    TransactionResponse:
      type: object
      required: [data]
      properties:
        data:
          $ref: '#/components/schemas/Transaction'

    TransactionListResponse:
      type: object
      required: [data]
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Transaction'

    ChartPrice:
      type: object
      properties:
        date:
          type: string
          format: date-time
        price:
          type: number
          format: double

    Allocation:
      type: object
      properties:
        name:
          type: string
        amount:
          type: number
          format: double
        percent:
          type: number
          format: double

    HoldingOptions:
      type: object
      properties:
        effectiveExposure:
          type: number
          format: double
          nullable: true
        cashValue:
          type: number
          format: double
          nullable: true
        dailyTheta:
          type: number
          format: double
          nullable: true
        breakEvenPrice:
          type: number
          format: double
          nullable: true
        distanceToBreakEven:
          type: number
          format: double
          nullable: true

    Holding:
      type: object
      properties:
        symbol:
          type: string
        companyName:
          type: string
        companyCurrency:
          type: string
        country:
          type: string
          nullable: true
        issueType:
          type: string
        sector:
          type: string
        industry:
          type: string
        marketValue:
          type: number
          format: double
        change:
          type: number
          format: double
        plRealized:
          type: number
          format: double
        plUnrealized:
          type: number
          format: double
        plSpent:
          type: number
          format: double
        avgBuyPrice:
          type: number
          format: double
        fees:
          type: number
          format: double
        shares:
          type: number
          format: double
        periodChange:
          type: number
          format: double
        periodChangePercent:
          type: number
          format: double
        logo:
          type: string
        isClosed:
          type: boolean
        options:
          $ref: '#/components/schemas/HoldingOptions'

    HoldingsView:
      type: object
      properties:
        marketValue:
          type: number
          format: double
        marketValueWithoutRealized:
          type: number
          format: double
        previousMarketValue:
          type: number
          format: double
        previousMarketValueWithCurrentShares:
          type: number
          format: double
        previousDayMarketValue:
          type: number
          format: double
        previousDayMarketValueWithCurrentShares:
          type: number
          format: double
        plRealized:
          type: number
          format: double
        plUnrealized:
          type: number
          format: double
        plSpent:
          type: number
          format: double
        plSpentRemaining:
          type: number
          format: double
        cash:
          type: number
          format: double
        goalHoldings:
          type: number
          format: double
        goalReachedInYears:
          type: number
          format: double
        horizonAnnualContribution:
          type: number
          format: double
        horizonDividendGrowthRate:
          type: number
          format: double
        horizonStockGrowthRate:
          type: number
          format: double
        horizonMarketValue:
          type: array
          items:
            type: number
            format: double
        currency:
          type: string
        sectorAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        industryAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        typeAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        regionAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        tradingDate:
          type: string
          format: date-time
        tradingBegin:
          type: string
          format: date-time
        tradingEnd:
          type: string
          format: date-time
        chart:
          type: array
          items:
            $ref: '#/components/schemas/ChartPrice'
        holdings:
          type: array
          items:
            $ref: '#/components/schemas/Holding'
        customSortOrder:
          type: array
          items:
            type: string

    DividendPosition:
      type: object
      properties:
        symbol:
          type: string
        companyName:
          type: string
        amount:
          type: number
          format: double
        yield:
          type: number
          format: double
        yieldOnCost:
          type: number
          format: double
        shares:
          type: number
          format: double
        logo:
          type: string
        quarters:
          type: array
          items:
            type: number
            format: double

    DividendsView:
      type: object
      properties:
        totalYearly:
          type: number
          format: double
        totalMonthly:
          type: number
          format: double
        totalDaily:
          type: number
          format: double
        yield:
          type: number
          format: double
        yieldOnCost:
          type: number
          format: double
        dividendGrowth5Y:
          type: number
          format: double
        dividendGrowth1Y:
          type: number
          format: double
        goalDividends:
          type: number
          format: double
        goalReachedInYears:
          type: number
          format: double
        horizonAnnualContribution:
          type: number
          format: double
        horizonDividendGrowthRate:
          type: number
          format: double
        horizonStockGrowthRate:
          type: number
          format: double
        months:
          type: array
          items:
            type: number
            format: double
        horizonAnnualDividends:
          type: array
          items:
            type: number
            format: double
        chart:
          type: array
          items:
            type: number
            format: double
        positions:
          type: array
          items:
            $ref: '#/components/schemas/DividendPosition'
        currency:
          type: string
        sectorAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        industryAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        typeAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        regionAllocation:
          type: array
          items:
            $ref: '#/components/schemas/Allocation'
        customSortOrder:
          type: array
          items:
            type: string
