Build with the DFO / API
Resolve a question
Use POST /api/v1/search/resolve to turn a plain-English question into one or more candidate data specifications.
Before you start
Set the development API URL.
export DFO_API=https://developmentfinance.org
Steps
-
Send a raw-text question.
GET /api/v1/search/capabilitiesreports the current query and variable limits.curl -fsS -X POST "$DFO_API/api/v1/search/resolve" \ -H "Content-Type: application/json" \ -d '{"input":{"kind":"raw_text","query":"ODA disbursements from Germany to Nigeria for basic health care"}}' \ > resolve.json jq 'if .kind == "resolution" then .parts[0] | {status, variable_text, spec_id: .spec.spec_id, sentence: .spec.resolved.rendered_sentence, warnings} else {kind, reason, scope} end' resolve.jsonimport json import os from pathlib import Path import httpx response = httpx.post( f"{os.environ['DFO_API']}/api/v1/search/resolve", json={ "input": { "kind": "raw_text", "query": "ODA disbursements from Germany to Nigeria for basic health care", } }, timeout=60, ) response.raise_for_status() document = response.json() Path("resolve.json").write_text(json.dumps(document)) if document["kind"] != "resolution": print(json.dumps({key: document.get(key) for key in ("kind", "reason", "scope")}, indent=2)) raise SystemExit part = document["parts"][0] summary = { "status": part["status"], "variable_text": part["variable_text"], "warnings": part["warnings"], } if part["status"] == "definite": spec = part["spec"] summary.update( { "spec_id": spec["spec_id"], "sentence": spec["resolved"]["rendered_sentence"], } ) print( json.dumps(summary, indent=2) )Check
kindbefore readingparts. A resolution has apartsentry for each extracted variable. Search reportsvariables_clampedwhen it drops variables beyond the current limit. -
Branch on the answer's
kind.Kind Result resolutionData answer with parts.catalogueA request to describe what DFO holds, with an optional country scope.place.declinedA question outside the available data or one that requires analysis. Read
GET /api/v1/search/cataloguefor the available data and example questions. Passplace=<country id>, the country's graph identifier such ascountry/NGA, to narrow it to one country.curl -fsS "$DFO_API/api/v1/search/catalogue?place=country/NGA" | jq . -
Branch on each part's
status.Status Meaning definiteSearch selected one reading. specholds its definition and result summary.candidatesSearch found more than one reading. candidates.specsis ordered bycandidates.ordering.no_dataSearch found no data for the reading. no_dataexplains why.unsupportedSearch understood the question but this deployment cannot express it. unsupportedgives the code.These are successful request outcomes and arrive with HTTP
200. Invalid requests use an application problem-details response. -
Check a definite result before using it. Read
spec.resolved.rendered_sentence, then inspectwarnings. For this question, check that Germany fills the donor role (origin), Nigeria fills the recipient role (destination), and basic health care isCRSPurposeCode12220. Open dimensions can expand the result to several StatVars (measures, each with its dimensions). -
Request observation previews when you need values in the response.
curl -fsS -X POST "$DFO_API/api/v1/search/resolve" \ -H "Content-Type: application/json" \ -d '{ "input":{"kind":"raw_text","query":"ODA disbursements from Germany to Nigeria for basic health care"}, "response_options":{"include_observations":true} }' \ | jq 'if .kind == "resolution" then .parts[0].spec.resolved.observations else {kind, reason, scope} end'A preview is delivered only for definite results. It can include a structured omission reason when the result exceeds the deployed preview limit or cannot be retrieved in time. Each delivered series has its own StatVar, role entities, points, and facet. Use Get a dataset for a complete downloadable result.
-
Read
no_data.reasonwhen a part has no data. Whenno_data.gateisonly_alternate_has_data,no_data.alternate_matchprovides another interpretation for review.
Stream a response
Send Accept: text/event-stream to receive a Search response as Server-Sent Events. The stream contains a response event, one observations event for each definite part that requested observations, and a terminal done event with the trace identifier. An observations event can report an omission reason.
Verify it worked
A usable result has a definite part whose confirmation sentence matches the requested measure, entities, date range, source, and unit. The spec_id is derived from the canonical spec definition. Keep the definition with the identifier when reproducibility matters.
Troubleshooting
422 query_too_longmeansinput.queryexceeds the current deployment limit. Split the request.- Use Look up names and codes when a place name resolves incorrectly or remains ambiguous.
Next
How the APIs fit together explains what a spec represents. Get a dataset turns a definite spec into files.