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

# Theses for a token, newest first, ask on a timer for a live feed

> The 20 most recent theses for one token, newest first by post time.

- **Live:** call with no `before` on a timer; dedupe on `thesisHash`, falling back to `id` when it is null.
- `before` is a thesis **`id`** — the last thesis you saw — not a timestamp.
  An id positions the walk exactly, including inside a group of theses
  posted in the same millisecond, which a timestamp cannot.
- An unknown `before` is a **400**.
- Ask on a sensible timer rather than in a tight loop.

A page can come back empty. Ask again on your normal interval.

**Price:** 200 CU per 20 requested rows (`limit`, up to 100). An empty page costs the same as a full one.



## OpenAPI

````yaml https://api.fomoscan.sh/openapi.json get /v2/thesis/token/{tokenAddress}
openapi: 3.1.0
info:
  title: FomoScan Identity API
  version: 1.1.0
  description: >-
    Resolve a FOMO trader handle to their on-chain wallet addresses, and

    any wallet back to the traders behind it. Every returned address is a

    verified match.


    ## Authentication

    Send your API key as `Authorization: Bearer fsk_live_…` (or the

    `X-Api-Key` header). Enter it under Authentication at the top of this

    page to call any endpoint live.


    ```bash

    curl -s -H "Authorization: Bearer $KEY" \
      "https://api.fomoscan.sh/v2/user/handle/tradername"
    ```


    ## Response format

    A successful response is the record itself, as flat JSON. There is no

    wrapper to unwrap. Timestamps on thesis and PnL records are epoch

    milliseconds.


    ## Billing

    - A lookup that finds nothing is still charged, at the miss price stated on
    the endpoint.

    - `GET /v2/me` is free and reports your remaining units.

    - Errors that are our fault or your client’s (`401`, `403`, `429`, `5xx`)
    are not billed.

    - When the allowance is spent, calls return `402 QUOTA_EXCEEDED` until the
    counter resets.


    ## Free keys

    A free key reveals wallets for the sample set below and nobody else.

    Sample lookups cost no credits. Outside the set, a wallet lookup, or a

    handle or id lookup whose answer carries a wallet, returns

    `403 SAMPLE_SET_ONLY`. Profiles without a wallet and misses answer as

    they do for any key. A self-serve free key cannot open the WebSocket.


    - Handles: `frankdegods`, `unipcs`, `pointfarmcap`, `orangie`, `theveeman`

    - Wallets: `498g1rVnFcnjBjpfw1xyqA1WvgQXUU8RWuELjxkjAayQ`,
    `0x696d1265c8fc4f14797abebfae3c43ebfa9d8e28`,
    `2heJbC32Tpfcb3nbUb5ER61K11FGZVfVGtVnDm6LDogF`,
    `Beqv6dzTcjV2eodo8RRXCiCcnSYrS1vkQKhfqwHXqeit`,
    `83b2LMf12aLec92kur3duRA8VvUkLaXUtML31aCcZNCM`,
    `F5hkYsi8JxjyA2JHN5CA7MbnnhWubkXB2ZQB7Gkaxqs6`


    ## 404 NOT_FOUND

    A lookup that finds nothing answers `404` with the code `NOT_FOUND`. On

    a handle or id lookup it means we hold no user under that handle or id.

    On a wallet lookup it means we hold no verified link from that address

    to a trader. Treat it as "no answer today", cache the negative briefly

    and ask again later. A user we hold without a verified wallet answers

    `200` with both addresses `null`.


    ## Errors

    Every error uses one shape: `{ "error": { "code": "…", "message": "…" } }`.


    | HTTP | Code | Meaning |

    |---|---|---|

    | 400 | `VALIDATION_ERROR` | A malformed handle, address or query parameter.
    |

    | 400 | `BAD_REQUEST` | The request cannot be served as sent. |

    | 401 | `UNAUTHORIZED` | Missing or invalid API key. |

    | 402 | `QUOTA_EXCEEDED` | Out of credits. |

    | 402 | `REVEAL_LIMIT_REACHED` | The key’s reveal limit is reached. |

    | 403 | `FORBIDDEN` | The key may not perform this action. |

    | 403 | `FORBIDDEN_SCOPE` | The key is not provisioned for this endpoint. |

    | 403 | `FREE_TIER_DISABLED` | The key has no allowance. |

    | 403 | `SAMPLE_SET_ONLY` | A free key asked for a wallet outside the sample
    set. |

    | 403 | `WEBSOCKET_PLAN_REQUIRED` | The key’s plan has no WebSocket. It is
    included from Growth ($899), and legacy plans keep it. |

    | 404 | `NOT_FOUND` | No answer for the handle, id or wallet you asked
    about, or no such route. See the section above. |

    | 409 | `CONFLICT` | The request conflicts with one already accepted. |

    | 429 | `RATE_LIMITED` | Per-minute limit exceeded. Retry after `retryAfter`
    seconds. |

    | 500 | `INTERNAL_ERROR` | Our fault. Retry. If it persists, contact support
    with the path and the time. |

    | 503 | `OVERLOADED` | We are shedding load. Retry. |

    | 503 | `B2B_DISABLED` | The API is switched off on this deployment. |

    | 504 | `TIMEOUT` | The answer did not arrive in time. Retry. |


    A `429` also carries `retryAfter`, in seconds.


    ## Rate limits

    Each key has one per-minute request limit across every endpoint,

    readable from `GET /v2/me` as `ratePerMinute`. A per-IP burst ceiling

    sits behind it. Exceeding either returns `429 RATE_LIMITED`.


    ## Pricing

    Paid plans reach every REST endpoint. Plans differ in credits, request rate,

    wallet reveals and the WebSocket. Credits and CU are the same unit.


    | Plan | Free | Starter | Builder | Growth | Scale | Enterprise |

    | --- | --- | --- | --- | --- | --- | --- |

    | Price per month | $0 | $99 | $299 | $899 | $2,499 | Set in the contract |

    | Credits | 25,000 once, for 30 days | 1,000,000 a month | 5,000,000 a month
    | 20,000,000 a month | 75,000,000 a month | Set in the contract |

    | Requests per minute | 60 | 150 | 300 | 600 | 1,200 | Set in the contract |

    | Wallet reveals per month | Sample set only | 150 | 500 | 1,500 | 4,000 |
    No cap |

    | Price per 30,000-credit reveal | $0 on the sample set | $2.97 | $1.79 |
    $1.35 | $1.00 | Set in the contract |

    | WebSocket | No | No | No | Included | Included | Included |


    Keys on legacy plans keep the WebSocket access they already have.


    ### Wallet reveals

    A wallet reveal is an answer that returns a verified wallet. Each reveal
    counts

    against the plan’s wallet reveals for the month. It costs the credits of the

    endpoint that returned it:


    | Reveal endpoint | Credits per reveal |

    | --- | --- |

    | `GET /v2/user/handle/{handle}` | 100 |

    | `GET /v2/user/wallet/{address}` | 30,000 |

    | `GET /v2/user/id/{id}` | 100 |

    | `POST /v2/user/handle/{handle}/resolve` | 30,000 |

    | `GET /v2/user/handle/{handle}/pnl` | 30,000 |

    | `POST /v2/user/handles/pnl` | 30,000 per handle revealed |


    The price per 30,000-credit reveal in the plan table is what 30,000 credits

    cost on the plan. It applies to `GET /v2/user/wallet/{address}`, `POST
    /v2/user/handle/{handle}/resolve`, `GET /v2/user/handle/{handle}/pnl`, `POST
    /v2/user/handles/pnl`.

    A reveal on another endpoint costs that endpoint’s credits.


    ### Credit cost per endpoint


    | Endpoint | Credits |

    | --- | --- |

    | `GET /v2/user/handle/{handle}` | 100 CU on a hit, 200 CU on a 404. |

    | `GET /v2/user/wallet/{address}` | 30,000 CU on a hit, 200 CU on a 404. |

    | `GET /v2/user/id/{id}` | 100 CU on a hit, 200 CU on a 404. |

    | `POST /v2/user/handle/{handle}/resolve` | 30,000 CU on a hit, 200 CU on a
    202 or a 404. A paused lookup (202 with reason unavailable and retryable
    false) is not charged. |

    | `GET /v2/user/handle/{handle}/pnl` | 30,000 CU on a hit, 200 CU on any
    answer that is not ready, and on a 404. |

    | `POST /v2/user/handles/pnl` | 30,000 CU per entry answered ready, 200 CU
    per entry not ready and per handle in `missing`. |

    | `GET /v2/thesis` | 200 CU per 20 requested rows (`limit`, up to 100). An
    empty page costs the same as a full one. |

    | `GET /v2/thesis/token/{tokenAddress}` | 200 CU per 20 requested rows
    (`limit`, up to 100). An empty page costs the same as a full one. |

    | `GET /v2/thesis/user/{id}` | 200 CU per 20 requested rows (`limit`, up to
    100). An empty page costs the same as a full one. |

    | `GET /v2/thesis/user/{id}/token/{tokenAddress}` | 200 CU per 20 requested
    rows (`limit`, up to 100). An empty page costs the same as a full one. |

    | `GET /v2/me` | Free. |

    | `GET /v2/pump/user/wallet/{wallet}` | 10 CU per call. |

    | `GET /v2/pump/thesis` | 10 CU per call. |

    | `GET /v2/pump/thesis/token/{mint}` | 10 CU per call. |

    | `GET /v2/pump/thesis/wallet/{wallet}` | 10 CU per call. |

    | `GET /v2/pump/leaderboard/traders` | 10 CU per call. |

    | `GET /v2/pump/user/wallet/{wallet}/pnl` | 500 CU per call. |

    | `GET /v2/ws` | 20,000 CU per minute held open. |

    | `GET /v2/ws/pump` | 20,000 CU per minute held open. |


    ### Credit packs

    A pack adds credits on top of a plan. Pack credits do not expire, and they
    are

    spent after the plan’s monthly credits run out.


    | Pack | Price |

    | --- | --- |

    | 250,000 credits | $29 |

    | 1,000,000 credits | $115 |

    | 5,000,000 credits | $349 |

    | 20,000,000 credits | $1,049 |

    | 75,000,000 credits | $2,899 |


    ### Payment

    Plans are paid by card, and Apple Pay counts as a card. Credit packs are
    paid

    in crypto only, with no surcharge.


    ## Chains

    Wallet lookups take a Solana address or an EVM address. A verified EVM
    address

    is the same address on every EVM chain.


    Theses carry their token’s chain in `tokenNetwork`. This table shows the
    value

    the API returns for each chain we serve. Some chains arrive as a short name
    and

    some as a numeric chain id. Match on the exact value in the table.


    | Chain | `tokenNetwork` |

    | --- | --- |

    | Solana | `sol` |

    | Base | `base` |

    | BNB Chain | `bsc` |

    | Robinhood Chain | `robinhood` |

    | Ethereum | `eth` |

    | Arc | `5042` |

    | Monad | `143` |


    A thesis on a chain outside this table arrives as a short name or a numeric
    chain id.


    ## Breaking changes

    A breaking change removes or renames an endpoint, a field or an error code,
    or

    changes what a field means. We announce each one at least 3 days before it

    ships. The notice goes out on the changelog, on the Telegram announcements

    channel (https://t.me/scanfomo) and on every other channel we run.


    New fields can appear without notice. Ignore fields you do not recognise.
  contact:
    name: FomoScan
    url: https://fomoscan.sh
    email: fomoscan-support@proton.me
servers:
  - url: https://api.fomoscan.sh
    description: Production
security: []
tags:
  - name: Identities
    description: Resolve handles ↔ wallets.
  - name: Thesis Feed
    description: >-
      Trader "thesis" posts, newest first, by token, by author, or both. Ask
      with no `before` for the newest page. Clients MUST dedupe on `id`.
  - name: WebSocket
    description: >-
      The streaming surface. Everything above is a request you make; this is a
      connection you hold. It delivers the same thesis objects `Thesis Feed`
      returns.
  - name: Pump
    description: >-
      pump.fun lookups: a user by wallet, the global callout feed or one coin's
      or wallet's wall, and the PnL leaderboard. On pump.fun the wallet IS the
      account, so a wallet lookup here is a stored read, not a resolution.
  - name: Account
    description: 'Your key: entitlements and usage.'
paths:
  /v2/thesis/token/{tokenAddress}:
    get:
      tags:
        - Thesis Feed
      summary: Theses for a token, newest first, ask on a timer for a live feed
      description: >-
        The 20 most recent theses for one token, newest first by post time.


        - **Live:** call with no `before` on a timer; dedupe on `thesisHash`,
        falling back to `id` when it is null.

        - `before` is a thesis **`id`** — the last thesis you saw — not a
        timestamp.
          An id positions the walk exactly, including inside a group of theses
          posted in the same millisecond, which a timestamp cannot.
        - An unknown `before` is a **400**.

        - Ask on a sensible timer rather than in a tight loop.


        A page can come back empty. Ask again on your normal interval.


        **Price:** 200 CU per 20 requested rows (`limit`, up to 100). An empty
        page costs the same as a full one.
      parameters:
        - schema:
            type: string
          in: query
          name: before
          required: false
          description: >-
            The `id` of the last thesis you saw — the previous page’s
            `nextBefore`. Returns theses older than it. Omit for the newest 20.
        - schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
          in: query
          name: limit
          required: false
          description: >-
            Rows per page, 1..100. Priced per started block of 20 rows on the
            REQUESTED limit.
        - schema:
            type: string
          example: So11111111111111111111111111111111111111112
          in: path
          name: tokenAddress
          required: true
          description: >-
            Mint / contract address. Case-sensitive for Solana base58; EVM `0x…`
            is lower-cased for you.
      responses:
        '200':
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                required:
                  - tokenAddress
                  - tokenNetwork
                  - symbol
                  - updatedAt
                  - count
                  - hasMore
                  - nextBefore
                  - items
                properties:
                  tokenAddress:
                    type: string
                    description: Normalised (EVM lower-cased).
                  tokenNetwork:
                    type:
                      - 'null'
                      - string
                    description: >-
                      Chain name (`sol`, `eth`, `base`, …). Null when the page
                      is empty.
                  symbol:
                    type:
                      - 'null'
                      - string
                    description: Ticker. Null when the page is empty.
                  updatedAt:
                    type:
                      - 'null'
                      - integer
                    description: Post time of the NEWEST thesis in this page, epoch millis.
                  count:
                    type: integer
                    description: Items in this page (0..20).
                  hasMore:
                    type: boolean
                    description: Whether older theses exist behind this page.
                  nextBefore:
                    type:
                      - 'null'
                      - string
                    description: >-
                      The OLDEST item’s `id`. Send back as `?before=` for the
                      next page while `hasMore` is true. Null on the last page.
                  items:
                    type: array
                    items:
                      type: object
                      required:
                        - id
                        - authorHandle
                        - thesis
                        - fomoCreatedAt
                      properties:
                        id:
                          type: string
                          description: >-
                            Thesis id. Send it back as `?before=` to paginate.
                            The same thesis can be issued again under a new id,
                            so dedupe on `thesisHash`. Not related to a user
                            `id`.
                        thesisHash:
                          type:
                            - 'null'
                            - string
                          description: >-
                            Stable key for deduping. Identical for theses with
                            the same author, the same trade, the same token and
                            the same text, whatever their `id` and post time.
                            Null when one of those is missing; fall back to `id`
                            then.
                        tokenAddress:
                          type:
                            - 'null'
                            - string
                          description: >-
                            The token this thesis is about. Present on every
                            item, including the narrowed feeds, so one item
                            shape works everywhere.
                        tokenNetwork:
                          type:
                            - 'null'
                            - string
                          description: Chain name (`sol`, `eth`, `base`, …).
                        tokenSymbol:
                          type:
                            - 'null'
                            - string
                          description: Ticker.
                        authorId:
                          type:
                            - 'null'
                            - string
                          description: >-
                            The author’s `id`, the same value a user record
                            carries. `/v2/user/id/{id}` returns their profile
                            and `/v2/thesis/user/{id}` everything else they have
                            posted.
                        authorHandle:
                          type:
                            - 'null'
                            - string
                          description: >-
                            Author’s handle. Display it; to look the author up
                            prefer `authorId`, which does not change when they
                            rename.
                        authorName:
                          type:
                            - 'null'
                            - string
                          description: Author display name.
                        authorIsDev:
                          type:
                            - 'null'
                            - boolean
                          description: Author is the token’s dev.
                        authorAvatarUrl:
                          type:
                            - 'null'
                            - string
                          description: >-
                            Author’s profile picture URL, for a callout mark or
                            avatar next to the thesis.
                        thesis:
                          type:
                            - 'null'
                            - string
                          description: The thesis text.
                        segments:
                          type:
                            - 'null'
                            - array
                          description: >-
                            Rich-text runs of the thesis text (text + optional
                            link).
                          items:
                            type: object
                            additionalProperties: true
                        likeCount:
                          type:
                            - 'null'
                            - integer
                        holdingsUsd:
                          type:
                            - 'null'
                            - number
                          description: Author’s position value in USD at post time.
                        authorTradeUsd:
                          type:
                            - 'null'
                            - number
                          description: USD size of the trade behind the thesis.
                        pnl:
                          type:
                            - 'null'
                            - number
                          description: >-
                            Single PnL figure in USD: realized, falling back to
                            unrealized.
                        realizedPnlUsd:
                          type:
                            - 'null'
                            - number
                          description: Realized PnL in USD.
                        unrealizedPnlUsd:
                          type:
                            - 'null'
                            - number
                          description: Unrealized PnL in USD.
                        percentageRealizedPnl:
                          type:
                            - 'null'
                            - number
                          description: Realized PnL as a percentage.
                        percentageUnrealizedPnl:
                          type:
                            - 'null'
                            - number
                          description: Unrealized PnL as a percentage.
                        tokenAmount:
                          type:
                            - 'null'
                            - number
                          description: Author’s token balance behind the thesis.
                        closedAt:
                          type:
                            - 'null'
                            - integer
                          description: >-
                            When the author’s position closed, epoch millis.
                            Null while open — the PnL above is then a running
                            figure, not a final one.
                        fomoCreatedAt:
                          type:
                            - 'null'
                            - integer
                          description: Post time, epoch milliseconds.
                        updatedAt:
                          type:
                            - 'null'
                            - integer
                          description: >-
                            When we last wrote this record, epoch milliseconds.
                            It can move without any field changing.
                        tokenImageUrl:
                          type:
                            - 'null'
                            - string
                          description: Token logo URL, or null. May no longer resolve.
      security:
        - b2bApiKey: []
components:
  securitySchemes:
    b2bApiKey:
      type: http
      scheme: bearer
      description: >-
        B2B API key (`fsk_live_…` / `fsk_test_…`), issued by FomoScan. Also
        accepted via `X-Api-Key`.

````

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