# Low-Latency Reads: /v1/latest and /v1/recent | FXMacroData API

> The FXMacroData /v1/latest and /v1/recent routes return the newest stored announcement, COT and commodity rows without building a full series. Routes, authentication, parameters, response shape and the event-then-read pattern.

Source: https://fxmacrodata.com/documentation/low-latency
Documentation index: https://fxmacrodata.com/documentation/llms.txt
API base URL: https://api.fxmacrodata.com

# Low-latency reads

The `/v1/latest` and `/v1/recent` routes answer one question: what is the newest row in the store right now? They read a precomputed snapshot instead of assembling a full series, so they are the right call to make the moment a release event arrives.

## Six routes, three data families

`latest` returns the single newest stored row. `recent` returns the newest rows, most recent first, up to `limit` (default 5, maximum 50). Neither accepts date windows, selectors or pagination; use the history endpoints on the [API reference](https://fxmacrodata.com/documentation/reference) for those.

| Route | Returns | History equivalent |
| --- | --- | --- |
| GET /v1/latest/announcements/{currency}/{indicator} | Newest announcement row for the series | /v1/announcements/{currency}/{indicator} |
| GET /v1/recent/announcements/{currency}/{indicator}?limit=5 | Newest announcement rows, most recent first | /v1/announcements/{currency}/{indicator} |
| GET /v1/latest/cot/{currency} | Newest CFTC Commitments of Traders row | /v1/cot/{currency} |
| GET /v1/recent/cot/{currency}?limit=5 | Newest COT rows, most recent first | /v1/cot/{currency} |
| GET /v1/latest/commodities/{indicator} | Newest commodity observation | /v1/commodities/{indicator} |
| GET /v1/recent/commodities/{indicator}?limit=5 | Newest commodity observations, most recent first | /v1/commodities/{indicator} |

Currency and indicator slugs are the same as on the history endpoints; the [data catalogue](https://api.fxmacrodata.com/v1/data_catalogue/usd) lists them. An unknown slug returns 404 with the supported values.

## Authentication follows the data family

Send your key in the `X-API-Key` header (or `Authorization: Bearer`). The free-access rules are the same as on the history endpoints.

| Family | Without a key | With a key |
| --- | --- | --- |
| Announcements | USD only. A release becomes readable 15 minutes after publication; the response reports the hold in `freemium_delay`. | Every supported currency, no delay. |
| COT | USD only, with the same 15-minute hold on the newest report. | Every COT currency, no delay. |
| Commodities | Not available; the request returns 401. | Every published commodity indicator. |

When free access holds back every stored print, the response still answers 200 and `freemium_delay.withheld_count` tells you how many rows are waiting and when the next one becomes available. See [free access](https://fxmacrodata.com/documentation/rate-limits#free-access).

## Response shape

The envelope is deliberately small. `data` is one row on `latest` and an array on `recent`; each row carries the same fields as a history row, documented on the [response fields](https://fxmacrodata.com/documentation/response-fields) page.

```
{
  "currency": "USD",
  "indicator": "inflation",
  "source": "U.S. Bureau of Labor Statistics",
  "provenance": { "publisher": "...", "storage": "...", "served_by": "...", "timestamp_field": "announcement_datetime", "value_field": "val" },
  "data_quality": { "quality_scope": "latest", "point_in_time_safe": true, "latest_available_date": "2026-08-31", "...": "..." },
  "data": {
    "date": "2026-08-31",
    "val": 2.9,
    "announcement_datetime": 1757512800,
    "publication_time_status": "confirmed",
    "release_timing": { "published_by": "2026-09-10T12:30:00.412Z", "available_at": "2026-09-10T12:30:00.9031Z", "pickup_ms_max": 491.0, "...": "..." },
    "...": "..."
  }
}
```

- `recent` adds `count` and returns `data` as an array ordered most recent first.

- `data_quality.quality_scope` is `latest` or `recent`, so the quality counters describe exactly the rows returned.

- `freemium_delay` is present only when free access withheld a newer print.

- A series with nothing stored yet returns 503 rather than an empty row.

## Event, then read, then history

These routes are designed to sit behind a release event rather than to be polled on a timer.

1. **Receive the event.** A [webhook](https://fxmacrodata.com/documentation/webhooks), [SSE](https://fxmacrodata.com/documentation/sse-streams) or [WebSocket](https://fxmacrodata.com/documentation/websocket-streams) event, or a poll of `/v1/announcements/changes`, tells you a release for a currency and indicator has landed.

2. **Read the row.** Call `/v1/latest/announcements/{currency}/{indicator}` for the full row, including `release_timing` and provenance.

3. **Fetch history when you need it.** Use `/v1/announcements/{currency}/{indicator}` with a window, selectors or `revisions=all` for anything beyond the newest rows.

Polling `latest` on a tight loop counts against your plan's request allowance like any other call. Let a stream or webhook tell you when to read; see [rate limits](https://fxmacrodata.com/documentation/rate-limits).

## Examples

Newest USD inflation print, no key:

```
curl "https://api.fxmacrodata.com/v1/latest/announcements/usd/inflation"
```

Three most recent ECB policy-rate decisions:

```
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://api.fxmacrodata.com/v1/recent/announcements/eur/policy_rate?limit=3"
```

Newest COT report for the euro, and the newest gold observation:

```
curl -H "X-API-Key: YOUR_API_KEY" "https://api.fxmacrodata.com/v1/latest/cot/eur"
curl -H "X-API-Key: YOUR_API_KEY" "https://api.fxmacrodata.com/v1/latest/commodities/gold"
```

Python, reacting to a release event:

```
import requests

API = "https://api.fxmacrodata.com"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}

def on_release(event):
    currency = event["currency"].lower()
    indicator = event["indicator"]
    row = requests.get(
        f"{API}/v1/latest/announcements/{currency}/{indicator}",
        headers=HEADERS,
        timeout=10,
    ).json()["data"]
    print(row["date"], row["val"], row["publication_time_status"])
```
