Lovely RouterDocs
Get a key
API reference

Tools endpoints

Reference for every /v1/tools endpoint, the tool object and the run object.

The tools API lists, searches and runs data tools. Requests and responses are JSON. The base URL is https://lovelyrouter.com/v1.

Authentication. The catalog endpoints (list, retrieve, search and plan) are public. Running tools and reading runs need an API key in the Authorization: Bearer header. Tool runs are billed from the same prepaid balance as models.

Errors. Failed requests return an error object with a type and a message. See Errors.

Languages. Catalog endpoints take lang (zh or ja) to localize tool names and descriptions, as a query parameter on GET or a body field on POST.

cURL
curl https://lovelyrouter.com/v1/tools/runs \
  -H "Authorization: Bearer $LOVELY_API_KEY"

The tool object#

A tool in the catalog. List and search endpoints return the summary fields. Retrieve a tool adds the input schema, an example input, the time limit and a ready-made run request.

Attributes

idstring

Tool id, used in run paths. For example google-maps-places.

namestring

Display name, localized with lang.

platformstring

The site or source the tool reads, such as Google Maps or TikTok.

categorystring

One of social-media, search, ecommerce, lead-generation, reviews, jobs, travel, web.

descriptionstring

What the tool returns, localized with lang.

priceobject

The live price.

default_resultsinteger

The result cap a run uses when you don't set max_results.

max_resultsinteger

The highest result cap a run of this tool accepts.

featuredboolean

Whether the tool is highlighted as popular on the tools page.

input_schemaobject

JSON Schema for a run's input. Retrieve only.

example_inputobject

An input that works as is. Retrieve only.

timeout_sinteger

The run's time limit in seconds. A run that exceeds it ends as timed_out. Retrieve only.

runobject

A ready-made run request: method, path and a body with the example input and default cap. Retrieve only.

The tool object
{
  "id": "google-maps-places",
  "name": "Search Google Maps places",
  "platform": "Google Maps",
  "category": "search",
  "description": "Find local businesses on Google Maps by keyword and location: name, address, phone, website, rating, review count, opening hours, coordinates.",
  "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,
  "featured": true
}

List tools#

GET/v1/tools

Returns every available tool. No key needed.

Query parameters

categorystring

Only tools in this category, such as reviews.

qstring

Keywords. Returns matching tools ranked by relevance, up to 100.

langstringDefault en

zh or ja to localize names and descriptions.

Returns a list object with the tools in data.

curl "https://lovelyrouter.com/v1/tools?category=reviews"
Response
{
  "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
    }
  ]
}

Retrieve a tool#

GET/v1/tools/{id}

Returns one tool with its input_schema, example_input, timeout_s and a ready-made run request. No key needed. Returns 404 for an unknown id.

Path parameters

idstringRequired

The tool id.

Query parameters

langstringDefault en

zh or ja to localize the name and description. Input schemas stay in English.

cURL
curl https://lovelyrouter.com/v1/tools/trustpilot-reviews
Response
{
  "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)",
        "default": 0,
        "minimum": 0
      }
    },
    "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
    }
  }
}

Search tools#

POST/v1/tools/discover

Keyword search over the catalog. Returns the best matches, each with a relevance score. No key needed.

Body parameters

querystringRequired

What you need, in a few words. For example tiktok comments. The first 1,000 characters are used.

limitintegerDefault 5

Number of results, from 1 to 40.

langstringDefault en

zh or ja to localize names and descriptions.

Returns query, count and results: tool objects with a score. Scores only compare tools within one query. A body without query returns 400.

cURL
curl https://lovelyrouter.com/v1/tools/discover \
  -H "content-type: application/json" \
  -d '{"query": "google maps reviews", "limit": 2}'
Response
{
  "query": "google maps reviews",
  "count": 2,
  "results": [
    {
      "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,
      "score": 0.889
    },
    {
      "id": "google-maps-places",
      "name": "Search Google Maps places",
      "platform": "Google Maps",
      "category": "search",
      "description": "Find local businesses on Google Maps by keyword and location: name, address, phone, website, rating, review count, opening hours, coordinates.",
      "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,
      "featured": true,
      "score": 0.717
    }
  ]
}

Plan a task#

POST/v1/tools/suggest

Describe a task in plain words and get an ordered plan: the tool to run first, an optional second tool and close alternatives, each with an example input and an estimated cost. Free, with a rate limit of 100 requests per minute per API key. Callers without a key share one pool of 100 requests per minute. Over the limit, the endpoint returns 429 with a retry-after header.

Body parameters

taskstringRequired

The task, up to 2,000 characters. Longer tasks return 413.

limitintegerDefault 5

Most suggestions to return, from 1 to 8.

langstringDefault en

zh or ja to localize names and descriptions.

Returns

taskstring

The task you sent.

sourcestring

ai for a plan from the planner, keyword for keyword matches when the planner is unavailable.

cachedboolean

Whether the plan came from a cache of identical tasks (kept for a day).

countinteger

Number of suggestions. 0 when no tool fits the task.

suggestionsarray

The plan, in order. Each entry is a tool object plus:

total_est_cost_usdnumber

Sum of the primary and next steps. Alternatives are not included.

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"}'
Response
{
  "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",
      "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" },
      "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",
      "platform": "Google Maps",
      "category": "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
}

The run object#

A run of a tool. Returned by run, retrieve, stop and list.

Attributes

idstring

Run id: run_ followed by 24 characters.

objectstring

Always tool_run.

toolstring

The tool id.

tool_namestring

The tool's display name.

statusstring

running, succeeded, failed, timed_out (hit the tool's time limit) or stopped (stopped by you).

inputobject or null

The input the run used: field names from a tool's earlier versions mapped to the current ones, and the tool's limit field filled in from the result cap (split across the searches for tools whose limit counts per search). Use it to match runs to your queries, for example after a dropped connection. null for some runs made before October 20, 2026.

resultsinteger

Results returned and billed. 0 until the run finishes.

max_resultsinteger

The result cap that applies to this run. It can differ from what you asked for: it is lowered to the tool's maximum, or raised to a tool's minimum run size.

charge_usdnumber or null

What the run cost. null until the run is settled.

reserved_usdnumber

The amount held from your balance while the run is unsettled. 0 once it is settled.

errorstring or null

Why the run ended early. null for running and succeeded runs.

created_atstring

When the run started, ISO 8601.

finished_atstring or null

When the run ended, ISO 8601. null while it is running.

pollstring

Path to poll for the result. Only in 202 responses.

itemsarray or null

The results, in the tool's own format. Only when the run has finished, and not in list. null if results are briefly unavailable; see items_error.

offsetinteger

Index of the first result in items. Only when the run has results.

next_offsetinteger or null

Offset of the next page of results, or null on the last page.

items_errorstring

Present only when items is null. Request the run again to load the results.

The run object
{
  "id": "run_8c1f0e2a9b7d4f3e6a5c2b1d",
  "object": "tool_run",
  "tool": "google-maps-places",
  "tool_name": "Search Google Maps places",
  "status": "succeeded",
  "input": {
    "searchTerms": ["coffee shop"],
    "location": "Austin, Texas, USA",
    "maxResults": 20,
    "language": "en",
    "radius": 20
  },
  "results": 20,
  "max_results": 20,
  "charge_usd": 0.00551,
  "reserved_usd": 0,
  "error": null,
  "created_at": "2026-10-11T15:02:11.204Z",
  "finished_at": "2026-10-11T15:02:38.917Z",
  "items": [
    {
      "title": "Godsent Coffee",
      "categoryName": "Coffee shop",
      "address": "9817 Anderson Mill Rd, Austin, TX 78750",
      "totalScore": 5,
      "reviewsCount": 237,
      "placeId": "ChIJq7RZDGczW4YRyCS5Z0KiiDE"
    }
  ],
  "offset": 0,
  "next_offset": null
}

Run a tool#

POST/v1/tools/{id}/run

Starts a run and waits up to wait seconds for it. The run's maximum cost (per-call fee plus per-result fee times the cap) is held from your balance and settled when it ends. Needs an API key.

Returns 200 with the finished run object and its items, or 202 with the running run and a poll path. A 200 can carry a run that failed or timed_out: check status. Any error status means the run didn't start and nothing was charged.

You can also send the tool id in the body: POST /v1/tools/run with "tool": "google-maps-places".

Running browser-agent returns 202 and a browser run instead, with max_results as the maximum number of steps. See Browser agent.

Path parameters

idstringRequired

The tool id.

Body parameters

inputobjectDefault {}

The tool's input, matching its input_schema. Fields in input_schema.required must be set. Up to 50,000 characters as JSON.

max_resultsinteger

Most results to return and bill, up to the tool's max_results. Defaults to the tool's default_results, or for tools that take a list of entries with one result each, to the list's length.

waitintegerDefault 60

Seconds to wait for the run to finish, from 0 to 300. Also accepted as a ?wait= query parameter.

curl https://lovelyrouter.com/v1/tools/google-maps-places/run \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "input": {"searchTerms": ["coffee shop"], "location": "Austin, Texas, USA"},
    "max_results": 20
  }'
Response (202)
{
  "id": "run_8c1f0e2a9b7d4f3e6a5c2b1d",
  "object": "tool_run",
  "tool": "google-maps-places",
  "tool_name": "Search Google Maps places",
  "status": "running",
  "results": 0,
  "max_results": 20,
  "charge_usd": null,
  "reserved_usd": 0.00551,
  "error": null,
  "created_at": "2026-10-11T15:02:11.204Z",
  "finished_at": null,
  "poll": "/v1/tools/runs/run_8c1f0e2a9b7d4f3e6a5c2b1d?wait=60"
}

Retrieve a run#

GET/v1/tools/runs/{run_id}

Returns a run, optionally waiting for it to finish. Polling a finished run settles it if it hasn't been settled yet. Returns 202 while the run is going and 200 once it has finished, with its results in items. Runs belonging to another account return 404.

For a browser-agent run, this returns the browser run. See Browser agent.

Path parameters

run_idstringRequired

The run id.

Query parameters

waitintegerDefault 0

Seconds to wait for a running run to finish, from 0 to 300.

offsetintegerDefault 0

Index of the first result to return.

limitinteger

Number of results to return, from 1 to the run's max_results, which is also the default.

cURL
curl "https://lovelyrouter.com/v1/tools/runs/run_8c1f0e2a9b7d4f3e6a5c2b1d?wait=60&offset=0&limit=50" \
  -H "Authorization: Bearer $LOVELY_API_KEY"
Response
{
  "id": "run_8c1f0e2a9b7d4f3e6a5c2b1d",
  "object": "tool_run",
  "tool": "google-maps-places",
  "tool_name": "Search Google Maps places",
  "status": "succeeded",
  "results": 20,
  "max_results": 20,
  "charge_usd": 0.00551,
  "reserved_usd": 0,
  "error": null,
  "created_at": "2026-10-11T15:02:11.204Z",
  "finished_at": "2026-10-11T15:02:38.917Z",
  "items": [
    { "title": "Godsent Coffee", "totalScore": 5, "reviewsCount": 237, "placeId": "ChIJq7RZDGczW4YRyCS5Z0KiiDE" }
  ],
  "offset": 0,
  "next_offset": null
}

Stop a run#

POST/v1/tools/runs/{run_id}/stop

Stops a running run. It ends as stopped, and you pay the per-result fee for results delivered before it stopped, with no per-call fee. Returns the settled run with those results, or 202 if it is still winding down after about 10 seconds. Stopping a finished run returns it unchanged.

Path parameters

run_idstringRequired

The run id.

cURL
curl -X POST https://lovelyrouter.com/v1/tools/runs/run_8c1f0e2a9b7d4f3e6a5c2b1d/stop \
  -H "Authorization: Bearer $LOVELY_API_KEY"
Response
{
  "id": "run_8c1f0e2a9b7d4f3e6a5c2b1d",
  "object": "tool_run",
  "tool": "google-maps-places",
  "tool_name": "Search Google Maps places",
  "status": "stopped",
  "results": 4,
  "max_results": 20,
  "charge_usd": 0.018,
  "reserved_usd": 0,
  "error": "The run was stopped. You are billed only for results delivered before it stopped.",
  "created_at": "2026-10-11T15:02:11.204Z",
  "finished_at": "2026-10-11T15:02:19.630Z",
  "items": [
    { "title": "Godsent Coffee", "totalScore": 5, "reviewsCount": 237, "placeId": "ChIJq7RZDGczW4YRyCS5Z0KiiDE" }
  ],
  "offset": 0,
  "next_offset": null
}

List runs#

GET/v1/tools/runs

Returns your account's runs, newest first, without their items. Includes runs started with any of your keys.

Query parameters

limitintegerDefault 20

Number of runs, from 1 to 100.

beforeinteger

Cursor: the next value from the previous page.

Returns a list object with run objects in data, and next: the cursor for the next page, or null when there are no more runs.

cURL
curl "https://lovelyrouter.com/v1/tools/runs?limit=2" \
  -H "Authorization: Bearer $LOVELY_API_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "run_8c1f0e2a9b7d4f3e6a5c2b1d",
      "object": "tool_run",
      "tool": "google-maps-places",
      "tool_name": "Search Google Maps places",
      "status": "succeeded",
      "results": 20,
      "max_results": 20,
      "charge_usd": 0.00551,
      "reserved_usd": 0,
      "error": null,
      "created_at": "2026-10-11T15:02:11.204Z",
      "finished_at": "2026-10-11T15:02:38.917Z"
    },
    {
      "id": "run_51d0b9e4c3a2f1e0d9c8b7a6",
      "object": "tool_run",
      "tool": "trustpilot-reviews",
      "tool_name": "Trustpilot reviews",
      "status": "succeeded",
      "results": 20,
      "max_results": 20,
      "charge_usd": 0.0375,
      "reserved_usd": 0,
      "error": null,
      "created_at": "2026-10-11T14:48:03.512Z",
      "finished_at": "2026-10-11T14:48:21.077Z"
    }
  ],
  "next": 1791730083512
}

Errors#

Every error has the same shape. type is stable and safe to branch on. message is for people and can change.

StatustypeCause
400invalid_request_errorBody isn't JSON, input isn't an object, a required input field is missing, the tool rejected the input, or query / task is missing
401authentication_errorMissing, invalid, revoked or expired API key
402insufficient_quotaBalance or the key's spend limit can't cover the run's hold
404not_foundUnknown tool id, or no run with that id on your account
413invalid_request_errorinput over 50,000 characters, or task over 2,000
429rate_limit_exceeded10 runs already in progress on your account, or the planner rate limit
500api_errorUnexpected error. Retry.
502tool_unavailableThe tool could not start. You were not charged. Retry shortly.

A run request that returns an error is not charged. See Errors for the API as a whole.

Error
{
  "error": {
    "type": "invalid_request_error",
    "message": "Missing required input: companyUrls. See GET /v1/tools/trustpilot-reviews."
  }
}