Documentation

Build with the DFO / API

API conventions

These conventions apply to the Search, Datasets, and Graph APIs in this guide.

Base URL

The API is served from the DFO website's address, and every route sits under /api/v1.

https://developmentfinance.org

The same routes also answer at /api without the version. Links that the API returns in a response use that form.

Use JSON request bodies and send Content-Type: application/json for requests with a body.

Versioning

Datasets requests and responses use schema_version: 1. Search responses also carry schema_version: 1. The Graph API has its own response shapes, which GET /api/v1/graph/schema publishes.

GET /api/v1/datasets/capabilities reports live Datasets formats, input kinds, feature flags, limits, and a capability version. Treat capability values as deployment data.

When the graph does not declare a facet default, the Datasets API uses dfo/facet-policy/most-observations version 1 as its deployment fallback.

Discover routes and contracts

RouteUse
GET /api/{search,datasets,graph}/healthzCheck that an API is available and identify its build.
GET /api/{search,datasets,graph}/capabilitiesRead deployment capabilities and limits.
GET /api/v1/search/schemaRead Search request and response schemas.
GET /api/v1/search/catalogueRead available data and example questions.
GET /api/v1/datasets/schemaRead Datasets request and response schemas.
GET /api/v1/graph/schemaRead Graph request and response schemas.
POST /api/v1/graph/nodesRead several graph nodes in one request.
GET /codes/{code}Read the registry entry for a problem code.
GET /openapi.jsonRead the OpenAPI document.
GET /docsOpen the interactive API documentation.

Trace headers

Application responses carry x-dfo-trace-id, except shared-cacheable responses. Include this identifier when reporting a problem. Search diagnostics and problem-details bodies carry the same trace identifier.

x-dfo-commit identifies the application build that answered the request. Server-Timing reports request timing where the response can carry it.

Problem details

Application-level non-2xx responses use application/problem+json with RFC 9457 fields and DFO extensions. A response has at least these fields:

{
  "type": "/codes/request_invalid",
  "title": "Bad Request",
  "status": 400,
  "detail": "Request body is invalid.",
  "code": "request_invalid",
  "trace_id": "...",
  "capability_version": "...",
  "retryable": false
}

pointer identifies the invalid location in a request body when available. alternatives, issues, cause, constraint_id, and ceiling details appear for the error types that define them. Branch on code and use retryable to decide whether to retry the same request.

Responses generated by infrastructure outside the application can use a different body.

Status codes

StatusMeaning
200Request completed. Search can still report candidates, no_data, or unsupported in a part.
202A Datasets operation is running. Poll the URL in operation.poll.
400 or 422Request validation or a request that cannot be satisfied. Read the problem code and pointer.
404The requested graph node, spec, snapshot, or operation is unknown.
410A snapshot is revoked or its artifacts are no longer servable.
500, 502, 503, or 504The application could not complete the request. Check retryable.

A Datasets 503 that reports a full instance carries Retry-After in seconds. Wait at least that long before you retry.

Graph limits

GET /api/v1/graph/capabilities reports the current Graph request and identifier limits. Read it before generating large resolver or node batches.

Next

How to resolve a question documents Search outcomes. How to get a dataset documents asynchronous operations and snapshot retention.

View as markdown