Zum Inhalt springen
KOTOVADOCS
App starten

XML rates feed

Als Markdown anzeigen

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

The XML rates feed publishes Kotova X rates in the XML format that rate monitors such as BestChange read. It is public and needs no key. Its rates are indicative: the rate your user gets is the one in a quote.

There are two documents, one per rate type:

URL Rates
https://api.kotova.io/x/v1/rates/variable.xml Variable rates (variable): the final amount is set when the deposit arrives.
https://api.kotova.io/x/v1/rates/fixed.xml Fixed rates (fixed).

Both answer GET and HEAD, need no key and carry no weight, and send Access-Control-Allow-Origin: *. Send no Authorization header and no query string: any query string at all, including an empty one such as ?&, is a 400 invalid_request, so the URLs cannot be cache-busted.

Terminal window
curl -si https://api.kotova.io/x/v1/rates/variable.xml

A successful answer has these headers (values from an example):

HTTP/2 200
content-type: application/xml; charset=utf-8
cache-control: public, s-maxage=10, stale-while-revalidate=20
etag: "9c1f0e4b7a2d6385"
last-modified: Tue, 10 Nov 2026 10:15:04 GMT
x-kotova-feed-status: ok
x-kotova-feed-sources: ccecash,ffio
x-kotova-feed-generated-at: 2026-11-10T10:15:04.512Z
x-request-id: req_8fK2mQ9xLp3vTz7nWc1bYd4h
Header Meaning
Cache-Control The CDN keeps a document for 10 seconds, and may serve it for 20 more while it fetches a new one.
ETag A strong validator, " + 16 hexadecimal characters + ". Send it back in If-None-Match to get a 304 Not Modified with no body when nothing has changed.
Last-Modified When the document was built. If-Modified-Since also gives a 304, when you send no If-None-Match.
X-Kotova-Feed-Status ok when the rates of every source the feed is built from are fresh and the document has at least one line; otherwise degraded: some sources’ rates are missing, or the document is empty.
X-Kotova-Feed-Sources The slugs of the sources whose rates are in the document, separated by commas, or none.
X-Kotova-Feed-Generated-At When the document was built, in ISO 8601 with milliseconds.

The other answers:

Status Code When
304 If-None-Match or If-Modified-Since matches the current document.
400 invalid_request A query string was sent. details.reason is unknown_parameter.
404 not_found A file name other than variable.xml or fixed.xml, or the feed is switched off.
405 method_not_allowed A method other than GET, HEAD or OPTIONS.
429 rate_limited More than 120 requests a minute from one IP address reached the server. Answers from the CDN do not count, and BestChange’s monitoring robots are exempt.
503 service_unavailable The API is not available.
Try itGET/rates/{file}No key
Connection
Parameters

`variable.xml` or `fixed.xml`.

The feed uses BestChange’s XML rates format: an XML declaration, a rates element, and one item element per line for each direction, sorted by from and then by to.

<?xml version="1.0" encoding="UTF-8"?>
<rates>
<item><from>BTC</from><to>USDTTRC20</to><in>1</in><out>68021.33412</out><amount>412000.5</amount><minamount>0.00092</minamount><maxamount>1.5</maxamount><tofee>0.1</tofee></item>
<item><from>ETH</from><to>BTC</to><in>1</in><out>0.0361</out><amount>12.5</amount><minamount>0.01</minamount><maxamount>40</maxamount></item>
<item><from>XMR</from><to>BTC</to><in>1</in><out>0.002511873</out><amount>18.5</amount><minamount>0.25</minamount><maxamount>310</maxamount><tofee>0.00012</tofee><param>manual</param></item>
</rates>

The elements of an item always come in this order:

Element Meaning
from The currency sent, as a BestChange code.
to The currency received, as a BestChange code.
in Always 1.
out The amount of to paid out per 1 unit of from, before tofee.
amount The reserve: how much of to the source reports it can pay out, in units of to.
minamount The smallest amount of from the source accepts.
maxamount The largest amount of from the source accepts.
tofee Optional. A fee taken from the payout: an amount in units of to, or a percentage written as N%.
param Optional. BestChange flags passed on from the source, separated by commas: manual, verifying, reg, otherin or otherout.

Numbers are plain decimals: no exponent, no sign, no unit, no spaces and no thousands separators. The document has no comments, no other elements and no per-line attribution; which sources contributed is in the X-Kotova-Feed-Sources header. When there is nothing to publish, the feed is the valid empty document:

<?xml version="1.0" encoding="UTF-8"?>
<rates></rates>

A line says that, when the document was built, a source the API routes to was offering this direction: it would take between minamount and maxamount of from, and pay out about out units of to for each unit sent, minus tofee.

A line is indicative, not an offer. The feed is built from rates that sources publish themselves, and only some sources publish them. A quote asks every source that serves the pair, at the moment your user asks, so the rate in a quote can be higher or lower than the line, and with a variable rate the final amount is set when the deposit arrives.

A direction is published only when a quote could be routed to the source right now: both currencies are in the code table and active in the catalogue, the source is active for the API and not paused, and it serves the direction (it is in the from leg’s send_sources and the to leg’s receive_sources).

Each line is then checked. It is left out unless out is positive, minamount is positive and below maxamount, the reserve is positive, and the fee at the minimum amount is at most 10% of the payout there.

When more than one source offers the same direction, one of them is published, with all of its values: the rate, the limits, the reserve and the fee always come from the same source and are never mixed or averaged.

  1. Each candidate’s payout is x × out − tofee (or x × out minus the percentage) for an amount x.
  2. When their ranges overlap, both are compared at the smallest amount both accept, the higher of the two minimums. When they do not, each is compared at its own minimum, per unit sent.
  3. The higher payout wins. A tie goes to the wider range, then to the lower minimum.
  4. A winner whose rate is more than 5% above the other candidate’s is treated as suspect, and the other candidate is published instead.

Rates are only compared with each other, never with a market price.

Every rounding goes against your user, so a line never promises more than its source offered:

Value Rounding
out Cut off (not rounded) to 10 significant digits, with at most 18 decimal places.
minamount Rounded up to min(decimals, 8) decimal places, where decimals are those of the from leg.
maxamount Rounded down to the same number of decimal places.
amount Rounded down to min(decimals, 8) decimal places of the to leg.
tofee Rounded up to min(decimals, 8) decimal places of the to leg. A percentage is published as the source gave it.

The feed never publishes stale rates:

  • A document is rebuilt from the sources’ latest rates when it is more than 10 seconds old and someone asks for it. Up to 60 seconds old, it is still served while the new one is built; older than that, the request waits for the rebuild. A document more than two minutes old is never served.
  • A source’s rates are left out once they are more than two minutes old. When no source’s rates are fresh, the feed is the empty document, with X-Kotova-Feed-Status: degraded.
  • On top of that, the CDN caches each document for 10 seconds (s-maxage=10).

X-Kotova-Feed-Generated-At tells you exactly how old the document you received is. Polling more often than every 10 seconds returns the same document; use If-None-Match so that an unchanged one costs a 304.

The feed uses BestChange currency codes, not the API’s identifiers. It publishes only the codes in this table; a direction whose currency has no code here is left out. Each code stands for one leg, with currency and network as in Currencies, networks and icons.

BestChange code currency network
BTC BTC btc
ETH ETH eth
ETHBEP20 ETH bsc
ETHARBTM ETH arbitrum
ETHOPTM ETH op
ETHBASE ETH base
BNBBEP20 BNB bsc
LTC LTC ltc
BCH BCH bch
XMR XMR xmr
SOL SOL sol
TRX TRX trx
XRP XRP xrp
DOGE DOGE doge
DASH DASH dash
ZEC ZEC zec
GRAM GRAM ton
USDTERC20 USDT eth
USDTTRC20 USDT trx
USDTBEP20 USDT bsc
USDTSOL USDT sol
USDTPOLYGON USDT matic
USDTTON USDT ton
USDTARBTM USDT arbitrum
USDCERC20 USDC eth
USDCSOL USDC sol
USDCBEP20 USDC bsc
USDCBASE USDC base
USDCARBTM USDC arbitrum
USDCPOLYGON USDC matic
POL POL matic
ADA ADA ada
XLM XLM xlm

Bitcoin on Lightning (BTCLN) is not in the feed in v1. Codes may be added to this table over time.