Ask Site
curl --request POST \
--url https://api.example.com/v1/ask-site \
--header 'Content-Type: application/json' \
--data '
{
"site_id": "<string>",
"question": "<string>"
}
'import requests
url = "https://api.example.com/v1/ask-site"
payload = {
"site_id": "<string>",
"question": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({site_id: '<string>', question: '<string>'})
};
fetch('https://api.example.com/v1/ask-site', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/ask-site",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'site_id' => '<string>',
'question' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/ask-site"
payload := strings.NewReader("{\n \"site_id\": \"<string>\",\n \"question\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/ask-site")
.header("Content-Type", "application/json")
.body("{\n \"site_id\": \"<string>\",\n \"question\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/ask-site")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"site_id\": \"<string>\",\n \"question\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Sites
POST /v1/ask-site
Ask a registered polygon a question — one model call over a dossier that was screened once.
POST
/
v1
/
ask-site
Ask Site
curl --request POST \
--url https://api.example.com/v1/ask-site \
--header 'Content-Type: application/json' \
--data '
{
"site_id": "<string>",
"question": "<string>"
}
'import requests
url = "https://api.example.com/v1/ask-site"
payload = {
"site_id": "<string>",
"question": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({site_id: '<string>', question: '<string>'})
};
fetch('https://api.example.com/v1/ask-site', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/ask-site",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'site_id' => '<string>',
'question' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/ask-site"
payload := strings.NewReader("{\n \"site_id\": \"<string>\",\n \"question\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/ask-site")
.header("Content-Type", "application/json")
.body("{\n \"site_id\": \"<string>\",\n \"question\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/ask-site")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"site_id\": \"<string>\",\n \"question\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Answers a question about a site registered with
An incomplete answer is stochastic rather than a property of the question, so
a retry usually succeeds. It is never returned as a
POST /v1/sites. One model call over the persisted
dossier — it never re-fetches, because the sieve already ran at
registration.
curl -s https://api.mireye.com/v1/ask-site \
-H "Authorization: Bearer $MIREYE_API_TOKEN" \
-H 'content-type: application/json' \
-d '{
"site_id": "'"$SITE_ID"'",
"question": "What limits how much of this site is buildable?"
}' | jq
question is capped at 2,000 characters. The answer comes back with
citations, the same as /v1/ask.
Why this exists
Ask ten questions about one parcel through/v1/ask and you pay for ten
planner runs and ten rounds of fetching over the same ground. Through a site,
you pay for the screen once and then ten cheap reads against it.
That maps onto how diligence actually goes: a site gets picked up, gets
interrogated from several angles over days, and gets dropped or advanced.
The expensive part should happen once, at the front.
Timing
If the site is stillbuilding, you get a 202 — poll
GET /v1/sites/{site_id} until it reports
ready. Registration runs a real screen across the polygon and takes
minutes, not seconds.
10 credits per question.
Failures
error | HTTP | Meaning | Retryable |
|---|---|---|---|
site_not_found | 404 | No ready dossier for that site_id. | no — register the polygon first |
ask_answer_incomplete | 502 | The model did not return a complete answer — it ran out of output budget mid-answer, or omitted a required part of it. The credits are refunded, best-effort. | yes |
ask_question_refused | 422 | The model declined to answer. Deterministic — rephrase rather than retry. The credits are refunded, best-effort. | no |
200 with an empty
answer — if you have code branching on an empty answer string, you can drop
it.
Scope
The dossier is a snapshot frombuilt_at. It does not refresh itself. For a
site you are tracking over months, re-register the polygon to rebuild —
same geometry, same site_id.