NativePort
← How-to

How to Use Tavily Search Through NativePort in Python

Run a Tavily search that returns relevance-scored results plus an optional grounded answer in one call — the exact request shape, in plain Python against NativePort's gateway.

Tavily was built for retrieval pipelines rather than adapted for one: every result carries a relevance score, and a single call can also return an LLM-ready answer synthesized from what it found, so there’s no separate summarization step. NativePort proxies Tavily’s API under one key and balance; this guide covers the /search endpoint, which covers the bulk of what agents built on Tavily actually call.

What you’ll need

  • A NativePort API key. Sign up to get a key and $5 in credits.
  • Python 3, standard library only — the example below uses urllib.request, no pip install.
  • Your key exported as an environment variable, never hardcoded:
export NATIVEPORT_API_KEY="np_..."

What’s admitted

/tavily/<endpoint> forwards to the matching endpoint on api.tavily.com, POST only — the method Tavily’s own action endpoints document:

  • search — the general-purpose query endpoint this guide covers.
  • extract — pull the full content of one or more known URLs, no search involved.
  • crawl — start from a URL and follow links outward, gathering content per page.
  • map — discover a site’s URL structure without extracting content.

Tavily’s /usage endpoint (account-wide credit and limit metadata) is deliberately not exposed — it’s account-wide billing state, not a search interface, and a per-client key has no business reading the shared account’s usage. Any endpoint outside the four above 404s before it ever reaches Tavily.

import json
import os
import urllib.request

GATEWAY = "https://api.nativeport.ai"
API_KEY = os.environ["NATIVEPORT_API_KEY"]


def search(query, **kwargs):
    body = json.dumps({"query": query, **kwargs}).encode()
    req = urllib.request.Request(f"{GATEWAY}/tavily/search", data=body, method="POST")
    req.add_header("Authorization", f"Bearer {API_KEY}")
    req.add_header("Content-Type", "application/json")
    req.add_header("User-Agent", "nativeport-python-guide/1.0")
    with urllib.request.urlopen(req, timeout=30) as resp:
        return json.loads(resp.read())


result = search("what changed in the latest Kubernetes release", max_results=5)
for item in result["results"]:
    print(f"{item['score']:.2f}  {item['title']}  {item['url']}")

query is the only required field; everything else is Tavily’s own optional parameter set, forwarded verbatim — max_results (0–20, default 5), topic (general, news, finance), time_range, include_domains/exclude_domains, and the two fields worth calling out on their own:

  • include_answer: true (or "basic"/"advanced") adds a synthesized answer string to the response, built from the result set Tavily itself just retrieved.
  • include_raw_content: true (or "markdown"/"text") adds each result’s full page content alongside its snippet, so a follow-up extract call isn’t needed just to get the whole page.

The response is Tavily’s own shape, untouched:

{
  "query": "what changed in the latest Kubernetes release",
  "answer": "The release adds ...",
  "results": [
    {
      "title": "Kubernetes v1.34 release notes",
      "url": "https://kubernetes.io/releases/...",
      "content": "This release introduces...",
      "score": 0.94
    }
  ],
  "response_time": 1.12,
  "usage": {"credits": 1},
  "request_id": "..."
}

answer is present only when include_answer was set on the request; usage likewise only shows up when include_usage: true is on the request — set it if you want the response itself to confirm what a call cost, since that’s also the same field the gateway bills from (see below).

Errors you’ll actually hit

  • 402 Payment Required: the NativePort balance is at $0. Every request answers this deterministically rather than degrading, so top up and retry.
  • 401 Unauthorized: the Authorization: Bearer <NATIVEPORT_API_KEY> header is missing, malformed, or doesn’t resolve to an account.
  • 403 Forbidden: the key is valid but the account isn’t active.
  • 404 on /tavily/usage or anything outside search/extract/crawl/map: not admitted at the gateway — see “What’s admitted” above.
  • An empty results array with a 200: not a gateway error — Tavily itself found nothing for that query at the requested search_depth. Retrying with search_depth: "advanced" or a broader time_range is a Tavily-side tuning question, not something to retry blindly.

Security

Treat NATIVEPORT_API_KEY like any other credential: environment variable or secret store, never a literal string in source, never logged. Tavily’s own credential never reaches your process — the gateway injects it server-side.

What this costs

The gateway bills from usage.credits when the response carries it (set include_usage: true to guarantee that), falling back to a 1-credit charge if it’s missing — at Tavily’s own per-credit rate, no NativePort markup. A basic-depth search is 1 credit; search_depth: "advanced" is 2; extract, crawl and map price per URL or page processed rather than per call. Current per-credit pricing is on the Tavily provider page. A zero balance answers every request with 402 instead of degrading. Adding credit carries a flat 5.5% fee on top-ups between $10 and $5,000 — never on the calls themselves. Full breakdown: pricing.

Where to go next