// exchange.nanoapi.dev

// CHANGELOG

// v1.0.1
// + POST requests are now also accepted. if you have multiple conversions to perform you may submit them as an array in a single POST request. see the below example.

// v1.0.0
// + GET requests for a single conversion
// + historical data from ECB
//
// [email protected]
    
        // the endpoint for exchanging currencies is https://exchange.nanoapi.dev/api/exchange
// ecb exchange rates start from 1999-01-04

// method: GET
// arguments are passed through url parameters:
//     - from: initial currency
//     - to: final currency
//     - amount: how much to exchange
//
// optional url parameters:
//     - source: ecb (european central bank - default)
//     - date: YYYY-MM-DD format if you need a certain historical exchange rate
//
// response:
// {
//   "nanoapi": float64
// }

// method: POST
// the request body has the following structure:
// {
//   "requests": [
//     {
//       "from": string,
//       "to": string,
//       "amount": float64,
//       "date": Optional<YYYY-MM-DD>
//     },
//     ...
//   ]
// }
//
// response:
// {
//   "nanoapi": []float64
// }

// you may call this api without installing any 3rd party dependencies
// https is always used
// the api may be called from any programming language
//
// below you may find some code snippets in python, golang or bash showing how to use the api
    
        # python

import requests
from requests import codes

def exchange(f: str, t: str, a: float) -> float:
    params = {
        "from": f,
        "to": t,
        "amount": a,
    }

    headers = {
        "Authorization": "FREE",
    }

    response = requests.get(
        "https://exchange.nanoapi.dev/api/exchange",
        params=params,
        headers=headers,
        timeout=10
    )

    if response.status_code != codes.ok:
        raise Exception(f"invalid api return code {response.status_code}")

    return response.json()["nanoapi"]

def exchange_array(x: list):
    data = {
        "requests": x,
    }

    headers = {
        "Authorization": "FREE",
    }

    response = requests.post(
        URL,
        json=data,
        headers=headers,
        timeout=10
    )

    if response.status_code != codes.ok:
        raise Exception(f"invalid api return code {response.status_code}")

    return response.json()["nanoapi"]

def test_exchange_array():
    requests = [
        {
            "from": "EUR",
            "to": "DKK",
            "amount": 1,
        },
        {
            "from": "EUR",
            "to": "DKK",
            "amount": 1,
        },
        {
            "from": "EUR",
            "to": "USD",
            "amount": 1,
        },
        {
            "from": "GBP",
            "to": "USD",
            "amount": 1,
        },
    ]
    res = exchange_array(requests)
    assert len(res) == len(requests)

def test_exchange():
    res = exchange("EUR", "DKK", 1)
    assert res > 1

# example
test_exchange()
test_exchange_array()
    
        // golang

type Response struct {
    Nanoapi   float64	`json:"nanoapi"`
}

func Exchange(from string, to string, amount float64) (float64, error) {
    url := fmt.Sprintf("https://exchange.nanoapi.dev/api/exchange?from=%s&to=%s&amount=%f", from, to, amount)
    client := &http.Client{}

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return 0, err
    }

    req.Header.Add("Authorization", "FREE")
    res, err := client.Do(req)
    if err != nil {
        return 0, err
    }

    body, err := io.ReadAll(res.Body)
    if err != nil {
        return 0, err
    }

    var response Response
    if err := json.Unmarshal(body, &response); err != nil {
        panic(err)
    }

    return response.Nanoapi, nil
}

// example
res, err := Exchange("EUR", "DKK", 1)
    
        # bash or sh

curl --header "Authorization: FREE" "https://exchange.nanoapi.dev/api/exchange?from=usd&to=eur&amount=1"