Perplexity API
Perplexity's answer with its citations, related queries, the searches it ran, and any videos, images, places, hotels or shopping cards it showed.
Price
$1.95 per 1,000 async requests, down to $1.80 on the biggest plan — deducted in credits at your plan's rate (47.3 credits at the headline rate, plus the sync surcharge and per-page premium synchronous).
Endpoint
POST /v1/monitor/perplexity
Countries
Any country, plus US states.
Request
curl -X POST "https://api.answerline.dev/v1/monitor/perplexity" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"Which project management tools do agencies use?","country":"US"}'
Request options
| Field | Type | Description |
|---|---|---|
prompt * |
string |
Prompt submitted to Perplexity |
country * |
string |
Code of the country or region used to localize the response |
include |
object |
Flags that add extra output formats to the response (optional) |
include.html |
boolean |
Return a link to the complete HTML of the response |
include.markdown |
boolean |
Add a markdown version of the response to the result |
include.rawResponse |
boolean |
Return the unprocessed stream of response events |
state |
string |
State code for targeting below the country level (e.g., "CA"; "DC" included). Allowed only when country is "US". Served for Gemini; on a model that cannot place a state yet, a request that includes it is rejected as a validation error and is not charged. |
What you get back
Field in result | Type | Description |
|---|---|---|
text | string | Text of Perplexity's answer |
markdown | string | Perplexity's answer rendered as Markdown (present when include.markdown is true) |
sources | object[] | Sources the response cites |
citationPills | object[] | Citation pills that appear inline in the Perplexity answer. Every element pairs one pill with one source: a pill backed by N sources (bracketed groups like Perplexity's `[1][2][3]`) yields N elements with the same `citationPillId`, each holding that source's own `label`, `url` and `domain`. Grouping by `citationPillId` rebuilds the pills. Not present in `result` if the answer has no pills. |
related_queries | string[] | Suggested searches to follow up with |
search_model_queries | string[] | Search queries the engine ran internally to build the response |
videos | object[] | Videos that appear in the response |
images | object[] | Image found in the response |
places | object[] | Places and locations in general |
hotels | object[] | Hotels listed when the query shows travel intent |
shopping_cards | object[] | Product cards for shopping with full product details (present when the query shows shopping intent) |
The perplexity.ai answer versus Perplexity’s developer APIs
This endpoint returns the answer a user reads on perplexity.ai, as structured fields. You do not pick a model or parameters.
Perplexity’s developer platform (checked 2026-09-17, docs.perplexity.ai) lists an Agent API that gives web-grounded answers with built-in citations, a Search API that returns ranked web results, a Router API for hosted open-weight models, and an Embeddings API. With those you choose the model and parameters and get the grounding data the API exposes.
The consumer answer carries more than text and links. Answers with shopping, travel, local or visual intent include shopping_cards, hotels, places, videos and images. A brand can be recommended in a product card without appearing in the prose, so monitoring that reads only the text undercounts it.
Perplexity cites in bracketed groups such as [1][2][3]. citationPills keeps which sources sit together behind one chip, which is what a reader sees next to a sentence.
Two fields capture demand. related_queries are the follow-up questions Perplexity suggests to the user; search_model_queries are the searches it ran to build the answer. Your own API call returns neither.
An annotated response
The excerpt follows the result schema for POST /v1/monitor/perplexity. Values are illustrative. Top-level fields such as related_queries and shopping_cards are snake_case, while fields inside products such as imageUrls and numReviews are camelCase. Parse them as written.
{
"success": true,
"result": {
"text": "Agencies tend to pick tools with client billing, such as ExampleBoard and SampleTask...",
// Cited pages in display order.
"sources": [
{
"position": 1,
"url": "https://www.example-reviews.com/agency-project-management",
"label": "Project management tools for agencies",
"description": "A comparison of tools built for client billing..."
},
{
"position": 2,
"url": "https://community.example.org/t/which-pm-tool",
"label": "Which PM tool does your agency use?",
"description": "Thread with 140 replies..."
}
],
// One entry per (chip, source). citationPillId is 1-based; both entries below
// belong to the same visible chip. position points into result.sources.
// Omitted when the answer carries no pills.
"citationPills": [
{ "label": "Project management tools for agencies", "citationPillId": 1, "url": "https://www.example-reviews.com/agency-project-management", "domain": "www.example-reviews.com", "position": 1 },
{ "label": "Which PM tool does your agency use?", "citationPillId": 1, "url": "https://community.example.org/t/which-pm-tool", "domain": "community.example.org", "position": 2 }
],
// Follow-up questions suggested to the user.
"related_queries": ["ExampleBoard vs SampleTask for agencies", "Agency time tracking software"],
// Searches Perplexity ran to build the answer.
"search_model_queries": ["project management software for agencies UK"],
"videos": [],
"images": [],
"places": [],
"hotels": [],
"shopping_cards": []
}
}
A shopping answer fills shopping_cards[].products[] with title, price, merchant, available, imageUrls, numReviews, rating, original_price (null when not on sale), a flat position across all cards, and offers[] with per-merchant prices. hotels[] carries name, rating, num_reviews, address (an array of lines), lat/lng and price_level; places[] carries name, rating, address, categories and map_url.
Synchronous calls
A synchronous call returns the answer in the response, can take up to five minutes, costs 54.3 credits and holds a concurrency slot while it runs.
Python (httpx)
import os
from urllib.parse import urlparse
import httpx
API = "https://api.answerline.dev"
with httpx.Client(base_url=API, headers={"Authorization": f"Bearer {os.environ['API_KEY']}"}, timeout=330) as client:
resp = client.post("/v1/monitor/perplexity", json={
"prompt": "Which project management tools do agencies use?",
"country": "US",
"include": {"markdown": True},
})
if resp.status_code != 200:
raise RuntimeError(f"{resp.status_code} {resp.headers.get('X-Request-Id')} {resp.text}")
result = resp.json()["result"]
domains = [urlparse(s["url"]).netloc for s in result.get("sources", [])]
print(result["markdown"][:300])
print("cited domains:", domains)
print("follow-ups:", result.get("related_queries", []))
print("credits charged:", resp.headers.get("X-Credits-Charged"))
TypeScript (fetch)
const API = "https://api.answerline.dev";
const res = await fetch(`${API}/v1/monitor/perplexity`, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ prompt: "Which project management tools do agencies use?", country: "US" }),
signal: AbortSignal.timeout(330_000),
});
if (!res.ok) throw new Error(`${res.status} ${res.headers.get("X-Request-Id")} ${await res.text()}`);
const { result } = await res.json();
// Rebuild the visible chips: one group per citationPillId.
const chips = new Map<number, string[]>();
for (const pill of result.citationPills ?? []) {
chips.set(pill.citationPillId, [...(chips.get(pill.citationPillId) ?? []), pill.domain]);
}
console.log([...chips.entries()]);
console.log("searches:", result.search_model_queries ?? []);
Batches: async tasks and a webhook
Scheduled monitoring belongs in async tasks: 47.3 credits each, queued until a slot is free, and delivered to your webhook when done. POST /v1/async/task/batch accepts 1 to 500 tasks and answers each by index; one invalid item does not reject the others.
Python: submit a batch with repeated samples
import datetime
import os
import requests
API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
day = datetime.date.today().isoformat()
SAMPLES = 3 # repeated runs per prompt and market
prompts = ["Which project management tools do agencies use?", "Best time tracking app for consultants"]
tasks = [
{
"taskType": "PERPLEXITY",
"payload": {"prompt": prompt, "country": "US"},
"idempotencyKey": f"pm-{i}-US-s{s}-{day}",
"webhook": {"url": "https://your-app.example/hooks/answers"},
}
for i, prompt in enumerate(prompts)
for s in range(SAMPLES)
]
resp = requests.post(f"{API}/v1/async/task/batch", headers=HEADERS, json=tasks, timeout=60)
resp.raise_for_status()
summary = resp.json()["summary"]
print(f"{summary['succeeded']} queued, {summary['failed']} refused")
TypeScript: receive and verify deliveries (Express)
The delivery body matches GET /v1/async/task/{taskId}: task, credits and response. Verify the Webhook-Signature header over the raw body before parsing it.
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(raw: Buffer, header: string | undefined, secret: string, toleranceSeconds = 300): boolean {
const pairs = (header ?? "").split(",").map((part) => part.split("="));
const stamps = pairs.filter(([k]) => k === "t").map(([, v]) => v);
const sigs = pairs.filter(([k]) => k === "v1").map(([, v]) => v);
if (stamps.length !== 1 || !/^\d+$/.test(stamps[0]) || sigs.length === 0) return false;
if (Math.abs(Date.now() / 1000 - Number(stamps[0])) > toleranceSeconds) return false;
const expected = createHmac("sha256", secret).update(`${stamps[0]}.`).update(raw).digest();
return sigs.some((sig) => {
const given = Buffer.from(sig, "hex");
return given.length === expected.length && timingSafeEqual(given, expected);
});
}
const app = express();
app.post("/hooks/answers", express.raw({ type: "application/json" }), (req, res) => {
if (!verify(req.body, req.get("webhook-signature"), process.env.WEBHOOK_SECRET!)) return res.sendStatus(400);
const delivery = JSON.parse(req.body.toString("utf8"));
if (delivery.test) return res.sendStatus(204);
if (delivery.task.status !== "COMPLETED") {
console.warn(delivery.task.id, "failed:", delivery.response.error.code);
return res.sendStatus(204);
}
const { text = "", sources = [], related_queries = [] } = delivery.response.result;
const mentioned = text.toLowerCase().includes("exampleboard");
console.log(delivery.task.idempotencyKey, mentioned ? "mentioned" : "absent", sources.length, related_queries);
res.sendStatus(204);
});
app.listen(3000);
Deduplicate on task.id; deliveries may repeat and arrive in any order. See webhooks and verifying webhook signatures.
Geo targeting
| Field | Values | Notes |
|---|---|---|
country |
ISO 3166-1 alpha-2 | Required. GET /v1/countries?model=perplexity lists supported codes. |
state |
Coming soon | US-state targeting is coming. |
The local and travel blocks (places, hotels) change most between markets, so run local-intent prompts in each market you report on instead of extrapolating from one country.
Include flags and what they cost
| Flag | Adds to result |
Credits |
|---|---|---|
include.markdown |
markdown |
0 |
include.html |
html, a URL to the full HTML |
0 |
include.rawResponse |
rawResponse, the raw stream chunks |
0 |
Every Perplexity request costs the base price: 47.3 credits as a task, 54.3 synchronously. rawResponse is provider-specific and undocumented by design; use it for debugging, not as a parsing contract.
Common workloads
- AI visibility tracking: citation share by domain and mention rate by prompt. See AI visibility tracking and monitoring Perplexity.
- Competitor analysis: which competitor pages Perplexity cites, and which products it puts in cards. See competitor analysis.
- Content gap research:
related_queriesandsearch_model_queriesshow what users ask next and what Perplexity searched. See keyword research. - Forum citations: when answers cite discussion threads, Reddit citations in AI answers covers how to measure them.
- Brand protection: answers that cite outdated or hostile pages about your brand. See brand protection.
Pitfalls
Sources and their order change between runs of the same prompt. The batch above puts a sample index in each idempotency key so you can report rates with a sample size; AI answer volatility covers how many samples to take.
videos, images, places, hotels and shopping_cards appear only when Perplexity judges the intent calls for them, and citationPills is omitted when there are none. A missing block is an observation, not an error.
A citationPills[].label can be an empty string. Use domain or url for identity.
A brand named in text and a brand cited in sources are different metrics with different causes; keep them apart. See mentions vs citations.
Synchronous calls compete for your plan’s concurrency slots and fail with 429 CONCURRENT_LIMIT_EXCEEDED when all are busy; async tasks queue. Limits and headers are in rate limits.
How failures are billed
For Perplexity the reserved and charged amounts are the same: 47.3 credits for a task, 54.3 synchronously, charged only on success. A failed request is charged nothing and its reservation is released. That includes a task that has not started within 72 hours of creation (details.cause QUEUE_WAIT_EXCEEDED) and one that started but could not finish within five minutes. Synchronous calls are charged on success even if your client disconnected, so retry them only when the request never reached the server. See credits and retrying safely.
Questions
How many credits does a Perplexity request cost?
An async task costs 47.3 credits and a synchronous call 54.3. Perplexity has no priced add-ons: include.markdown, include.html and include.rawResponse add nothing.
Is this the same as Perplexity's own API?
No. This endpoint returns the answer perplexity.ai shows its users, with citations, related queries, the searches it ran and any media, place, hotel or shopping blocks as fields. Perplexity's developer APIs are separate products you call and configure yourself.
What is the difference between sources and citationPills for Perplexity?
sources lists the cited pages in display order. citationPills has one entry per chip and source pair for the bracketed inline citations, grouped by a 1-based citationPillId, with position pointing back into sources.
Can I target a US state with Perplexity?
Not yet. The Perplexity endpoint is paused for now and coming back soon, and US-state targeting is coming.
Are failed Perplexity requests charged?
No. A failed request is charged nothing and its credit reservation is released; only completed requests are charged.