---
title: "Resolve a ticker or name to candidate mints"
method: GET
path: "/tokens/search"
tags: ["Tokens"]
---

# Resolve a ticker or name to candidate mints

`GET /tokens/search`

## Request

- Base URL: `https://madeonsol.com/api/v1`
- URL: `https://madeonsol.com/api/v1/tokens/search`
- Auth: HTTP bearer

Search our token universe by **symbol or name** and get back candidate mints ranked so the right one is first: exact ticker match, then symbol prefix, then name prefix, then fuzzy — and *inside* each tier by liquidity, so `bonk` returns the $2M-liquidity Bonk before ten thousand squats named BONK. Each result carries `market_cap_usd`, `liquidity_usd`, `primary_dex` and `last_trade_at` so you can disambiguate in one hop and pass the `mint` on to `/token/{mint}` and friends.

**Why this exists (2026-08-16):** 73% of all API 400s were tickers sent to mint routes (`/token/SOL`, `/token/WORLDCUP`). Those routes now answer a ticker with `code: ticker_not_mint` and a `search_url` pointing here.

**Honesty:** this searches the memecoin/launchpad universe our market-cap tracker has seen (pump.fun, PumpSwap, LaunchLab/bonk, Raydium, Meteora, Orca). Native SOL and blue-chips are deliberately not in it — `q=SOL` returns tokens *named* SOL and the response says so in `note`. Any authenticated key, including Free.

## Query parameters

- `q` string, required
- `limit` integer

## Response `200`

OK

- object
  - `q` string
  - `count` integer
  - `note` string, nullable: Present when q is a blue-chip ticker (results are namesakes) or when nothing matched.
  - `results` object[]
    - `mint` string
    - `symbol` string, nullable
    - `name` string, nullable
    - `match` 'symbol_exact' | 'symbol_prefix' | 'name_prefix' | 'fuzzy'
    - `market_cap_usd` number, nullable
    - `liquidity_usd` number, nullable
    - `primary_dex` string, nullable
    - `last_trade_at` string, date-time, nullable
    - `image_url` string, nullable: From token_metadata; null when not known.
    - `twitter` string, nullable: From token_metadata; null when not known.
    - `website` string, nullable: From token_metadata; null when not known.

## Other responses

- `400`: Missing/invalid q or limit
- `401`: Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.
- `403`: Forbidden. One of: the key's tier is below this endpoint's or parameter's gate (`tier_required` with an `upgrade` block); the public demo key used outside its allow-list (`demo_key_endpoint_not_allowed`); an invalid or revoked key; an origin-restricted key called from a disallowed origin (`code` `origin_not_allowed` / `origin_required`). `X-RateLimit-*` headers are present only on `tier_required`.
- `429`: Too many requests. Every 429 carries `Retry-After`. A quota 429 (`rate_limit_exceeded`, with `X-RateLimit-*`), a heavy-query concurrency 429 (`error_kind` `concurrency`/`capacity`), or the per-IP authentication-failure block (30 failed auths/min; plain `error` + `retry_after_seconds`, no `X-RateLimit-*`).
- `500`: Unexpected server error from the route (`Internal server error`, with `_rid`). Safe to retry with backoff. A failed API-key lookup is a 503 `auth_backend_unavailable`, never a 500.
- `503`: Temporarily unavailable — a Postgres statement timeout while the dataset is under load or maintenance (`statement_timeout`, with `X-RateLimit-*` and `_rid`), or the API-key lookup itself unavailable (`auth_backend_unavailable`, authentication stage: no `X-RateLimit-*`, no `_rid`, not counted as a failed authentication). Always carries `Retry-After`; honour it.

---

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