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

# Discover

> POST /v1/discover. Rank the catalog against a plain-English query and get each match with its price and a fillable sample input.

```
POST https://api.usegoro.ai/v1/discover
```

Describe the job in plain language. Goro ranks the catalog against it and
returns the best matches, each with its price and a sample input you can fill
in, so you can often go straight to [`run`](/api/run) without inspecting first.

## Request

| Field   | Type    | Required | Notes                                                                           |
| ------- | ------- | -------- | ------------------------------------------------------------------------------- |
| `query` | string  | yes      | What you are trying to accomplish. Must be non-empty                            |
| `limit` | integer |          | How many matches to return. Default 5, capped at 20. Must be a positive integer |

```bash theme={null}
curl -X POST https://api.usegoro.ai/v1/discover \
  -H "Authorization: Bearer $GORO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "tweets about ai agents", "limit": 3}'
```

## Response

```json theme={null}
{
  "items": [
    {
      "slug": "twitter.search",
      "name": "Twitter search",
      "category": "social",
      "when_to_use": "Use when you need tweets about a topic, sentiment or chatter on X, mentions of a brand or person, or what people are saying right now.",
      "price": {
        "type": "cost_plus",
        "markup": 3,
        "min_micro": 2000,
        "min_usd": "$0.0020",
        "max_micro": 3000000,
        "max_usd": "$3.00",
        "billed_on_actual_usage": true,
        "per_unit_micro": 1200,
        "per_unit_usd": "$0.0012",
        "unit_label": "result",
        "summary": "$0.0012 per result, billed on actual usage (3x provider cost, minimum $0.0020), up to $3.00 per call"
      },
      "sample_input": {
        "sort": "Latest",
        "maxItems": 20,
        "searchTerms": "<searchTerms>"
      }
    }
  ]
}
```

| Field                  | Type   | Notes                                                    |
| ---------------------- | ------ | -------------------------------------------------------- |
| `items`                | array  | Matches, best first. Can be empty                        |
| `items[].slug`         | string | The identifier to pass to `inspect` and `run`            |
| `items[].name`         | string | Human name                                               |
| `items[].category`     | string | Catalog category, for example `social`, `search`, `maps` |
| `items[].when_to_use`  | string | Guidance on when this tool is the right one              |
| `items[].price`        | object | See below                                                |
| `items[].sample_input` | object | A ready-to-fill input object                             |

Ranking is lexical and deterministic: the same query returns the same order
every time. Matches that score zero are dropped, so a query nothing answers
returns `{"items": []}` rather than a list of bad guesses.

### sample\_input

`sample_input` is built from the tool's own input schema. It contains every
required field, plus every optional field that declares a default. Values come
from the schema's examples, then its defaults, then its enums. A required field
with none of those appears as a placeholder like `"<searchTerms>"`, which you
are expected to replace.

It is a starting point, not a validated input. `run` validates what you
actually send.

### price

`price` is the same object [`inspect`](/api/inspect) and [`run`](/api/run)
return. Its fields depend on `type`.

| Field                                | Type            | Present on               | Notes                                                                                   |
| ------------------------------------ | --------------- | ------------------------ | --------------------------------------------------------------------------------------- |
| `type`                               | string          | all                      | `cost_plus`, `metered`, `per_call` or `per_result`                                      |
| `summary`                            | string          | all                      | One-line human description                                                              |
| `per_unit_micro`, `per_unit_usd`     | integer, string | `cost_plus`, `metered`   | The rate you pay per unit. Absent on a `cost_plus` tool with no published rate          |
| `unit_label`                         | string          | `cost_plus`, `metered`   | What one unit is: `profile`, `page`, `second of audio`                                  |
| `markup`                             | number          | `cost_plus`, `metered`   | Multiplier applied to what the provider charges                                         |
| `min_micro`, `min_usd`               | integer, string | `cost_plus`, `metered`   | Floor for a call that delivered something                                               |
| `max_micro`, `max_usd`               | integer, string | `cost_plus`, `metered`   | Ceiling. You are never charged above it                                                 |
| `billed_on_actual_usage`             | boolean         | `cost_plus`, `metered`   | Always `true`. The total depends on the call, so `max_usd` is a maximum and not a price |
| `base_micro`, `base_usd`             | integer, string | `per_call`, `per_result` | Flat component. On `per_call` it is the entire price                                    |
| `per_result_micro`, `per_result_usd` | integer, string | `per_result`             | Charged per row                                                                         |
| `max_results_cap`                    | integer         | `per_result`             | Rows past this are neither delivered nor billed                                         |

Most of the catalog is `cost_plus`: billed at `markup` times what the provider
actually charged, floored at `min_micro` and capped at `max_micro`. The image
tools are `per_call`, one flat price with no ceiling to read. The voice tools
are `metered`, an exact rate against the size of your request, with a ceiling
on top. `per_result` is part of the contract but nothing in the catalog uses it
today, so handle it if you parse `price` generically.

<Note>
  On a `cost_plus` or `metered` tool, `max_usd` is a ceiling and the hold Goro
  places is sized from what you request, so it usually sits well below that
  number. On a `per_call` tool there is no ceiling: `base_usd` is what the call
  costs. Every tool's page in the [catalog](/tools/overview) says which it is.
</Note>

## Errors

| Status | `code`             | When                                                           |
| ------ | ------------------ | -------------------------------------------------------------- |
| 400    | `validation_error` | `query` missing or empty, or `limit` is not a positive integer |
| 401    | `unauthorized`     | Missing or invalid API key                                     |

Discovery is free. It places no hold and charges nothing.

<Card title="Then inspect the match" icon="magnifying-glass" href="/api/inspect">
  Read the full input schema before you run it.
</Card>
