{
  "openapi": "3.1.0",
  "info": {
    "title": "FxFeed API",
    "version": "2.0.0",
    "summary": "Foreign exchange rates: latest, historical, conversion and time series.",
    "description": "The FxFeed API serves mid-market exchange rates for 160+ currencies, with history back to 1999, as JSON. Every request authenticates with an API key in the `api_key` query parameter; get a free key at https://fxfeed.io/signup. The Free plan includes 5,000 requests per month on daily data; Pro is unlimited with hourly data (https://fxfeed.io/pricing). Human-readable reference: https://fxfeed.io/docs.",
    "termsOfService": "https://fxfeed.io/terms",
    "contact": {
      "name": "FxFeed",
      "url": "https://fxfeed.io/contact-us"
    }
  },
  "externalDocs": {
    "description": "API documentation",
    "url": "https://fxfeed.io/docs"
  },
  "servers": [
    {
      "url": "https://api.fxfeed.io/v2",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyQuery": []
    }
  ],
  "tags": [
    {
      "name": "Exchange Rates",
      "description": "Latest and historical rates, conversion and time series."
    }
  ],
  "paths": {
    "/latest": {
      "get": {
        "operationId": "getLatestRates",
        "summary": "Latest exchange rates",
        "description": "The latest exchange rates against a base currency. Free plan users receive rates from the most recent available historical date.",
        "tags": ["Exchange Rates"],
        "parameters": [
          { "$ref": "#/components/parameters/Base" },
          { "$ref": "#/components/parameters/Currencies" }
        ],
        "responses": {
          "200": {
            "description": "The latest rates.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RatesResponse" },
                "example": {
                  "success": true,
                  "base": "USD",
                  "date": "2024-09-02",
                  "rates": { "EUR": 0.85, "GBP": 0.73, "JPY": 110.22 }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/historical": {
      "get": {
        "operationId": "getHistoricalRates",
        "summary": "Historical exchange rates",
        "description": "Exchange rates against a base currency on one date.",
        "tags": ["Exchange Rates"],
        "parameters": [
          { "$ref": "#/components/parameters/Base" },
          { "$ref": "#/components/parameters/Currencies" },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "The date of the rates (YYYY-MM-DD). Defaults to the current date.",
            "schema": { "type": "string", "format": "date", "examples": ["2023-12-31"] }
          }
        ],
        "responses": {
          "200": {
            "description": "The rates on the requested date.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/HistoricalRatesResponse" },
                "example": {
                  "success": true,
                  "historical": true,
                  "base": "USD",
                  "date": "2023-12-31",
                  "rates": { "EUR": 0.84, "GBP": 0.74, "JPY": 108.95 }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/convert": {
      "get": {
        "operationId": "convertCurrency",
        "summary": "Convert an amount",
        "description": "Converts an amount from one currency to another, at the latest rate or, with `date`, at that day's rate.",
        "tags": ["Exchange Rates"],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "The three-letter currency code to convert from. Defaults to USD.",
            "schema": { "$ref": "#/components/schemas/CurrencyCode", "default": "USD" }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "The three-letter currency code to convert to.",
            "schema": { "$ref": "#/components/schemas/CurrencyCode" }
          },
          {
            "name": "amount",
            "in": "query",
            "required": true,
            "description": "The amount to convert; must be greater than 0.",
            "schema": { "type": "number", "exclusiveMinimum": 0, "examples": [100] }
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Convert at the rate of this date (YYYY-MM-DD) instead of the latest.",
            "schema": { "type": "string", "format": "date", "examples": ["2024-09-02"] }
          }
        ],
        "responses": {
          "200": {
            "description": "The converted amount.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ConvertResponse" },
                "example": {
                  "success": true,
                  "query": { "from": "USD", "to": "EUR", "amount": 100 },
                  "info": { "timestamp": 1630540800, "rate": 0.85 },
                  "date": "2024-09-02",
                  "result": 85.0
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/timeseries": {
      "get": {
        "operationId": "getTimeseries",
        "summary": "Time series of exchange rates",
        "description": "Exchange rates for each day within a date range.",
        "tags": ["Exchange Rates"],
        "parameters": [
          {
            "name": "start_date",
            "in": "query",
            "required": true,
            "description": "The first day of the range (YYYY-MM-DD).",
            "schema": { "type": "string", "format": "date", "examples": ["2024-09-01"] }
          },
          {
            "name": "end_date",
            "in": "query",
            "required": true,
            "description": "The last day of the range (YYYY-MM-DD).",
            "schema": { "type": "string", "format": "date", "examples": ["2024-09-03"] }
          },
          { "$ref": "#/components/parameters/Base" },
          { "$ref": "#/components/parameters/Currencies" }
        ],
        "responses": {
          "200": {
            "description": "The rates of every day in the range.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/TimeseriesResponse" },
                "example": {
                  "success": true,
                  "timeseries": true,
                  "start_date": "2024-09-01",
                  "end_date": "2024-09-03",
                  "base": "USD",
                  "rates": {
                    "2024-09-01": { "EUR": 0.85, "GBP": 0.73 },
                    "2024-09-02": { "EUR": 0.86, "GBP": 0.74 },
                    "2024-09-03": { "EUR": 0.84, "GBP": 0.72 }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PaymentRequired" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "api_key",
        "description": "Your FxFeed API key, from the dashboard after signing up at https://fxfeed.io/signup."
      }
    },
    "parameters": {
      "Base": {
        "name": "base",
        "in": "query",
        "required": false,
        "description": "The base currency code (e.g. USD, EUR). Defaults to USD.",
        "schema": { "$ref": "#/components/schemas/CurrencyCode", "default": "USD" }
      },
      "Currencies": {
        "name": "currencies",
        "in": "query",
        "required": false,
        "description": "A comma-separated list of currency codes to return rates for. Every quoted currency when omitted.",
        "schema": { "type": "string", "examples": ["EUR,GBP,JPY"] }
      }
    },
    "schemas": {
      "CurrencyCode": {
        "type": "string",
        "description": "A three-letter ISO 4217 currency code.",
        "pattern": "^[A-Za-z]{3}$",
        "examples": ["USD"]
      },
      "Rates": {
        "type": "object",
        "description": "Rates keyed by currency code: units of that currency per one unit of the base.",
        "additionalProperties": { "type": "number" }
      },
      "RatesResponse": {
        "type": "object",
        "required": ["success", "base", "date", "rates"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "base": { "type": "string", "description": "The base currency code." },
          "date": {
            "type": "string",
            "description": "The date of the rates. Documented as YYYY-MM-DD; clients should also accept an RFC 3339 timestamp and read its first ten characters."
          },
          "timestamp": { "type": "integer", "description": "Unix time of the rates." },
          "rates": { "$ref": "#/components/schemas/Rates" }
        }
      },
      "HistoricalRatesResponse": {
        "allOf": [
          { "$ref": "#/components/schemas/RatesResponse" },
          {
            "type": "object",
            "properties": {
              "historical": { "type": "boolean", "description": "True: these are a past day's rates." }
            }
          }
        ]
      },
      "ConvertResponse": {
        "type": "object",
        "required": ["success", "query", "info", "date", "result"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "query": {
            "type": "object",
            "required": ["from", "to", "amount"],
            "properties": {
              "from": { "type": "string" },
              "to": { "type": "string" },
              "amount": { "type": "number" }
            }
          },
          "info": {
            "type": "object",
            "required": ["timestamp", "rate"],
            "properties": {
              "timestamp": { "type": "integer", "description": "Unix time of the rate used." },
              "rate": { "type": "number", "description": "The rate used for the conversion." }
            }
          },
          "historical": { "type": "boolean", "description": "True when a date was given." },
          "date": {
            "type": "string",
            "description": "The date of the rate used. Documented as YYYY-MM-DD; clients should also accept an RFC 3339 timestamp."
          },
          "result": { "type": "number", "description": "The converted amount." }
        }
      },
      "TimeseriesResponse": {
        "type": "object",
        "required": ["success", "timeseries", "start_date", "end_date", "base", "rates"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "timeseries": { "type": "boolean", "const": true },
          "start_date": { "type": "string", "format": "date" },
          "end_date": { "type": "string", "format": "date" },
          "base": { "type": "string" },
          "rates": {
            "type": "object",
            "description": "One rates object per day (YYYY-MM-DD).",
            "additionalProperties": { "$ref": "#/components/schemas/Rates" }
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "An error. The documented form is `success: false` with an `error` object; clients should also accept a top-level `message` and `code`.",
        "properties": {
          "success": { "type": "boolean", "const": false },
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "integer", "description": "The HTTP status." },
              "info": { "type": "string", "description": "What went wrong." }
            }
          },
          "message": { "type": "string", "description": "What went wrong." },
          "code": { "type": "integer", "description": "The HTTP status." }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "An invalid base currency, currency list, date, amount or timeframe.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "PaymentRequired": {
        "description": "The monthly request limit is exceeded or the subscription is not active.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": {
              "success": false,
              "error": { "code": 402, "info": "Monthly API request limit reached. Please upgrade your plan." }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The plan does not include this feature.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "Resource or API endpoint not found.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded: wait a few seconds before retrying.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  }
}
