Get Field Request
curl --request GET \
--url https://api.example.com/v1/field-requests/{request_id}import requests
url = "https://api.example.com/v1/field-requests/{request_id}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.example.com/v1/field-requests/{request_id}', 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/field-requests/{request_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/field-requests/{request_id}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/v1/field-requests/{request_id}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/field-requests/{request_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Catalog
GET /v1/field-requests/{request_id}
Poll a field request: status, queue position, the promised ETA, and — once the field is live — the resume call that answers your original ask.
GET
/
v1
/
field-requests
/
{request_id}
Get Field Request
curl --request GET \
--url https://api.example.com/v1/field-requests/{request_id}import requests
url = "https://api.example.com/v1/field-requests/{request_id}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.example.com/v1/field-requests/{request_id}', 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/field-requests/{request_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/field-requests/{request_id}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/v1/field-requests/{request_id}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/field-requests/{request_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Poll first — your session will be dead when this completes
A new-field build takes hours, not seconds. The agent (or session) that filed the request is almost certainly gone by the time the field is live, so the contract is built around resumption:- On
accepted_new, store therequest_idand theresumecall in durable task state — not in conversation context. - Poll this endpoint whenever a successor picks the task up. The poll state is the source of truth: it is always right, and it works even if every callback failed.
- When
statusislive, execute the storedresumecall (or re-read it from this response) — the exact/v1/fetchrequest that answers the original ask.
curl -s https://api.mireye.com/v1/field-requests/fr_5d81c02e94aa4f31b7c6d2a90e8f1c3b \
-H "Authorization: Bearer $MIREYE_API_TOKEN" | jq
{
"request_id": "fr_5d81c02e94aa4f31b7c6d2a90e8f1c3b",
"status": "building",
"waiting_on": null,
"phase": null,
"queue_position": null,
"estimated_ready_at": "2026-08-01T14:05:00+00:00",
"resolved_locations": [
{ "index": 0, "resolved_location": { "lat": 30.199699, "lng": -97.496411, "source": "address" },
"resolved_address": "480 Berdoll Ln, Cedar Creek, TX 78612" }
],
"disposition": [ { "ask": "…", "disposition": "accepted_new", "field_id": "…",
"estimated_ready_at": "2026-08-01T14:05:00+00:00", "resume": { "…": "…" } } ],
"resume": { "method": "POST", "url": "https://api.mireye.com/v1/fetch",
"body": { "lat": 30.199699, "lng": -97.496411, "fields": ["…"] } },
"context_blob": "{\"job\":\"site-screen-114\"}",
"created_at": "2026-07-31T14:05:00+00:00",
"updated_at": "2026-07-31T16:40:12+00:00"
}
404 field_request_not_found either way, never a 403: a 403 would confirm
the id exists, which is a cross-tenant existence oracle over an enumerable
id space.
Response fields
| Field | Type | Notes |
|---|---|---|
request_id | string | The id you filed. |
status | string | See the vocabulary below. |
waiting_on | string or null | Who progress is blocked on, in your terms: "requester" (a confirm/clarify is waiting on you), "operator" (a human on our side has to look — e.g. screening failed and was parked rather than skipping dedup), or null (nobody — either done, or we’re working). |
phase | null | Reserved for finer-grained build progress inside building; currently always null on this surface. |
queue_position | number or null | Position in the build queue while a build ticket is open. Builds are single-flight, so it is real. |
estimated_ready_at | string or null | The promise that was made at acceptance, read back verbatim — never recomputed on poll. An ETA that slides forward every time you look is not an ETA. |
resolved_locations | array | Your example locations as resolved (the {lat, lng, source} echo, plus resolved_address for address inputs). |
disposition | array | The per-sub-ask screening outcome, unchanged from the POST response — see the disposition reference. |
resume | object or null | The first resume call found in disposition — the /v1/fetch request that answers the ask. |
context_blob | string or null | Your blob, byte-identical (first write wins across idempotent replays). |
created_at / updated_at | string | ISO-8601. |
Status vocabulary
The full set, in lifecycle order. Intake outcomes first:status | Meaning | What to do |
|---|---|---|
received | Filed and durable; screening hasn’t finished (the 202 path). | Poll; the disposition lands here. |
screening | Being screened asynchronously. If waiting_on is "operator", screening failed and a human has to look — it is parked rather than queueing a build without dedup. | Poll. |
matched | The catalog already answers it — the value and resume call are in disposition. | Use the resume call. Done. |
awaiting_confirm | A near-miss or clarify is waiting on you (waiting_on: "requester"). Nothing is built on ambiguity. | Accept the near-miss (use its resume), or re-POST with the candidate excluded via constraints.must_not_be. |
rejected | Every sub-ask was refused — typed codes and routing hints in disposition. Terminal. | Follow the routing hint. |
queued | Accepted; a build ticket exists. queue_position and estimated_ready_at are live. | Store the id, poll later. |
status | Meaning |
|---|---|
claimed | A build runner holds the ticket (usually passes straight to building). |
building | The build is running: source research, contract authoring, implementation, a frozen truth eval — your example_locations (and any claimed_value) seed its eval cases. |
in_review | Built; in human review. Every new field is reviewed before it ships. |
approved | Review passed; publish is being triggered. |
publishing | Code/data are rolling out. The request does not go live on “the PR merged” or “the publish command exited 0” — only on the check that matters (next row). |
live | Prod /v1/fetch returned a real, cited, non-null value at your own example locations. The resume call works now. Terminal. |
blocked | An honest no, at whatever stage it became true. Terminal — see below. |
expired | Reserved for a confirm window lapsing on an awaiting_confirm request. Terminal. |
live, blocked, expired, rejected (and matched, which
is answered rather than terminal-by-refusal). Everything else is in motion —
poll at whatever cadence your task runs on (builds move on a scale of hours;
your plan’s normal request-per-minute limit is the only constraint).
The three build outcomes
A finished build lands in one of three terminal outcomes. On the poll surface they appear aslive or blocked; the callbacks (below) carry the finer
status distinction:
DONE→live, callbackevent_type: "request_live". The field passed its eval cleanly.SHIP_LOW_CONFIDENCE→live, callbackevent_type: "request_live_low_confidence". The field is live with an honest, stated limit — thecaveatfield in the callback. This is not a lesser approval: the caveat travels with the value, worded so an agent can propagate it into its own citations. If you consume the field, repeat the caveat wherever you cite the number.BLOCKED→blocked, callbackevent_type: "request_blocked", with a typedblocked_reason.code, an explanation, and — where one exists — acounter_offernaming the nearest thing that is possible. The typed codes:no_indexable_source,licensing,coverage_gap,quality_below_bar(we built it and the eval says it would mislead),realtime_only,cost_prohibitive,upstream_dead,pr_closed(built, but declined in review),other.
blocked, the
reason was also emailed/webhooked to the callback you registered (a callback
can be added after filing: re-POST the identical body with the same
idempotency_key and a callback — a present callback replaces the stored
one).
Webhook callbacks
If you registeredcallback.webhook_url, each event is POSTed to it as JSON.
Headers:
| Header | Value |
|---|---|
X-Mireye-Event | The event type (screening_completed, request_live, request_live_low_confidence, request_blocked). |
X-Mireye-Delivery | <request_id>:<event_type> — your dedup key. Delivery is at-least-once; drop a delivery key you have already processed. |
Content-Type | application/json |
screening_completed fires when screening settles (useful mainly on the 202
path) and carries {request_id, status, disposition} — the same disposition
array the poll shows.
Completion events carry the machine-readable document:
{
"request_id": "fr_5d81c02e94aa4f31b7c6d2a90e8f1c3b",
"event_type": "request_live_low_confidence",
"status": "SHIP_LOW_CONFIDENCE",
"field_id": "state_highway_aadt",
"fetch": {
"method": "POST",
"url": "https://api.mireye.com/v1/fetch",
"body": { "lat": 30.199699, "lng": -97.496411, "fields": ["state_highway_aadt"] }
},
"value": 4300,
"unit": "vehicles/day",
"citation": "TxDOT Traffic Count Database, 2025 annual counts",
"confidence": "medium",
"caveat": "Count stations are sparse outside metro counties; values more than 2 miles from a station are interpolated along the route.",
"context_blob": "{\"job\":\"site-screen-114\"}"
}
value/unit/citationare the resolved value at your original example location — a value you can check beats a field id you have to go fetch to believe.caveatis present even whennull: an explicit null says “we checked, there isn’t one,” so a consumer branching on key-presence never mistakes a clean DONE for an un-inspected one.request_blockedadds ablocked_reasonobject:{"code": "coverage_gap", "explanation": "...", "counter_offer": "..."}.- Webhook URLs must resolve to a public address (private, loopback, and link-local targets are refused). Deliveries are retried on failure with backoff; the poll state stays correct regardless of delivery outcome.
- Webhooks are unsigned in V1 — the body contains only what you already know plus the result. Treat the payload as untrusted input to your own pipeline and verify via the poll endpoint if it matters.
Email callbacks
If you registeredcallback.email, completion mail is written for a human
and ends with the same machine-readable document in a fenced JSON block,
so the recipient can be an agent without asking it to parse prose:
state_highway_aadt is live, with one limit on it.
At 30.199699, -97.496411: 4300 vehicles/day
Source: TxDOT Traffic Count Database, 2025 annual counts
The limit: Count stations are sparse outside metro counties; values more
than 2 miles from a station are interpolated along the route.
It travels with the value — repeat it wherever you cite the number.
Fetch it:
POST https://api.mireye.com/v1/fetch
{"lat": 30.199699, "lng": -97.496411, "fields": ["state_highway_aadt"]}
Everything above, including the caveat, machine-readable:
```json
{ "request_id": "fr_5d81c02e94aa4f31b7c6d2a90e8f1c3b", "event_type": "request_live_low_confidence", ... }
```
— Mireye
Errors
| Error code | HTTP | Meaning |
|---|---|---|
field_request_not_found | 404 | No such request under your credential — including someone else’s id (never a 403). |
field_requests_unavailable | 503 | The request store is unreachable. Retry with backoff. |
What we keep
Same policy as the POST page: address strings fromexample_locations are scrubbed 30 days after the
request reaches a terminal state; resolved coordinates and geocode metadata
are kept. Poll responses remain available after the scrub — only the address
text is removed.Path Parameters
Response
Successful Response
The response is of type Response Get Field Request V1 Field Requests Request Id Get · object.