Build a native Perplexity Sonar Pro example that prints a short researched answer, its finish reason and returned source metadata. Keep the key in your environment and inspect the result before extending the program.
What you'll build
The program asks why an HTTP conditional request can avoid resending an unchanged resource. It prints the answer, finish reason, citations and usage when available. This fixed documentation question needs no private information and is short enough to review against its returned sources.
This example uses the official perplexityai package and its native client.chat.completions.create method with the explicit sonar-pro model. The official Sonar quickstart demonstrates that combination. The Sonar Pro model record and calculator below identify the same model, so the request and estimate can be compared directly.
A successful run establishes the request path and output handling. It does not prove every claim in the generated answer. Open the relevant source references, confirm that the explanation matches them and note any uncertainty. Keep that review as part of the example’s acceptance rather than judging the response only by whether it sounds plausible.
Prerequisites
Follow Perplexity project and key setup and configure PERPLEXITY_API_KEY in the environment that will run the script. Confirm usable project credit and review Perplexity billing by product before executing it. The program does not query your private balance or establish free entitlement.
Use a separate Python environment for the example. This keeps dependency changes and interpreter selection clear, especially if your editor and terminal use different environments. Record the installed native client version after you establish a passing run so a later change can be reproduced.
Begin with the safe documentation question in the example. It needs no personal data or confidential source files. When you replace it with your own workload, choose input you may send to the provider and define the expected artifact. Include a missing-information case before presenting the output as a reliable research feature.
The script also checks for a missing PERPLEXITY_API_KEY before constructing a request. If it reports a missing setting, restore the variable through protected configuration and restart the process where needed. This additional local check is separate from the wrong-model API test below.
Install SDK
python -m pip install perplexityai
Install the package with the interpreter that will execute the script. The import is perplexity, while the package name is perplexityai. The native Sonar quickstart documents both the SDK interface and its environment-variable convention. Do not name your script perplexity.py, because that would shadow the installed package.
Configure the key through a secret manager or your environment tooling without copying it into the source. A local secret file should remain outside version control. If the running process loads settings only at startup, restart it after changing the configuration. Check presence without printing the value when diagnosing a setup issue.
Full script
import json
import os
import sys
import perplexity
from perplexity import Perplexity
key = os.environ.get("PERPLEXITY_API_KEY", "").strip()
if not key:
raise SystemExit("Set PERPLEXITY_API_KEY before running this script.")
model = "ai-api-hub-invalid-model" if "--bad-model" in sys.argv else "sonar-pro"
prompt = "Explain why an HTTP conditional request can avoid resending an unchanged resource in one sentence."
try:
with Perplexity(api_key=key, timeout=30.0, max_retries=0) as client:
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
max_tokens=256,
temperature=0,
stream=False,
)
except perplexity.APIConnectionError:
raise SystemExit("Connection failed. Check connectivity before retrying.")
except perplexity.APIStatusError as exc:
print(f"HTTP {exc.status_code}")
print(exc.response.text)
raise SystemExit(1)
if not response.choices:
raise SystemExit("No completion choice was returned.")
choice = response.choices[0]
answer = choice.message.content or ""
if not answer.strip():
raise SystemExit("No final answer text was returned.")
data = response.model_dump(mode="json")
print("ANSWER")
print(answer)
print("FINISH_REASON", choice.finish_reason)
print("CITATIONS", json.dumps(data.get("citations") or [], ensure_ascii=False))
print("SEARCH_RESULTS", json.dumps(data.get("search_results") or [], ensure_ascii=False))
if data.get("usage") is not None:
print("USAGE", json.dumps(data["usage"], ensure_ascii=False))
if choice.finish_reason != "stop":
raise SystemExit("The returned completion did not finish normally.")
Save this as perplexity_first_call.py and run it with the prepared interpreter. The timeout is an example application setting rather than a published service limit. Automatic client retries are disabled here so the initial request path is explicit; the official SDK configuration guide describes how to adjust that policy later. Official Perplexity documentation.
The exception paths print a connection category or the actual HTTP status and response body. The safe fixture contains no private input; remove secrets and private content before sharing a real error transcript. On success, the program reads the completion choice and the response’s citation and search-result fields, matching the documented Sonar response structure. It never substitutes a fabricated source for a missing field.
Expected output
ANSWER
<actual generated answer pending authenticated capture>
FINISH_REASON <actual finish reason>
CITATIONS <actual returned citation array>
SEARCH_RESULTS <actual returned search-result array>
USAGE <actual usage object, when returned>
The labels above are literal strings in the program; the angle-bracket fields are placeholders. This structural illustration is not a captured successful run. A complete authenticated output transcript is still pending. Check that the eventual answer explains the requested HTTP behavior, then inspect whether its actual references support the explanation.
If no citations or search results appear, do not invent evidence links from the answer’s wording. Inspect the actual response and distinguish a supported explanation from one with missing evidence. A source URL alone is not enough: open it, find the relevant passage and check that the answer preserves its meaning.
Review the finish reason as well as the text. The script rejects an empty answer and a finish reason other than stop. Its short output ceiling is an example setting, not a service limit. If it truncates a response, preserve the incomplete outcome and review the request before running another attempt. Do not present partial research as a completed result.
One deliberate error and its fix
Run the same safe fixture with an intentionally invalid model identifier. Keep the credential configured so the request can reach model validation; a missing key tests a different stage.
python perplexity_first_call.py --bad-model
The branch supplies ai-api-hub-invalid-model to the same Sonar method and prints the actual HTTP status and response body if rejected. Do not retry that unchanged request. Remove --bad-model to restore sonar-pro, then inspect the ordinary request independently if it also fails.
Only the model identifier changes in this exercise. The client, prompt, output setting and timeout remain the same, which helps distinguish a model-selection problem from unrelated changes. No preset or fallback model is sent. The Sonar quickstart shows the explicit model-selection field used by the ordinary request.
Preserve the returned code and message rather than assigning a guessed error type. Authentication, funding and request validation can fail at different stages. Official error-handling guidance.
A literal wrong-model response has not yet been captured for this tutorial. The linked official reference does not supply an exact response for this fixture, so no invented error envelope is shown. Run the command with an authorized API credential and retain its actual status and body to complete this verification.
What this request costs
Estimate your API costs
Your text and estimates stay in this browser. No API requests are sent to model providers.
Loading verified model records…
The calculator is preset to the exact sonar-pro model used by this script. Enter the prompt and completion token counts actually returned by your run. This is a model-token estimate: include any separately applicable request or search charge when reconciling a Sonar bill, and do not treat a component absent from the calculator as free. Check the official pricing categories and returned usage before relying on a total.
When extending the program, estimate the entire accepted task: any additional research, follow-up or correction calls belong in the workload. Keep returned usage with a safe task identifier and compare it with project activity after the experiment. That evidence is more useful than extrapolating a monthly total from the length of the final paragraph.
Next steps
Turn the returned citation and search-result fields into a source display after checking their actual values. Keep citation order and answer references associated with the same response. Add a fixture where the requested fact is absent and verify that the application preserves uncertainty. Validate any structured record and its supporting evidence before accepting it.
If you later move this example to the Agent API, follow the official migration guide and update the request method, output parser and cost assumptions together. The completion-choice parser shown here belongs to this Sonar request. Preserve a known fixture while evaluating the new interface instead of assuming the two response objects are interchangeable.
Review Perplexity product admission rules before adding workers and model and preset selection before changing configuration. Return to the Perplexity API overview for current product context. A useful next milestone is a representative researched artifact your application can validate, account for and recover when it fails.
Frequently asked questions
Which Perplexity interface does this script use?
What is the Python package name?
Will the generated answer match the example exactly?
What does the wrong-model exercise verify?
Does the calculator select the model in this script?
Should I publish every returned answer automatically?
Sources
- Native Sonar quickstart and response structure ↗
- SDK timeout and retry configuration ↗
- SDK error handling ↗
- Sonar Pro model documentation ↗
- Pricing categories ↗
- Sonar to Agent migration ↗
Last verified · Source ↗