1ToolRing Docs Get a key
View as markdown
reference/tools

Base path: https://api.1toolring.com/api/v1/tools

Auth: Authorization: Bearer <key> (or x-api-key: <key>). Discover, inspect and the runs list also accept a dashboard session JWT, so the console can browse the catalog. Price: per call, in credits (1 credit = Rp1), shown on every tool before you run it. Discover, inspect and run status are free.

The tool catalog holds thousands of third-party tools across SERP, web scraping, people and company enrichment, social, ecommerce, maps and SEO. It is searched live, so this page documents the routes and the pricing model rather than listing every tool.

The flow: discover, inspect, run

  1. Discover. Describe the job in plain words. You get tool ids, a short description and the price.
  2. Inspect. Read one tool’s input_schema and its exact price model before you spend anything.
  3. Run. Send the input. Credits are held up front, the call runs, and the hold settles to the real cost. A slow tool answers 202 with a run_id you poll.

The same flow is available to agents as MCP tools (discover_tools, inspect_tool, run_tool, get_tool_run). See MCP.

Endpoints

MethodPathPriceDescription
POST/discoverfreeSearch the catalog by job. Body {query, limit?} (limit 1 to 20, default 10).
POST/inspectfreeOne tool’s detail: input_schema, price, notes, health. Body {tool} or {provider, endpoint}.
POST/runper the tool’s priceRun a tool. Body {tool, input}. 200 when it finishes in time, 202 while it runs.
GET/runs/{run_id}freeStatus and result of one of your runs. Refreshes a running run before answering.
GET/runsfreeYour runs, newest first. limit and cursor query parameters.

Discover

curl -X POST https://api.1toolring.com/api/v1/tools/discover \
  -H "Authorization: Bearer $TOOLRING_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"google search results for a keyword","limit":3}'
{
  "data": {
    "query": "google search results for a keyword",
    "count": 3,
    "results": [
      {
        "id": "dataforseo/serp/google-organic",
        "provider": "dataforseo",
        "provider_name": "DataForSEO",
        "endpoint": "/serp/google-organic",
        "description": "Live Google organic results for a keyword, location and language.",
        "price": { "model": "per_call", "credits": 60, "usd": 0.0033 }
      }
    ]
  }
}

Values in the examples on this page are illustrative. Read the real price from discover or inspect.

Inspect

curl -X POST https://api.1toolring.com/api/v1/tools/inspect \
  -H "Authorization: Bearer $TOOLRING_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool":"dataforseo/serp/google-organic"}'
{
  "data": {
    "id": "dataforseo/serp/google-organic",
    "provider": "dataforseo",
    "provider_name": "DataForSEO",
    "endpoint": "/serp/google-organic",
    "description": "Live Google organic results for a keyword, location and language.",
    "summary": "Top organic results with title, URL, snippet and rank.",
    "method": "POST",
    "price": { "model": "per_call", "credits": 60, "usd": 0.0033 },
    "input_schema": {
      "body": {
        "type": "object",
        "required": ["keyword"],
        "properties": {
          "keyword": { "type": "string" },
          "location_code": { "type": "integer" },
          "language_code": { "type": "string" }
        }
      }
    },
    "notes": [],
    "categories": ["serp", "seo"],
    "tags": ["google", "search"],
    "doc_url": "https://docs.dataforseo.com/",
    "health": { "status": "ok", "p50_ms": 2100, "p95_ms": 5400 }
  }
}

input_schema has up to three parts, each a JSON Schema: body (the JSON body), queryParams and pathParams. Send only the parts the schema declares.

Run

curl -X POST https://api.1toolring.com/api/v1/tools/run \
  -H "Authorization: Bearer $TOOLRING_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool":"dataforseo/serp/google-organic","input":{"body":{"keyword":"kopi pontianak","language_code":"id"}}}'

A run that finishes in time answers 200:

{
  "data": {
    "run_id": "run_01JC8Q4Z6N4M2V9W3X7Y5T1R0P",
    "tool": "dataforseo/serp/google-organic",
    "status": "completed",
    "output": { "items": [ { "rank": 1, "title": "...", "url": "..." } ] },
    "provider_status": 200,
    "credits_charged": 60,
    "credits_held": 0,
    "created_at": "2026-11-02T09:00:00Z",
    "completed_at": "2026-11-02T09:00:03Z"
  }
}

output is the tool’s answer, passed through as is. The X-ToolRing-Credits header on a finished run is the number of credits actually charged.

RunResult fields

FieldTypeDescription
run_idstringYour run id, e.g. run_<ulid>.
toolstringThe tool id that ran.
statusstringrunning, completed or failed.
outputanyThe tool’s answer, verbatim.
provider_statusintegerThe HTTP status the tool’s provider returned.
provider_errorstringShort reason when the provider failed.
credits_chargedintegerCredits actually charged (0 while running and on failure).
credits_heldintegerCredits held while the run is in flight.
created_at, completed_atstringISO 8601 timestamps.

Async runs and polling

Scrapers and bulk enrichment can take longer than one request. Then /run answers 202 with status: "running" and the hold still in place:

{
  "data": {
    "run_id": "run_01JC8Q7B2K9D4F6H8J0L2N4P6R",
    "tool": "apify/google-maps-scraper",
    "status": "running",
    "credits_held": 9000,
    "created_at": "2026-11-02T09:05:00Z"
  }
}

Poll until status is completed or failed:

curl https://api.1toolring.com/api/v1/tools/runs/run_01JC8Q7B2K9D4F6H8J0L2N4P6R \
  -H "Authorization: Bearer $TOOLRING_KEY"

Every 3 to 5 seconds is a sensible interval. Polling is free. The hold settles when the run finishes, whether you poll or not: a background job also checks running runs. Only runs made by your own account are visible.

Pricing model

Every tool carries a price object:

FieldDescription
modelper_call, per_result, per_unit, tiered or free.
creditsPrice per call, result or unit, in credits (1 credit = Rp1). Any non-free unit costs at least 1 credit.
usdThe same price in US dollars, for reference.
unit_labelWhat one unit is, for per_unit tools (for example 1,000 characters).
flat_creditsA fixed fee on top of the unit price, when the tool has one.
notesExtra pricing detail, such as tier boundaries.

How a run is billed:

  • Hold, then settle. Before the call, 1ToolRing holds the most the run can cost. per_call holds the price. per_result, per_unit and tiered hold an estimate from your input (fields such as limit, maxItems, max_results, depth or num). When the run finishes, the hold settles to the real cost and the rest is released.
  • Failed calls cost 0. A provider error or a failed run releases the whole hold. You are charged nothing.
  • Run cap. A single run has a spending cap. If the estimate is above it, the run is refused with 400 RUN_TOO_LARGE before anything is held. Lower the result count or split the job.
  • Balance check. If your balance is below the hold, the run is refused with 402 INSUFFICIENT_CREDITS and nothing runs.

Credits come from the same prepaid wallet as every other 1ToolRing call. See Rate limits and credits and pricing.

Errors

Envelope: {"error":{"code","message"}}.

StatusCodeMeaning
400VALIDATION_ERRORThe body is malformed or input does not match the tool.
400RUN_TOO_LARGEThe estimated cost is above the per-run cap. Nothing was held.
401UNAUTHORIZEDMissing or invalid key.
402INSUFFICIENT_CREDITSThe wallet cannot cover the hold. Carries balance, needed and topup_url.
403TOOL_BLOCKEDThis tool is not offered through 1ToolRing. Pick another from discover.
404TOOL_NOT_FOUNDUnknown tool id.
404NOT_FOUNDUnknown run, or the tool catalog is not enabled on this host.
429RATE_LIMITEDToo many requests. Retry after a short wait.
502UPSTREAM_ERRORThe tool network could not be reached. Nothing was charged.
503TOOLS_UNAVAILABLEThird-party tools are temporarily unavailable. Nothing was charged.
{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Credit balance is too low for this run.",
    "balance": 40,
    "needed": 60,
    "topup_url": "https://app.1toolring.com/billing"
  }
}

A provider failure inside a run is not an HTTP error: the run comes back with status: "failed", provider_status, a short provider_error and credits_charged: 0.