AnswerLine Start free

Engines

Copilot API

Copilot's Bing-grounded answer with every source it cited.

Price

$2.74 per 1,000 requests at Starter, down to $2.74 at Max, deducted from your prepaid USD balance.

Endpoint

POST /v1/monitor/copilot

Or queue it with POST /v1/async/task and taskType: "COPILOT".

Countries

Any country.

Coverage

Request

curl -X POST "https://api.answerline.dev/v1/monitor/copilot" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"Cheapest way to send money abroad","country":"US"}'

Request options

* required. Nested fields are written with a dot, e.g. include.markdown.

FieldTypeDescription
prompt * string Prompt submitted to Copilot, up to 2,000 characters. A longer prompt is refused with a 400 that states its length.
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 `true` is refused with a validation error on this engine.
include.markdown boolean Add a markdown version of the response to the result
include.rawResponse boolean Return the answer as normalized stream events. For the engine's answer as received, use `include.rawWire`.
include.rawWire boolean Return the engine's own response as received in result.rawWire: the answer stream, the rendered results pages or the RSS feed, without Gemini's detected location or ChatGPT's session tokens; null where it was not captured. Free. See https://answerline.dev/docs/output-formats#raw-wire
include.screenshot boolean Return a full-page PNG screenshot of the engine's page as it showed the finished answer, in result.screenshot: a link, or one link per results page on Google Search. On ChatGPT, Gemini, AI Mode, Google Search, Perplexity and Grok; other engines refuse it with a 400. Absent when the answer was read without a rendered page. Free. See https://answerline.dev/docs/output-formats#screenshots
state string State code for targeting below the country level (e.g., "CA"; "DC" included). Allowed only when country is "US". Served for Gemini only; ChatGPT, Copilot, Perplexity and Grok refuse `state` with a 400, uncharged. "DC" fails uncharged: no exit serves it.
answerDepth "any" | "full" | "quick" How deep an answer the engine writes, where it offers a choice. any (the default): a full answer when the engine can give one now, else its short one. full: a full answer or a retryable error, never charged. quick: the short one, the fastest. Perplexity offers the choice; every other engine has one depth and ignores the field. provenance.answerDepth says what was served. Same price for every value. See https://answerline.dev/docs/engine-features/#answer-depth

What you get back

Field in resultTypeDescription
textstringText of Copilot's reply
markdownstringCopilot's reply as Markdown; returned only if include.markdown is true
sourcesobject[]Sources the response cites
citationPillsobject[]Citation pills that appear inline in the Copilot answer. Every element pairs one pill with one source: a pill backed by N sources (a chip made from consecutive citation events) 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.

Full field definitions are in the API reference.

The Copilot answer versus Microsoft’s developer offerings

This endpoint returns the answer the consumer Copilot app gives a user, as text and markdown, with the sources it cites and its citation chips. The searches it ran, product cards and map results are coming.

Developers used to reach Bing results through the Bing Search APIs. Microsoft’s lifecycle notice (checked 2026-09-17, learn.microsoft.com) states those APIs retired on August 11, 2025 and encourages customers to migrate to Grounding with Bing Search as part of Azure AI Agents. Grounding lets your own agent use web data when it generates a response. The answer comes from your model and instructions, not Copilot’s.

For measurement that leaves what only the consumer answer has: Copilot’s own wording (which brands it names, in which order, with which caveats) and the pages it cites for it. Its commercial and local modules and its query fan-out are coming: shoppingCards with structured prices, sellers and ratings, map with businesses, addresses, coordinates, review aggregations and open state, and searchQueries with the web searches Copilot ran. None of the three is returned yet.

An annotated response

The excerpt follows the result schema for POST /v1/monitor/copilot. Values are illustrative.

{
  "success": true,
  "result": {
    "text": "The cheapest option depends on the amount and destination...",
    // Cited pages in order: url and label.
    "sources": [
      {
        "position": 1,
        "url": "https://www.example-finance.com/guides/international-transfer-fees",
        "label": "International transfer fees compared"
      }
    ],
    // One entry per (chip, source) pair; see Copilot sources. Omitted when the answer shows no chips.
    "citationPills": [
      { "citationPillId": 1, "position": 1, "url": "https://www.example-finance.com/guides/international-transfer-fees", "domain": "example-finance.com", "label": "International transfer fees compared" }
    ]
    // searchQueries, shoppingCards and map are coming; not returned yet.
  }
}

Shopping cards and map results are coming; Copilot shopping and map results describes their fields.

Synchronous calls

A synchronous call can take up to five minutes.

Python (requests)

import os
import requests

API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}

resp = requests.post(
    f"{API}/v1/monitor/copilot",
    headers=HEADERS,
    json={"prompt": "Cheapest way to send money abroad", "country": "US"},
    timeout=330,
)
if resp.status_code != 200:
    raise RuntimeError(f"{resp.status_code} {resp.headers.get('X-Request-Id')} {resp.text}")

result = resp.json()["result"]
print(result["text"][:200])
for src in result.get("sources", []):
    print(src.get("position"), src.get("url"), src.get("label"))

TypeScript (fetch)

const API = "https://api.answerline.dev";

const res = await fetch(`${API}/v1/monitor/copilot`, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ prompt: "Best noise-cancelling headphones under $300", 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();
for (const s of result.sources ?? []) {
  console.log(s.position, s.url, s.label);
}
console.log("credits charged:", res.headers.get("X-Credits-Charged"));

Batches: async tasks and a webhook

Tasks cost $0.00274, wait in your queue until they start and post their result to your webhook. POST /v1/async/task/batch takes 1 to 500 tasks, each admitted on its own and answered by index.

Python: submit a batch

import datetime
import os
import requests

API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
day = datetime.date.today().isoformat()

prompts = ["Best credit union for a first mortgage", "Cheapest way to send money abroad"]
tasks = [
    {
        "taskType": "COPILOT",
        "payload": {"prompt": prompt, "country": "US"},
        "idempotencyKey": f"copilot-{i}-US-{day}",
        "webhook": {"url": "https://your-app.example/hooks/answers"},
    }
    for i, prompt in enumerate(prompts)
]

resp = requests.post(f"{API}/v1/async/task/batch", headers=HEADERS, json=tasks, timeout=60)
resp.raise_for_status()
print(resp.json()["summary"])

TypeScript: receive and verify deliveries (Express)

The body is the GET /v1/async/task/{taskId} shape. Verify Webhook-Signature over the raw body before parsing.

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);
  const { task, response, credits } = delivery;
  if (task.status === "COMPLETED") {
    const { sources = [] } = response.result;
    const domains = [...new Set(sources.map((s: any) => new URL(s.url).hostname))].sort();
    console.log(task.idempotencyKey, domains, credits.creditsCharged);
  } else {
    console.warn(task.idempotencyKey, "failed:", response.error.code);
  }
  res.sendStatus(204);
});
app.listen(3000);

Deliveries can repeat or arrive out of order: deduplicate on task.id. See webhooks.

Geo targeting

Field Values Notes
country ISO 3166-1 alpha-2 Required. GET /v1/countries?model=copilot lists supported codes.
state Not available A request that sends state is refused with a 400 and not billed.

Include flags and what they cost

Flag Adds to result Price
include.markdown markdown 0
include.rawResponse rawResponse, the answer as normalized stream events 0
include.rawWire rawWire: always null on Copilot (what it holds) 0

At the Starter tier every Copilot request costs $0.00274.

result.provenance reads searchMode forced: every answer searches the web (all fields).

Common workloads

Pitfalls

sources depends on the answer and can be empty; default it to an empty list in your code. citationPills is omitted when the answer shows no chips. searchQueries, shoppingCards and map are not returned yet.

Before comparing Copilot with ChatGPT or Google AI Mode, map each engine’s sources to a common record (URL, domain, position).

A large batch is many tasks in your queue, which holds about 100,000 tasks of a typical prompt at a time; there is no concurrency cap and no request rate limit. See rate limits.

Copilot answers differ between runs of the same prompt and market. Take several samples per period and report rates with sample sizes; see AI answer volatility.

How failures are billed

An accepted request reserves its price, $0.00274 on every tier, and is charged only on success. Failures are charged nothing and release the reservation, including tasks that never start within 4 hours (QUEUE_WAIT_EXCEEDED; resubmit them) and queued tasks you delete with DELETE /v1/async/queue. Batch items refused with INSUFFICIENT_CREDITS create nothing and claim no idempotency key, so you can resubmit them unchanged after topping up. See credits.

Related: monitoring Copilot answers and the Copilot API options compared.

Questions

How much does a Copilot request cost?

At the Starter tier a request costs $0.00274. The Copilot include flags (markdown, rawResponse and rawWire) add nothing to the price.

Does this endpoint use the Bing Search API?

No. It returns the answer the consumer Copilot app shows its users. Microsoft retired the Bing Search APIs on August 11, 2025 and points customers to Grounding with Bing Search in Azure AI Agents instead.

Does the Copilot result include map results?

Not yet; map results are coming. Today a Copilot result carries the answer text, markdown and its cited sources. Each map entry will be a business or place from the answer: name, position, Google Place ID, address and coordinates, phone number, website, review aggregations per provider, photos, open state, category and price level where available.

Can I target a US state with Copilot?

No. Copilot takes a country only. A request that sends state is refused with a 400 and not billed.

Are failed Copilot requests charged?

No. Failed requests are charged nothing and their reservation is released. Only completed requests are charged.

Other engines