---
title: "Search markets"
method: POST
path: "/v1/tools/betteroff_search_markets"
tags: ["tools"]
---

# Search markets

`POST /v1/tools/betteroff_search_markets`

## Request

- Base URL: `https://api.betteroff.finance`
- URL: `https://api.betteroff.finance/v1/tools/betteroff_search_markets`
- Auth: one of:
  - OpenID Connect (`https://app.betteroff.finance/api/auth/.well-known/openid-configuration`, scopes: `investments:read`)
  - HTTP bearer

Use this when the user asks to find public FX reference rates, Hyperliquid spot or perpetual markets, or prediction outcomes. Search public FX reference rates (USD base), Hyperliquid spot/perpetual markets, and prediction markets. Filter by kind or source to narrow coverage. Returns at most 50 dated observations per page, busiest first by 24-hour USD volume where reported. For the next page, pass page.nextCursor as cursor with the same query, kind, source, and limit.

## Request body

- object
  - `query` string, required
  - `kind` 'fx' | 'perpetual' | 'spot' | 'prediction', nullable, required
  - `source` 'frankfurter' | 'hyperliquid-perps' | 'hyperliquid-spot' | 'polymarket' | 'polymarket-us' | 'kalshi' | 'pascal', nullable, required
  - `limit` integer, required
  - `offset` integer, required
  - `cursor` string, nullable

## Response `200`

Tool result

- union
  - object
    - `ok` false, required
    - `requestId` string
    - `error` string, required
    - `code` string, required
    - `retryable` boolean, required
    - `nextStep` string, required
    - `field` string
    - `missingInputs` object[]
      - `id` string, required
      - `name` string, required
      - `balanceMissing` boolean, required
      - `interestRateMissing` boolean, required
      - `minimumPaymentMissing` boolean, required
  - object
    - `ok` true, required
    - `requestId` string
    - `schemaVersion` '4', required
    - `data` object, required
      - `markets` object[], required
        - `id` string, required
        - `symbol` string, required
        - `name` string, required
        - `kind` 'fx' | 'perpetual' | 'spot' | 'prediction', required
        - `source` 'frankfurter' | 'hyperliquid-perps' | 'hyperliquid-spot' | 'polymarket' | 'polymarket-us' | 'kalshi' | 'pascal', required
        - `price` number, nullable, required
        - `quoteCurrency` string, required
        - `priceType` 'reference' | 'mark' | 'probability' | 'yes-ask' | 'yes-bid', required
        - `asOf` string, nullable, required
        - `observedAt` string, required
        - `url` string, uri, nullable, required
        - `volume24hUsd` number, nullable
      - `coverage` object[], required
        - `source` 'frankfurter' | 'hyperliquid-perps' | 'hyperliquid-spot' | 'polymarket' | 'polymarket-us' | 'kalshi' | 'pascal', required
        - `status` 'available' | 'partial' | 'unavailable', required
        - `observedAt` string, required
        - `count` integer, required
      - `page` object, required
        - `total` integer, required
        - `nextOffset` integer, nullable, required
        - `nextCursor` string, nullable
        - `truncated` boolean, required
    - `currency` string, nullable, required
    - `timezone` string, required
    - `asOf` string, nullable, required
    - `revision` integer, required
    - `householdRevision` integer, required
    - `quality` object, required
      - `state` 'complete' | 'partial' | 'unavailable', required
      - `reasons` string[], required
    - `evidence` object[], required
      - `source` string, required
      - `id` string
      - `observedAt` string, nullable, required
    - `page` object, required
      - `returnedCount` integer, required
      - `totalCount` integer, nullable, required
      - `truncated` boolean, required
      - `nextCursor` Schema0, required (unresolved $ref)
    - `warnings` string[], required
    - `notes` string

## Other responses

- `400`: INVALID_INPUT (a missing, unknown, or invalid argument, named in `fields`), TOOL_CALL_REJECTED, or a body that is not JSON.
- `401`: AGENT_TOKEN_INVALID: the token is missing, expired, or revoked.
- `402`: AGENT_SUBSCRIPTION_INACTIVE or FEATURE_NOT_INCLUDED: needs BetterOff Core.
- `403`: INSUFFICIENT_SCOPE, ACCESS_DENIED, or AGENT_GRANT_REVOKED.
- `404`: TOOL_NOT_FOUND, or NOT_FOUND for a record the org does not have.
- `409`: CONFLICT: the record's state rules this call out. Read it again.
- `422`: INCOMPLETE_DATA or RESULT_TOO_LARGE. Narrow the request; don't retry as is.
- `429`: RATE_LIMITED. Retry after Retry-After seconds.
- `503`: DATA_UNAVAILABLE, DEPENDENCY_UNAVAILABLE (including the 25-second tool deadline), or AGENT_AUTHZ_UNAVAILABLE. Retryable.
- `default`: Problem details

---

[API](https://skmtc.dev/betteroff/apis/betteroff-api.md) · [All operations](https://skmtc.dev/betteroff/apis/betteroff-api/llms.txt) · [OpenAPI document](https://skmtc.dev/betteroff/apis/betteroff-api/revisions/bc858c8d428d?raw)
