---
title: Find the right tool
description: Browse the catalog, search it by keyword, describe a task to get an ordered plan with costs, and read a tool's input schema before you run it.
---

The catalog endpoints are public and free. You can call them without a key, and agents can call them as often as they need to pick the right tool. Four endpoints cover the search:

| You want to | Call |
| --- | --- |
| See every tool, or one category | [`GET /v1/tools`](#browse-the-catalog) |
| Find tools for a short query like "tiktok comments" | [`POST /v1/tools/discover`](#search-by-keyword) |
| Describe a whole task and get a plan with costs | [`POST /v1/tools/suggest`](#plan-a-task) |
| Read one tool's input schema, example and price | [`GET /v1/tools/{id}`](#inspect-a-tool) |

## Browse the catalog

`GET /v1/tools` returns every available tool with its price. Narrow the list with query parameters:

- `category`: one category id, such as `reviews` or `lead-generation`. See [categories](/docs/tools#categories).
- `q`: keywords. Results are ranked by relevance, up to 100.
- `lang`: `zh` or `ja` to localize tool names and descriptions. The default is English.

```bash title="cURL"
curl "https://lovelyrouter.com/v1/tools?category=reviews"
```

The response is a list of tool objects (trimmed to one here):

```json
{
  "object": "list",
  "data": [
    {
      "id": "google-maps-reviews",
      "name": "Google Maps reviews",
      "platform": "Google Maps",
      "category": "reviews",
      "description": "Reviews of a Google Maps place (by place ID or URL): text, stars, date, owner replies.",
      "price": {
        "per_call_usd": 0,
        "per_result_usd": 0.000675,
        "unit": "review",
        "label": "$0.000675 / review"
      },
      "default_results": 20,
      "max_results": 500,
      "featured": false
    }
  ]
}
```

The `price` object is the live price. `default_results` is the result cap a run uses when you don't set `max_results`, and `max_results` is the highest cap the tool accepts. Every field is described in [the tool object](/docs/api/tools#the-tool-object).

## Search by keyword

`POST /v1/tools/discover` takes a short query and returns the best matches with a relevance `score`. Platform and tool names weigh more than descriptions, so a query that names a platform ranks that platform's tools first.

```bash title="cURL"
curl https://lovelyrouter.com/v1/tools/discover \
  -H "content-type: application/json" \
  -d '{"query": "google maps reviews", "limit": 3}'
```

```json
{
  "query": "google maps reviews",
  "count": 3,
  "results": [
    {
      "id": "google-maps-reviews",
      "name": "Google Maps reviews",
      "platform": "Google Maps",
      "category": "reviews",
      "price": { "per_call_usd": 0, "per_result_usd": 0.000675, "unit": "review", "label": "$0.000675 / review" },
      "default_results": 20,
      "max_results": 500,
      "score": 0.889
    },
    {
      "id": "google-maps-places",
      "name": "Search Google Maps places",
      "platform": "Google Maps",
      "category": "search",
      "price": { "per_call_usd": 0.00075, "per_result_usd": 0.000238, "unit": "place", "label": "$0.000238 / place + $0.00075 / call" },
      "default_results": 10,
      "max_results": 200,
      "score": 0.717
    },
    {
      "id": "google-maps-leads",
      "name": "Google Maps leads with emails",
      "platform": "Google Maps",
      "category": "lead-generation",
      "price": { "per_call_usd": 0, "per_result_usd": 0.00075, "unit": "place", "label": "$0.00075 / place" },
      "default_results": 10,
      "max_results": 200,
      "score": 0.556
    }
  ]
}
```

`limit` defaults to 5 and goes up to 40. Use `score` to order results, not as an absolute measure: it only compares tools for the same query.

## Plan a task

When a task needs more than one tool, or you don't know which one fits, describe it in plain words. `POST /v1/tools/suggest` returns an ordered plan in under a second: the tool to run first, an optional second tool, and close alternatives, each with an example input and an estimated cost.

```bash title="cURL"
curl https://lovelyrouter.com/v1/tools/suggest \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{"task": "Find vegan restaurants in Austin and summarize what their reviews complain about"}'
```

The response, trimmed:

```json
{
  "task": "Find vegan restaurants in Austin and summarize what their reviews complain about",
  "source": "ai",
  "cached": false,
  "count": 2,
  "suggestions": [
    {
      "step": 1,
      "role": "primary",
      "match": 0.961,
      "id": "google-maps-places",
      "name": "Search Google Maps places",
      "price": { "per_call_usd": 0.00075, "per_result_usd": 0.000238, "unit": "place", "label": "$0.000238 / place + $0.00075 / call" },
      "input": {
        "searchTerms": ["coffee shop"],
        "location": "Austin, Texas, USA",
        "maxResults": 3,
        "language": "en"
      },
      "input_required": [],
      "max_results": 10,
      "est_cost_usd": 0.00313,
      "run": {
        "method": "POST",
        "path": "/v1/tools/google-maps-places/run",
        "body": { "input": { "searchTerms": ["coffee shop"], "location": "Austin, Texas, USA", "maxResults": 3, "language": "en" }, "max_results": 10 }
      }
    },
    {
      "step": 2,
      "role": "next",
      "match": 0.875,
      "id": "google-maps-reviews",
      "name": "Google Maps reviews",
      "price": { "per_call_usd": 0, "per_result_usd": 0.000675, "unit": "review", "label": "$0.000675 / review" },
      "input": { "placeIds": ["ChIJN1t_tDeuEmsRUsoyG83frY4"], "maxReviews": 3, "reviewsSort": "newest" },
      "input_required": [],
      "max_results": 20,
      "est_cost_usd": 0.0135,
      "run": {
        "method": "POST",
        "path": "/v1/tools/google-maps-reviews/run",
        "body": { "input": { "placeIds": ["ChIJN1t_tDeuEmsRUsoyG83frY4"], "maxReviews": 3, "reviewsSort": "newest" }, "max_results": 20 }
      }
    }
  ],
  "total_est_cost_usd": 0.01663
}
```

### Read the plan

- **`role`** says how a step fits: `primary` is the tool to run first, `next` gets a second kind of data the task asks for (here, reviews of the places found in step 1), and `alternative` is a close runner-up you could use instead of the primary.
- **`match`** is the planner's confidence in that step, from 0 to 1.
- **`input` is the tool's example input, not one written for your task.** Replace its values with yours: above, `"coffee shop"` becomes `"vegan restaurant"`. `input_required` lists the fields you must set. For the full schema, call [`GET /v1/tools/{id}`](#inspect-a-tool).
- **`est_cost_usd`** is the most the step costs at the `max_results` shown, which is the tool's default cap. Change `max_results` and the cost scales with it.
- **`total_est_cost_usd`** adds up the `primary` and `next` steps. Alternatives are not included because you run them instead, not as well.
- **`run`** is a ready-made request for [Run a tool](/docs/tools/run): send `body` to `path` once you've filled in the input.

An empty `suggestions` list means no tool in the catalog fits the task, for example "write a poem". If the planner is unavailable, the endpoint falls back to keyword matches and sets `source` to `keyword`. Identical tasks are answered from a cache for a day, with `cached: true`.

### Options and limits

The body takes `task` (required, up to 2,000 characters), `limit` (number of suggestions, 1 to 8, default 5) and `lang` (`zh` or `ja`).

Planning is free, with a rate limit:

| Caller | Limit |
| --- | --- |
| With an API key | 100 requests per minute per key |
| Without a key | 100 requests per minute, shared by every anonymous caller |

Over the limit, the endpoint returns `429` with a `retry-after` header in seconds. Send your key for a limit of your own.

## Inspect a tool

Before you run a tool, read its input schema. `GET /v1/tools/{id}` returns the tool object plus `input_schema` (JSON Schema for `input`), an `example_input` that works as is, the run's time limit in `timeout_s`, and a ready-made `run` request.

```bash title="cURL"
curl https://lovelyrouter.com/v1/tools/trustpilot-reviews
```

The response, trimmed:

```json
{
  "id": "trustpilot-reviews",
  "name": "Trustpilot reviews",
  "platform": "Trustpilot",
  "category": "reviews",
  "description": "Trustpilot reviews of a company by domain: stars, text, date, reply.",
  "price": {
    "per_call_usd": 0.0075,
    "per_result_usd": 0.0015,
    "unit": "review",
    "label": "$0.0015 / review + $0.0075 / call"
  },
  "default_results": 20,
  "max_results": 500,
  "featured": false,
  "input_schema": {
    "type": "object",
    "properties": {
      "companyUrls": {
        "type": "array",
        "title": "Company URLs or Domains",
        "description": "Enter Trustpilot company URLs (e.g., https://www.trustpilot.com/review/example.com) or just the domain (e.g., example.com). One per line."
      },
      "maxReviewsPerCompany": {
        "type": "integer",
        "title": "Max reviews per company (reviews)",
        "description": "Maximum number of reviews to scrape per company. Set to 0 for unlimited reviews.",
        "default": 0,
        "minimum": 0
      },
      "sort": {
        "type": "string",
        "title": "Sort Order",
        "enum": ["relevance", "recency"],
        "default": "recency"
      }
    },
    "required": ["companyUrls"]
  },
  "example_input": {
    "companyUrls": ["pipedrive.com"],
    "maxReviewsPerCompany": 20
  },
  "timeout_s": 300,
  "run": {
    "method": "POST",
    "path": "/v1/tools/trustpilot-reviews/run",
    "body": { "input": { "companyUrls": ["pipedrive.com"], "maxReviewsPerCompany": 20 }, "max_results": 20 }
  }
}
```

Field names and their meaning differ from tool to tool, so always build `input` from `input_schema`. You don't need to set the tool's own count field (here `maxReviewsPerCompany`) to control cost: `max_results` caps the run either way. The [tools page](/tools) shows the same schema for every tool, and you can try a tool there once you're signed in.

An unknown or retired tool id returns `404`.

## Localize names and descriptions

Add `lang=zh` or `lang=ja` to any catalog request, as a query parameter on `GET` or as `"lang"` in a `POST` body. Tool names and descriptions come back translated. Ids, prices and input schemas stay the same.

```bash title="cURL"
curl "https://lovelyrouter.com/v1/tools/google-maps-reviews?lang=ja"
```

## Next steps

:::cards
- :tool: [Run a tool](/docs/tools/run) Start a run with the input you just built.
- :plug: [MCP server](/docs/tools/mcp) Let your agent search, plan and run on its own.
:::
