openapi: 3.1.0
info:
  title: fxapi
  version: "3"
  summary: Current and historical foreign exchange (fiat, metal and crypto) rates.
  description: >-
    fxapi provides real-time and historical currency exchange rates for
    fiat, precious metal and crypto currencies. All endpoints are served over
    HTTPS and return JSON. Authenticate every request with your API key, either
    as the `apikey` query parameter or the `apikey` request header.


    `HEAD` answers 405 (`method_not_allowed`; `Allow` names the methods the
    endpoint takes) on every billed endpoint, without running or billing it.
    `/v1/status` and the other free endpoints answer it like `GET`.


    This document is generated from the fxapi service implementation and is
    the machine-readable source of truth for the v3 REST API. A human-readable
    version is available at https://fxapi.com/docs.
  contact:
    name: fxapi support
    email: support@fxapi.com
    url: https://support.fxapi.com/
  x-logo:
    url: https://fxapi.com/img/logo-fxapi.png
servers:
  - url: https://api.fxapi.com
    description: Production
security:
  - ApiKeyQuery: []
  - ApiKeyHeader: []
tags:
  - name: Rates
    description: Live, historical and converted exchange rates.
  - name: Metadata
    description: Supported currencies and account status.
paths:
  /v1/latest:
    get:
      tags:
        - Rates
      summary: Latest exchange rates
      operationId: getLatest
      description: >-
        Returns the latest exchange rates for a given base currency (default
        `USD`). The update interval of the returned data depends on your
        subscription plan (from daily down to minutely).


        Optional representations, none of which changes the default response:
        `shape=compact` for plain values (`"EUR": 0.918456`), `precision` to
        round, `inverse=true` for the value of one unit of each currency in
        the base currency, `include=change` for the change since the previous
        day's close, and `format=csv`.
      parameters:
        - $ref: '#/components/parameters/BaseCurrency'
        - $ref: '#/components/parameters/Currencies'
        - $ref: '#/components/parameters/Type'
        - name: include
          in: query
          required: false
          description: >-
            `change` adds `change` and `change_pct` to every rate: the
            difference to the close of the day before `last_updated_at`
            (`meta.change_since`), computed like `/v1/fluctuation`. Null when
            that close has no rate for the currency. Not with `shape=compact`.
          schema:
            type: string
            enum:
              - change
        - $ref: '#/components/parameters/Shape'
        - $ref: '#/components/parameters/Inverse'
        - $ref: '#/components/parameters/Precision'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: Latest exchange rates.
          headers:
            X-RateLimit-Limit-Quota-Month:
              $ref: '#/components/headers/RateLimitLimitQuotaMonth'
            X-RateLimit-Remaining-Quota-Month:
              $ref: '#/components/headers/RateLimitRemainingQuotaMonth'
            X-Cost:
              $ref: '#/components/headers/Cost'
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="latest.xlsx"`.
              schema:
                type: string
              example: attachment; filename="latest.xlsx"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExchangeRatesResponse'
              example:
                meta:
                  last_updated_at: "2023-06-23T10:15:59Z"
                  base_currency: USD
                data:
                  AED:
                    code: AED
                    value: 3.67306
                  AFN:
                    code: AFN
                    value: 91.80254
                  EUR:
                    code: EUR
                    value: 0.918456
            text/csv:
              schema:
                type: string
              example: |
                datetime,base_currency,currency,value
                2023-06-23T10:15:59Z,USD,AED,3.67306
                2023-06-23T10:15:59Z,USD,EUR,0.918456
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/historical:
    get:
      tags:
        - Rates
      summary: Historical exchange rates
      operationId: getHistorical
      description: >-
        Returns the exchange rates for a specific date. Historical data is
        available back to 1999. The `date` must be at least one day in the past.


        Send `dates` instead of `date` for up to 31 days in one request: `data`
        is then keyed by date and the request costs one request per date (see
        `X-Cost`). Takes the same optional representations as `/v1/latest`
        (`shape`, `precision`, `inverse`, `format=csv`).
      parameters:
        - name: date
          in: query
          required: false
          description: >-
            Date to retrieve historical rates for (format `YYYY-MM-DD`).
            Required unless `dates` is sent; not together with `dates`.
          schema:
            type: string
            format: date
          example: "2022-01-01"
        - name: dates
          in: query
          required: false
          description: >-
            Up to 31 dates (format `YYYY-MM-DD`), comma-separated or as
            `dates[]=`. Each date is answered once, oldest first, and costs one
            request.
          style: form
          explode: false
          schema:
            type: array
            maxItems: 31
            items:
              type: string
              format: date
          example:
            - "2022-01-31"
            - "2022-02-28"
        - $ref: '#/components/parameters/BaseCurrency'
        - $ref: '#/components/parameters/Currencies'
        - $ref: '#/components/parameters/Type'
        - $ref: '#/components/parameters/Shape'
        - $ref: '#/components/parameters/Inverse'
        - $ref: '#/components/parameters/Precision'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: >-
            Historical exchange rates for the requested date, or keyed by date
            for `dates`.
          headers:
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="historical.xlsx"`.
              schema:
                type: string
              example: attachment; filename="historical.xlsx"
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ExchangeRatesResponse'
                  - $ref: '#/components/schemas/HistoricalDatesResponse'
              example:
                meta:
                  last_updated_at: "2022-01-01T23:59:59Z"
                  base_currency: USD
                  date: "2022-01-01"
                data:
                  AED:
                    code: AED
                    value: 3.67306
                  AFN:
                    code: AFN
                    value: 91.80254
            text/csv:
              schema:
                type: string
              example: |
                datetime,base_currency,currency,value
                2022-01-01T23:59:59Z,USD,AED,3.67306
                2022-01-01T23:59:59Z,USD,EUR,0.918456
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/convert:
    get:
      tags:
        - Rates
      summary: Convert a value between currencies
      operationId: getConvert
      description: >-
        Converts a value from the base currency into all (or a filtered set of)
        currencies, for today or for a given historical date. Requires a plan
        that includes the convert endpoint. Optional: `shape=compact`,
        `precision` and `format=csv`.


        Send `values` instead of `value` to convert up to 100 amounts in one
        request: `data` is then a list with one `{value, currencies}` entry
        per amount, in the order sent, and `meta.values` replaces
        `meta.value`. `datetime` converts at a moment within your plan's
        intraday history, like `/v1/rate` (the minute, quarter hour or hour it
        falls in: minutes for the last 7 days, hours for the last 3 months);
        it needs a plan with intraday updates.


        For shop prices, `round_step` or `price_ending` (with `round_mode`)
        add `rounded` to every converted value, and `locale` adds
        `formatted`, the amount as text for that locale (e.g.
        `"€ 1.233,99"` for `de_AT`). `value` itself always stays exact.
        Rounding and `locale` are not available with `shape=compact`.
      parameters:
        - name: value
          in: query
          required: false
          description: >-
            The value to convert. Must be greater than 0 and at most 10^18.
            Required unless `values` is sent; not together with `values`.
          schema:
            type: number
            exclusiveMinimum: 0
            maximum: 1000000000000000000
          example: 12
        - name: values
          in: query
          required: false
          description: >-
            Up to 100 values to convert (each greater than 0 and at most
            10^18), comma-separated or as `values[]=`. `data` becomes a list
            with one entry per value, in the order sent. The request costs one request.
          style: form
          explode: false
          schema:
            type: array
            minItems: 1
            maxItems: 100
            items:
              type: number
              exclusiveMinimum: 0
              maximum: 1000000000000000000
          example:
            - 9.99
            - 24.5
            - 100
        - name: date
          in: query
          required: false
          description: >-
            Optional date to convert against historical rates (format
            `YYYY-MM-DD`). Must be at least one day in the past. Omit for the
            latest rates. Not together with `datetime`.
          schema:
            type: string
            format: date
          example: "2022-01-01"
        - name: datetime
          in: query
          required: false
          description: >-
            Convert at this moment within your plan's intraday history (ISO
            8601): the rate of the minute, quarter hour or hour it falls in,
            as `/v1/rate` finds it. `meta.last_updated_at` is that point.
            Needs a plan with intraday updates (`403` on daily plans); moments
            beyond the plan's history return a `422`.
          schema:
            type: string
            format: date-time
          example: "2026-09-30T10:07:30Z"
        - $ref: '#/components/parameters/BaseCurrency'
        - $ref: '#/components/parameters/Currencies'
        - $ref: '#/components/parameters/Type'
        - name: round_step
          in: query
          required: false
          description: >-
            Adds `rounded`: every converted value rounded to a multiple of
            this step (greater than 0, at most 10^18), e.g. `0.05`, `1` or
            `10`. Not together with `price_ending`; not with `shape=compact`.
          schema:
            type: number
            exclusiveMinimum: 0
            maximum: 1000000000000000000
          example: 0.05
        - name: price_ending
          in: query
          required: false
          description: >-
            Adds `rounded`: every converted value rounded to a price with this
            ending (at least 0, below 1), e.g. `0.99` turns 10.97 into 10.99.
            Not together with `round_step`; not with `shape=compact`.
          schema:
            type: number
            minimum: 0
            exclusiveMaximum: 1
          example: 0.99
        - name: round_mode
          in: query
          required: false
          description: >-
            How `round_step` and `price_ending` round: to the `nearest`
            candidate (default), always `up` or always `down`.
          schema:
            type: string
            enum:
              - nearest
              - up
              - down
            default: nearest
        - name: locale
          in: query
          required: false
          description: >-
            Adds `formatted`: every converted value as text in this ICU locale
            (e.g. `de_AT`, `en-US`), with the currency's symbol and decimal
            places (at most 8; none with a whole-number `round_step`). With
            rounding, the rounded price is formatted. An unknown locale
            returns a `422`. Not with `shape=compact`.
          schema:
            type: string
            maxLength: 20
          example: de_AT
        - $ref: '#/components/parameters/Shape'
        - $ref: '#/components/parameters/Precision'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: >-
            Converted values keyed by currency code, or with `values` a list
            with one entry per value.
          headers:
            X-Cost:
              $ref: '#/components/headers/Cost'
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="convert.xlsx"`.
              schema:
                type: string
              example: attachment; filename="convert.xlsx"
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ExchangeRatesResponse'
                  - $ref: '#/components/schemas/ConvertValuesResponse'
              examples:
                value:
                  summary: One value on a past date
                  value:
                    meta:
                      last_updated_at: "2022-01-01T23:59:59Z"
                      base_currency: USD
                      value: 12
                      date: "2022-01-01"
                    data:
                      AED:
                        code: AED
                        value: 44.07672
                      EUR:
                        code: EUR
                        value: 11.021472
                values:
                  summary: Several values (values=10,2.5, shape=compact)
                  value:
                    meta:
                      last_updated_at: "2026-09-29T23:59:59Z"
                      base_currency: USD
                      values:
                        - 10
                        - 2.5
                    data:
                      - value: 10
                        currencies:
                          EUR: 9
                      - value: 2.5
                        currencies:
                          EUR: 2.25
                shop_prices:
                  summary: A shop price (price_ending=0.99, locale=de_AT)
                  value:
                    meta:
                      last_updated_at: "2026-09-29T23:59:59Z"
                      base_currency: USD
                      value: 1371.11
                    data:
                      EUR:
                        code: EUR
                        value: 1233.999
                        rounded: 1233.99
                        formatted: "€ 1.233,99"
            text/csv:
              schema:
                type: string
              examples:
                value:
                  summary: One value
                  value: |
                    datetime,base_currency,currency,value
                    2022-01-01T23:59:59Z,USD,AED,44.07672
                    2022-01-01T23:59:59Z,USD,EUR,11.021472
                values:
                  summary: Several values (an amount column after base_currency)
                  value: |
                    datetime,base_currency,amount,currency,value
                    2026-09-29T23:59:59Z,USD,10,EUR,9
                    2026-09-29T23:59:59Z,USD,2.5,EUR,2.25
                shop_prices:
                  summary: With rounding and locale (rounded and formatted columns)
                  value: |
                    datetime,base_currency,currency,value,rounded,formatted
                    2026-09-29T23:59:59Z,USD,EUR,1233.999,1233.99,"€1,233.99"
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/rate:
    get:
      tags:
        - Rates
      summary: Exchange rate of one currency pair
      operationId: getRate
      description: >-
        Returns the rate of one pair as a single number: how many units of
        `to` one unit of `from` buys, and the inverse. Latest at your plan's
        update interval by default, the close of a past `date`, or the rate at
        a `datetime` within your plan's intraday history (the minute, quarter
        hour or hour it falls in, as `/v1/range` reports it: minutes for the
        last 7 days, hours for the last 3 months). `datetime` needs a plan
        with intraday updates.


        `format=text` answers with the bare number, so spreadsheets can read
        it directly, e.g. Google Sheets
        `=IMPORTDATA("https://api.fxapi.com/v1/rate?from=EUR&to=USD&format=text&apikey=YOUR-API-KEY")`
        or Excel `=WEBSERVICE(...)`.
      parameters:
        - name: from
          in: query
          required: true
          description: The currency to convert from.
          schema:
            $ref: '#/components/schemas/CurrencyCode'
          example: EUR
        - name: to
          in: query
          required: true
          description: The currency to convert to.
          schema:
            $ref: '#/components/schemas/CurrencyCode'
          example: USD
        - name: date
          in: query
          required: false
          description: >-
            The close of this past day (format `YYYY-MM-DD`). Not together
            with `datetime`.
          schema:
            type: string
            format: date
          example: "2022-01-01"
        - name: datetime
          in: query
          required: false
          description: >-
            A moment within your plan's intraday history (ISO 8601). A moment
            not stored yet gets the newest rate.
          schema:
            type: string
            format: date-time
          example: "2026-09-30T10:07:30Z"
        - $ref: '#/components/parameters/Precision'
        - name: format
          in: query
          required: false
          description: >-
            `json` (default), `csv` (`from,to,rate,inverse,last_updated_at`),
            `xlsx` (the same table as an Excel workbook, `rate.xlsx`) or
            `text` (only the rate, as plain text without exponent notation).
          schema:
            type: string
            enum:
              - json
              - csv
              - text
              - xlsx
            default: json
      responses:
        '200':
          description: The rate of the pair.
          headers:
            X-Cost:
              $ref: '#/components/headers/Cost'
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="rate.xlsx"`.
              schema:
                type: string
              example: attachment; filename="rate.xlsx"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateResponse'
              example:
                meta:
                  last_updated_at: "2023-06-23T10:15:59Z"
                data:
                  from: EUR
                  to: USD
                  rate: 1.0887771
                  inverse: 0.918456
            text/plain:
              schema:
                type: string
              example: "1.0887771"
            text/csv:
              schema:
                type: string
              example: |
                from,to,rate,inverse,last_updated_at
                EUR,USD,1.0887771,0.918456,2023-06-23T10:15:59Z
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/matrix:
    get:
      tags:
        - Rates
      summary: Cross rates between several currencies
      operationId: getMatrix
      description: >-
        Returns every cross rate between 2 to 25 currencies in one request:
        `data.EUR.USD` is the price of 1 EUR in USD. Latest at your plan's
        update interval, or the close of a past `date`. `format=csv` gives the
        table with one row per base currency.
      parameters:
        - name: currencies
          in: query
          required: true
          description: >-
            2 to 25 currency codes, comma-separated (e.g. `USD,EUR,GBP`) or as
            `currencies[]=`. Rows and columns keep this order.
          style: form
          explode: false
          schema:
            type: array
            minItems: 2
            maxItems: 25
            items:
              $ref: '#/components/schemas/CurrencyCode'
          example:
            - USD
            - EUR
            - GBP
        - name: date
          in: query
          required: false
          description: The close of this past day (format `YYYY-MM-DD`).
          schema:
            type: string
            format: date
          example: "2022-01-01"
        - $ref: '#/components/parameters/Precision'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: The cross rates, one row per base currency.
          headers:
            X-Cost:
              $ref: '#/components/headers/Cost'
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="matrix.xlsx"`.
              schema:
                type: string
              example: attachment; filename="matrix.xlsx"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MatrixResponse'
              example:
                meta:
                  last_updated_at: "2023-06-23T10:15:59Z"
                  currencies:
                    - USD
                    - EUR
                    - GBP
                data:
                  USD:
                    USD: 1
                    EUR: 0.918456
                    GBP: 0.786123
                  EUR:
                    USD: 1.0887771
                    EUR: 1
                    GBP: 0.8559168
                  GBP:
                    USD: 1.2720671
                    EUR: 1.1683413
                    GBP: 1
            text/csv:
              schema:
                type: string
              example: |
                base_currency,USD,EUR,GBP
                USD,1,0.918456,0.786123
                EUR,1.0887771,1,0.8559168
                GBP,1.2720671,1.1683413,1
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/range:
    get:
      tags:
        - Rates
      summary: Historical exchange rates for a time range
      operationId: getRange
      description: >-
        Returns exchange rates for every interval between `datetime_start` and
        `datetime_end` at the requested accuracy. Requires a plan that includes
        the range endpoint (medium and up). The allowed span and look-back
        depend on the chosen accuracy:


        - `day`: not more than 366 days between start and end.

        - `hour`: not more than 7 days between start and end, and not more than 3
          months back.

        - `quarter_hour`: not more than 24 hours between start and end, and not
          more than 7 days back.

        - `minute`: not more than 6 hours between start and end, and not more
          than 7 days back.

        - `week`: the daily rate at the end of each week (Sunday), not more
          than 1830 days between start and end.

        - `month`: the daily rate at the end of each month, any span back to
          1999.


        For `week` and `month` the last point is `datetime_end` itself when it
        falls inside a period. Add `format=csv` for one row per point and
        currency: `datetime,base_currency,currency,value`.


        `orient=currency` returns one series per currency instead of one
        point per datetime (`data.EUR` is a list of `{datetime, value}`),
        `shape=compact` drops the code/value objects (with `orient=currency`
        each point is `[datetime, value]`), and `precision` rounds.
      parameters:
        - name: datetime_start
          in: query
          required: true
          description: >-
            Start of the range as an ISO 8601 datetime (e.g.
            `2021-11-30T23:59:59Z`). Must be before or equal to `datetime_end`.
          schema:
            type: string
            format: date-time
          example: "2021-11-30T23:59:59Z"
        - name: datetime_end
          in: query
          required: true
          description: >-
            End of the range as an ISO 8601 datetime (e.g.
            `2021-12-31T23:59:59Z`). Must be after or equal to `datetime_start`.
          schema:
            type: string
            format: date-time
          example: "2021-12-31T23:59:59Z"
        - name: accuracy
          in: query
          required: false
          description: The interval accuracy of the returned data.
          schema:
            type: string
            enum:
              - day
              - hour
              - quarter_hour
              - minute
              - week
              - month
            default: day
        - $ref: '#/components/parameters/BaseCurrency'
        - $ref: '#/components/parameters/Currencies'
        - $ref: '#/components/parameters/Type'
        - name: orient
          in: query
          required: false
          description: >-
            `datetime` (default): one point per datetime. `currency`: one
            series per currency, keyed by code.
          schema:
            type: string
            enum:
              - datetime
              - currency
            default: datetime
        - $ref: '#/components/parameters/Shape'
        - $ref: '#/components/parameters/Precision'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: Exchange rates per interval within the requested range.
          headers:
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="range.xlsx"`.
              schema:
                type: string
              example: attachment; filename="range.xlsx"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RangeResponse'
              example:
                meta:
                  base_currency: USD
                  accuracy: day
                  datetime_start: "2022-01-01T00:00:00Z"
                  datetime_end: "2022-01-02T23:59:59Z"
                data:
                  - datetime: "2022-01-01T23:59:59Z"
                    currencies:
                      AED:
                        code: AED
                        value: 3.67306
                      EUR:
                        code: EUR
                        value: 0.918456
                  - datetime: "2022-01-02T23:59:59Z"
                    currencies:
                      AED:
                        code: AED
                        value: 3.67308
                      EUR:
                        code: EUR
                        value: 0.919012
            text/csv:
              schema:
                type: string
              example: |
                datetime,base_currency,currency,value
                2022-01-01T23:59:59Z,USD,AED,3.67306
                2022-01-01T23:59:59Z,USD,EUR,0.918456
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/ohlc:
    get:
      tags:
        - Rates
      summary: Hourly or daily OHLC candles
      operationId: getOhlc
      description: >-
        Returns open, high, low and close per hour or per day for 1 to 10
        currencies, built from the stored rates. Requires a plan that includes
        the range endpoint (medium and up).


        - `hour`: from the minute rates. `datetime_start` not more than 7 days
          back, not more than 7 days between start and end. Needs a plan with
          quarter-hourly updates or finer.

        - `day` (default): from the hourly rates. `datetime_start` not more
          than 3 months back, not more than 92 days between start and end.
          Needs a plan with hourly updates or finer.


        Each candle closes on the stored rate at the end of its hour or day and
        opens on the close of the candle before it (on its own close after a
        gap); `high` and `low` are the
        extremes of the finer rates in between and always include the
        open and the close. `datetime` is the start of the candle. Candles whose
        close is not stored yet (e.g. the hour or day still running) are left
        out. A request costs one request, however many currencies and candles
        it holds.


        `shape=compact` gives every candle as `[datetime, open, high, low,
        close]`, `precision` rounds, and `format=csv` gives one row per
        candle: `datetime,base_currency,currency,open,high,low,close`.
      parameters:
        - name: currencies
          in: query
          required: true
          description: >-
            1 to 10 currency codes, comma-separated (e.g. `EUR,GBP`) or as
            `currencies[]=`.
          style: form
          explode: false
          schema:
            type: array
            minItems: 1
            maxItems: 10
            items:
              $ref: '#/components/schemas/CurrencyCode'
          example:
            - EUR
            - GBP
        - $ref: '#/components/parameters/BaseCurrency'
        - name: interval
          in: query
          required: false
          description: The length of each candle.
          schema:
            type: string
            enum:
              - hour
              - day
            default: day
        - name: datetime_start
          in: query
          required: true
          description: >-
            Start of the range as an ISO 8601 datetime or date (e.g.
            `2026-09-29T00:00:00Z`). The first candle is the one this moment
            falls in.
          schema:
            type: string
            format: date-time
          example: "2026-09-29T00:00:00Z"
        - name: datetime_end
          in: query
          required: true
          description: >-
            End of the range as an ISO 8601 datetime or date, on or after
            `datetime_start`. The last candle is the one this moment falls in.
          schema:
            type: string
            format: date-time
          example: "2026-09-30T23:59:59Z"
        - $ref: '#/components/parameters/Shape'
        - $ref: '#/components/parameters/Precision'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: The candles of each currency, oldest first.
          headers:
            X-Cost:
              $ref: '#/components/headers/Cost'
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="ohlc.xlsx"`.
              schema:
                type: string
              example: attachment; filename="ohlc.xlsx"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OhlcResponse'
              example:
                meta:
                  base_currency: USD
                  interval: hour
                  datetime_start: "2026-09-30T10:00:00Z"
                  datetime_end: "2026-09-30T11:00:00Z"
                data:
                  EUR:
                    - datetime: "2026-09-30T10:00:00Z"
                      open: 0.91
                      high: 0.95
                      low: 0.9
                      close: 0.92
                    - datetime: "2026-09-30T11:00:00Z"
                      open: 0.92
                      high: 0.925
                      low: 0.9165
                      close: 0.9188
            text/csv:
              schema:
                type: string
              example: |
                datetime,base_currency,currency,open,high,low,close
                2026-09-30T10:00:00Z,USD,EUR,0.91,0.95,0.9,0.92
                2026-09-30T11:00:00Z,USD,EUR,0.92,0.925,0.9165,0.9188
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: No rates are stored in the requested range.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/fluctuation:
    get:
      tags:
        - Rates
      summary: How rates changed between two dates
      operationId: getFluctuation
      description: >-
        Returns, for every requested currency, its rate at the end of
        `date_from` and of `date_to` and how much it changed in between, in
        absolute terms and in percent. Both days are UTC days back to
        1999-01-01; the newest allowed is yesterday.


        The JSON response also has the `high`, `low` and `average` of the
        daily closes from `date_from` to `date_to` (null when the two days are
        more than 1830 days apart or the span has no data). The CSV keeps its
        columns.
      parameters:
        - name: date_from
          in: query
          required: true
          description: First day (`YYYY-MM-DD`).
          schema:
            type: string
            format: date
          example: "2026-01-01"
        - name: date_to
          in: query
          required: true
          description: Last day (`YYYY-MM-DD`), on or after `date_from`.
          schema:
            type: string
            format: date
          example: "2026-06-30"
        - $ref: '#/components/parameters/BaseCurrency'
        - $ref: '#/components/parameters/Currencies'
        - $ref: '#/components/parameters/Type'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: >-
            Start rate, end rate, change, and high, low and average per
            currency.
          headers:
            X-Cost:
              $ref: '#/components/headers/Cost'
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="fluctuation.xlsx"`.
              schema:
                type: string
              example: attachment; filename="fluctuation.xlsx"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FluctuationResponse'
              example:
                meta:
                  base_currency: USD
                  date_from: "2026-01-01"
                  date_to: "2026-06-30"
                data:
                  EUR:
                    code: EUR
                    start_rate: 0.9654
                    end_rate: 0.8771
                    change: -0.0883
                    change_pct: -9.1465
                    high: 0.9712
                    low: 0.8695
                    average: 0.9183
            text/csv:
              schema:
                type: string
              example: |
                date_from,date_to,base_currency,currency,start_rate,end_rate,change,change_pct
                2026-01-01,2026-06-30,USD,EUR,0.9654,0.8771,-0.0883,-9.1465
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: No rates are stored for one of the two days.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/average:
    get:
      tags:
        - Rates
      summary: Average, low and high rates per month, quarter or year
      operationId: getAverage
      description: >-
        Averages the daily rates per calendar `period` (`month`, `quarter`,
        `year`, or `total` for the whole span) and reports each period's low
        and high. Daily rates are first expressed against `base_currency` and
        then averaged, so the average EUR rate in GBP is the mean of the daily
        EUR/GBP rates. Average rates are what IFRS and US GAAP allow for
        translating income and expenses.


        `date_from` and `date_to` may be at most 1830 days apart. The first
        and last period are cut to the requested span; `date_from`, `date_to`
        and `days` of each period tell exactly which days went into it.
      parameters:
        - name: date_from
          in: query
          required: true
          description: First day (`YYYY-MM-DD`), 1999-01-01 or later.
          schema:
            type: string
            format: date
          example: "2026-01-01"
        - name: date_to
          in: query
          required: true
          description: Last day (`YYYY-MM-DD`), yesterday at the latest.
          schema:
            type: string
            format: date
          example: "2026-06-30"
        - name: period
          in: query
          required: false
          description: How to group the days.
          schema:
            type: string
            enum:
              - month
              - quarter
              - year
              - total
            default: month
        - $ref: '#/components/parameters/BaseCurrency'
        - $ref: '#/components/parameters/Currencies'
        - $ref: '#/components/parameters/Type'
        - $ref: '#/components/parameters/Format'
      responses:
        '200':
          description: One entry per period with each currency's average, low and high.
          headers:
            X-Cost:
              $ref: '#/components/headers/Cost'
            Content-Disposition:
              description: >-
                With `format=xlsx`: `attachment; filename="average.xlsx"`.
              schema:
                type: string
              example: attachment; filename="average.xlsx"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AverageResponse'
              example:
                meta:
                  source: market
                  base_currency: USD
                  period: month
                  date_from: "2026-01-01"
                  date_to: "2026-02-28"
                data:
                  - period: "2026-01"
                    date_from: "2026-01-01"
                    date_to: "2026-01-31"
                    days: 31
                    currencies:
                      EUR:
                        code: EUR
                        value: 0.9612
                        min: 0.9504
                        max: 0.9711
                  - period: "2026-02"
                    date_from: "2026-02-01"
                    date_to: "2026-02-28"
                    days: 28
                    currencies:
                      EUR:
                        code: EUR
                        value: 0.9558
                        min: 0.9461
                        max: 0.9640
            text/csv:
              schema:
                type: string
              example: |
                period,date_from,date_to,days,source,base_currency,currency,average,min,max
                2026-01,2026-01-01,2026-01-31,31,market,USD,EUR,0.9612,0.9504,0.9711
            application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
              schema:
                type: string
                format: binary
                description: >-
                  With `format=xlsx`: the table of `format=csv` as an Excel
                  workbook (one sheet, frozen header row, numbers as numbers).
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: No rates are stored in the requested span.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/currencies:
    get:
      tags:
        - Metadata
      summary: List supported currencies
      operationId: getCurrencies
      description: >-
        Returns metadata for all supported currencies, optionally filtered by
        code or type.
      parameters:
        - $ref: '#/components/parameters/Currencies'
        - $ref: '#/components/parameters/Type'
        - name: as_html
          in: query
          required: false
          description: >-
            When `true`, returns an HTML table of currency codes and names
            instead of a JSON payload.
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Supported currency metadata keyed by currency code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrenciesResponse'
              example:
                data:
                  AED:
                    symbol: "AED"
                    name: "UAE Dirham"
                    symbol_native: "د.إ"
                    decimal_digits: 2
                    rounding: 0
                    code: "AED"
                    name_plural: "UAE dirhams"
                    type: "fiat"
                    countries:
                      - "AE"
                  BTC:
                    symbol: "₿"
                    name: "Bitcoin"
                    symbol_native: "₿"
                    decimal_digits: 8
                    rounding: 0
                    code: "BTC"
                    name_plural: "Bitcoin"
                    type: "crypto"
                    countries: []
            text/html:
              schema:
                type: string
              example: "<table><tr><th>Code</th><th>Name</th></tr><tr><td>AED</td><td>UAE Dirham</td></tr></table>"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimited'
  /v1/status:
    get:
      tags:
        - Metadata
      summary: Account quota status
      operationId: getStatus
      description: >-
        Returns your current monthly and grace quota usage and the plan of your
        API key's account. Requests to this endpoint do not count against your
        quota or rate limit.
      responses:
        '200':
          description: Current quota usage for the authenticated account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatusResponse'
              example:
                account_id: 313373133731337
                account_id_str: "313373133731337"
                quotas:
                  month:
                    total: 300
                    used: 72
                    remaining: 228
                  grace:
                    total: 0
                    used: 0
                    remaining: 0
                plan:
                  name: "free"
                  interval: "month"
                  price_id: "price_1AbCdEfGhIjKlMnOpQrStUvW"
                  free: true
                  custom: false
                  status: "active"
                  renews_at: "2026-11-01T00:00:00+00:00"
                  scheduled: null
                  upgrade_url: "https://app.fxapi.com/upgrade?utm_source=agent&utm_campaign=status&team=313373133731337"
                  plans_url: "https://api.fxapi.com/v1/agent/plans"
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  securitySchemes:
    ApiKeyQuery:
      type: apiKey
      in: query
      name: apikey
      description: API key passed as the `apikey` query parameter.
    ApiKeyHeader:
      type: apiKey
      in: header
      name: apikey
      description: >-
        API key passed as the `apikey` request header. This is the recommended
        method as it keeps the key out of URLs and access logs.
  parameters:
    BaseCurrency:
      name: base_currency
      in: query
      required: false
      description: >-
        The base currency that all returned values are relative to. Defaults to
        `USD`.
      schema:
        $ref: '#/components/schemas/CurrencyCode'
    Currencies:
      name: currencies
      in: query
      required: false
      description: >-
        Comma-separated list of currency codes to include (e.g. `EUR,USD,CAD`).
        The array form `currencies[]=EUR&currencies[]=USD` is also accepted. By
        default all supported currencies are returned.
      style: form
      explode: false
      schema:
        type: array
        items:
          $ref: '#/components/schemas/CurrencyCode'
      example:
        - EUR
        - USD
        - CAD
    Format:
      name: format
      in: query
      required: false
      description: >-
        `json` (default), `csv` or `xlsx`. CSV has a header line and one row
        per currency (and point in time), values without exponent notation.
        `xlsx` is the same table as an Excel workbook (one sheet, bold frozen
        header row, numbers as numbers), sent as a download named after the
        endpoint, e.g. `latest.xlsx`.
      schema:
        type: string
        enum:
          - json
          - csv
          - xlsx
        default: json
    Shape:
      name: shape
      in: query
      required: false
      description: >-
        `default`: every rate as `{"code": "EUR", "value": 0.918456}`.
        `compact`: plain values, `"EUR": 0.918456`.
      schema:
        type: string
        enum:
          - default
          - compact
        default: default
    Inverse:
      name: inverse
      in: query
      required: false
      description: >-
        `true` adds `inverse` to every rate: the value of one unit of the
        currency in the base currency (1 / value). Not with `shape=compact`.
      schema:
        type: boolean
        default: false
    Precision:
      name: precision
      in: query
      required: false
      description: >-
        Round every value to this many decimals (0 to 10). By default values
        carry up to 10 decimals (10 significant digits below 0.1).
      schema:
        type: integer
        minimum: 0
        maximum: 10
      example: 4
    Type:
      name: type
      in: query
      required: false
      description: Filter the returned currencies by type.
      schema:
        type: string
        enum:
          - fiat
          - metal
          - crypto
  headers:
    RateLimitLimitQuotaMonth:
      description: Your monthly request quota.
      schema:
        type: integer
      example: 300
    RateLimitRemainingQuotaMonth:
      description: Remaining requests in your monthly quota.
      schema:
        type: integer
      example: 228
    Cost:
      description: >-
        Number of requests this call counted against your quota (0 for sandbox
        keys). Only successful responses from the data endpoints carry this
        header.
      schema:
        type: integer
      example: 1
  responses:
    Unauthorized:
      description: >-
        The API key is missing or invalid: every request needs one, in the
        `apikey` header or query parameter. Without a key the message is "No
        API key found in request" (`error.code` `missing_api_key`), with an
        unknown key "Unauthorized" (`invalid_api_key`). `actions.sign_up`
        creates an account with a free API key. `actions` can also carry
        `agent_setup` (setup steps for AI coding agents), `pricing` (the plans
        as JSON) and `openapi`; `docs` then points to the docs' llms.txt
        (example `missing_api_key_agent_links`).
      headers:
        WWW-Authenticate:
          description: Always `Key`.
          schema: { type: string }
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          examples:
            missing_api_key:
              summary: No API key sent
              value:
                message: "No API key found in request"
                error: { code: "missing_api_key", message: "No API key found in request" }
                actions:
                  sign_up: "https://app.fxapi.com/register?utm_source=api_error&utm_campaign=missing_api_key"
                  docs: "https://fxapi.com/docs/openapi.yaml"
            invalid_api_key:
              summary: Unknown API key
              value:
                message: "Unauthorized"
                error: { code: "invalid_api_key", message: "Unauthorized" }
                actions:
                  sign_up: "https://app.fxapi.com/register?utm_source=api_error&utm_campaign=invalid_api_key"
                  docs: "https://fxapi.com/docs/openapi.yaml"
            missing_api_key_agent_links:
              summary: No API key sent, with the links for AI coding agents
              value:
                message: "No API key found in request"
                error: { code: "missing_api_key", message: "No API key found in request" }
                actions:
                  agent_setup: "https://fxapi.com/agents.md"
                  sign_up: "https://app.fxapi.com/register?utm_source=api_error&utm_campaign=missing_api_key"
                  pricing: "https://api.fxapi.com/v1/agent/plans"
                  docs: "https://fxapi.com/docs/llms.txt"
                  openapi: "https://fxapi.com/docs/openapi.yaml"
    Forbidden:
      description: >-
        Your plan does not permit this endpoint or parameter combination.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: "You are not allowed to use the convert endpoint, please upgrade your plan"
            info: "For more information, see documentation: https://fxapi.com/docs/status-codes#_403"
    ValidationError:
      description: One or more request parameters failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationError'
          example:
            message: "Validation error"
            errors:
              base_currency:
                - "The selected base currency is invalid."
            info: "For more information, see documentation: https://fxapi.com/docs/status-codes#_422"
    RateLimited:
      description: >-
        A limit is used up. `error.code` says which: `quota_exceeded` (the
        month's requests; `quota.resets_at` says when they come back),
        `grace_quota_exceeded` (the grace quota of an unpaid invoice:
        `actions.complete_payment` pays it), `overage_quota_exceeded` (the
        overage budget) or `rate_limit_exceeded` (the free plan's 10 requests
        a minute). Quota errors carry `quota`. Only successful requests count
        against your quota. `actions.upgrade` opens the plans of the API key's
        account. `actions` can also carry `pricing` (the plans as JSON) and
        `openapi`; `docs` then points to the docs' llms.txt (the examples
        ending in `_agent_links`).
      headers:
        Retry-After:
          description: >-
            Seconds until the next full minute, with the requests-per-minute
            `rate_limit_exceeded` of an API key. A used-up quota has none: it
            lasts until `quota.resets_at`.
          schema: { type: integer }
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          examples:
            quota_exceeded:
              summary: The month's requests are used up
              value:
                message: "You used all your monthly requests. Please upgrade your plan at https://app.fxapi.com/upgrade"
                error: { code: "quota_exceeded", message: "You used all your monthly requests. Please upgrade your plan at https://app.fxapi.com/upgrade" }
                quota: { limit: 300, used: 300, remaining: 0, resets_at: "2026-11-01T00:00:00+00:00" }
                actions:
                  upgrade: "https://app.fxapi.com/upgrade?utm_source=api_error&utm_campaign=quota_exceeded&team=7123456789012345678"
                  docs: "https://fxapi.com/docs/openapi.yaml"
            rate_limit_exceeded:
              summary: The requests per minute are used up
              value:
                message: "API rate limit exceeded"
                error: { code: "rate_limit_exceeded", message: "API rate limit exceeded" }
                actions:
                  upgrade: "https://app.fxapi.com/upgrade?utm_source=api_error&utm_campaign=rate_limit_exceeded&team=7123456789012345678"
                  docs: "https://fxapi.com/docs/openapi.yaml"
            quota_exceeded_agent_links:
              summary: The month's requests are used up, with the links for AI coding agents
              value:
                message: "You used all your monthly requests. Please upgrade your plan at https://app.fxapi.com/upgrade"
                error: { code: "quota_exceeded", message: "You used all your monthly requests. Please upgrade your plan at https://app.fxapi.com/upgrade" }
                quota: { limit: 300, used: 300, remaining: 0, resets_at: "2026-11-01T00:00:00+00:00" }
                actions:
                  upgrade: "https://app.fxapi.com/upgrade?utm_source=api_error&utm_campaign=quota_exceeded&team=7123456789012345678"
                  pricing: "https://api.fxapi.com/v1/agent/plans"
                  docs: "https://fxapi.com/docs/llms.txt"
                  openapi: "https://fxapi.com/docs/openapi.yaml"
            rate_limit_exceeded_agent_links:
              summary: The requests per minute are used up, with the links for AI coding agents
              value:
                message: "API rate limit exceeded"
                error: { code: "rate_limit_exceeded", message: "API rate limit exceeded" }
                actions:
                  upgrade: "https://app.fxapi.com/upgrade?utm_source=api_error&utm_campaign=rate_limit_exceeded&team=7123456789012345678"
                  pricing: "https://api.fxapi.com/v1/agent/plans"
                  docs: "https://fxapi.com/docs/llms.txt"
                  openapi: "https://fxapi.com/docs/openapi.yaml"
  schemas:
    CurrencyCode:
      type: string
      description: >-
        A supported currency code (ISO 4217 for fiat and metals, common tickers
        for crypto).
      enum:
        - AED
        - AFN
        - ALL
        - AMD
        - ANG
        - AOA
        - ARS
        - AUD
        - AWG
        - AZN
        - BAM
        - BBD
        - BDT
        - BGN
        - BHD
        - BIF
        - BMD
        - BND
        - BOB
        - BRL
        - BSD
        - BTN
        - BWP
        - BYN
        - BYR
        - BZD
        - CAD
        - CDF
        - CHF
        - CLF
        - CLP
        - CNY
        - COP
        - CRC
        - CUC
        - CUP
        - CVE
        - CZK
        - DJF
        - DKK
        - DOP
        - DZD
        - EGP
        - ERN
        - ETB
        - EUR
        - FJD
        - FKP
        - GBP
        - GEL
        - GGP
        - GHS
        - GIP
        - GMD
        - GNF
        - GTQ
        - GYD
        - HKD
        - HNL
        - HRK
        - HTG
        - HUF
        - IDR
        - ILS
        - IMP
        - INR
        - IQD
        - IRR
        - ISK
        - JEP
        - JMD
        - JOD
        - JPY
        - KES
        - KGS
        - KHR
        - KMF
        - KPW
        - KRW
        - KWD
        - KYD
        - KZT
        - LAK
        - LBP
        - LKR
        - LRD
        - LSL
        - LTL
        - LVL
        - LYD
        - MAD
        - MDL
        - MGA
        - MKD
        - MMK
        - MNT
        - MOP
        - MRO
        - MUR
        - MVR
        - MWK
        - MXN
        - MYR
        - MZN
        - NAD
        - NGN
        - NIO
        - NOK
        - NPR
        - NZD
        - OMR
        - PAB
        - PEN
        - PGK
        - PHP
        - PKR
        - PLN
        - PYG
        - QAR
        - RON
        - RSD
        - RUB
        - RWF
        - SAR
        - SBD
        - SCR
        - SDG
        - SEK
        - SGD
        - SHP
        - SLL
        - SOS
        - SRD
        - STD
        - SVC
        - SYP
        - SZL
        - THB
        - TJS
        - TMT
        - TND
        - TOP
        - TRY
        - TTD
        - TWD
        - TZS
        - UAH
        - UGX
        - USD
        - UYU
        - UZS
        - VEF
        - VND
        - VUV
        - WST
        - XAF
        - XAG
        - XAU
        - XCD
        - XDR
        - XOF
        - XPF
        - YER
        - ZAR
        - ZMK
        - ZMW
        - ZWL
        - XPT
        - XPD
        - BTC
        - ETH
        - BNB
        - XRP
        - SOL
        - DOT
        - AVAX
        - MATIC
        - LTC
        - ADA
        - USDT
        - USDC
        - DAI
        - ARB
        - OP
        - TRX
        - VES
        - STN
        - MRU
        - ZWG
        - SLE
        - XCG
    CurrencyRate:
      type: object
      description: A single currency rate entry.
      properties:
        code:
          $ref: '#/components/schemas/CurrencyCode'
        value:
          type: number
          description: The conversion rate relative to the base currency.
          example: 3.67306
        inverse:
          type:
            - number
            - 'null'
          description: With `inverse=true`, the value of one unit of the currency in the base currency.
          example: 0.2722548
        change:
          type:
            - number
            - 'null'
          description: With `include=change`, the change since the previous day's close.
          example: 0.00012
        change_pct:
          type:
            - number
            - 'null'
          description: With `include=change`, that change in percent.
          example: 0.0033
        rounded:
          type: number
          description: >-
            Convert with `round_step` or `price_ending`: the converted value
            rounded as a shop price (`value` stays exact).
          example: 10.99
        formatted:
          type: string
          description: >-
            Convert with `locale`: the amount as text in that locale, with the
            currency's symbol and decimal places; the rounded price when
            rounding is on.
          example: "€\u00a01.233,99"
      required:
        - code
        - value
    RatesMap:
      type: object
      description: >-
        Map of currency code to its rate entry, or to the plain value with
        `shape=compact`.
      additionalProperties:
        oneOf:
          - $ref: '#/components/schemas/CurrencyRate'
          - type: number
    ExchangeRatesResponse:
      type: object
      description: Standard rates response used by latest, historical and convert.
      properties:
        meta:
          type: object
          properties:
            last_updated_at:
              type: string
              format: date-time
              description: When this dataset was last updated (ISO 8601, UTC).
              example: "2023-06-23T10:15:59Z"
            base_currency:
              $ref: '#/components/schemas/CurrencyCode'
            date:
              type: string
              format: date
              description: The requested date (historical, and convert with `date`).
              example: "2022-01-01"
            value:
              type: number
              description: The converted value (convert with `value`).
              example: 12
            change_since:
              type: string
              format: date-time
              description: With `include=change`, the close the change is measured from.
              example: "2023-06-21T23:59:59Z"
          required:
            - last_updated_at
        data:
          $ref: '#/components/schemas/RatesMap'
      required:
        - meta
        - data
    ConvertValuesResponse:
      type: object
      description: '`/v1/convert` with `values`: one entry per value, in the order sent.'
      properties:
        meta:
          type: object
          properties:
            last_updated_at:
              type: string
              format: date-time
              description: When the rates used were last updated (ISO 8601, UTC).
              example: "2026-09-29T23:59:59Z"
            base_currency:
              $ref: '#/components/schemas/CurrencyCode'
            values:
              type: array
              description: The values converted, in the order sent.
              items:
                type: number
            date:
              type: string
              format: date
              description: The requested date, when one was sent.
              example: "2022-01-01"
          required:
            - last_updated_at
            - base_currency
            - values
        data:
          type: array
          items:
            type: object
            properties:
              value:
                type: number
                description: The value converted.
                example: 10
              currencies:
                $ref: '#/components/schemas/RatesMap'
            required:
              - value
              - currencies
      required:
        - meta
        - data
    HistoricalDatesResponse:
      type: object
      description: '`/v1/historical` with `dates`: the rates keyed by date.'
      properties:
        meta:
          type: object
          properties:
            base_currency:
              $ref: '#/components/schemas/CurrencyCode'
            dates:
              type: array
              description: The dates answered, each once, oldest first.
              items:
                type: string
                format: date
          required:
            - base_currency
            - dates
        data:
          type: object
          description: Map of date (`YYYY-MM-DD`) to the rates of that day's close.
          additionalProperties:
            $ref: '#/components/schemas/RatesMap'
      required:
        - meta
        - data
    RateResponse:
      type: object
      properties:
        meta:
          type: object
          properties:
            last_updated_at:
              type: string
              format: date-time
              description: The moment the rate applies to (ISO 8601, UTC).
              example: "2023-06-23T10:15:59Z"
          required:
            - last_updated_at
        data:
          type: object
          properties:
            from:
              $ref: '#/components/schemas/CurrencyCode'
            to:
              $ref: '#/components/schemas/CurrencyCode'
            rate:
              type: number
              description: Units of `to` for one unit of `from`.
              example: 1.0887771
            inverse:
              type:
                - number
                - 'null'
              description: Units of `from` for one unit of `to`.
              example: 0.918456
          required:
            - from
            - to
            - rate
            - inverse
      required:
        - meta
        - data
    MatrixResponse:
      type: object
      properties:
        meta:
          type: object
          properties:
            last_updated_at:
              type: string
              format: date-time
              example: "2023-06-23T10:15:59Z"
            currencies:
              type: array
              description: The currencies of the rows and columns, in order.
              items:
                $ref: '#/components/schemas/CurrencyCode'
          required:
            - last_updated_at
            - currencies
        data:
          type: object
          description: >-
            One row per base currency: `data.EUR.USD` is the price of 1 EUR in
            USD. Null where a currency has no rate.
          additionalProperties:
            type: object
            additionalProperties:
              type:
                - number
                - 'null'
      required:
        - meta
        - data
    RangeResponse:
      type: object
      description: >-
        One point per datetime, or with `orient=currency` one series per
        currency.
      properties:
        meta:
          type: object
          description: The range as requested. Not in CSV.
          properties:
            base_currency:
              $ref: '#/components/schemas/CurrencyCode'
            accuracy:
              type: string
              example: day
            datetime_start:
              type: string
              format: date-time
              example: "2022-01-01T00:00:00Z"
            datetime_end:
              type: string
              format: date-time
              example: "2022-01-02T00:00:00Z"
        data:
          oneOf:
            - $ref: '#/components/schemas/RangePoints'
            - $ref: '#/components/schemas/RangeSeries'
      required:
        - data
    RangeSeries:
      type: object
      description: >-
        `orient=currency`: map of currency code to its points, oldest first;
        each point is `{datetime, value}`, or `[datetime, value]` with
        `shape=compact`.
      additionalProperties:
        type: array
        items:
          oneOf:
            - type: object
              properties:
                datetime:
                  type: string
                  format: date-time
                value:
                  type: number
              required:
                - datetime
                - value
            - type: array
              prefixItems:
                - type: string
                  format: date-time
                - type: number
              minItems: 2
              maxItems: 2
    RangePoints:
      type: array
      description: One point per datetime (the default).
      items:
        type: object
        properties:
          datetime:
            type: string
            format: date-time
            description: The datetime this interval's rates apply to.
            example: "2022-01-01T23:59:59Z"
          currencies:
            $ref: '#/components/schemas/RatesMap'
        required:
          - datetime
          - currencies
    OhlcResponse:
      type: object
      properties:
        meta:
          type: object
          description: The range as answered. Not in CSV.
          properties:
            base_currency:
              $ref: '#/components/schemas/CurrencyCode'
            interval:
              type: string
              enum: [hour, day]
            datetime_start:
              type: string
              format: date-time
              description: Start of the first candle.
              example: "2026-09-30T10:00:00Z"
            datetime_end:
              type: string
              format: date-time
              description: Start of the last candle (the end, or now when the end is in the future).
              example: "2026-09-30T11:00:00Z"
          required: [base_currency, interval, datetime_start, datetime_end]
        data:
          type: object
          description: >-
            Map of currency code to its candles, oldest first; each candle is
            an object, or `[datetime, open, high, low, close]` with
            `shape=compact`.
          additionalProperties:
            type: array
            items:
              oneOf:
                - $ref: '#/components/schemas/Candle'
                - type: array
                  prefixItems:
                    - type: string
                      format: date-time
                    - type: number
                    - type: number
                    - type: number
                    - type: number
                  minItems: 5
                  maxItems: 5
      required: [meta, data]
    Candle:
      type: object
      properties:
        datetime:
          type: string
          format: date-time
          description: Start of the hour or day.
          example: "2026-09-30T10:00:00Z"
        open:
          type: number
          description: The close of the candle before.
          example: 0.91
        high:
          type: number
          description: The highest rate in the candle.
          example: 0.95
        low:
          type: number
          description: The lowest rate in the candle.
          example: 0.9
        close:
          type: number
          description: The stored rate at the end of the hour or day.
          example: 0.92
      required: [datetime, open, high, low, close]
    FluctuationResponse:
      type: object
      properties:
        meta:
          type: object
          properties:
            base_currency:
              $ref: '#/components/schemas/CurrencyCode'
            date_from:
              type: string
              format: date
            date_to:
              type: string
              format: date
          required: [base_currency, date_from, date_to]
        data:
          type: object
          description: Map of currency code to its change.
          additionalProperties:
            type: object
            properties:
              code:
                $ref: '#/components/schemas/CurrencyCode'
              start_rate:
                type: number
                description: Rate at the end of `date_from`.
              end_rate:
                type: number
                description: Rate at the end of `date_to`.
              change:
                type: number
                description: '`end_rate - start_rate`.'
              change_pct:
                type: number
                description: Change in percent of `start_rate`, 4 decimals.
              high:
                type:
                  - number
                  - 'null'
                description: >-
                  Highest daily close from `date_from` to `date_to`. Null when
                  the span is longer than 1830 days or has no data. Not in CSV.
              low:
                type:
                  - number
                  - 'null'
                description: >-
                  Lowest daily close from `date_from` to `date_to`. Null like
                  `high`. Not in CSV.
              average:
                type:
                  - number
                  - 'null'
                description: >-
                  Average of the daily closes from `date_from` to `date_to`, as
                  `/v1/average` with `period=total` computes it. Null like
                  `high`. Not in CSV.
            required: [code, start_rate, end_rate, change, change_pct, high, low, average]
      required: [meta, data]
    AverageResponse:
      type: object
      properties:
        meta:
          type: object
          properties:
            source:
              type: string
              description: Always `market`.
            base_currency:
              $ref: '#/components/schemas/CurrencyCode'
            period:
              type: string
              enum: [month, quarter, year, total]
            date_from:
              type: string
              format: date
            date_to:
              type: string
              format: date
          required: [source, base_currency, period, date_from, date_to]
        data:
          type: array
          items:
            type: object
            properties:
              period:
                type: string
                description: '`2026-01`, `2026-Q1`, `2026`, or `date_from/date_to` for `total`.'
              date_from:
                type: string
                format: date
                description: First day with data in this period.
              date_to:
                type: string
                format: date
                description: Last day with data in this period.
              days:
                type: integer
                description: Number of days (or publications) averaged.
              currencies:
                type: object
                additionalProperties:
                  type: object
                  properties:
                    code:
                      $ref: '#/components/schemas/CurrencyCode'
                    value:
                      type: number
                      description: Average rate over the period.
                    min:
                      type: number
                      description: Lowest daily rate in the period.
                    max:
                      type: number
                      description: Highest daily rate in the period.
                  required: [code, value, min, max]
            required: [period, date_from, date_to, days, currencies]
      required: [meta, data]
    CurrencyInfo:
      type: object
      properties:
        symbol:
          type: string
          example: "AED"
        name:
          type: string
          example: "UAE Dirham"
        symbol_native:
          type: string
          example: "د.إ"
        decimal_digits:
          type: integer
          example: 2
        rounding:
          type: number
          example: 0
        code:
          $ref: '#/components/schemas/CurrencyCode'
        name_plural:
          type: string
          example: "UAE dirhams"
        type:
          type: string
          enum:
            - fiat
            - metal
            - crypto
        countries:
          type: array
          description: ISO 3166-1 alpha-2 country codes that use this currency.
          items:
            type: string
          example:
            - "AE"
    CurrenciesResponse:
      type: object
      properties:
        data:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/CurrencyInfo'
      required:
        - data
    StatusResponse:
      type: object
      properties:
        account_id:
          type: integer
          description: Your account (team) id.
          example: 313373133731337
        account_id_str:
          type: string
          description: >-
            The same id as `account_id`, as a string for JavaScript clients,
            whose numbers lose precision above 2^53.
          example: "313373133731337"
        quotas:
          type: object
          properties:
            month:
              $ref: '#/components/schemas/QuotaBucket'
            grace:
              $ref: '#/components/schemas/QuotaBucket'
          required:
            - month
        plan:
          type: object
          description: >-
            The plan of the API key's account, so you can check that an upgrade
            took effect.
          properties:
            name: { type: [string, "null"], example: "free" }
            interval: { type: [string, "null"], example: "month" }
            price_id: { type: [string, "null"] }
            free: { type: [boolean, "null"], example: true }
            custom:
              type: boolean
              description: A plan made for this account only; it has no `upgrade_url`.
              example: false
            status:
              type: [string, "null"]
              description: The status of the subscription, e.g. `active` or `past_due`.
              example: "active"
            renews_at: { type: [string, "null"], format: date-time, example: "2026-11-01T00:00:00+00:00" }
            scheduled:
              type: [object, "null"]
              description: A plan change that starts later, e.g. a downgrade at the end of the period.
              properties:
                name: { type: [string, "null"] }
                interval: { type: [string, "null"], example: "month" }
                starts_at: { type: string, format: date-time }
            upgrade_url:
              type: [string, "null"]
              format: uri
              description: Opens the plans of this account. `null` for a custom plan.
            plans_url:
              type: string
              format: uri
              description: Every plan as JSON.
              example: "https://api.fxapi.com/v1/agent/plans"
      required:
        - quotas
    QuotaBucket:
      type: object
      properties:
        total:
          type: integer
          example: 300
        used:
          type: integer
          example: 72
        remaining:
          type: integer
          example: 228
    Error:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message.
        info:
          type: string
          description: >-
            Link to the relevant documentation. Present on validation (422) and
            plan (403) errors.
        error:
          type: object
          description: >-
            Machine-readable error envelope, on 401, 403, 404 and 429
            responses (gateway errors included).
          properties:
            code:
              type: string
              description: >-
                Stable machine-readable error code, e.g. `missing_api_key`,
                `invalid_api_key`, `key_not_allowed_for_product`,
                `referrer_not_allowed`, `quota_exceeded`,
                `grace_quota_exceeded`, `overage_quota_exceeded`,
                `rate_limit_exceeded`, `not_found`, `forbidden`,
                `plan_upgrade_required` (a plan does not include the endpoint or
                parameter).
              example: quota_exceeded
            message:
              type: string
              description: The same text as the top-level `message`.
          required: [code, message]
        quota:
          type: object
          description: The quota of the API key's account. Present on quota errors only.
          properties:
            limit: { type: integer, example: 300 }
            used: { type: integer, example: 300 }
            remaining: { type: integer, example: 0 }
            resets_at:
              type: [string, 'null']
              format: date-time
              description: When the quota resets. Null when unknown.
        actions:
          type: object
          description: >-
            Next steps as absolute URLs, keyed by action. A key is only
            present when it applies to this error and is available for this
            product right now, so read the keys you know and ignore the
            others. `sign_up`: create an account with a free API key.
            `upgrade`: the plans of the API key's account (quota and plan
            errors). `complete_payment`: pay the open invoice (grace quota).
            `verify_email`: confirm the account's email address. `docs`: the
            documentation (always present). `openapi`: this specification.
            `pricing`: the plans as JSON. `agent_setup`: setup steps for AI
            coding agents. `get_free_api_key`, `get_trial_key`, `get_api_key`:
            endpoints that issue API keys to agents; `agent_setup` explains
            them.
            `enable_overage`: turn on overage for the account, so requests past
            the monthly quota are served and billed per request up to a budget
            (quota_exceeded of a paid plan that has overage, while it is off).
          additionalProperties: { type: string, format: uri }
      required:
        - message
    ValidationError:
      type: object
      properties:
        message:
          type: string
          example: "Validation error"
        errors:
          type: object
          description: Map of parameter name to an array of validation messages.
          additionalProperties:
            type: array
            items:
              type: string
        info:
          type: string
      required:
        - message
        - errors
