SAFE Rate Gateway API
POST write keyGET read keyD1 idempotent upsert
Authentication
Use Authorization: Bearer <key> or X-API-Key: <key>. WRITE_API_KEY is required for POST ingestion. READ_API_KEY is required for GET queries. /health and this page are public.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /health | Public health check. |
POST | /api/v1/rates | Collector upserts one or more daily SAFE rate rows. |
GET | /api/v1/rates | Downstream systems read rates by date, range, currency, or latest date. |
GET | /api/v1/rates/date-ranges | Downstream systems read stored start and end dates for one or more currencies. |
POST Format
All exchange-rate and amount-like values must be strings. The database key is rateDate + currencyCode, so retries are safe.
curl -X POST "$BASE_URL/api/v1/rates" \
-H "Authorization: Bearer $WRITE_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"rates": [
{
"rateDate": "2026-06-30",
"currencyCode": "USD",
"currencyName": "US Dollar",
"unit": "100",
"rate": "713.4200",
"publishedAt": "2026-06-30T09:15:00Z"
}
]
}'
GET Examples
curl -H "Authorization: Bearer $READ_API_KEY" \
"$BASE_URL/api/v1/rates?latest=true"
curl -H "X-API-Key: $READ_API_KEY" \
"$BASE_URL/api/v1/rates?date=2026-06-30¤cy=USD,EUR"
curl -H "Authorization: Bearer $READ_API_KEY" \
"$BASE_URL/api/v1/rates?from=2026-06-01&to=2026-06-30&limit=200"
curl -H "Authorization: Bearer $READ_API_KEY" \
"$BASE_URL/api/v1/rates/date-ranges?currency=USD,EUR"
Date Range Lookup
Use GET /api/v1/rates/date-ranges to find the earliest and latest stored SAFE rate date for one or more currencies. Pass comma-separated codes such as currency=USD,EUR or repeat currency/currencies. Requested currencies with no stored rows are returned in missingCurrencies.
Response Shape
{
"count": 1,
"rates": [
{
"rateDate": "2026-06-30",
"currencyCode": "USD",
"currencyName": "US Dollar",
"unit": "100",
"rate": "713.4200",
"source": "safe.gov.cn",
"publishedAt": "2026-06-30T09:15:00Z"
}
]
}
Date Range Response Shape
{
"count": 2,
"ranges": [
{
"currencyCode": "EUR",
"startDate": "2026-06-01",
"endDate": "2026-06-30",
"recordCount": 20
},
{
"currencyCode": "USD",
"startDate": "2026-06-01",
"endDate": "2026-06-30",
"recordCount": 20
}
],
"missingCurrencies": []
}