# GET /v1/fx

Current USD-based exchange rates used for currency conversion.

Returns the current USD-based exchange rates used to convert latest prices when you request a [currency](/docs/using-the-api#currency) other than USD. Rates update about every hour.

## Access

Available on all plans.

## Request

`GET https://api.cs2.sh/v1/fx`

**curl**

```bash
curl https://api.cs2.sh/v1/fx \
  -H "Authorization: Bearer <<YOUR_API_KEY>>" \
  -H "Accept-Encoding: gzip" --compressed
```

**Python**

```python
import requests

headers = {
    "Authorization": "Bearer <<YOUR_API_KEY>>",
    "Accept-Encoding": "gzip",
}

response = requests.get(
    "https://api.cs2.sh/v1/fx",
    headers=headers,
)

response.raise_for_status()
data = response.json()
```

**Node**

```javascript
const headers = {
  "Authorization": "Bearer <<YOUR_API_KEY>>",
  "Accept-Encoding": "gzip",
};

const response = await fetch("https://api.cs2.sh/v1/fx", { headers });

if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
```

**Go**

```go
package main

import (
    "compress/gzip"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    req, _ := http.NewRequest("GET", "https://api.cs2.sh/v1/fx", nil)
    req.Header.Set("Authorization", "Bearer <<YOUR_API_KEY>>")
    req.Header.Set("Accept-Encoding", "gzip")

    resp, err := http.DefaultClient.Do(req)
    if err != nil { panic(err) }
    defer resp.Body.Close()

    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
        body, _ := io.ReadAll(resp.Body)
        panic(fmt.Sprintf("HTTP %d: %s", resp.StatusCode, body))
    }

    var reader io.Reader = resp.Body
    if resp.Header.Get("Content-Encoding") == "gzip" {
        gz, err := gzip.NewReader(resp.Body)
        if err != nil { panic(err) }
        defer gz.Close()
        reader = gz
    }

    var data any
    if err := json.NewDecoder(reader).Decode(&data); err != nil { panic(err) }
    fmt.Printf("%#v\n", data)
}
```

**R**

```r
library(httr2)

resp <- request("https://api.cs2.sh/v1/fx") |>
  req_headers(
    Authorization = "Bearer <<YOUR_API_KEY>>",
    `Accept-Encoding` = "gzip"
  ) |>
  req_perform()

data <- resp_body_json(resp)
```

## Response

```json
{
  "base": "USD",
  "updated_at": "2026-09-22T23:00:02Z",
  "collected_at": "2026-09-22T23:00:54.577Z",
  "fresh": true,
  "rates": {
    "AUD": 1.40622087,
    "CAD": 1.40543053,
    "CHF": 0.82058071,
    "CNY": 6.71350215,
    "EUR": 0.87319354,
    "GBP": 0.74932836,
    "JPY": 157.40767305,
    "NZD": 1.74524572,
    "SGD": 1.27536852,
    "USD": 1
  }
}
```

## Response fields

[FXResponse](/docs/objects#fxresponse) fields:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `base` | `string` | Yes | Base currency (always `USD`). |
| `updated_at` | `string (date-time)` | Yes | When the rate provider published these rates. |
| `collected_at` | `string (date-time)` | Yes | When cs2.sh collected them. |
| `fresh` | `boolean` | Yes | `false` when the rates are more than 2 hours old. Latest-price conversion keeps using them for up to 24 hours. |
| `rates` | `Record<string, number>` | Yes | Units of each currency per 1 USD, keyed by currency code. |

## Errors

`400 validation_error` means query parameters were supplied. `503 service_unavailable` means exchange rates are unavailable. See [Request errors](/docs/using-the-api#request-errors) for shared errors.
