Skip to main content
POST
/
markets
/
collateral
/
holders
/
historical
Time-weighted historical collateral deposits per holder
curl --request POST \
  --url https://tars.loopscale.com/v1/markets/collateral/holders/historical \
  --header 'Content-Type: application/json' \
  --data '
{
  "mint": "So11111111111111111111111111111111111111112",
  "rangeStart": 1735689600,
  "rangeEnd": 1738368000,
  "pdas": false
}
'
import requests

url = "https://tars.loopscale.com/v1/markets/collateral/holders/historical"

payload = {
"mint": "So11111111111111111111111111111111111111112",
"rangeStart": 1735689600,
"rangeEnd": 1738368000,
"pdas": False
}
headers = {"Content-Type": "application/json"}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
mint: 'So11111111111111111111111111111111111111112',
rangeStart: 1735689600,
rangeEnd: 1738368000,
pdas: false
})
};

fetch('https://tars.loopscale.com/v1/markets/collateral/holders/historical', 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://tars.loopscale.com/v1/markets/collateral/holders/historical",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'mint' => 'So11111111111111111111111111111111111111112',
'rangeStart' => 1735689600,
'rangeEnd' => 1738368000,
'pdas' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);

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

curl_close($curl);

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

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

func main() {

url := "https://tars.loopscale.com/v1/markets/collateral/holders/historical"

payload := strings.NewReader("{\n \"mint\": \"So11111111111111111111111111111111111111112\",\n \"rangeStart\": 1735689600,\n \"rangeEnd\": 1738368000,\n \"pdas\": false\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Content-Type", "application/json")

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

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

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://tars.loopscale.com/v1/markets/collateral/holders/historical")
.header("Content-Type", "application/json")
.body("{\n \"mint\": \"So11111111111111111111111111111111111111112\",\n \"rangeStart\": 1735689600,\n \"rangeEnd\": 1738368000,\n \"pdas\": false\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://tars.loopscale.com/v1/markets/collateral/holders/historical")

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

request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"mint\": \"So11111111111111111111111111111111111111112\",\n \"rangeStart\": 1735689600,\n \"rangeEnd\": 1738368000,\n \"pdas\": false\n}"

response = http.request(request)
puts response.read_body
[
  {
    "collateralMint": "So11111111111111111111111111111111111111112",
    "rangeStart": 1735689600,
    "rangeEnd": 1738368000,
    "userDepositSeconds": {
      "9xQe...borrower1": 2678400,
      "Bz4k...borrower2": 1339200
    }
  }
]
"Something went wrong: You have an error in your SQL syntax."
"Failed to deserialize the JSON body into the target type: missing field `mints` at line 1 column 1."

Body

application/json
mint
string
required

Collateral identifier to query. For standard SPL tokens this is the token mint; for CLP/LP positions it is the pool id (whatever is stored as asset_identifier on the loan event). Unknown mints return an empty result rather than an error.

Example:

"So11111111111111111111111111111111111111112"

rangeStart
integer<int64>
required

Window start, unix seconds. Events before this timestamp are collapsed into a single starting-balance bucket at rangeStart.

Example:

1735689600

rangeEnd
integer<int64>
required

Window end, unix seconds. Must be >= rangeStart. Events with eventTime == rangeEnd contribute zero seconds (boundary).

Example:

1738368000

pdas
boolean
default:false

Controls the holder identity in the response keys: false (default) — aggregate by loans.borrower (wallet). true — aggregate by loan address (le.loan). Each loan is a separate holder.

Response

Array containing a single entry for the requested mint. Returned as an array (rather than a bare object) for parity with the active /collateral/holders endpoint, which fans out across multiple mints.

collateralMint
string
required

Echo of the request mint.

rangeStart
integer<int64>
required

Echo of the request rangeStart.

rangeEnd
integer<int64>
required

Echo of the request rangeEnd.

userDepositSeconds
object
required

Map of holder → integral of balance over the window. Units: decimal-adjusted token units × seconds. Keys: borrower wallet when pdas=false, loan address when pdas=true. Holders whose integrated value is within f64::EPSILON of zero are omitted.