Prefer not to write code? Install the Nimble plugin and describe what you need in plain language. Onboard your Agent has the one-command setup for every coding agent.
Get your API key
Sign up and copy your key from Settings → API Keys. Then set it as an environment variable:Every SDK and the CLI read
export NIMBLE_API_KEY="your-api-key"
$env:NIMBLE_API_KEY="your-api-key"
NIMBLE_API_KEY automatically.Install a client
Requires Python 3.9+, Node.js 20 LTS+, or Go 1.22+.Full client docs: Python, Node, Go, and CLI. Python also offers an aiohttp extra:
pip install nimble_python
npm install @nimble-way/nimble-js
go get github.com/Nimbleway/nimble-go@latest
npm install -g @nimble-way/nimble-cli
pip install "nimble_python[aiohttp]".Calling the API over plain HTTP? Skip this step and see the API Reference.NIMBLE_API_KEY. The first Search example is a complete program; the rest are abbreviated and assume you have already created a client the same way.
Search
Real-time web search with structured results:import os
from nimble_python import Nimble
nimble = Nimble(api_key=os.environ["NIMBLE_API_KEY"])
result = nimble.search(
query="latest developments in AI agents",
max_results=5
)
for r in result.results:
print(f"- {r.title}: {r.url}")
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
const result = await nimble.search({
query: "latest developments in AI agents",
max_results: 5,
});
result.results.forEach((r) => {
console.log(`- ${r.title}: ${r.url}`);
});
package main
import (
"context"
"fmt"
"os"
nimble "github.com/Nimbleway/nimble-go"
"github.com/Nimbleway/nimble-go/option"
"github.com/Nimbleway/nimble-go/packages/param"
)
func main() {
client := nimble.NewClient(option.WithAPIKey(os.Getenv("NIMBLE_API_KEY")))
result, err := client.Search(context.Background(), nimble.SearchParams{
Query: "latest developments in AI agents",
MaxResults: param.NewOpt(int64(5)),
})
if err != nil {
panic(err)
}
for _, r := range result.Results {
fmt.Printf("- %s: %s\n", r.Title, r.URL)
}
}
nimble search \
--query "latest developments in AI agents" \
--max-results 5
curl -X POST 'https://sdk.nimbleway.com/v2/search' \
--header "Authorization: Bearer $NIMBLE_API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"query": "latest developments in AI agents",
"max_results": 5
}'
Extract
Get clean HTML and structured data from any URL:import os
from nimble_python import Nimble
nimble = Nimble(api_key=os.environ["NIMBLE_API_KEY"])
result = nimble.extract.run(
url="https://www.example.com",
render=True,
formats=["html", "markdown"]
)
print(result.data.html)
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
const result = await nimble.extract.run({
url: "https://www.example.com",
render: true,
formats: ["html", "markdown"],
});
console.log(result.data?.html);
result, err := client.Extract.Run(ctx, nimble.ExtractRunParams{
URL: "https://www.example.com",
Render: nimble.ExtractRunParamsRenderUnion{OfBool: param.NewOpt(true)},
Formats: []string{"html", "markdown"},
})
if err != nil {
panic(err)
}
fmt.Println(result.Data.HTML)
nimble extract run \
--url "https://www.example.com" \
--render true \
--format html --format markdown
curl -X POST 'https://sdk.nimbleway.com/v2/extract' \
--header "Authorization: Bearer $NIMBLE_API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"render": true,
"formats": ["html", "markdown"]
}'
Extract Template
Run pre-built Extract Templates for popular sites, or create one for any website:import os
from nimble_python import Nimble
nimble = Nimble(api_key=os.environ["NIMBLE_API_KEY"])
result = nimble.extract.templates.run(
template="amazon_pdp",
params={
"asin": "B08N5WRWNW"
}
)
parsed = result.data.parsing
print(f"Product: {parsed['product_title']}")
print(f"Price: ${parsed['web_price']}")
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
const result = await nimble.extract.templates.run({
template: "amazon_pdp",
params: {
asin: "B08N5WRWNW",
},
});
const parsed = result.data?.parsing as Record<string, any>;
console.log(`Product: ${parsed.product_title}`);
console.log(`Price: $${parsed.web_price}`);
result, err := client.Extract.Templates.Run(ctx, nimble.ExtractTemplateRunParams{
Template: "amazon_pdp",
Params: map[string]any{
"asin": "B08N5WRWNW",
},
})
if err != nil {
panic(err)
}
fmt.Println(result.Data.Parsing)
nimble extract:templates run \
--template amazon_pdp \
--params '{asin: B08N5WRWNW}'
curl -X POST 'https://sdk.nimbleway.com/v2/extract/templates/run' \
--header "Authorization: Bearer $NIMBLE_API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"template": "amazon_pdp",
"params": {
"asin": "B08N5WRWNW"
}
}'
Map
Fast URL discovery and site structure mapping:import os
from nimble_python import Nimble
nimble = Nimble(api_key=os.environ["NIMBLE_API_KEY"])
result = nimble.map(
url="https://www.example.com",
sitemap="include"
)
for link in result.links:
print(f"{link.title}: {link.url}")
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
const result = await nimble.map({
url: "https://www.example.com",
sitemap: "include",
});
result.links.forEach((link) => {
console.log(`${link.title}: ${link.url}`);
});
result, err := client.Map(ctx, nimble.MapParams{
URL: "https://www.example.com",
Sitemap: nimble.MapParamsSitemapInclude,
})
if err != nil {
panic(err)
}
for _, link := range result.Links {
fmt.Printf("%s: %s\n", link.Title, link.URL)
}
nimble map \
--url "https://www.example.com" \
--sitemap include
curl -X POST 'https://sdk.nimbleway.com/v2/map' \
--header "Authorization: Bearer $NIMBLE_API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://www.example.com",
"sitemap": "include"
}'
Crawl
Extract content from entire websites:import os
from nimble_python import Nimble
nimble = Nimble(api_key=os.environ["NIMBLE_API_KEY"])
result = nimble.crawl.run(
url="https://docs.example.com",
limit=10
)
print(f"Crawl started: {result.crawl_id}")
print(f"Status: {result.status}")
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
const result = await nimble.crawl.run({
url: "https://docs.example.com",
limit: 10,
});
console.log(`Crawl started: ${result.crawl_id}`);
console.log(`Status: ${result.status}`);
result, err := client.Crawl.Run(ctx, nimble.CrawlRunParams{
URL: "https://docs.example.com",
Limit: param.NewOpt(int64(10)),
})
if err != nil {
panic(err)
}
fmt.Println("Crawl started:", result.CrawlID)
fmt.Println("Status:", result.Status)
nimble crawl run \
--url "https://docs.example.com" \
--limit 10
curl -X POST 'https://sdk.nimbleway.com/v2/crawl' \
--header "Authorization: Bearer $NIMBLE_API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://docs.example.com",
"limit": 10
}'
Agent
Ask a research question, get a cited answer. See the full flow in the Agent quickstart:import os, time
from nimble_python import Nimble
nimble = Nimble(api_key=os.environ["NIMBLE_API_KEY"])
run = nimble.agents.run(
input="Compare the pricing of Datadog, Grafana Cloud, and New Relic.",
)
agent_id = run.web_search_agent_id
while run.is_active:
time.sleep(10)
run = nimble.agents.runs.get(run.id, agent_id=agent_id)
result = nimble.agents.runs.result(run.id, agent_id=agent_id)
print(result.output.content)
import Nimble from "@nimble-way/nimble-js";
const nimble = new Nimble({ apiKey: process.env.NIMBLE_API_KEY });
let run = await nimble.agents.run({
input: "Compare the pricing of Datadog, Grafana Cloud, and New Relic.",
});
const agentId = run.web_search_agent_id;
while (run.is_active) {
await new Promise((r) => setTimeout(r, 10000));
run = await nimble.agents.runs.get(run.id, { agent_id: agentId });
}
const result = await nimble.agents.runs.result(run.id, { agent_id: agentId });
if ("output" in result) {
console.log(result.output.content);
}
run, err := client.Agents.Run(ctx, nimble.AgentRunParams{
Input: "Compare the pricing of Datadog, Grafana Cloud, and New Relic.",
})
if err != nil {
panic(err)
}
for run.IsActive {
time.Sleep(10 * time.Second)
polled, err := client.Agents.Runs.Get(ctx, run.ID, nimble.AgentRunGetParams{
AgentID: run.WebSearchAgentID,
})
if err != nil {
panic(err)
}
run.IsActive = polled.IsActive
}
result, err := client.Agents.Runs.Result(ctx, run.ID, nimble.AgentRunResultParams{
AgentID: run.WebSearchAgentID,
})
if err != nil {
panic(err)
}
fmt.Println(result.Output.Content.OfString)
RUN=$(nimble agents run \
--input "Compare the pricing of Datadog, Grafana Cloud, and New Relic.")
RUN_ID=$(echo "$RUN" | jq -r .id)
AGENT_ID=$(echo "$RUN" | jq -r .web_search_agent_id)
# repeat while "is_active" is true
nimble agents:runs get --agent-id "$AGENT_ID" --run-id "$RUN_ID"
# then fetch the result
nimble agents:runs result --agent-id "$AGENT_ID" --run-id "$RUN_ID"
curl -X POST 'https://sdk.nimbleway.com/v2/agents/runs' \
--header "Authorization: Bearer $NIMBLE_API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"input": "Compare the pricing of Datadog, Grafana Cloud, and New Relic."
}'
# => { "id": "task_run_...", "web_search_agent_id": "wsa_...", "status": "queued" }
# repeat while "is_active" is true
curl "https://sdk.nimbleway.com/v2/agents/$AGENT_ID/runs/$RUN_ID" \
--header "Authorization: Bearer $NIMBLE_API_KEY"
# then fetch the result
curl "https://sdk.nimbleway.com/v2/agents/$AGENT_ID/runs/$RUN_ID/result" \
--header "Authorization: Bearer $NIMBLE_API_KEY"
Next steps
Choose your integration
Plugin, MCP, SDK, or warehouse: which path fits and how each authenticates
API Reference
Full REST documentation for every endpoint
Agent
Efforts, trust reports, and use cases
Rate limits
Concurrency and throughput per plan