# Search Models

`GET /v1/catalog/models`

Search the models a provider offers too many of to list.

`GET /catalog` carries every model except these. A provider marked
`browse: "search"` there — OpenRouter — reaches hundreds of models through
one key, so they are searched a page at a time instead; its `searched_kinds`
says which `kind`s. With no `q` the order is real-world popularity. Everything
returned is a valid `llm.model` or `stt.model`, per `kind`.

Authenticate with `Authorization: Bearer $TALQING_API_KEY`. Errors use the shared envelope: https://docs.talqing.com/api-reference/errors.md

## OpenAPI

```json
{
 "openapi":"3.1.0",
 "servers":[
  {
   "description":"Talqing API",
   "url":"https://api.talqing.com"
  }
 ],
 "paths":{
  "/v1/catalog/models":{
   "get":{
    "description":"Search the models a provider offers too many of to list.\n\n`GET /catalog` carries every model except these. A provider marked\n`browse: \"search\"` there \u2014 OpenRouter \u2014 reaches hundreds of models through\none key, so they are searched a page at a time instead; its `searched_kinds`\nsays which `kind`s. With no `q` the order is real-world popularity. Everything\nreturned is a valid `llm.model` or `stt.model`, per `kind`.",
    "operationId":"catalog.models.search",
    "parameters":[
     {
      "in":"query",
      "name":"q",
      "required":false,
      "schema":{
       "default":"",
       "title":"Q",
       "type":"string"
      }
     },
     {
      "in":"query",
      "name":"limit",
      "required":false,
      "schema":{
       "default":20,
       "maximum":50,
       "minimum":1,
       "title":"Limit",
       "type":"integer"
      }
     },
     {
      "in":"query",
      "name":"cursor",
      "required":false,
      "schema":{
       "default":"",
       "title":"Cursor",
       "type":"string"
      }
     },
     {
      "in":"query",
      "name":"kind",
      "required":false,
      "schema":{
       "default":"llm",
       "enum":[
        "llm",
        "stt"
       ],
       "title":"Kind",
       "type":"string"
      }
     }
    ],
    "responses":{
     "200":{
      "content":{
       "application/json":{
        "schema":{
         "discriminator":{
          "mapping":{
           "llm":"#/components/schemas/LLMModelSearchResponse",
           "stt":"#/components/schemas/STTModelSearchResponse"
          },
          "propertyName":"kind"
         },
         "oneOf":[
          {
           "$ref":"#/components/schemas/LLMModelSearchResponse"
          },
          {
           "$ref":"#/components/schemas/STTModelSearchResponse"
          }
         ],
         "title":"Response Catalog.Models.Search"
        }
       }
      },
      "description":"Successful Response"
     },
     "401":{
      "$ref":"#/components/responses/Unauthorized"
     },
     "422":{
      "$ref":"#/components/responses/ValidationFailed"
     },
     "default":{
      "$ref":"#/components/responses/Error"
     }
    },
    "security":[
     {
      "BearerAuth":[]
     },
     {
      "SessionCookie":[]
     }
    ],
    "summary":"Search Models",
    "tags":[
     "catalog"
    ]
   }
  }
 },
 "components":{
  "responses":{
   "Error":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Unexpected error. Every error this API returns carries this body."
   },
   "Unauthorized":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Missing credential, or one that is revoked or no longer a member of this organization."
   },
   "ValidationFailed":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"The request did not match this operation's schema; `detail.errors` lists each field."
   }
  },
  "schemas":{
   "BuiltinTool":{
    "description":"A tool the model provider runs on its own servers during the agent's turn.\n\nWe never see the call: the provider searches, executes or retrieves, and\nfolds the result into the assistant's reply. That is also why there is no\nPython class per tool \u2014 the wire form is `{\"type\": ..., **options}`, so this\ndeclaration plus the agent's chosen values is the whole definition.",
    "properties":{
     "description":{
      "title":"Description",
      "type":"string"
     },
     "fixed":{
      "additionalProperties":true,
      "title":"Fixed",
      "type":"object"
     },
     "label":{
      "title":"Label",
      "type":"string"
     },
     "options":{
      "items":{
       "$ref":"#/components/schemas/BuiltinToolOption"
      },
      "title":"Options",
      "type":"array"
     },
     "price_note":{
      "title":"Price Note",
      "type":"string"
     },
     "type":{
      "title":"Type",
      "type":"string"
     }
    },
    "required":[
     "type",
     "label",
     "description",
     "price_note"
    ],
    "title":"BuiltinTool",
    "type":"object"
   },
   "BuiltinToolOption":{
    "description":"One configurable field of a provider built-in tool.\n\n`key` is what the agent config stores; `path` is where the value belongs\ninside the tool object on the wire. The two differ because providers nest\nthe same idea differently \u2014 domain filters sit under `filters` for both xAI\nand OpenAI, while xAI's image switches are top-level.",
    "properties":{
     "choices":{
      "items":{
       "type":"string"
      },
      "title":"Choices",
      "type":"array"
     },
     "conflicts_with":{
      "items":{
       "type":"string"
      },
      "title":"Conflicts With",
      "type":"array"
     },
     "description":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Description"
     },
     "key":{
      "title":"Key",
      "type":"string"
     },
     "label":{
      "title":"Label",
      "type":"string"
     },
     "max_items":{
      "anyOf":[
       {
        "type":"integer"
       },
       {
        "type":"null"
       }
      ],
      "title":"Max Items"
     },
     "path":{
      "items":{
       "type":"string"
      },
      "minItems":1,
      "title":"Path",
      "type":"array"
     },
     "required":{
      "default":false,
      "title":"Required",
      "type":"boolean"
     },
     "type":{
      "enum":[
       "boolean",
       "string",
       "string_list",
       "integer",
       "enum"
      ],
      "title":"Type",
      "type":"string"
     }
    },
    "required":[
     "key",
     "path",
     "label",
     "type"
    ],
    "title":"BuiltinToolOption",
    "type":"object"
   },
   "ErrorBody":{
    "description":"The structured half of our error contract: a human `message` plus a list\nof individual `errors` (used wherever we surface many problems at once,\nincluding tool publish, op-tree checks, and request validation). The global\nexception handlers normalize every API error to\n`{detail: {message, errors, code}}`, so SDKs can parse one shape consistently.",
    "properties":{
     "code":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "default":null,
      "description":"A stable identifier for this error, when it has one.",
      "title":"Code"
     },
     "errors":{
      "items":{
       "type":"string"
      },
      "title":"Errors",
      "type":"array"
     },
     "message":{
      "title":"Message",
      "type":"string"
     }
    },
    "required":[
     "message",
     "errors"
    ],
    "title":"ErrorBody",
    "type":"object"
   },
   "ErrorResponse":{
    "description":"The body of every error response, at every status code.",
    "properties":{
     "detail":{
      "$ref":"#/components/schemas/ErrorBody"
     }
    },
    "required":[
     "detail"
    ],
    "title":"ErrorResponse",
    "type":"object"
   },
   "LLMCatalogEntryResponse":{
    "additionalProperties":true,
    "properties":{
     "base_url":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Base Url"
     },
     "builtin_tools":{
      "items":{
       "$ref":"#/components/schemas/BuiltinTool"
      },
      "title":"Builtin Tools",
      "type":"array"
     },
     "channel":{
      "items":{
       "type":"string"
      },
      "title":"Channel",
      "type":"array"
     },
     "context_length":{
      "anyOf":[
       {
        "type":"integer"
       },
       {
        "type":"null"
       }
      ],
      "title":"Context Length"
     },
     "label":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Label"
     },
     "logo_url":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Logo Url"
     },
     "model":{
      "title":"Model",
      "type":"string"
     },
     "note":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Note"
     },
     "pricing":{
      "additionalProperties":true,
      "title":"Pricing",
      "type":"object"
     },
     "priority":{
      "anyOf":[
       {
        "$ref":"#/components/schemas/PriorityTier"
       },
       {
        "type":"null"
       }
      ]
     },
     "provider":{
      "title":"Provider",
      "type":"string"
     },
     "reasoning_efforts":{
      "items":{
       "enum":[
        "none",
        "minimal",
        "low",
        "medium",
        "high"
       ],
       "type":"string"
      },
      "title":"Reasoning Efforts",
      "type":"array"
     },
     "vision":{
      "default":false,
      "title":"Vision",
      "type":"boolean"
     }
    },
    "required":[
     "provider",
     "channel",
     "model",
     "label",
     "note",
     "logo_url",
     "pricing",
     "base_url",
     "builtin_tools",
     "reasoning_efforts",
     "priority",
     "vision",
     "context_length"
    ],
    "title":"LLMCatalogEntryResponse",
    "type":"object"
   },
   "LLMModelSearchResponse":{
    "description":"One page of a searched provider's language models \u2014 never the whole\nregistry.\n\nOrdered by real-world popularity when `q` is empty (OpenRouter ranks its own\nlist by tokens processed, so the first screen is the models people actually\nrun) and by match quality when it is not, popularity breaking the ties.",
    "properties":{
     "kind":{
      "const":"llm",
      "default":"llm",
      "title":"Kind",
      "type":"string"
     },
     "models":{
      "items":{
       "$ref":"#/components/schemas/LLMCatalogEntryResponse"
      },
      "title":"Models",
      "type":"array"
     },
     "next_cursor":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Next Cursor"
     }
    },
    "required":[
     "kind",
     "models",
     "next_cursor"
    ],
    "title":"LLMModelSearchResponse",
    "type":"object"
   },
   "LLMPricing":{
    "properties":{
     "cache_write_per_1m":{
      "anyOf":[
       {
        "type":"number"
       },
       {
        "type":"null"
       }
      ],
      "title":"Cache Write Per 1M"
     },
     "cached_input_per_1m":{
      "anyOf":[
       {
        "type":"number"
       },
       {
        "type":"null"
       }
      ],
      "title":"Cached Input Per 1M"
     },
     "input_per_1m":{
      "anyOf":[
       {
        "type":"number"
       },
       {
        "type":"null"
       }
      ],
      "title":"Input Per 1M"
     },
     "output_per_1m":{
      "anyOf":[
       {
        "type":"number"
       },
       {
        "type":"null"
       }
      ],
      "title":"Output Per 1M"
     }
    },
    "title":"LLMPricing",
    "type":"object"
   },
   "LanguageOption":{
    "properties":{
     "code":{
      "title":"Code",
      "type":"string"
     },
     "name":{
      "title":"Name",
      "type":"string"
     }
    },
    "required":[
     "code",
     "name"
    ],
    "title":"LanguageOption",
    "type":"object"
   },
   "PriorityTier":{
    "description":"The low-latency lane a model sells, and what that lane costs.\n\nEvery provider we carry schedules priority traffic ahead of standard traffic\nfor a per-token premium, asked for with the same `service_tier` body\nparameter. Presence of this block is what declares support \u2014 there is no\nseparate boolean, for the same reason `reasoning_efforts: []` needs none.\n\nThe premium is NOT a multiplier: it is 2x across OpenAI's 5.6 family, 2.5x on\ngpt-5.5, 1.75x on gpt-4.1 and a flat 1.8x at Gemini \u2014 so the rates are\ntranscribed per model rather than derived.",
    "properties":{
     "confirms":{
      "default":true,
      "title":"Confirms",
      "type":"boolean"
     },
     "pricing":{
      "$ref":"#/components/schemas/LLMPricing"
     },
     "value":{
      "default":"priority",
      "title":"Value",
      "type":"string"
     }
    },
    "required":[
     "pricing"
    ],
    "title":"PriorityTier",
    "type":"object"
   },
   "STTCatalogEntryResponse":{
    "additionalProperties":true,
    "properties":{
     "channel":{
      "items":{
       "type":"string"
      },
      "title":"Channel",
      "type":"array"
     },
     "default_language":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Default Language"
     },
     "file_transcription":{
      "anyOf":[
       {
        "enum":[
         "whole",
         "chunked"
        ],
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"File Transcription"
     },
     "label":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Label"
     },
     "language_required":{
      "default":false,
      "title":"Language Required",
      "type":"boolean"
     },
     "languages":{
      "items":{
       "$ref":"#/components/schemas/LanguageOption"
      },
      "title":"Languages",
      "type":"array"
     },
     "logo_url":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Logo Url"
     },
     "model":{
      "title":"Model",
      "type":"string"
     },
     "note":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Note"
     },
     "pricing":{
      "additionalProperties":true,
      "title":"Pricing",
      "type":"object"
     },
     "provider":{
      "title":"Provider",
      "type":"string"
     },
     "streaming":{
      "default":true,
      "title":"Streaming",
      "type":"boolean"
     }
    },
    "required":[
     "provider",
     "channel",
     "model",
     "label",
     "note",
     "logo_url",
     "pricing",
     "default_language",
     "languages",
     "language_required",
     "streaming",
     "file_transcription"
    ],
    "title":"STTCatalogEntryResponse",
    "type":"object"
   },
   "STTModelSearchResponse":{
    "description":"One page of a searched provider's speech-to-text models, ordered as the\nprovider lists them.",
    "properties":{
     "kind":{
      "const":"stt",
      "default":"stt",
      "title":"Kind",
      "type":"string"
     },
     "models":{
      "items":{
       "$ref":"#/components/schemas/STTCatalogEntryResponse"
      },
      "title":"Models",
      "type":"array"
     },
     "next_cursor":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Next Cursor"
     }
    },
    "required":[
     "kind",
     "models",
     "next_cursor"
    ],
    "title":"STTModelSearchResponse",
    "type":"object"
   }
  }
 }
}
```
