{
  "openapi": "3.0.3",
  "info": {
    "title": "AllRatesToday Exchange Rate & Central Bank Rates API",
    "description": "Live mid-market exchange rates for 160+ currencies plus official rates from 102 central banks and 3 tax authorities (ECB, the Fed, Bank of Canada, CBSL, Banxico, HMRC, US Treasury and more).\n\n## Data\n- **Market rates** (`/api/rate`, `/api/v1/rates`, `/api/historical-rates`): live interbank mid-market rates, refreshed roughly every 60 seconds.\n- **Central-bank rates** (`/api/v1/central-bank/*`, `/api/open/central-bank/*`): the official tables exactly as published by each institution, one table per publication date. History reaches back to 2000 and earlier for major sources (ECB from 1999, Bank of Canada from 1950s-era series where published).\n\n## Authentication\nMost endpoints require an API key sent as `Authorization: Bearer art_live_...`. Get a free key at https://allratestoday.com/register. Logged-in dashboard users can also authenticate with their session cookie.\n\nKeyless endpoints: `/api/v1/symbols` and `/api/open/central-bank/{bank}` (attribution required), plus JSON reads of `/api/public/central-bank/{bank}`.\n\n## Output formats\nEndpoints that return tabular data accept `?format=json|csv|xml|xlsx` (CSV is UTF-8 with BOM; XLSX is a real Excel workbook; default json).\n\n## Plans\nFree plan: 300 requests in total (a lifetime allowance that never resets), latest central-bank tables included. Historical central-bank dates and time series require a paid plan. See https://allratestoday.com/pricing.",
    "version": "2.1.0",
    "contact": {
      "name": "AllRatesToday Support",
      "url": "https://allratestoday.com",
      "email": "support@allratestoday.com"
    }
  },
  "servers": [
    {
      "url": "https://allratestoday.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Market Rates",
      "description": "Live and historical interbank mid-market rates (updated ~every 60 seconds)"
    },
    {
      "name": "Central Bank Rates",
      "description": "Official reference rates as published by central banks and tax authorities (API key required)"
    },
    {
      "name": "Open Endpoints",
      "description": "Keyless endpoints — no API key needed"
    }
  ],
  "paths": {
    "/api/rate": {
      "get": {
        "tags": [
          "Market Rates"
        ],
        "operationId": "getRate",
        "summary": "Current exchange rate for one currency pair",
        "description": "Live interbank mid-market rate between two currencies, refreshed roughly every 60 seconds. Requires an API key: pass it as `Authorization: Bearer art_live_...` or, for simple cross-origin GETs, as `?key=` (alias `?apiKey=`). CORS-enabled.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "apiKeyQuery": []
          }
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": true,
            "description": "Source currency code (ISO 4217)",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 3,
              "example": "USD"
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": true,
            "description": "Target currency code (ISO 4217)",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 3,
              "example": "EUR"
            }
          },
          {
            "name": "key",
            "in": "query",
            "required": false,
            "description": "API key (alternative to the Authorization header; `apiKey` also accepted)",
            "schema": {
              "type": "string",
              "example": "art_live_xxxxx"
            }
          },
          {
            "name": "apiKey",
            "in": "query",
            "required": false,
            "description": "Alias for `key` — the same query-string fallback under its camelCase name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current rate",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "rate",
                    "source"
                  ],
                  "properties": {
                    "rate": {
                      "type": "number",
                      "format": "double",
                      "example": 0.92145
                    },
                    "source": {
                      "type": "string",
                      "description": "Data source class",
                      "example": "interbank"
                    }
                  }
                },
                "example": {
                  "rate": 0.92145,
                  "source": "interbank"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "502": {
            "description": "Upstream rate provider error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/historical-rates": {
      "get": {
        "tags": [
          "Market Rates"
        ],
        "operationId": "getHistoricalRates",
        "summary": "Historical market rates for a currency pair",
        "description": "Time series of interbank mid-market rates for one pair over a preset period. `1d` returns hourly points; `7d` and `30d` daily points; `1y` weekly-sampled points. Requires an API key (Bearer header) or a logged-in session.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": true,
            "description": "Source currency code (ISO 4217)",
            "schema": {
              "type": "string",
              "example": "USD"
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": true,
            "description": "Target currency code (ISO 4217)",
            "schema": {
              "type": "string",
              "example": "LKR"
            }
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "description": "Time window",
            "schema": {
              "type": "string",
              "enum": [
                "1d",
                "7d",
                "30d",
                "1y"
              ],
              "default": "7d"
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Historical series (oldest first)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "source",
                    "target",
                    "data",
                    "period"
                  ],
                  "properties": {
                    "source": {
                      "type": "string",
                      "example": "USD"
                    },
                    "target": {
                      "type": "string",
                      "example": "LKR"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string",
                            "description": "YYYY-MM-DD (ISO date-time for 1d period)",
                            "example": "2026-08-10"
                          },
                          "rate": {
                            "type": "number",
                            "format": "double",
                            "example": 302.4512
                          },
                          "timestamp": {
                            "type": "integer",
                            "format": "int64",
                            "description": "Unix time in milliseconds"
                          }
                        }
                      }
                    },
                    "source_api": {
                      "type": "string",
                      "example": "interbank"
                    },
                    "period": {
                      "type": "string",
                      "enum": [
                        "1d",
                        "7d",
                        "30d",
                        "1y"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "500": {
            "description": "Server or upstream error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rates": {
      "get": {
        "tags": [
          "Market Rates"
        ],
        "operationId": "getRatesV1",
        "summary": "Live and historical market rates (Wise-compatible)",
        "description": "The main authenticated rates endpoint, parameter-compatible with the Wise `/v1/rates` API. Refreshed roughly every 60 seconds (responses cached 60s). Omit `target` for all rates from `source`; pass comma-separated targets (e.g. `target=EUR,GBP,JPY`) for multiple pairs in one call; use `time` for a point-in-time rate or `from`/`to` (+ optional `group`) for a series.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Source currency code (ISO 4217)",
            "schema": {
              "type": "string",
              "example": "USD"
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": false,
            "description": "Target currency code; comma-separated list allowed (e.g. `EUR,GBP,JPY`)",
            "schema": {
              "type": "string",
              "example": "EUR"
            }
          },
          {
            "name": "time",
            "in": "query",
            "required": false,
            "description": "Historical point-in-time (ISO 8601)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Series start date (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Series end date (YYYY-MM-DD, exclusive)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "group",
            "in": "query",
            "required": false,
            "description": "Series granularity when using from/to",
            "schema": {
              "type": "string",
              "enum": [
                "minute",
                "hour",
                "day"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          },
          {
            "name": "amount",
            "in": "query",
            "required": false,
            "description": "Convert this amount instead of returning a bare rate. Changes the response to a conversion object and requires exactly one source and one target (400 with a comma-separated target list). Must be non-negative.",
            "schema": {
              "type": "number",
              "minimum": 0
            },
            "example": 1000
          },
          {
            "name": "api_key",
            "in": "query",
            "required": false,
            "description": "API key as a query parameter, for callers that cannot set a header (browser address bar, spreadsheet IMPORTDATA). Prefer the Authorization header in production.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of rate objects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "rate": {
                        "type": "number",
                        "format": "double",
                        "example": 0.92145
                      },
                      "source": {
                        "type": "string",
                        "example": "USD"
                      },
                      "target": {
                        "type": "string",
                        "example": "EUR"
                      },
                      "time": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-08-11T09:00:00Z"
                      }
                    }
                  }
                },
                "example": [
                  {
                    "rate": 0.92145,
                    "source": "USD",
                    "target": "EUR",
                    "time": "2026-08-11T09:00:00Z"
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "500": {
            "description": "Server or upstream error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/symbols": {
      "get": {
        "tags": [
          "Market Rates",
          "Open Endpoints"
        ],
        "operationId": "getSymbols",
        "summary": "List supported currencies",
        "description": "All supported currency codes, names, and symbols. No authentication required; CORS-enabled; cached 24 hours; does not count toward your monthly quota.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Supported currencies",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currencies": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "example": "USD"
                          },
                          "name": {
                            "type": "string",
                            "example": "US Dollar"
                          },
                          "symbol": {
                            "type": "string",
                            "example": "$"
                          }
                        }
                      }
                    },
                    "count": {
                      "type": "integer",
                      "example": 161
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/v1/central-banks": {
      "get": {
        "tags": [
          "Central Bank Rates"
        ],
        "operationId": "listCentralBanks",
        "summary": "List covered central banks and official sources",
        "description": "Every covered source (37+ central banks, monetary authorities, and tax authorities) with metadata: country, home currency, published rate types, latest available date, days of history, official source URL, and ready-made endpoint URLs. Available on all plans.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Covered sources",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "banks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "example": "ecb"
                          },
                          "name": {
                            "type": "string",
                            "example": "European Central Bank"
                          },
                          "country": {
                            "type": "string",
                            "example": "Euro area"
                          },
                          "home_ccy": {
                            "type": "string",
                            "example": "EUR"
                          },
                          "kind": {
                            "type": "string",
                            "description": "Source type, e.g. central_bank or tax_authority",
                            "example": "central_bank"
                          },
                          "rate_types": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "example": [
                              "reference"
                            ]
                          },
                          "latest_date": {
                            "type": "string",
                            "format": "date",
                            "example": "2026-08-10"
                          },
                          "days_of_history": {
                            "type": "integer",
                            "description": "Distinct publication dates stored (major sources reach back to 2000 and earlier)",
                            "example": 6890
                          },
                          "source_url": {
                            "type": "string",
                            "example": "https://www.ecb.europa.eu/stats/eurofxref/"
                          },
                          "endpoints": {
                            "type": "object",
                            "properties": {
                              "latest": {
                                "type": "string"
                              },
                              "by_date": {
                                "type": "string"
                              },
                              "history": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "disclaimer": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    },
    "/api/v1/central-banks/rates": {
      "get": {
        "tags": [
          "Central Bank Rates"
        ],
        "operationId": "compareCentralBankRates",
        "summary": "Every bank's latest official rate for one pair",
        "description": "Cross-bank comparison: each covered source's most recent official rate for the requested pair in a single call, with min/max/median and spread in basis points. Pairs a bank does not publish directly are cross-computed via that bank's own table only (never mixing banks) and flagged `derived`. Sources whose newest publication is older than 30 days are flagged `stale` and excluded from the spread stats. Banks that cannot produce the pair are skipped. Methodology: https://allratestoday.com/official-rates-methodology/. Available on all plans.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": true,
            "description": "Source currency, 3-letter code",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 3,
              "example": "USD"
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": true,
            "description": "Target currency, 3-letter code",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 3,
              "example": "EUR"
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Latest rate for the pair from every source that can produce it",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "type": "string",
                      "example": "USD"
                    },
                    "target": {
                      "type": "string",
                      "example": "EUR"
                    },
                    "as_of": {
                      "type": "string",
                      "format": "date",
                      "description": "Newest rate_date among the returned banks; each bank also carries its own rate_date",
                      "example": "2026-08-10"
                    },
                    "count": {
                      "type": "integer",
                      "example": 41
                    },
                    "banks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "example": "ecb"
                          },
                          "name": {
                            "type": "string",
                            "example": "European Central Bank"
                          },
                          "rate": {
                            "type": "number",
                            "example": 0.9214
                          },
                          "rate_date": {
                            "type": "string",
                            "format": "date",
                            "example": "2026-08-10"
                          },
                          "rate_type": {
                            "type": "string",
                            "example": "reference"
                          },
                          "derived": {
                            "type": "boolean",
                            "description": "True when the pair was inverted or cross-computed from the bank's own table rather than printed directly",
                            "example": true
                          },
                          "method": {
                            "type": "string",
                            "enum": [
                              "published",
                              "inverse",
                              "cross"
                            ],
                            "example": "inverse"
                          },
                          "stale": {
                            "type": "boolean",
                            "description": "True when the bank's newest publication is older than 30 days (e.g. quarterly sources)",
                            "example": false
                          }
                        }
                      }
                    },
                    "stats": {
                      "type": "object",
                      "nullable": true,
                      "description": "Computed over non-stale banks only; null when no fresh source covers the pair",
                      "properties": {
                        "min": {
                          "type": "number",
                          "example": 0.9187
                        },
                        "max": {
                          "type": "number",
                          "example": 0.9241
                        },
                        "median": {
                          "type": "number",
                          "example": 0.9214
                        },
                        "spread_bps": {
                          "type": "number",
                          "description": "(max - min) / median in basis points",
                          "example": 58.6
                        },
                        "banks_in_stats": {
                          "type": "integer",
                          "example": 38
                        }
                      }
                    },
                    "methodology": {
                      "type": "string",
                      "example": "https://allratestoday.com/official-rates-methodology/"
                    },
                    "disclaimer": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No covered source publishes rates covering the requested pair",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    },
    "/api/v1/central-bank/{bank}/latest": {
      "get": {
        "tags": [
          "Central Bank Rates"
        ],
        "operationId": "getCentralBankLatest",
        "summary": "Latest official rate table for a bank",
        "description": "The bank's most recent published table (e.g. `ecb`, `boc`, `cbsl`, `banxico`). Pass `source`+`target` to get a single pair — cross-computed via the bank's home currency when not directly published and flagged `derived`. Available on all plans.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BankCode"
          },
          {
            "$ref": "#/components/parameters/PairSource"
          },
          {
            "$ref": "#/components/parameters/PairTarget"
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Latest published table (or single resolved pair when source+target given)",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/CbTable"
                    },
                    {
                      "$ref": "#/components/schemas/CbPair"
                    }
                  ]
                },
                "example": {
                  "bank": "ecb",
                  "name": "European Central Bank",
                  "rate_date": "2026-08-10",
                  "rates": [
                    {
                      "base": "EUR",
                      "quote": "USD",
                      "type": "reference",
                      "value": 1.0853
                    }
                  ],
                  "disclaimer": "Official rates as published by the named central bank. On weekends/holidays the most recent published rate_date is returned."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown bank, or the bank does not publish the requested pair",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "503": {
            "description": "No rates ingested yet for this bank",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/central-bank/{bank}/{date}": {
      "get": {
        "tags": [
          "Central Bank Rates"
        ],
        "operationId": "getCentralBankByDate",
        "summary": "Official rate table for a specific date",
        "description": "The bank's published table in force on a date. Weekends and holidays return the most recent published date on or before the requested one — `rate_date` says which, and `published_on_requested_date` is false when they differ (this is the rate compliance users must apply). Optional `source`+`target` narrows to one pair. History reaches back to 2000 and earlier for major sources. Paid plans only. JSON only.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BankCode"
          },
          {
            "name": "date",
            "in": "path",
            "required": true,
            "description": "Requested date (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-06-30"
            }
          },
          {
            "$ref": "#/components/parameters/PairSource"
          },
          {
            "$ref": "#/components/parameters/PairTarget"
          }
        ],
        "responses": {
          "200": {
            "description": "Table (or single pair) in force on the date",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/CbTableDated"
                    },
                    {
                      "$ref": "#/components/schemas/CbPairDated"
                    }
                  ]
                },
                "example": {
                  "bank": "cbsl",
                  "name": "Central Bank of Sri Lanka",
                  "requested_date": "2026-06-28",
                  "rate_date": "2026-06-26",
                  "published_on_requested_date": false,
                  "source": "USD",
                  "target": "LKR",
                  "rate": 298.7654,
                  "rate_type": "indicative",
                  "derived": false,
                  "method": "published",
                  "disclaimer": "Official rates as published by the named central bank. On weekends/holidays the most recent published rate_date is returned."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PaidPlanRequired"
          },
          "404": {
            "description": "Unknown bank, no data on/before the date, or pair not covered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    },
    "/api/v1/central-bank/{bank}/history": {
      "get": {
        "tags": [
          "Central Bank Rates"
        ],
        "operationId": "getCentralBankHistory",
        "summary": "Official rate time series",
        "description": "Daily series over a date range (defaults to the last year; capped at 5000 rows — narrow the range if `truncated` is true). Use `symbol` for every published pair involving one currency, or `source`+`target` for a single resolved pair per date (cross-computed via the home currency when needed, flagged `derived`). Archives reach back to 2000 and earlier for major sources. Paid plans only.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BankCode"
          },
          {
            "name": "symbol",
            "in": "query",
            "required": false,
            "description": "3-letter currency code matching either side of the pair. Required unless source+target are given.",
            "schema": {
              "type": "string",
              "example": "USD"
            }
          },
          {
            "$ref": "#/components/parameters/PairSource"
          },
          {
            "$ref": "#/components/parameters/PairTarget"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Range start (YYYY-MM-DD; default: one year before `to`)",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-01-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Range end (YYYY-MM-DD; default: today)",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2025-12-31"
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Ascending daily series",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bank": {
                      "type": "string",
                      "example": "ecb"
                    },
                    "name": {
                      "type": "string",
                      "example": "European Central Bank"
                    },
                    "symbol": {
                      "type": "string",
                      "example": "USD"
                    },
                    "source": {
                      "type": "string",
                      "description": "Present in pair mode",
                      "example": "USD"
                    },
                    "target": {
                      "type": "string",
                      "description": "Present in pair mode",
                      "example": "LKR"
                    },
                    "from": {
                      "type": "string",
                      "format": "date"
                    },
                    "to": {
                      "type": "string",
                      "format": "date"
                    },
                    "count": {
                      "type": "integer",
                      "example": 254
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "True when the 5000-row cap was hit"
                    },
                    "rates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate_date": {
                            "type": "string",
                            "format": "date"
                          },
                          "date": {
                            "type": "string",
                            "format": "date",
                            "description": "Used instead of rate_date in pair mode"
                          },
                          "base": {
                            "type": "string"
                          },
                          "quote": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string"
                          },
                          "value": {
                            "type": "number",
                            "format": "double"
                          },
                          "rate": {
                            "type": "number",
                            "format": "double",
                            "description": "Pair mode"
                          },
                          "derived": {
                            "type": "boolean",
                            "description": "Pair mode: true when not directly published"
                          },
                          "method": {
                            "type": "string",
                            "enum": [
                              "published",
                              "inverse",
                              "cross"
                            ],
                            "description": "Pair mode"
                          }
                        }
                      }
                    },
                    "disclaimer": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PaidPlanRequired"
          },
          "404": {
            "description": "Unknown bank or pair not covered in range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    },
    "/api/v1/central-bank/{bank}/availability": {
      "get": {
        "tags": [
          "Central Bank Rates"
        ],
        "operationId": "getCentralBankAvailability",
        "summary": "Publication calendar for a bank",
        "description": "The dates a bank actually published a table, for one year (`?year=2026`) or a date range (defaults to the last year; capped at 3700 dates). Weekends, holidays, and weekly/quarterly cadences show up as missing dates. Dates only, no values — available on all plans.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BankCode"
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Whole calendar year (overrides from/to)",
            "schema": {
              "type": "integer",
              "example": 2026
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "description": "Ascending list of published dates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bank": {
                      "type": "string",
                      "example": "boc"
                    },
                    "name": {
                      "type": "string",
                      "example": "Bank of Canada"
                    },
                    "from": {
                      "type": "string",
                      "format": "date"
                    },
                    "to": {
                      "type": "string",
                      "format": "date"
                    },
                    "count": {
                      "type": "integer",
                      "example": 251
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "dates": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "date"
                      },
                      "example": [
                        "2026-01-02",
                        "2026-01-05"
                      ]
                    },
                    "note_semantics": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown bank",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    },
    "/api/open/central-bank/{bank}": {
      "get": {
        "tags": [
          "Central Bank Rates",
          "Open Endpoints"
        ],
        "operationId": "getOpenCentralBankLatest",
        "summary": "Latest official table — keyless, attribution required",
        "description": "The latest published table for a central bank or tax authority, with no API key. CORS-enabled and edge-cached (30–60 min), built for embeds and widgets. Free to use with a visible attribution link to allratestoday.com (the response includes the attribution object). Pass `source`+`target` for a single pair (direct or inverse only). JSON only. For historical dates, time series, or cross-computed pairs use the keyed `/api/v1/central-bank/*` endpoints.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BankCode"
          },
          {
            "$ref": "#/components/parameters/PairSource"
          },
          {
            "$ref": "#/components/parameters/PairTarget"
          }
        ],
        "responses": {
          "200": {
            "description": "Latest published table (or single pair) with attribution",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bank": {
                      "type": "string",
                      "example": "ecb"
                    },
                    "rate_date": {
                      "type": "string",
                      "format": "date",
                      "example": "2026-08-10"
                    },
                    "rates": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CbRate"
                      }
                    },
                    "source": {
                      "type": "string",
                      "description": "Pair mode",
                      "example": "EUR"
                    },
                    "target": {
                      "type": "string",
                      "description": "Pair mode",
                      "example": "USD"
                    },
                    "rate": {
                      "type": "number",
                      "format": "double",
                      "description": "Pair mode",
                      "example": 1.0853
                    },
                    "rate_type": {
                      "type": "string",
                      "description": "Pair mode",
                      "example": "reference"
                    },
                    "derived": {
                      "type": "boolean",
                      "description": "Pair mode: true when computed as the inverse of the published rate"
                    },
                    "method": {
                      "type": "string",
                      "enum": [
                        "published",
                        "inverse"
                      ],
                      "description": "Pair mode"
                    },
                    "attribution": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": "string",
                          "example": "Official rates published by ECB, served by AllRatesToday"
                        },
                        "url": {
                          "type": "string",
                          "example": "https://allratestoday.com/central-bank-rates-api/ecb/"
                        },
                        "terms": {
                          "type": "string",
                          "example": "Free to use with visible attribution linking to allratestoday.com"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown source, no published table yet, or pair not covered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/central-bank/{bank}": {
      "get": {
        "tags": [
          "Central Bank Rates",
          "Open Endpoints"
        ],
        "operationId": "downloadCentralBankLatest",
        "summary": "Latest official table as JSON (open) or CSV/XLSX download (free account)",
        "description": "The latest published table for one source. JSON is open (no key). `format=csv` and `format=xlsx` return a downloadable file and require a logged-in free account (session cookie) — register at https://allratestoday.com/register. XML is not supported on this endpoint.",
        "security": [
          {},
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BankCode"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (open) or csv/xlsx file download (requires logged-in session)",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv",
                "xlsx"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Latest table (raw cache shape) or file download",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bank": {
                      "type": "string",
                      "example": "ecb"
                    },
                    "rate_date": {
                      "type": "string",
                      "format": "date",
                      "example": "2026-08-10"
                    },
                    "rates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "base_ccy": {
                            "type": "string",
                            "example": "EUR"
                          },
                          "quote_ccy": {
                            "type": "string",
                            "example": "USD"
                          },
                          "rate_type": {
                            "type": "string",
                            "example": "reference"
                          },
                          "value": {
                            "type": "number",
                            "format": "double",
                            "example": 1.0853
                          }
                        }
                      }
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "File downloads (csv/xlsx) require a logged-in free account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown source or no published table yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/open/geo": {
      "get": {
        "operationId": "getVisitorGeo",
        "tags": [
          "Open Endpoints"
        ],
        "summary": "Visitor's country and currency — keyless",
        "description": "The calling IP's country (from Cloudflare's edge) and the currency it maps to. Keyless and CORS-open (`Access-Control-Allow-Origin: *`), so browser packages such as react-currency-localizer-realtime can detect a visitor's currency without a third-party geo-IP service. Never cached — the answer is per-IP. `country` and `currency` are null when the edge cannot determine a country.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Country and mapped currency for the calling IP.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "country": {
                      "type": "string",
                      "nullable": true,
                      "description": "ISO 3166-1 alpha-2, or null"
                    },
                    "currency": {
                      "type": "string",
                      "nullable": true,
                      "description": "ISO 4217 code mapped from the country, or null"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "cloudflare"
                      ]
                    }
                  }
                },
                "example": {
                  "country": "GB",
                  "currency": "GBP",
                  "source": "cloudflare"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/central-bank/{bank}/history": {
      "get": {
        "operationId": "downloadCentralBankHistory",
        "tags": [
          "Central Bank Rates"
        ],
        "summary": "Whole-table history download for one source",
        "description": "Every currency the bank published, one row per currency per date, over a chosen range (max one year) — the endpoint behind the history download buttons on the per-bank pages. This is the table download's historical sibling, not the single-pair series: for an API-key-metered time series of one pair use /api/v1/central-bank/{bank}/history. Session-authenticated (log in at allratestoday.com in the same browser) and paid plans only. Billed by volume: one API call per currency series per month of history in the file.",
        "parameters": [
          {
            "name": "bank",
            "in": "path",
            "required": true,
            "description": "Central bank or tax authority code — list from /api/v1/central-banks.",
            "schema": {
              "type": "string"
            },
            "example": "ecb"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Range start, YYYY-MM-DD (default: one year before `to`).",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-01-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Range end, YYYY-MM-DD (default: today). Range is capped at 366 days.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "csv (default UTF-8 BOM download), xlsx, or json.",
            "schema": {
              "type": "string",
              "enum": [
                "csv",
                "xlsx",
                "json"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The table as JSON rows, CSV, or an Excel workbook."
          },
          "401": {
            "description": "Not logged in — history downloads require an account session."
          },
          "403": {
            "description": "Free plan — history downloads require a paid plan."
          },
          "429": {
            "description": "The download would exceed the plan's remaining monthly quota."
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Format": {
        "name": "format",
        "in": "query",
        "required": false,
        "description": "Response format (default json). csv is UTF-8 with a BOM; xlsx is a real Excel workbook with typed dates and numbers; xml mirrors the JSON fields.",
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv",
            "xml",
            "xlsx"
          ],
          "default": "json"
        }
      },
      "BankCode": {
        "name": "bank",
        "in": "path",
        "required": true,
        "description": "Source code from /api/v1/central-banks (e.g. ecb, boc, cbsl, banxico, ustreasury)",
        "schema": {
          "type": "string",
          "pattern": "^[a-z0-9_-]{2,20}$",
          "example": "ecb"
        }
      },
      "PairSource": {
        "name": "source",
        "in": "query",
        "required": false,
        "description": "Pair mode: source currency, 3-letter code (requires target)",
        "schema": {
          "type": "string",
          "minLength": 3,
          "maxLength": 3,
          "example": "USD"
        }
      },
      "PairTarget": {
        "name": "target",
        "in": "query",
        "required": false,
        "description": "Pair mode: target currency, 3-letter code (requires source)",
        "schema": {
          "type": "string",
          "minLength": 3,
          "maxLength": 3,
          "example": "LKR"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid or missing parameters",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Authentication required — provide an API key via `Authorization: Bearer art_live_...` (free keys at https://allratestoday.com/register)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PaidPlanRequired": {
        "description": "Historical central-bank data requires a paid plan; /latest is available on all plans",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                },
                "upgrade_url": {
                  "type": "string",
                  "example": "https://allratestoday.com/pricing"
                }
              }
            }
          }
        }
      },
      "QuotaExceeded": {
        "description": "Monthly request limit exceeded (X-Monthly-Limit / X-Monthly-Used / X-Monthly-Resets headers included)",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "example": "Request limit exceeded"
                },
                "used": {
                  "type": "integer"
                },
                "limit": {
                  "type": "integer"
                },
                "plan": {
                  "type": "string",
                  "example": "free"
                },
                "resets_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "upgrade_url": {
                  "type": "string",
                  "example": "https://allratestoday.com/pricing"
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Error message"
          },
          "hint": {
            "type": "string",
            "description": "Optional remediation hint"
          }
        }
      },
      "CbRate": {
        "type": "object",
        "properties": {
          "base": {
            "type": "string",
            "example": "EUR"
          },
          "quote": {
            "type": "string",
            "example": "USD"
          },
          "type": {
            "type": "string",
            "description": "Rate type as labeled by the bank (reference, buying, selling, indicative, ...)",
            "example": "reference"
          },
          "value": {
            "type": "number",
            "format": "double",
            "example": 1.0853
          }
        }
      },
      "CbTable": {
        "type": "object",
        "properties": {
          "bank": {
            "type": "string",
            "example": "ecb"
          },
          "name": {
            "type": "string",
            "example": "European Central Bank"
          },
          "rate_date": {
            "type": "string",
            "format": "date",
            "example": "2026-08-10"
          },
          "rates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CbRate"
            }
          },
          "disclaimer": {
            "type": "string"
          }
        }
      },
      "CbPair": {
        "type": "object",
        "properties": {
          "bank": {
            "type": "string",
            "example": "cbsl"
          },
          "name": {
            "type": "string",
            "example": "Central Bank of Sri Lanka"
          },
          "rate_date": {
            "type": "string",
            "format": "date"
          },
          "source": {
            "type": "string",
            "example": "USD"
          },
          "target": {
            "type": "string",
            "example": "LKR"
          },
          "rate": {
            "type": "number",
            "format": "double",
            "example": 298.7654
          },
          "rate_type": {
            "type": "string",
            "example": "indicative"
          },
          "derived": {
            "type": "boolean",
            "description": "True when not directly published by the bank (inverse or cross-computed)"
          },
          "method": {
            "type": "string",
            "enum": [
              "published",
              "inverse",
              "cross"
            ]
          },
          "disclaimer": {
            "type": "string"
          }
        }
      },
      "CbTableDated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CbTable"
          },
          {
            "type": "object",
            "properties": {
              "requested_date": {
                "type": "string",
                "format": "date"
              },
              "published_on_requested_date": {
                "type": "boolean",
                "description": "False when the bank did not publish on the requested date and the most recent prior table is returned"
              }
            }
          }
        ]
      },
      "CbPairDated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CbPair"
          },
          {
            "type": "object",
            "properties": {
              "requested_date": {
                "type": "string",
                "format": "date"
              },
              "published_on_requested_date": {
                "type": "boolean"
              }
            }
          }
        ]
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from your AllRatesToday dashboard. Example: `Authorization: Bearer art_live_xxxxx`. Free keys at https://allratestoday.com/register."
      },
      "apiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "key",
        "description": "API key as a query parameter (accepted on /api/rate only; `apiKey` is an alias)"
      },
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "art_session",
        "description": "Session cookie for logged-in dashboard users"
      }
    }
  }
}