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

# Report which simulated accounts are actually running

> Performs, once and on demand, the comparison the scheduler makes every second: what should be running, against what the connection bucket says is. `observed` counts every tenant's runners by state and carries no tenant. `test_accounts` lists the caller's simulated accounts, each with what the bucket says about it, and only simulated accounts: for a live account the scheduler additionally requires the organization's live trading entitlement, which this service does not check, so comparing one here would report a billing exclusion as a missing runner. Bucket entries expire sixty seconds after the last heartbeat, so an absent runner means nothing has reported within the minute rather than that none exists, and `checked_at` is when the bucket was read. Readable by a client credential holding the credential:read scope, which sees every organization's simulated accounts, and by an organization admin of a configured internal organization, which sees its own.



## OpenAPI

````yaml /api-reference/accounts.openapi.json get /v1/accounts/runners/health
openapi: 3.1.0
info:
  title: accounts
  description: ''
  license:
    name: ''
  version: 0.1.0
servers:
  - url: https://api.anthid.com
    description: Production
security: []
tags:
  - name: Accounts
    description: Create, inspect, update, and disable trading accounts
  - name: Broker Credentials
    description: Inspect and manage credentials linked to trading accounts
paths:
  /v1/accounts/runners/health:
    get:
      tags:
        - Accounts
      summary: Report which simulated accounts are actually running
      description: >-
        Performs, once and on demand, the comparison the scheduler makes every
        second: what should be running, against what the connection bucket says
        is. `observed` counts every tenant's runners by state and carries no
        tenant. `test_accounts` lists the caller's simulated accounts, each with
        what the bucket says about it, and only simulated accounts: for a live
        account the scheduler additionally requires the organization's live
        trading entitlement, which this service does not check, so comparing one
        here would report a billing exclusion as a missing runner. Bucket
        entries expire sixty seconds after the last heartbeat, so an absent
        runner means nothing has reported within the minute rather than that
        none exists, and `checked_at` is when the bucket was read. Readable by a
        client credential holding the credential:read scope, which sees every
        organization's simulated accounts, and by an organization admin of a
        configured internal organization, which sees its own.
      operationId: getRunnerHealth
      responses:
        '200':
          description: What is running, against what should be
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunnerHealthResponse'
              example:
                checked_at: '2026-08-26T12:00:00Z'
                missing: 1
                observed:
                  active: 12
                  deleting: 0
                  pending: 1
                stranded: 0
                test_accounts:
                  - enabled: true
                    name: load-test-01
                    state: active
                    trading_account_id: 550e8400-e29b-41d4-a716-446655440111
                  - enabled: true
                    name: load-test-02
                    state: absent
                    trading_account_id: 550e8400-e29b-41d4-a716-446655440222
        '401':
          description: Caller is an API key, or a user whose token carries no organization
          content:
            text/plain:
              schema:
                type: string
        '403':
          description: >-
            The client credential is missing the credential:read scope, the
            caller's organization is not configured as internal, or the caller
            is not an organization admin
          content:
            text/plain:
              schema:
                type: string
        '429':
          description: Caller exceeded the request rate limit
          content:
            text/plain:
              schema:
                type: string
        '500':
          description: Unexpected server error while reading the connection bucket
          content:
            text/plain:
              schema:
                type: string
      security:
        - bearerAuth: []
components:
  schemas:
    RunnerHealthResponse:
      type: object
      description: The reconciliation the scheduler performs every second, reported once.
      required:
        - observed
        - test_accounts
        - missing
        - stranded
        - checked_at
      properties:
        checked_at:
          type: string
          format: date-time
          description: >-
            When the bucket was read.


            Returned rather than left to the caller's clock because every state
            here

            is relative to the bucket's sixty second expiry, and a reader
            working

            out staleness from its own `now` would be measuring its own latency
            into

            the answer.
        missing:
          type: integer
          format: int64
          description: Enabled accounts in `test_accounts` that nothing is running.
        observed:
          $ref: '#/components/schemas/ObservedRunners'
          description: Every tenant's runners, counted by state. No tenant in it.
        stranded:
          type: integer
          format: int64
          description: Disabled accounts in `test_accounts` that something still is.
        test_accounts:
          type: array
          items:
            $ref: '#/components/schemas/TestAccountRunner'
          description: >-
            The caller's simulated accounts, each with what the bucket says.


            Test accounts only, and that is a correctness boundary rather than
            an

            omission. See the handler for why real trading accounts are not

            compared here.
    ObservedRunners:
      type: object
      description: >-
        How many accounts the bucket is holding in each state, across every
        tenant.


        Counts and nothing else. No account id, no organization: this is the "is
        the

        fleet up at all" figure, and it carries no tenant for the same reason
        the

        outbox health does. See [`can_read_test_accounts`] for the line.


        [`can_read_test_accounts`]:
        crate::policy::can_read_test_accounts::can_read_test_accounts
      required:
        - active
        - pending
        - deleting
      properties:
        active:
          type: integer
          format: int64
        deleting:
          type: integer
          format: int64
        pending:
          type: integer
          format: int64
    TestAccountRunner:
      type: object
      description: One simulated account, and whether anything is running it.
      required:
        - trading_account_id
        - name
        - enabled
        - state
      properties:
        enabled:
          type: boolean
          description: |-
            Whether the account is registered to run at all. A disabled account
            being `Absent` is the correct outcome, not a fault.
        name:
          type: string
        state:
          $ref: '#/components/schemas/RunnerState'
        trading_account_id:
          type: string
          format: uuid
    RunnerState:
      type: string
      description: >-
        What the connection bucket says about one account, right now.


        Observed rather than authoritative, and the distinction is load bearing.
        The

        bucket's entries expire after sixty seconds unless a runner's heartbeat

        refreshes them, so [`RunnerState::Absent`] means "nothing has
        heartbeated

        for this account within the last minute", not "no runner exists". A
        reader

        must not treat this as the desired state's contradiction; it is the last

        thing anybody saw.
      enum:
        - active
        - pending
        - deleting
        - absent
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````