Getting started
Quickstart
Every dataset uses the same base URL, the same key and the same response envelope, so what follows works for each of them. The examples read ecb/fx-reference, the European Central Bank’s euro reference rates; swap in any dataset id from the catalogue.
Get a key
Create an account, then create a key from your dashboard. A key is shown once, so put it straight into an environment variable; the samples here read it from ODR_KEY, and no sample on this site holds one.
export ODR_KEY="<your key>"Find a dataset
Search the catalogue. Search, metadata and schemas need no key and cost nothing.
curl -G 'https://api.opendatarouter.com/v1/datasets' \
--data-urlencode 'q=exchange rates'Each result has an id of the form publisher/dataset and an availability: api_ready datasets read row by row.
Read its schema
The schema lists each field with its type and unit, and the access paths: the filters a query must use to read the rows in a given order.
curl 'https://api.opendatarouter.com/v1/datasets/ecb/fx-reference/schema'Query rows
Ask for rows with your key. Filters follow the schema: currency=USD binds the layout ordered by currency, and date[gte] bounds the dates. Rows cost units; see the free plan.
The request
curl --globoff -G 'https://api.opendatarouter.com/v1/datasets/ecb/fx-reference/rows' \
--data-urlencode 'currency=USD' \
--data-urlencode 'date[gte]=2026-01-01' \
-H "Authorization: Bearer $ODR_KEY"Read the envelope
Every row response has the same parts:
| Field | Type | Meaning |
|---|---|---|
| data | array | The rows, keyed by field name and typed by the schema. |
| meta.release_id | string | The immutable release the rows came from. |
| meta.licence | object | The licence terms frozen with that release. |
| meta.citation | object | A citation to paste, with a pinned link. |
| meta.source | object | The upstream publisher the release was built from. |
| meta.route | object | How this response was served: from the edge cache, a replica or a live snapshot. |
| meta.usage | object | The units this request used. |
| meta.cost_usd | number | What it cost in US dollars: always zero in the pilot. |
| next_cursor | string or null | Pass it back as cursor for the next page; null on the last. |
Page through and pin
Pass next_cursor back as cursor until it is null. A cursor is pinned to its release, so a walk never mixes two releases.
To read exactly the same rows later, add release= with the meta.release_id you got. Releases are immutable, and each dataset page lists the ones it keeps, with links pinned to each.