---
title: Best Practices
description: Tips for building reliable, performant integrations with the Kiyotaka Data API.
---

# Best Practices

## Discover markets before querying

Always start with the `GET /v1/markets` endpoint to discover available exchanges, symbols, and data types. Don't hardcode exchange IDs or symbols -- use the discovery API to find what's available.

<CodeTabs>

<CodePanel lang="curl">
<pre><span class="s-f">curl</span> <span class="s-s">"https://api.kiyotaka.ai/v1/markets?exchange=BINANCE_FUTURES&amp;coin=BTC&amp;pageSize=10"</span> \\
  <span class="s-k">-H</span> <span class="s-s">"X-Kiyotaka-Key: YOUR_API_KEY"</span></pre>
</CodePanel>

<CodePanel lang="python">
<pre><span class="s-k">import</span> <span class="s-v">requests</span>
&#10;
<span class="s-v">response</span> = requests.<span class="s-f">get</span>(
    <span class="s-s">"https://api.kiyotaka.ai/v1/markets?exchange=BINANCE_FUTURES&coin=BTC&pageSize=10 "</span>,
    headers={<span class="s-s">"X-Kiyotaka-Key"</span>: <span class="s-s">"YOUR_API_KEY"</span>}
)
<span class="s-v">data</span> = response.<span class="s-f">json</span>()</pre>
</CodePanel>

<CodePanel lang="javascript">
<pre><span class="s-k">const</span> <span class="s-v">response</span> = <span class="s-k">await</span> <span class="s-f">fetch</span>(
  <span class="s-s">"https://api.kiyotaka.ai/v1/markets?exchange=BINANCE_FUTURES&coin=BTC&pageSize=10 "</span>,
  { headers: { <span class="s-s">"X-Kiyotaka-Key"</span>: <span class="s-s">"YOUR_API_KEY"</span> } }
)
<span class="s-k">const</span> <span class="s-v">data</span> = <span class="s-k">await</span> response.<span class="s-f">json</span>()</pre>
</CodePanel>

</CodeTabs>

Use the `rawSymbol` field from the response when constructing data queries.

## Choose the right symbol parameter

| Parameter | Use when |
| --- | --- |
| `rawSymbol` | You want data for a specific trading pair on a specific exchange (e.g., `BTCUSDT` on Binance Futures) |
| `coin` | You want data across all pairs for a base asset, or you're using multi-exchange aggregation |
| `normalizedSymbol` | You want a normalized market symbol form across exchanges (e.g., `BTC-USDT`, `BTC-USD`) |

When aggregating across exchanges, always use `coin` -- `rawSymbol` values differ between exchanges (`BTCUSDT` vs `BTC-USD` vs `XBTUSD`).

## Use appropriate intervals for your time range

Smaller intervals over large time ranges produce massive result sets. Match your interval to your time range:

| Time Range | Recommended Intervals |
| --- | --- |
| Minutes to hours | `MINUTE` |
| Hours to days | `FIVE_MINUTES`, `FIFTEEN_MINUTES`, `HOUR` |
| Days to weeks | `HOUR`, `FOUR_HOURS` |
| Weeks to months | `FOUR_HOURS`, `DAY` |
| Months to years | `DAY`, `WEEK` |

Each data type has a maximum points-per-request limit (e.g., 100,000 for candles, 4,000 for orderbook heatmaps). If your time range + interval combination exceeds this, reduce the range or use a larger interval.

## Always set `period` when using `from`

Both `from` and `period` are required for time-range queries. If `period` is 0 or missing, the query may return empty results.

<CodeBlock lang="Examples">
<pre><span class="s-v">from</span>=<span class="s-n">1774800000</span>&amp;<span class="s-v">period</span>=<span class="s-n">3600</span>    <span class="s-c"># 1 hour of data</span>
<span class="s-v">from</span>=<span class="s-n">1774800000</span>&amp;<span class="s-v">period</span>=<span class="s-n">86400</span>   <span class="s-c"># 1 day of data</span></pre>
</CodeBlock>

If you omit `from` and only provide `period`, the API returns data for the last `period` seconds from now.

## Monitor your rate limit usage

Check your quota before heavy operations using the zero-cost usage endpoint:

<CodeTabs>

<CodePanel lang="curl">
<pre><span class="s-f">curl</span> <span class="s-s">"https://api.kiyotaka.ai/v1/usage"</span> \\
  <span class="s-k">-H</span> <span class="s-s">"X-Kiyotaka-Key: YOUR_API_KEY"</span></pre>
</CodePanel>

<CodePanel lang="python">
<pre><span class="s-k">import</span> <span class="s-v">requests</span>
&#10;
<span class="s-v">response</span> = requests.<span class="s-f">get</span>(
    <span class="s-s">"https://api.kiyotaka.ai/v1/usage "</span>,
    headers={<span class="s-s">"X-Kiyotaka-Key"</span>: <span class="s-s">"YOUR_API_KEY"</span>}
)
<span class="s-v">data</span> = response.<span class="s-f">json</span>()</pre>
</CodePanel>

<CodePanel lang="javascript">
<pre><span class="s-k">const</span> <span class="s-v">response</span> = <span class="s-k">await</span> <span class="s-f">fetch</span>(
  <span class="s-s">"https://api.kiyotaka.ai/v1/usage "</span>,
  { headers: { <span class="s-s">"X-Kiyotaka-Key"</span>: <span class="s-s">"YOUR_API_KEY"</span> } }
)
<span class="s-k">const</span> <span class="s-v">data</span> = <span class="s-k">await</span> response.<span class="s-f">json</span>()</pre>
</CodePanel>

</CodeTabs>

Every response also includes `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers. Use these to implement client-side throttling.

## Handle rate limits gracefully

When you receive a 429 response, use the `Retry-After` header to wait before retrying:

<CodeBlock lang="HTTP Response">
<pre><span class="s-k">HTTP/1.1</span> <span class="s-n">429</span> <span class="s-v">Too Many Requests</span>
<span class="s-p">Retry-After</span>: <span class="s-n">12</span>
<span class="s-p">X-RateLimit-Reset</span>: <span class="s-n">1712345678</span></pre>
</CodeBlock>

Don't retry immediately -- you'll waste requests. Wait for the `Retry-After` seconds or until the `X-RateLimit-Reset` timestamp.

## Optimize weight costs

For `/v1/points` requests, weight is calculated as:

<CodeBlock lang="Formula">
<pre><span class="s-f">ceil</span>(points / <span class="s-n">1000</span>) <span class="s-o">x</span> cost_multiplier <span class="s-o">x</span> exchange_multiplier <span class="s-o">x</span> depth_multiplier</pre>
</CodeBlock>

Metadata and discovery endpoints are zero-weight, and `/v1/polymarket/analytics/*` endpoints use fixed per-endpoint weights instead of this formula.
To reduce `/v1/points` weight:
- **Use larger intervals** -- fewer points = lower weight
- **Narrow your time range** -- request only what you need
- **Minimize exchanges** when aggregating -- each additional exchange adds 20% to the multiplier
- **Keep `maxDepth` at the included depth unless you need more range** -- orderbook heatmap adds 20% per extra 3500 levels, liquidation heatmap adds 20% per extra 1500 levels
- **Avoid 10x types** (orderbook heatmap) in tight loops -- batch your requests

## Use gapfill intentionally

`gapfill=true` is supported only for candle types: `TRADE_SIDE_AGNOSTIC_AGG` and `TRADE_AGG`.
For those types, it fills missing intervals using last-observation-carried-forward (LOCF). This is useful for charting but changes the semantics of your data:
- Volume is **not** carried forward -- gapfilled bars have zero volume
- Only the close price is carried forward
- A lookback window (typically 1 hour) seeds the LOCF -- if there's no data in the lookback, the gap remains
Skip gapfill if gaps in data are meaningful to your analysis (e.g., studying market activity patterns).

## Get block sizes before querying heatmaps

Always call `GET /v1/block-sizes` to get the correct block size for your symbol before requesting orderbook heatmap data. Don't guess block sizes.

<CodeBlock lang="cURL -- Step 1">
<pre><span class="s-c"># Step 1: Get the block size</span>
<span class="s-f">curl</span> <span class="s-s">"https://api.kiyotaka.ai/v1/block-sizes?exchange=BINANCE_FUTURES&amp;rawSymbol=BTCUSDT"</span> \\
  <span class="s-k">-H</span> <span class="s-s">"X-Kiyotaka-Key: YOUR_API_KEY"</span></pre>
</CodeBlock>

<CodeBlock lang="cURL -- Step 2">
<pre><span class="s-c"># Step 2: Use it (4K = raw value, HD = 5x)</span>
<span class="s-f">curl</span> <span class="s-s">"https://api.kiyotaka.ai/v1/points</span>
    <span class="s-p">?type</span>=<span class="s-s">BLOCK_BOOK_SNAPSHOT_AGG</span>
    <span class="s-p">&amp;exchange</span>=<span class="s-s">BINANCE_FUTURES</span>
    <span class="s-p">&amp;rawSymbol</span>=<span class="s-s">BTCUSDT</span>
    <span class="s-p">&amp;interval</span>=<span class="s-s">MINUTE</span>
    <span class="s-p">&amp;period</span>=<span class="s-n">1140</span>
    <span class="s-p">&amp;blockSize</span>=<span class="s-n">25</span>
    <span class="s-p">&amp;maxDepth</span>=<span class="s-n">1000</span>
    <span class="s-p">&amp;sortDirection</span>=<span class="s-s">SORT_DIRECTION_DESC</span><span class="s-s">"</span> \\
  <span class="s-k">-H</span> <span class="s-s">"X-Kiyotaka-Key: YOUR_API_KEY"</span></pre>
</CodeBlock>

## TPO block sizes are fixed

TPO only supports block sizes of **5, 30, 60, or 240 minutes**. Other values will return an error. Default is 30 minutes.

## Treat empty results as normal

If your query matches no data (e.g., a symbol that doesn't exist on that exchange, or a time range with no activity), the API returns an empty `series` array -- not an error. Always check for empty results in your client code.

## Secure your API keys

- Never expose keys in client-side code, browser applications, or public repositories
- Use environment variables or secret managers to store keys
- Rotate keys if you suspect they've been compromised
- Use separate keys for different applications to isolate access