{
  "openapi": "3.1.0",
  "info": {
    "title": "CC API",
    "version": "1.0.0",
    "description": "Live mid-market exchange rates for 340+ fiat currencies, cryptocurrencies, stablecoins and metals, rate history, and transfer services compared by what the recipient gets after fees. Free, no API key, CORS enabled. Limits: 30 requests per minute and 1,000 per day per IP, 20,000 per day for all users; days are UTC. Documentation: https://ccvia.app/developers",
    "termsOfService": "https://ccvia.app/developers#terms"
  },
  "externalDocs": {
    "description": "Documentation",
    "url": "https://ccvia.app/developers"
  },
  "servers": [
    {
      "url": "https://currency-backend.currency-backend.workers.dev/v1"
    }
  ],
  "paths": {
    "/rates": {
      "get": {
        "summary": "Latest mid-market rates against a base currency",
        "operationId": "getRates",
        "parameters": [
          {
            "name": "base",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "USD",
              "examples": [
                "USD"
              ]
            },
            "description": "Currency the rates are quoted against. Case-insensitive."
          },
          {
            "name": "symbols",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "examples": [
                "EUR,GBP,JPY"
              ]
            },
            "description": "Comma-separated currency codes to return. Default: all."
          }
        ],
        "responses": {
          "200": {
            "description": "Rates",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rates"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/convert": {
      "get": {
        "summary": "Convert an amount at the mid-market rate",
        "operationId": "convert",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "amount",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "exclusiveMinimum": 0,
              "default": 1,
              "examples": [
                100
              ]
            },
            "description": "Amount in `from`."
          }
        ],
        "responses": {
          "200": {
            "description": "Conversion",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversion"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/quote": {
      "get": {
        "summary": "Compare transfer services: what the recipient gets after fees (or chains through 2–3 services)",
        "operationId": "quote",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "amount",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "exclusiveMinimum": 0,
              "examples": [
                500
              ]
            },
            "description": "Amount sent, in `from`. Default: about 100 USD."
          },
          {
            "name": "chains",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "`1` — also return `chains` when direct providers exist. Without direct providers `chains` always comes back."
          },
          {
            "$ref": "#/components/parameters/Lang"
          }
        ],
        "responses": {
          "200": {
            "description": "Providers sorted from best to worst",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/history": {
      "get": {
        "summary": "Daily (up to a year) or weekly (up to five years) rate history",
        "operationId": "history",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1825,
              "default": 30
            },
            "description": "How far back. Up to 365 — daily points; more — weekly (Thursdays)."
          }
        ],
        "responses": {
          "200": {
            "description": "History",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/History"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/currencies": {
      "get": {
        "summary": "Supported currencies",
        "operationId": "listCurrencies",
        "parameters": [
          {
            "$ref": "#/components/parameters/Lang"
          }
        ],
        "responses": {
          "200": {
            "description": "Currencies",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "currencies": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Currency"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/providers": {
      "get": {
        "summary": "Transfer services, exchanges and wallets compared in /quote",
        "operationId": "listProviders",
        "responses": {
          "200": {
            "description": "Providers",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "providers": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Provider"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/usage": {
      "get": {
        "summary": "Today's usage of the limits by your IP address",
        "operationId": "usage",
        "responses": {
          "200": {
            "description": "Usage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "From": {
        "name": "from",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "examples": [
            "USD"
          ]
        },
        "description": "Currency code (ISO 4217, crypto ticker or XAU/XAG/XPT/XPD). Case-insensitive."
      },
      "To": {
        "name": "to",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "examples": [
            "EUR"
          ]
        },
        "description": "Currency code. Case-insensitive."
      },
      "Lang": {
        "name": "lang",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "en",
            "es",
            "pt",
            "fr",
            "de",
            "it",
            "ru",
            "tr",
            "ar",
            "hi",
            "id",
            "zh",
            "ja",
            "ko"
          ],
          "default": "en"
        }
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "schema": {
          "type": "integer"
        },
        "description": "Requests per day for your IP."
      },
      "X-RateLimit-Remaining": {
        "schema": {
          "type": "integer"
        },
        "description": "Requests left today (approximate)."
      },
      "X-RateLimit-Reset": {
        "schema": {
          "type": "integer"
        },
        "description": "Unix time of the next reset (00:00 UTC)."
      }
    },
    "schemas": {
      "Rates": {
        "type": "object",
        "properties": {
          "base": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "rates": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Units of each currency for 1 base."
          }
        }
      },
      "Conversion": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "rate": {
            "type": "number",
            "description": "Units of `to` for 1 `from`."
          },
          "result": {
            "type": "number"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "QuoteProvider": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "received": {
            "type": "number",
            "description": "What the recipient gets, in `to`."
          },
          "fee_pct": {
            "type": "number",
            "description": "Total cost against the mid-market rate, % of the amount sent."
          },
          "estimate": {
            "type": "boolean",
            "description": "Part of the cost is an estimate rather than a published tariff."
          },
          "best": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Quote": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "mid_rate": {
            "type": "number"
          },
          "mid_result": {
            "type": "number"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "providers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuoteProvider"
            }
          },
          "chains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuoteChain"
            },
            "description": "Present when no provider converts the pair directly (or with `chains=1`): up to 3 paths through 2–3 providers via USDT, USDC, USD, EUR, BTC or ETH, the cheapest first. Three steps only when two aren't possible."
          },
          "converter_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "History": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "interval": {
            "type": "string",
            "enum": [
              "day",
              "week"
            ]
          },
          "points": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "rate": {
                  "type": "number"
                }
              }
            }
          }
        }
      },
      "Currency": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "fiat",
              "crypto",
              "stablecoin",
              "metal"
            ]
          },
          "decimals": {
            "type": "integer"
          }
        }
      },
      "Provider": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "send": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "receive": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "reset_at": {
            "type": "string",
            "format": "date-time"
          },
          "per_ip": {
            "type": "object",
            "properties": {
              "used": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "limit": {
                "type": "integer"
              }
            }
          },
          "shared": {
            "type": "object",
            "properties": {
              "used": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "limit": {
                "type": "integer"
              }
            }
          },
          "per_minute": {
            "type": "integer"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "not_found_error",
                  "rate_limit_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "param": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "docs": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "QuoteChainLeg": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string",
            "description": "The currency this step pays out; the next step starts with it."
          },
          "amount": {
            "type": "number"
          },
          "received": {
            "type": "number"
          },
          "fee_pct": {
            "type": "number",
            "description": "Cost of this step against its mid-market rate, % of `amount`."
          },
          "estimate": {
            "type": "boolean"
          },
          "provider": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "website": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "QuoteChain": {
        "type": "object",
        "properties": {
          "received": {
            "type": "number",
            "description": "What the recipient gets at the end, in `to`."
          },
          "fee_pct": {
            "type": "number",
            "description": "Total cost against the mid-market rate of the pair, % of the amount sent."
          },
          "estimate": {
            "type": "boolean"
          },
          "best": {
            "type": "boolean"
          },
          "path": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "RUB",
                "USDT",
                "USDS"
              ]
            ]
          },
          "legs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuoteChainLeg"
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid parameter: missing_parameter, unknown_currency, invalid_amount, invalid_parameter",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "not_found or history_unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "rate_limited, daily_limit_exceeded or daily_budget_exhausted; see Retry-After",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unavailable": {
        "description": "rates_unavailable: retry in a minute",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
