LSD

AI Answer Sampling

Asks the same prompt several times and returns how the answers differed — per business, how many runs named it, its best, worst and average position, and the text of every run.

When to use this

A client asking "am I showing up in ChatGPT?" is asking for a rate, and one call cannot give one. A model composes its answer per request, so ask twice ten minutes apart and the businesses and their order can differ. This runs the prompt 2-25 times and hands back the distribution: named in 8 of 10 runs, average position 2.1.

POST/v1/ai/sample
Cost: samples × the per-run price: 4 credits a run on chat_gpt and gemini, 2 on google_ai_mode. Ten samples on chat_gpt is 40 credits.
Rate Limit: Varies by plan
Response: Asynchronous. The samples run in parallel upstream, so the wait is the slowest run, not samples × one run. Measured over ten samples per platform: median ~27 seconds, nine of ten under 80, slowest 101s on the scrapers and 129s on AI Mode.

Parameters

ParameterTypeRequiredDescription
keywordstringYesThe prompt or keyword to ask repeatedly (max 500 chars)
platformstringYes"chat_gpt", "gemini" or "google_ai_mode". The mention endpoints are not sampleable — they read stored aggregates, so running one ten times returns the same numbers ten times.
samplesnumberYesHow many times to run the prompt, 2-25. Below about 5 the rate is too coarse to act on; 10 is the usual figure for daily tracking.
locationstringNoLocation (e.g. "Orchard Park, NY"). Required on google_ai_mode, which is a Google search and depends on where it runs from. Gemini supports city-level; ChatGPT resolves to country.
force_web_searchbooleanNoRequire the platform to search the web before answering. chat_gpt only; gemini returns a 400.
languagestringNoLanguage to ask in, as an ISO 639-1 code or name ("fr", "French"). Defaults to the language of the market you pass.
callback_urlstringNoPublic https URL to POST the finished sample to, instead of polling.

Example Request

curl -X POST https://api.localseodata.com/v1/ai/sample \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "keyword": "best plumber in Orchard Park NY",
    "platform": "chat_gpt",
    "samples": 10
  }'

Example Response

JSON
{
  "status": "success",
  "credits_used": 40,
  "data": {
    "job_id": "sample_V1StGXR8Z5",
    "status": "complete",
    "keyword": "best plumber in Orchard Park NY",
    "platform": "chat_gpt",
    "samples_requested": 10,
    "samples_returned": 10,
    "samples_failed": 0,
    "businesses": [
      {
        "name": "Bolt Plumbing",
        "matched_on": "domain",
        "cid": "",
        "domain": "boltplumbing.com",
        "category": "Plumber",
        "rating": 4.8,
        "reviews_count": 412,
        "address": "1200 Southwestern Blvd, Orchard Park, NY",
        "phone": "+1 716-555-0142",
        "website": "https://boltplumbing.com",
        "appearances": 8,
        "appearance_rate": 0.8,
        "best_rank": 1,
        "worst_rank": 4,
        "mean_rank": 2.13,
        "runs_seen": [1, 2, 3, 5, 6, 8, 9, 10]
      }
    ],
    "runs": [
      {
        "run": 1,
        "ok": true,
        "businesses": [],
        "response_text": "For plumbing in Orchard Park, the names that come up most are..."
      }
    ]
  }
}

Response Fields

FieldTypeDescription
samples_requestedintegerHow many runs were asked for
samples_returnedintegerHow many came back. Every rate below is out of this number
samples_failedintegerRuns the provider did not deliver. These are refunded
businesses[].namestringBusiness name, as the last run that named it wrote it
businesses[].matched_onstring"cid", "domain" or "name" — how runs were tied together into one business
businesses[].cidstringGoogle's identifier in decimal, on google_ai_mode only. Empty elsewhere
businesses[].appearancesintegerHow many runs named this business
businesses[].appearance_ratefloatappearances / samples_returned, to 3 places
businesses[].best_rankintegerHighest position it reached in any run
businesses[].worst_rankintegerLowest position it reached in any run
businesses[].mean_rankfloatAverage position across the runs that named it. Absent runs are not counted
businesses[].runs_seenarrayWhich run numbers named it
runs[].runinteger1-based run number
runs[].okbooleanWhether that run came back
runs[].businessesarrayBusinesses named in that run, in the same shape as /v1/serp/local-pack
runs[].response_textstringThe answer text for that run
runs[].errorstringThe provider's message, on failed runs only

Notes

  • appearance_rate is out of samples_returned, not samples_requested. A run the provider failed to deliver is a measurement that was not taken, so it is refunded rather than counted as an absence — samples_failed says how many there were.
  • mean_rank averages only the runs that named the business. Named 2nd in 3 of 10 runs reads mean_rank 2 and appearance_rate 0.3; the two say different things and which one is bad is the actionable part.
  • matched_on says how runs were tied together: "cid" is Google's own identifier and is exact, "domain" is domain plus name (never domain alone — two branches of a chain share one), "name" is the string alone and is the weakest.
  • On google_ai_mode prefer the cid. Google labels cards editorially, so the same business can be named differently between runs and a name-keyed count would report it twice at half the rate each.
  • Results are never cached. Serving a sample from cache would answer a later question with an earlier answer, which is the failure this endpoint exists to avoid.