AnswerLine Start free

Use cases

ChatGPT state targeting API: AI answers by US state

ChatGPT shapes local answers around where the asker is. Send state as a two-letter code and ChatGPT and Gemini answer from inside that state, in all 50 states and DC, with the businesses, brands and sources a person there sees.

Who it's for

Multi-location and franchise brands, agencies reporting AI visibility per state, regional service businesses, insurance, legal and healthcare marketers whose providers and rules change at the state line, and retailers checking where ChatGPT sends buyers in each market.

What you get

Try it

curl -X POST "https://api.answerline.dev/v1/monitor/chatgpt" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"Which car insurance company is cheapest for a new driver?","state":"TX"}'

Sync or queue it with POST /v1/async/task. Full field list on the ChatGPT page and in the API reference.

Engines for this workload

What state targeting does

A person in Houston and a person in Boston who ask ChatGPT “which car insurance is cheapest” can get different companies, different sources and, for local questions, different businesses on the map. Add state to a ChatGPT request and the answer comes from inside that state, as a person there sees it. All 50 states and DC are covered.

On 2026-11-09 we asked ChatGPT “best pizza near me” once in each state and once without a state. Each of the 50 state answers was placed in a city inside the state asked, from Anchorage to San Antonio. Without a state, ChatGPT picked New York. The homepage map shows each recorded answer, and Local AI answers has the table.

Who needs it

What each engine does with a state

Engine With state
ChatGPT Answers from inside the state, in all 50 states and DC.
Gemini Answers from inside the state, as ChatGPT does.
Perplexity, Copilot, Grok Accepted. Answers for the whole US, the same as without it.
Google AI Mode, Google Search Accepted. Answers for the whole US. For a city, send location or uule instead.
Google News Accepted. Answers for the whole US.

provenance.requestedState echoes the state on every engine, so a mixed run stays labeled. Read an answer from any engine but ChatGPT as a whole-US answer. The coverage page is the reference.

How it works

  1. List the codes with GET /v1/states?country=US: 51 entries, each {code, name}.
  2. Send state with a ChatGPT request. Leave country out or set it to "US"; any other country is a 400.
  3. Read the answer. map holds the businesses the answer names, with address, rating, latitude and longitude. entities lists every brand, product and local business it names. citationPills and sources show the cited domains and pages.
  4. Store result.provenance.requestedState with each row.

One request, synchronous:

curl -X POST "https://api.answerline.dev/v1/monitor/chatgpt" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Which car insurance company is cheapest for a new driver?", "state": "TX"}'

The list of codes:

curl "https://api.answerline.dev/v1/states?country=US" \
  -H "Authorization: Bearer $API_KEY"

An excerpt of a state answer. The values are an example, not a recorded answer; the fields follow the POST /v1/monitor/chatgpt result schema:

{
  "success": true,
  "result": {
    "text": "For a new driver in Texas, quotes from ...",
    "citationPills": [
      { "url": "https://www.example-rates.com/texas", "label": "Texas car insurance rates", "domain": "example-rates.com", "citationPillId": 0, "type": "searchResult", "position": 1 }
    ],
    "entities": [{ "type": "brand", "name": "Example Mutual" }],
    "provenance": {
      "prompt": "Which car insurance company is cheapest for a new driver?",
      "requestedCountry": "US",
      "requestedState": "TX",
      "attempt": 1,
      "complete": true
    }
  }
}

All 51 in one batch

POST /v1/async/task/batch takes up to 500 tasks, so one prompt in every state is one call, and 9 prompts still fit. Each task succeeds or fails on its own.

Python, with the answerline SDK:

import os

from answerline import Client

PROMPT = "Which car insurance company is cheapest for a new driver?"
RUN = "2026-11-11"

with Client(os.environ["API_KEY"]) as client:
    states = client.states()  # the 50 states and DC
    batch = client.create_batch([
        {"taskType": "CHATGPT",
         "payload": {"prompt": PROMPT, "state": s["code"]},
         "idempotencyKey": f"insurance-{s['code']}-{RUN}"}
        for s in states
    ])
    for item in batch["results"]:
        code = states[item["index"]]["code"]
        if not item["success"]:
            print(code, item["error"]["code"])
            continue
        done = client.wait_for_task(item["task"]["id"])
        if done["task"]["status"] != "COMPLETED":
            print(code, done["task"]["status"])
            continue
        result = done["response"]["result"]
        names = [e["name"] for e in result.get("entities", [])]
        print(result["provenance"]["requestedState"], names[:5])

TypeScript, with @answerline/sdk:

import { Client } from "@answerline/sdk";

type Answer = { success: boolean; result: { entities?: { name: string }[]; provenance: { requestedState?: string } } };

const client = new Client({ apiKey: process.env.API_KEY! });
const prompt = "Which car insurance company is cheapest for a new driver?";
const run = "2026-11-11";

const states = await client.states();
const batch = await client.createBatch(
  states.map((s) => ({ taskType: "CHATGPT", payload: { prompt, state: s.code }, idempotencyKey: `insurance-${s.code}-${run}` })),
);

for (const item of batch.results) {
  if (!item.success) {
    console.log(states[item.index]!.code, item.error.code);
    continue;
  }
  const done = await client.waitForTask<Answer>(item.task.id);
  const result = done.response?.result;
  if (done.task.status !== "COMPLETED" || !result) continue;
  console.log(result.provenance.requestedState, (result.entities ?? []).slice(0, 5).map((e) => e.name));
}

The tasks run whether or not you wait; the loop only collects them. For a recurring run, add a webhook to each task instead of waiting (webhooks). How to see ChatGPT answers by US state walks through comparing the 51 answers.

What it costs

A state does not change the price. A ChatGPT request costs $0.0015 at the Starter tier, $1.00–$1.50 per 1,000 across tiers.

Run Tasks Cost at Starter
One prompt, every state and DC 51 $0.0765
20 prompts, every state and DC 1,020 $1.53
The same, weekly for 4 weeks 4,080 $6.12

A failed request is not charged. A new account’s 100 free requests work on ChatGPT with a state too. Tiers are on pricing.

Pitfalls

For city grids on Google, see local rank tracking. For the full field list, see the ChatGPT engine page.

Questions

Can ChatGPT answers be targeted to a US state?

Yes. Send state as a two-letter code, for example TX, and ChatGPT and Gemini answer from inside that state, in all 50 states and DC. The state implies country US; with any other country the request is refused with a 400 and not billed.

Which engines answer from inside a state?

ChatGPT and Gemini. Every other engine accepts state and answers for the whole US, the same as without it. For a city, Google AI Mode and Google Search take location or uule. See /docs/coverage#states.

How do I get the list of state codes?

GET /v1/states?country=US returns the 51 entries, the 50 states and the District of Columbia, each as code and name. Any other country returns an empty list.

How do I know which state an answer is for?

Every answer carries result.provenance.requestedState, the state the request named. It is absent when the request named none. A failed task has no result, so also keep your own map from task id to state.

Does a state cost extra?

No. A ChatGPT request with a state costs the same as one without: $0.0015 at the Starter tier. One prompt in all 51 entries is $0.0765.

Can I get the HTML page or a screenshot of a state answer?

No. The answer text, sources, map, entities and links all come back as JSON.

More use cases