Discover API
The Discover API helps LLM agents and programmatic clients find relevant datasets using natural language queries. Unlike the Search endpoint, Discover returns enriched metadata including column schemas, canonical questions, and relevance scores designed for machine consumption.
Authentication
The Discover endpoint requires authentication. Pass your API key in the Authorization header. See the Authentication guide to get your key.
GET /v1/discover?q=inflation+dataAuthorization: Bearer od_live_your_key_here
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| q | string | required | Natural language query describing the data you need |
| provider | string | null | Filter by provider slug (e.g. bls, census) |
| category | string | null | Filter by category or subject tag |
| format | string | null | Filter by data format |
| status | string | "ready" | Filter by dataset status |
| limit | int (1-20) | 5 | Maximum number of results |
| include_columns | bool | true | Include column schemas in each result |
Response Shape
Each result includes enriched metadata that goes well beyond basic search results. Null fields are omitted for a clean payload. Here is what a typical response looks like:
{"results": [{"name": "Life Expectancy","provider": "owid","path": "/v1/datasets/owid/life-expectancy","description": "Life expectancy data by country...","rows": 19504,"format": "auto","categories": ["demographics", "health"],"temporal_granularity": "annual","geographic_scope": "country","canonical_questions": ["How has life expectancy changed over the past 50 years?"],"methodology_summary": "Compiled from UN Population Division...","columns": [{"name": "life_expectancy","type": "float","sample_values": ["28.15", "37.93", "51.02"],"distinct_count": 996,"display_name": "Life Expectancy (years)","value_range": {"min": 18.2, "max": 86.37}}],"available_views": [{"name": "latest", "description": "Most recent life expectancy by country"},{"name": "by-country", "description": "Time series by country"}],"relevance": 0.94,"semantic_score": 0.82,"quality_score": 0.87,"is_enriched": true}],"total": 3,"query": "life expectancy by country","processing_time_ms": 142,"available_categories": ["demographics", "economics", "education", "health", "labor"]}
Key fields
- columns - Column schemas with types, sample values, display names, value ranges, and units. Use these to construct follow-up queries without a separate columns introspection call.
- available_views - Named views that pre-aggregate or transform the raw data. Saves a separate
/viewscall. - available_categories (top-level) - All platform category slugs, so agents know what
category=values are valid. - canonical_questions - Example questions the dataset can answer. Useful for LLM agents deciding which dataset to query.
- sample_rows - Up to 5 representative rows (when available), letting agents evaluate data format without a SQL call.
- path - The API path to fetch actual data rows from this dataset.
- relevance / semantic_score / quality_score - Scoring breakdown to help agents rank and select datasets programmatically.
- is_enriched - Whether LLM-generated metadata (categories, canonical questions, methodology) is available for this dataset.
Batch Discover
Run multiple queries in a single call. Results are deduplicated across queries, so datasets matching multiple topics appear once with full metadata.
curl -X POST 'https://api.tryopendata.ai/v1/discover/batch' \-H 'Authorization: Bearer YOUR_API_KEY' \-H 'Content-Type: application/json' \-d '{"queries": ["healthcare spending", "life expectancy", "drug prices"],"limit_per_query": 3,"deduplicate": true}'
The response includes query_results (per-query dataset references with relevance) and datasets (deduplicated full metadata). This is useful for multi-agent workflows where a main thread discovers everything upfront and dispatches agents with pre-identified datasets.
Finding Datasets
Pass a natural language query describing the data you are looking for. The endpoint combines text search with semantic similarity to find the best matches.
GET /v1/discover?q=county+level+poverty+ratesAuthorization: Bearer od_live_...
{"results": [{"name": "Small Area Income and Poverty Estimates","provider": "census","path": "/v1/datasets/census/saipe","relevance": 0.91,...}],"total": 2,"query": "county level poverty rates","processing_time_ms": 98}
Using Column Schemas for Follow-up Queries
The column schemas in discover results give you everything you need to construct a data query without an extra API call. Here is a two-step workflow:
Step 1: Discover the dataset
GET /v1/discover?q=monthly+employment+statistics&provider=blsAuthorization: Bearer od_live_...
Step 2: Query using column info from the response
The response tells you the column names, types, and sample values. Use that to build a filtered query:
GET /v1/datasets/bls/employment?filter[year][gte]=2020&sort=-year&limit=50Authorization: Bearer od_live_...
Filtering Results
Narrow discover results by provider, category, or format:
# Only BLS datasetsGET /v1/discover?q=employment&provider=blsAuthorization: Bearer od_live_...# Only economics categoryGET /v1/discover?q=prices&category=economicsAuthorization: Bearer od_live_...
Lighter Responses
If you only need dataset-level metadata and want to skip column schemas, set include_columns=false for a smaller payload:
GET /v1/discover?q=inflation&include_columns=falseAuthorization: Bearer od_live_...
Discover vs Search
| /v1/search | /v1/discover | |
|---|---|---|
| Auth | Not required | Required |
| Audience | Human users, web UI | LLM agents, programmatic clients |
| Metadata | Basic (name, description, provider) | Enriched (columns, questions, methodology) |
| Scoring | Text relevance | Semantic + quality scoring |
| Facets | Yes | No |
| Views | No | Yes (available_views per dataset) |
| Batch | No | Yes (POST /v1/discover/batch) |
Related
- Search Guide - Full-text search for browsing datasets
- API Reference - Complete endpoint documentation
- Authentication - Get your API key
- Querying Data - Query dataset rows after discovery