Skip to main content
GET
/
streaming-quotes
Stream quotes (SSE)
curl --request GET \
  --url https://api.leokit.dev/streaming-quotes \
  --header 'Api-Key: <api-key>'
import requests

url = "https://api.leokit.dev/streaming-quotes"

headers = {"Api-Key": "<api-key>"}

response = requests.get(url, headers=headers)

print(response.text)
const options = {method: 'GET', headers: {'Api-Key': '<api-key>'}};

fetch('https://api.leokit.dev/streaming-quotes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.leokit.dev/streaming-quotes",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Api-Key: <api-key>"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"net/http"
"io"
)

func main() {

url := "https://api.leokit.dev/streaming-quotes"

req, _ := http.NewRequest("GET", url, nil)

req.Header.Add("Api-Key", "<api-key>")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.get("https://api.leokit.dev/streaming-quotes")
.header("Api-Key", "<api-key>")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.leokit.dev/streaming-quotes")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Api-Key"] = '<api-key>'

response = http.request(request)
puts response.read_body
"data: {\"type\":\"init\",\"quote_id\":\"019b4c6e-d6c2-7000-b851-48a863f2f4b7\",\"timestamp\":\"2025-12-23T18:18:14.213Z\",\"total\":5}\n\ndata: {\"type\":\"quote\",\"protocol\":\"thorchain\",\"data\":{...}}\n\ndata: {\"type\":\"final\",\"quotes\":[...],\"timestamp\":\"...\",\"quote_id\":\"...\"}\n\ndata: {\"type\":\"finished\"}\n\n"
{
"message": "<string>",
"code": "<string>"
}

Overview

The streaming-quotes endpoint emits Server-Sent Events as each protocol returns a quote, instead of waiting for all protocols to complete. Use this for snappy UI — display the first quote in ~200ms instead of waiting 5+ seconds for the slowest aggregator. For a hands-on walkthrough see the Streaming Quotes guide.

Endpoint

GET /leokit/streaming-quotes

Request

Authentication

EventSource cannot set custom headers reliably, so authentication accepts both styles:
MethodExample
Api-Key headerApi-Key: YOUR_API_KEY (preferred when possible)
api_key query parameter?api_key=YOUR_API_KEY

Query Parameters

ParameterTypeRequiredDescription
from_assetstringYesSource asset in CHAIN.SYMBOL-ADDRESS format
to_assetstringYesDestination asset in CHAIN.SYMBOL-ADDRESS format
amountstringYesAmount in source-asset base units (wei, sats, etc.)
originstringNoSource wallet address (improves quote accuracy)
destinationstringNoDestination wallet address
streaming_intervalnumberNoTHORChain/MAYAChain streaming interval (default 1)
streaming_quantitynumberNoTHORChain/MAYAChain streaming sub-swap count
api_keystringNoAlternative to Api-Key header (see above)

Response

Headers

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

Event Sequence

Events are sent as data: <json>\n\n chunks (legacy SSE format — no named event: fields).
OrderEvent payload typeDescription
1initStream opened, includes quote_id and total protocols being queried
2..NquoteOne per protocol that returns a valid quote
N+1finalAggregated, sorted, deduplicated payload (after all settle)
N+2finishedStream closing
If no protocols return a usable quote, an error event is sent in place of final.

Event Payloads

{
  "type": "init",
  "quote_id": "01953c9a-...",
  "timestamp": "2026-04-28T12:00:00.000Z",
  "total": 7
}

Quote Object Fields (in final event)

FieldDescription
expectedAmountOutNumNumeric expected output (for sorting)
totalFeesUsdTotal combined fees in USD
totalSwapSecondsEstimated time-to-settle
flagsTags like FASTEST, CHEAPEST, BEST_OUTPUT

Timeouts

  • Total budget: 8 seconds. Protocols that haven’t responded by then are dropped.
  • Per-protocol circuit breaker: 5 seconds. Protocols that fail repeatedly are skipped.

Examples

Browser (EventSource)

const url = new URL("https://api.leokit.dev/leokit/streaming-quotes");
url.searchParams.set("from_asset", "ETH.ETH");
url.searchParams.set("to_asset", "BTC.BTC");
url.searchParams.set("amount", "1000000000000000000");
url.searchParams.set("api_key", "YOUR_API_KEY");

const es = new EventSource(url.toString());

es.onmessage = (e) => {
  const event = JSON.parse(e.data);
  switch (event.type) {
    case "init":     console.log("started", event.quote_id); break;
    case "quote":    console.log("got", event.protocol);     break;
    case "final":    console.log("done", event.quotes.length); break;
    case "finished": es.close(); break;
    case "error":    console.error(event); es.close(); break;
  }
};

Server (fetch)

const res = await fetch(
  "https://api.leokit.dev/leokit/streaming-quotes?from_asset=ETH.ETH&to_asset=BTC.BTC&amount=1000000000000000000",
  { headers: { "Api-Key": "YOUR_API_KEY" } }
);

const reader = res.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  const chunk = decoder.decode(value);
  for (const line of chunk.split("\n\n")) {
    if (!line.startsWith("data: ")) continue;
    const event = JSON.parse(line.slice(6));
    // handle event
  }
}

Errors

StatusCodeDescription
400BAD_REQUESTMissing or malformed from_asset, to_asset, or amount
400INVALID_ASSET_FORMATAsset string not in CHAIN.SYMBOL-ADDRESS format
401INVALID_API_KEYMissing or invalid API key
The UNABLE_TO_RETRIEVE_QUOTES error is delivered inside the SSE stream as a type: "error" event, not as an HTTP error. See the error codes catalog for the full list.

Authorizations

Api-Key
string
header
required

Demo API-Key (Sandbox): 7037d2b3-9c76-4f62-b730-c544f7570fa4

Query Parameters

from_asset
string
required

Input asset identifier.

to_asset
string
required

Output asset identifier.

origin
string
required

From wallet address.

destination
string
required

To wallet address.

amount
string
required

Amount to swap.

api_key
string

Alternative to Api-Key header (useful for EventSource which cannot set headers).

Response

Server-Sent Events stream. Events are sent as data: {json}\n\n format.

SSE stream with events: init, quote (per protocol), final (sorted), finished.