# Exchange rates

Source: https://docs.settlemint.com/docs/api-reference/feeds/exchange-rates
Read current and historical fiat currency pair rates, discover supported currencies, and understand how DALP selects one feed per pair and resolves inverse pairs.



The exchange rates API exposes fiat currency pairs for pricing, valuation, and reconciliation workflows. Call the routes under `/api/v2` for all new integrations: they return DALP response envelopes and use the shared collection query format for lists.

The routes cover reads only. Feed setup, feed governance, and legal valuation policy remain outside this API contract.

## Endpoints [#endpoints]

| Job                        | Method and path                                                     | Use it for                                                                                             | Response shape                                         |
| -------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ |
| List exchange rates        | `GET /api/v2/exchange-rates`                                        | Discover available base and quote pairs, latest observations, and feed links.                          | Collection envelope with `data`, `meta`, and `links`.  |
| Read the current pair rate | `GET /api/v2/exchange-rates/{baseCurrency}/{quoteCurrency}`         | Read the latest observed rate for one currency pair.                                                   | Single-resource envelope with `data` and `links.self`. |
| Read historical pair rates | `GET /api/v2/exchange-rates/{baseCurrency}/{quoteCurrency}/history` | Inspect observations for one pair with collection filters and pagination.                              | Collection envelope with `data`, `meta`, and `links`.  |
| List supported currencies  | `GET /api/v2/exchange-rates/supported-currencies`                   | Build currency pickers from the ISO 4217 codes the configured exchange-rate source currently supports. | Single-resource envelope with `data` and `links.self`. |

Exchange rate routes use ISO 4217 alpha-3 currency codes. Use uppercase codes such as `EUR` and `USD` in path parameters and filters.

## List available rates [#list-available-rates]

Call the list endpoint before you request a specific conversion path. It returns one record per currency pair after DALP deduplicates the active feed rows for each pair. When several active feeds describe the same pair, DALP keeps the most recently observed feed; see [feed selection](#feed-selection) for the full rule.

```bash
curl --globoff "https://your-platform.example.com/api/v2/exchange-rates?filter[baseCurrency]=EUR&filter[quoteCurrency]=USD&page[limit]=50&page[offset]=0&sort=-effectiveAt" \
  -H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"
```

The response uses the collection envelope:

```json
{
  "data": [
    {
      "baseCurrency": "EUR",
      "quoteCurrency": "USD",
      "rate": 1.08,
      "effectiveAt": "2026-03-22T10:30:00.000Z",
      "updatedAt": "2026-03-22T10:31:00.000Z",
      "feedAddress": "0xabcdef1234567890abcdef1234567890abcdef12"
    }
  ],
  "meta": {
    "total": 1,
    "facets": {
      "baseCurrency": [{ "value": "EUR", "count": 1 }],
      "quoteCurrency": [{ "value": "USD", "count": 1 }]
    }
  },
  "links": {
    "self": "/v2/exchange-rates?filter[baseCurrency]=EUR&filter[quoteCurrency]=USD&page[limit]=50&page[offset]=0&sort=-effectiveAt",
    "first": "/v2/exchange-rates?filter[baseCurrency]=EUR&filter[quoteCurrency]=USD&page[limit]=50&page[offset]=0&sort=-effectiveAt",
    "next": null,
    "prev": null,
    "last": "/v2/exchange-rates?filter[baseCurrency]=EUR&filter[quoteCurrency]=USD&page[limit]=50&page[offset]=0&sort=-effectiveAt"
  }
}
```

`rate`, `effectiveAt`, `updatedAt`, and `feedAddress` can be `null` when a listed pair exists but has no usable observation yet. Treat a listed pair as discoverable; do not assume it is fresh enough for a valuation workflow.

## Read one current rate [#read-one-current-rate]

Call the pair read endpoint when you already know the pair you need. DALP responds with `404` and `EXCHANGE_RATE_NOT_FOUND` when no current rate exists for the requested pair; the endpoint never returns `null` for a missing rate. When `baseCurrency` and `quoteCurrency` are the same code, DALP gives an identity rate of `1`.

```bash
curl "https://your-platform.example.com/api/v2/exchange-rates/EUR/USD" \
  -H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"
```

The response carries one `data` object and a self link:

```json
{
  "data": {
    "baseCurrency": "EUR",
    "quoteCurrency": "USD",
    "rate": 1.08,
    "effectiveAt": "2026-03-22T10:30:00.000Z"
  },
  "links": {
    "self": "/v2/exchange-rates/EUR/USD"
  }
}
```

## Feed selection [#feed-selection]

DALP keeps one rate per currency pair. When more than one active feed describes the same pair, DALP resolves a single record using these rules:

* A feed that has produced an observation outranks a feed with no observations yet.
* Among feeds with observations, the most recently observed rate wins, and that choice is stable: the same set of active feeds resolves to the same rate on every call.

Once a pair has at least one observed feed, the list and read endpoints agree on the resolved rate. A pair with overlapping observed feeds always returns one consistent rate, never a different feed on each request. Use `feedAddress` on a list record to confirm which feed produced the rate you read. Before any feed for a pair has been observed, the two endpoints differ: the list endpoint surfaces the pair as a discoverable record with a `null` `rate`, while the read endpoint returns `404` with `EXCHANGE_RATE_NOT_FOUND`. Treat a freshly registered pair as discoverable until its first observation lands.

### Inverse-pair resolution on a read [#inverse-pair-resolution-on-a-read]

The single-pair read at `GET /api/v2/exchange-rates/{baseCurrency}/{quoteCurrency}` also resolves the reverse pair when the requested direction has no observed feed:

* If an observed feed exists for the requested pair, DALP returns its rate directly.
* If the requested pair has no observed feed but the reverse pair does, DALP inverts the reverse-pair rate and serves that value.
* If neither direction has an observed feed, DALP responds with `404` and `EXCHANGE_RATE_NOT_FOUND`.

A read can therefore return a usable rate for `EUR/USD` even when only a `USD/EUR` feed is observed, by inverting that reverse rate. The list route preserves feed direction: it returns each pair exactly as its feed describes it. To confirm whether a rate came from a direct or inverted feed, compare the read result against the corresponding list record.

## Read historical rates [#read-historical-rates]

Call the history route when you need a time-bounded record of observations for reconciliation, reporting, or a valuation review.

```bash
curl --globoff "https://your-platform.example.com/api/v2/exchange-rates/EUR/USD/history?filter[effectiveAt][gte]=2026-03-01T00:00:00.000Z&filter[effectiveAt][lte]=2026-03-31T23:59:59.999Z&page[limit]=100&sort=-effectiveAt" \
  -H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"
```

The history response uses the same collection envelope as the list endpoint:

```json
{
  "data": [
    {
      "baseCurrency": "EUR",
      "quoteCurrency": "USD",
      "rate": "1.08",
      "effectiveAt": "2026-03-22T10:30:00.000Z"
    }
  ],
  "meta": {
    "total": 1,
    "facets": {}
  },
  "links": {
    "self": "/v2/exchange-rates/EUR/USD/history?filter[effectiveAt][gte]=2026-03-01T00:00:00.000Z&filter[effectiveAt][lte]=2026-03-31T23:59:59.999Z&page[limit]=100&sort=-effectiveAt",
    "first": "/v2/exchange-rates/EUR/USD/history?filter[effectiveAt][gte]=2026-03-01T00:00:00.000Z&filter[effectiveAt][lte]=2026-03-31T23:59:59.999Z&page[limit]=100&page[offset]=0&sort=-effectiveAt",
    "next": null,
    "prev": null,
    "last": "/v2/exchange-rates/EUR/USD/history?filter[effectiveAt][gte]=2026-03-01T00:00:00.000Z&filter[effectiveAt][lte]=2026-03-31T23:59:59.999Z&page[limit]=100&page[offset]=0&sort=-effectiveAt"
  }
}
```

Historical `rate` values are decimal strings. Use decimal arithmetic instead of converting them through binary floating-point numbers in financial workflows.

## List supported currencies [#list-supported-currencies]

Call the supported-currencies endpoint before you render a target-currency picker. It returns the ISO 4217 alpha-3 codes currently present in the configured rate-source snapshot.

```bash
curl "https://your-platform.example.com/api/v2/exchange-rates/supported-currencies" \
  -H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"
```

```json
{
  "data": {
    "providerKey": "open-er-api",
    "currencies": ["AED", "EUR", "USD"]
  },
  "links": {
    "self": "/v2/exchange-rates/supported-currencies"
  }
}
```

`providerKey` identifies the configured exchange-rate source snapshot. Treat `currencies` as the allowed picker set for the next exchange-rate refresh cycle.

## Parameters and fields [#parameters-and-fields]

| Field                 | Location       | Type                      | Notes                                                                                             |
| --------------------- | -------------- | ------------------------- | ------------------------------------------------------------------------------------------------- |
| `baseCurrency`        | Path or filter | ISO 4217 fiat code        | Currency the rate converts from. The list endpoint supports `filter[baseCurrency]=EUR`.           |
| `quoteCurrency`       | Path or filter | ISO 4217 fiat code        | Currency the rate converts to. The list endpoint supports `filter[quoteCurrency]=USD`.            |
| `filter[q]`           | Query          | string                    | Free-text search across base and quote currency codes on the list endpoint.                       |
| `filter[rate]`        | Query          | number filter             | Filter list or history rows by rate. Use operators such as `filter[rate][gte]=1`.                 |
| `filter[effectiveAt]` | Query          | timestamp filter          | Filter list or history rows by observation timestamp. Use ISO 8601 UTC timestamps.                |
| `filter[updatedAt]`   | Query          | timestamp filter          | Filter list rows by last update timestamp.                                                        |
| `page[limit]`         | Query          | integer                   | Page size for collection responses.                                                               |
| `page[offset]`        | Query          | integer                   | Offset for collection responses.                                                                  |
| `sort`                | Query          | string                    | Sort field. Prefix with `-` for descending order, such as `sort=-effectiveAt`.                    |
| `rate`                | Response       | number, string, or `null` | List and current reads return numbers; history returns decimal strings; list items may be `null`. |
| `effectiveAt`         | Response       | timestamp or `null`       | Time when the returned rate became effective. List items may be `null` before an observation.     |
| `updatedAt`           | Response       | timestamp or `null`       | Time when the listed rate record was last updated.                                                |
| `feedAddress`         | Response       | EVM address or `null`     | Feed contract address for a listed pair when one is available.                                    |
| `providerKey`         | Response       | string                    | Identifier for the supported-currencies snapshot.                                                 |
| `currencies`          | Response       | ISO 4217 fiat code array  | Currency codes available from the supported-currencies endpoint.                                  |

## Related pages [#related-pages]

* [Token price resolution](/docs/api-reference/tokens/token-price-resolution) explains how token pricing can use base-price and FX feeds for converted token prices.
* [Operational integration patterns](/docs/api-reference/reference/operational-integration-patterns) covers retries, readback checks, and reconciliation patterns around API integrations.
* [API reference](/docs/api-reference/reference/openapi) remains the contract source for generated clients and route details.
