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

# List transactions

> Returns transactions ordered by `date` descending, then `id`.

This is a statement of an account: one row per movement, as the account recorded it.
Every movement is returned, including the two legs of a transfer between the
workspace's own accounts and transactions the user has excluded from cash flow.
Neither is marked, because neither changes what happened on the account.

Pending bank transactions are returned with `status: pending`. Duplicates detected by
ThinkOut are never returned and cannot be requested.

Where a transaction has been split inside ThinkOut, the original movement is
returned and its pieces are not. Reports count differently; see
`/transactions/summary`.




## OpenAPI

````yaml /openapi/v1.yaml get /transactions
openapi: 3.1.0
info:
  title: ThinkOut API
  version: '1.0'
  description: >
    Programmatic access to the data of a ThinkOut workspace.


    Every endpoint in version 1 is a `GET`. Lists share one response envelope,
    and page

    with a cursor wherever the list can grow.


    Version 1 changes additively. New endpoints, new optional parameters, new
    response

    fields and new enum values can appear at any time, so tolerate unknown
    fields and

    never treat an enum as a closed set.
  contact:
    name: ThinkOut developer support
    url: https://developers.thinkout.io/guides/support
servers:
  - url: https://api.thinkout.io/v1
security:
  - apiKey: []
tags:
  - name: Banks
    description: The workspace's bank connections and the state of each one.
  - name: Accounts
    description: Manual, bank-synced and delegated accounts with computed balances.
  - name: Transactions
    description: Booked and pending movements on the workspace's accounts.
  - name: Categories
    description: The workspace category tree, split by direction and business activity.
  - name: Counterparties
    description: Customers and suppliers that transactions and forecasts are attributed to.
  - name: Labels
    description: Free-form tags grouped by label type.
  - name: Forecasts
    description: Planned inflows and outflows and the transactions that realised them.
  - name: Reports
    description: >-
      Totals rather than rows. Summaries over transactions and forecasts, and
      the workspace's own saved cash flow views.
paths:
  /transactions:
    get:
      tags:
        - Transactions
      summary: List transactions
      description: >
        Returns transactions ordered by `date` descending, then `id`.


        This is a statement of an account: one row per movement, as the account
        recorded it.

        Every movement is returned, including the two legs of a transfer between
        the

        workspace's own accounts and transactions the user has excluded from
        cash flow.

        Neither is marked, because neither changes what happened on the account.


        Pending bank transactions are returned with `status: pending`.
        Duplicates detected by

        ThinkOut are never returned and cannot be requested.


        Where a transaction has been split inside ThinkOut, the original
        movement is

        returned and its pieces are not. Reports count differently; see

        `/transactions/summary`.
      operationId: listTransactions
      parameters:
        - $ref: '#/components/parameters/from'
        - $ref: '#/components/parameters/to'
        - $ref: '#/components/parameters/bank_id'
        - $ref: '#/components/parameters/account_id'
        - $ref: '#/components/parameters/category_id'
        - $ref: '#/components/parameters/label_id'
        - $ref: '#/components/parameters/counterparty_id'
        - $ref: '#/components/parameters/direction'
        - name: status
          in: query
          schema:
            $ref: '#/components/schemas/TransactionStatus'
        - $ref: '#/components/parameters/transaction_expand'
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/cursor'
      responses:
        '200':
          description: A page of transactions.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/List'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Transaction'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    from:
      name: from
      in: query
      description: Earliest `date` to include, inclusive. Ignored when `period` is given.
      schema:
        type: string
        format: date
    to:
      name: to
      in: query
      description: Latest `date` to include, inclusive. Ignored when `period` is given.
      schema:
        type: string
        format: date
    bank_id:
      name: bank_id
      in: query
      description: >-
        Only rows on the accounts fed by these bank connections. Comma-separated
        for several.
      style: form
      explode: false
      schema:
        type: array
        items:
          type: string
          format: uuid
    account_id:
      name: account_id
      in: query
      description: Only rows on these accounts. Comma-separated for several.
      style: form
      explode: false
      schema:
        type: array
        items:
          type: string
          format: uuid
    category_id:
      name: category_id
      in: query
      description: >
        Only rows in these categories. Comma-separated for several. On
        transactions this

        also matches a split transaction whose pieces are in one of them, even
        though the

        row itself carries no category.
      style: form
      explode: false
      schema:
        type: array
        items:
          type: string
          format: uuid
    label_id:
      name: label_id
      in: query
      description: >-
        Only rows carrying at least one of these labels. Comma-separated for
        several.
      style: form
      explode: false
      schema:
        type: array
        items:
          type: string
          format: uuid
    counterparty_id:
      name: counterparty_id
      in: query
      description: >-
        Only rows attributed to these counterparties. Comma-separated for
        several.
      style: form
      explode: false
      schema:
        type: array
        items:
          type: string
          format: uuid
    direction:
      name: direction
      in: query
      schema:
        $ref: '#/components/schemas/Direction'
    transaction_expand:
      name: expand
      in: query
      description: >
        Relations to return as full objects instead of ids. Comma-separated.


        Without it every relation is an id. Naming one here replaces the id with
        the object

        it points at. Expansion goes one level deep; an unsupported name is
        rejected.


        Supported here: `account`, `category`, `counterparty`, `labels`.
      style: form
      explode: false
      schema:
        type: array
        items:
          type: string
          enum:
            - account
            - category
            - counterparty
            - labels
      example: category,counterparty
    limit:
      name: limit
      in: query
      description: Page size.
      schema:
        type: integer
        minimum: 1
        maximum: 500
        default: 100
    cursor:
      name: cursor
      in: query
      description: Opaque token from the previous page's `next_cursor`.
      schema:
        type: string
  schemas:
    TransactionStatus:
      type: string
      description: >
        `pending` transactions come from a bank and are not yet booked. A
        pending amount can

        change when it books, and `updated_at` moves when it does, so upsert by
        `id` rather

        than treating a pending row as final.
      enum:
        - booked
        - pending
    List:
      type: object
      required:
        - object
        - data
        - has_more
        - next_cursor
      properties:
        object:
          type: string
          const: list
        data:
          type: array
          items: {}
        has_more:
          type: boolean
          description: Whether another page exists.
        next_cursor:
          type:
            - string
            - 'null'
          description: Pass as `cursor` to fetch the next page. `null` on the last page.
    Transaction:
      type: object
      required:
        - object
        - id
        - date
        - amount
        - currency
        - direction
        - status
        - source
        - description
        - comment
        - account
        - category
        - counterparty
        - labels
        - bank_details
        - created_at
        - updated_at
      properties:
        object:
          type: string
          const: transaction
        id:
          type: string
          format: uuid
        date:
          type: string
          format: date
          description: Booking date. There is no time component.
          example: '2026-09-03'
        amount:
          $ref: '#/components/schemas/Money'
        currency:
          $ref: '#/components/schemas/Currency'
        direction:
          $ref: '#/components/schemas/Direction'
        status:
          $ref: '#/components/schemas/TransactionStatus'
        source:
          $ref: '#/components/schemas/TransactionSource'
        description:
          type:
            - string
            - 'null'
          example: ORANGE ROMANIA SA
        comment:
          type:
            - string
            - 'null'
          description: Free text added by users in ThinkOut.
        account:
          $ref: '#/components/schemas/ExpandableAccount'
        category:
          oneOf:
            - $ref: '#/components/schemas/ExpandableCategory'
            - type: 'null'
          description: >
            `null` when the transaction has no category. That includes every
            transaction

            split inside ThinkOut, where categorisation moved to the pieces and
            the pieces

            are not exposed by this API.
        counterparty:
          $ref: '#/components/schemas/ExpandableCounterparty'
        labels:
          $ref: '#/components/schemas/ExpandableLabels'
        bank_details:
          oneOf:
            - $ref: '#/components/schemas/BankDetails'
            - type: 'null'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        object: transaction
        id: 8f1c0a4e-2b1d-4c8e-9f3a-7d6e5c4b3a21
        date: '2026-09-03'
        amount: '-1250.00'
        currency: RON
        direction: outflow
        status: booked
        source: bank
        description: ORANGE ROMANIA SA
        comment: null
        account: c2d7e8f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f
        category: 3b4c5d6e-7f80-4a1b-9c2d-3e4f5a6b7c8d
        counterparty: 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
        labels:
          - 1f2e3d4c-5b6a-4978-8877-665544332211
        bank_details:
          payer: THINKOUT SRL
          payer_details: RO49INGB0000999900000001
          payee: ORANGE ROMANIA SA
          payee_details: RO12BTRL0000000000000002
          reference: Factura 2026-08 nr 1234567
          additional: null
        created_at: '2026-09-03T08:12:44Z'
        updated_at: '2026-09-03T08:12:44Z'
    Direction:
      type: string
      description: >
        Whether money comes in or goes out.


        On a transaction or a forecast it follows the sign of `amount` and can
        never

        disagree with it. It is present so that responses can be grouped and
        read without

        inspecting signs.
      enum:
        - inflow
        - outflow
    Money:
      type: string
      description: >
        Decimal amount as a string. Signed on transactions, forecasts and report
        figures,

        where negative means an outflow. The sign is authoritative: `direction`
        is derived

        from it and the two can never disagree.
      pattern: ^-?[0-9]+(\.[0-9]+)?$
      example: '-1250.00'
    Currency:
      type: string
      description: ISO 4217 alphabetic currency code.
      pattern: ^[A-Z]{3}$
      example: RON
    TransactionSource:
      type: string
      description: How the transaction entered ThinkOut.
      enum:
        - manual
        - import
        - bank
    ExpandableAccount:
      description: An account id, or the full account when named in `expand`.
      oneOf:
        - type: string
          format: uuid
        - $ref: '#/components/schemas/Account'
    ExpandableCategory:
      description: A category id, or the full category when named in `expand`.
      oneOf:
        - type: string
          format: uuid
        - $ref: '#/components/schemas/Category'
    ExpandableCounterparty:
      description: >-
        A counterparty id, the full counterparty when named in `expand`, or
        `null` when unattributed.
      oneOf:
        - type: string
          format: uuid
        - $ref: '#/components/schemas/Counterparty'
        - type: 'null'
    ExpandableLabels:
      description: Label ids, or the full labels when `labels` is named in `expand`.
      type: array
      items:
        oneOf:
          - type: string
            format: uuid
          - $ref: '#/components/schemas/Label'
    BankDetails:
      type: object
      description: >-
        Raw fields received from the bank. Present only on `source: bank`
        transactions.
      required:
        - payer
        - payer_details
        - payee
        - payee_details
        - reference
        - additional
      properties:
        payer:
          type:
            - string
            - 'null'
        payer_details:
          type:
            - string
            - 'null'
          description: Payer account identifiers as provided by the bank.
        payee:
          type:
            - string
            - 'null'
        payee_details:
          type:
            - string
            - 'null'
        reference:
          type:
            - string
            - 'null'
          description: Payment reference or information line.
        additional:
          type:
            - string
            - 'null'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - code
            - message
            - param
            - request_id
          properties:
            type:
              type: string
              enum:
                - invalid_request
                - authentication
                - not_found
                - rate_limit
                - server
            code:
              type: string
              description: >
                Stable machine-readable reason. Branch on this, not on
                `message`.

                Report-specific codes are `too_many_groups`, `period_too_long`,

                `as_of_in_future` and `invalid_expand`.
            message:
              type: string
              description: Human-readable explanation. Wording may change.
            param:
              type:
                - string
                - 'null'
              description: The query or path parameter at fault, when there is one.
            request_id:
              type: string
              description: Quote this when contacting support.
    Account:
      type: object
      required:
        - object
        - id
        - name
        - currency
        - group
        - source
        - balance
        - balance_as_of
        - opening_balance
        - opening_date
        - bank
        - external_account_id
        - original_name
        - created_at
        - updated_at
      properties:
        object:
          type: string
          const: account
        id:
          type: string
          format: uuid
        name:
          type: string
          example: ING Curent
        currency:
          $ref: '#/components/schemas/Currency'
        group:
          type:
            - string
            - 'null'
          description: Free-text grouping assigned in ThinkOut.
          example: Operational
        source:
          $ref: '#/components/schemas/AccountSource'
        balance:
          $ref: '#/components/schemas/Money'
        balance_as_of:
          type: string
          format: date
          description: >-
            The day whose end-of-day balance is reported. Computed at request
            time.
        opening_balance:
          $ref: '#/components/schemas/Money'
        opening_date:
          type: string
          format: date
          description: >-
            The date the opening balance applies to. Transactions before it are
            not expected.
        bank:
          $ref: '#/components/schemas/ExpandableBank'
        external_account_id:
          type:
            - string
            - 'null'
          description: >-
            The account identifier at the provider, useful for reconciliation.
            `null` for manual accounts.
        original_name:
          type:
            - string
            - 'null'
          description: >-
            The account name as the bank reports it, before any rename in
            ThinkOut. `null` for manual accounts.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        object: account
        id: c2d7e8f9-1a2b-4c3d-8e9f-0a1b2c3d4e5f
        name: ING Curent
        currency: RON
        group: Operational
        source: bank
        balance: '15230.45'
        balance_as_of: '2026-09-03'
        opening_balance: '1000.00'
        opening_date: '2024-01-01'
        bank: 5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f
        external_account_id: ACC-00012345
        original_name: Cont curent RON
        created_at: '2024-01-01T10:00:00Z'
        updated_at: '2026-08-30T06:00:00Z'
    Category:
      type: object
      required:
        - object
        - id
        - name
        - code
        - direction
        - activity
        - parent_id
        - position
        - color
        - created_at
        - updated_at
      properties:
        object:
          type: string
          const: category
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Telecom
        code:
          type:
            - string
            - 'null'
          description: >
            The category's identifier in the template this workspace was created
            from.

            `null` for a category someone created.


            Only `uncategorized_inflows` and `uncategorized_outflows` are worth
            branching

            on. They mark the two categories holding unclassified money, they
            exist in

            every workspace, and ThinkOut refuses to delete them. Every other
            code depends

            on which template was used.
          example: uncategorized_outflows
        direction:
          $ref: '#/components/schemas/Direction'
        activity:
          $ref: '#/components/schemas/Activity'
        parent_id:
          type:
            - string
            - 'null'
          format: uuid
          description: '`null` for top-level categories.'
        position:
          type: integer
          description: Order among siblings, as shown in ThinkOut.
        color:
          type:
            - string
            - 'null'
          description: Lowercase hex color as shown in ThinkOut.
          pattern: ^#[0-9a-f]{6}$
          example: '#1b7fe4'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        object: category
        id: 3b4c5d6e-7f80-4a1b-9c2d-3e4f5a6b7c8d
        name: Telecom
        code: null
        direction: outflow
        activity: operating
        parent_id: 6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d
        position: 2
        color: '#1b7fe4'
        created_at: '2024-01-01T10:00:00Z'
        updated_at: '2024-01-01T10:00:00Z'
    Counterparty:
      type: object
      required:
        - object
        - id
        - name
        - country_code
        - color
        - symbol
        - created_at
        - updated_at
      properties:
        object:
          type: string
          const: counterparty
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Orange
        country_code:
          type:
            - string
            - 'null'
          description: ISO 3166-1 alpha-2 country code.
          pattern: ^[A-Z]{2}$
          example: RO
        color:
          type:
            - string
            - 'null'
          pattern: ^#[0-9a-f]{6}$
        symbol:
          type:
            - string
            - 'null'
          description: Short text shown in the counterparty avatar in ThinkOut.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        object: counterparty
        id: 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
        name: Orange
        country_code: RO
        color: '#e4571b'
        symbol: OR
        created_at: '2024-02-14T08:00:00Z'
        updated_at: '2024-02-14T08:00:00Z'
    Label:
      type: object
      required:
        - object
        - id
        - name
        - type
        - color
        - created_at
        - updated_at
      properties:
        object:
          type: string
          const: label
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Q3
        type:
          oneOf:
            - $ref: '#/components/schemas/LabelType'
            - type: 'null'
          description: >
            The group this label belongs to, or `null` when it is ungrouped. A
            type is

            created with the first label that uses it and deleted with the last
            one, so it

            has no endpoint of its own.
        color:
          type:
            - string
            - 'null'
          pattern: ^#[0-9a-f]{6}$
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        object: label
        id: 1f2e3d4c-5b6a-4978-8877-665544332211
        name: Q3
        type:
          id: 7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f
          name: Quarter
        color: '#7c3aed'
        created_at: '2026-01-05T09:00:00Z'
        updated_at: '2026-01-05T09:00:00Z'
    AccountSource:
      type: string
      description: >-
        `delegated` accounts are bank accounts another workspace has delegated
        to this one.
      enum:
        - manual
        - bank
        - delegated
    ExpandableBank:
      description: >-
        A bank connection id, the full connection when named in `expand`, or
        `null` for a manual account.
      oneOf:
        - type: string
          format: uuid
        - $ref: '#/components/schemas/Bank'
        - type: 'null'
    Activity:
      type: string
      description: Cash flow statement section the category belongs to.
      enum:
        - operating
        - investing
        - financing
    LabelType:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          example: Quarter
    Bank:
      type: object
      description: >
        One authorisation with one bank. Several accounts can share a
        connection, and a

        workspace can hold several connections to the same bank.
      required:
        - object
        - id
        - name
        - country_code
        - status
        - last_sync_at
        - consent_expires_at
        - created_at
        - updated_at
      properties:
        object:
          type: string
          const: bank
        id:
          type: string
          format: uuid
        name:
          type: string
          description: The bank's name as the provider reports it.
          example: ING Bank
        country_code:
          type:
            - string
            - 'null'
          description: ISO 3166-1 alpha-2 country of the bank.
          pattern: ^[A-Z]{2}$
          example: RO
        status:
          $ref: '#/components/schemas/BankStatus'
        last_sync_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            When the provider last returned data successfully. `null` when it
            never has.


            This is the age of the data, not the age of the connection. A
            connection can sit

            at `connected` with a `last_sync_at` days old, which is the case
            worth alerting

            on.
        consent_expires_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            When the bank consent needs renewal, if the provider reports it.
            Once it passes,

            the connection stops returning new transactions until someone
            re-approves it.
        created_at:
          type: string
          format: date-time
          description: When the connection was first authorised.
        updated_at:
          type: string
          format: date-time
      example:
        object: bank
        id: 5d6e7f80-9a1b-4c2d-8e3f-4a5b6c7d8e9f
        name: ING Bank
        country_code: RO
        status: connected
        last_sync_at: '2026-09-03T06:00:00Z'
        consent_expires_at: '2026-11-30T00:00:00Z'
        created_at: '2024-01-01T10:00:00Z'
        updated_at: '2026-09-03T06:00:00Z'
    BankStatus:
      type: string
      description: >
        The state of the connection as of ThinkOut's last exchange with the
        provider.


        `connected` is working. `loading` is a sync in progress.
        `requires_action` needs a

        person to sign in or re-approve the connection in ThinkOut, and no new
        transactions

        arrive until they do. `error` is a failure ThinkOut could not resolve on
        its own,

        and covers any provider state ThinkOut cannot place.


        Only `connected` means the data behind it is current.
      enum:
        - connected
        - loading
        - requires_action
        - error
  responses:
    BadRequest:
      description: A parameter is invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: invalid_request
              code: invalid_parameter
              message: Parameter 'from' must be a date in YYYY-MM-DD format.
              param: from
              request_id: req_01J8ZT4Q7Y6M3K
    Unauthorized:
      description: The API key is missing, unknown or revoked.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: authentication
              code: unauthorized
              message: Invalid API key.
              param: null
              request_id: req_01J8ZT4Q7Y6M3K
    RateLimited:
      description: Too many requests. Wait for the number of seconds in `Retry-After`.
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: rate_limit
              code: rate_limited
              message: Rate limit exceeded. Retry after 12 seconds.
              param: null
              request_id: req_01J8ZT4Q7Y6M3K
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        A workspace API key created in ThinkOut settings. One key reads one
        workspace.

````