Snapshot API
The Snapshot API renders on-chain analytics charts as PNG images or SVG vector graphics. Send metric IDs and optional display parameters, and receive a fully-rendered chart image ready for embedding in reports, dashboards, or AI conversations. Currently supports Bitcoin metrics, with multi-chain coverage (ETH, TON, TRON) expanding.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/chart/snapshot | Simple charts via query parameters |
POST | /v1/chart/snapshot | Full customization via JSON body |
Both endpoints return image/png by default.
Authentication
All requests require an API key via the Authorization header:
Authorization: Bearer YOUR_API_KEY
See Authentication for details on obtaining API keys.
Access & Rate Limits
The Snapshot API requires Pro or Enterprise tier. Demo and Free tier keys receive 403 Forbidden.
Snapshot API follows the same rate limits as the Data API. See Rate Limits for details.
When rate limited, the API returns 429 Too Many Requests with a retry_after field.
Metric access is also grade-gated: grade 0 metrics (price, supply, MVRV) are available to all Pro+ keys, grade 1 metrics (SOPR, P&L) require Pro, and grade 2 metrics (CBD heatmaps) require Enterprise.
GET /v1/chart/snapshot
Generate a chart from query parameters. Best for simple, single-metric or template-based charts.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
metric | string | - | Single metric ID (e.g., price, lth_supply). Mutually exclusive with metrics and template. |
metrics | string | - | Comma-separated metric IDs, max 6 (e.g., lth_supply,sth_supply). Mutually exclusive with metric and template. |
template | string | - | Predefined template ID. Mutually exclusive with metric and metrics. |
days | integer | 365 | Days of historical data (7-10000). |
start_date | string | - | Start date (YYYY-MM-DD). Overrides days. |
end_date | string | - | End date (YYYY-MM-DD). Defaults to today. |
style | string | auto | Chart style: line, area, bar. Auto-detected from metric registry if omitted. |
scale | string | linear | Y-axis scale: linear or log. |
overlay | string | - | Add price overlay as a subtle dashed line on the right axis (use price). Currently BTC price. |
width | integer | 1200 | Image width in pixels (600-2400). |
height | integer | 600 | Image height in pixels (300-1200). |
title | string | auto | Chart title. Auto-generated from metric names if omitted. |
theme | string | light | Color theme: light or dark. |
Exactly one of metric, metrics, or template must be provided.
Available Templates
| Template | Metrics |
|---|---|
price | BTC Price |
price_volume | Price + Volume |
market_cap | Market Cap |
holder_supply | LTH Supply + STH Supply |
mvrv_ratio | LTH MVRV + STH MVRV |
realized_price | LTH Realized Price + STH Realized Price |
realized_cap | LTH Realized Cap + STH Realized Cap |
unrealized_pl | LTH Unrealized P/L + STH Unrealized P/L |
realized_pl | LTH Realized P/L + STH Realized P/L |
sopr | LTH SOPR + STH SOPR |
block_height | Block Height |
Examples
# Bitcoin example: BTC price, 1 year, line chart
curl -H "Authorization: Bearer YOUR_KEY" \
"https://api.blocklens.co/v1/chart/snapshot?metric=price" \
--output price.png
# Bitcoin example: two metrics with area style
curl -H "Authorization: Bearer YOUR_KEY" \
"https://api.blocklens.co/v1/chart/snapshot?metrics=lth_supply,sth_supply&style=area&days=730" \
--output supply.png
# Template with dark theme
curl -H "Authorization: Bearer YOUR_KEY" \
"https://api.blocklens.co/v1/chart/snapshot?template=mvrv_ratio&theme=dark" \
--output mvrv_dark.png
# Log scale with price overlay
curl -H "Authorization: Bearer YOUR_KEY" \
"https://api.blocklens.co/v1/chart/snapshot?metric=lth_supply&scale=log&overlay=price&days=1095" \
--output supply_with_price.png
# Get JSON metadata instead of image
curl -H "Authorization: Bearer YOUR_KEY" \
-H "Accept: application/json" \
"https://api.blocklens.co/v1/chart/snapshot?metric=price" | jq
# Get SVG instead of PNG
curl -H "Authorization: Bearer YOUR_KEY" \
-H "Accept: image/svg+xml" \
"https://api.blocklens.co/v1/chart/snapshot?metric=price" \
--output price.svg
Success Response
HTTP/1.1 200 OK
Content-Type: image/png
Cache-Control: public, max-age=3600
X-Snapshot-Cache: HIT
X-Snapshot-Render-Ms: 0
<binary PNG data>
POST /v1/chart/snapshot
Full chart customization via JSON body. Supports per-metric styling, custom axes, formulas, reference lines, reference areas, and more. Designed for AI agents (via MCP) and advanced users.
Request Body
Provide exactly one data source (metric, metrics, or template):
{
"metric": "price",
"days": 365,
"start_date": "2025-01-01",
"end_date": "2026-02-23",
"title": "Custom Chart Title",
"width": 1200,
"height": 600,
"theme": "light",
"format": "png",
"style": "line",
"scale": "linear",
"overlay": "price",
"y_axes": [
{"id": "axis-left", "side": "left", "scale": "linear", "format": "number"},
{"id": "axis-right", "side": "right", "scale": "log", "format": "currency"}
],
"formulas": [
{"expression": "sma(m1, 200)", "label": "200-day SMA", "color": "#9333ea", "style": "line"}
],
"reference_lines": [
{"y": 1.0, "stroke": "#9ca3af", "stroke_dasharray": "3 3", "label": "Break-even"}
],
"reference_areas": [
{"y1": 0, "y2": 0.85, "fill": "#16a34a", "fill_opacity": 0.08, "label": "Undervalued"}
]
}
Note: Exactly one of metric, metrics, or template must be provided.
Metrics Field
The metrics field supports mixed types:
// String shorthand
["price", "lth_supply"]
// Full config objects
[{"id": "price", "axis": "right", "style": "line", "color": "#374151"}]
// Mixed
["price", {"id": "lth_supply", "axis": "left", "style": "area"}]
// With params for parameterized metrics
[
{"id": "funding_binance", "params": {"exchange": "binance"}},
{"id": "price"}
]
Some metrics require additional parameters (e.g., exchange, ticker, id). Include the params object from the metric definition when using these metrics.
Per-Metric Options
| Field | Type | Description |
|---|---|---|
id | string | Required. Metric ID from registry. |
params | object | Parameters for parameterized metrics (e.g., {"exchange": "binance"}). See metric definition for required params. |
axis | left / right | Y-axis side. Auto-assigned if omitted. |
y_axis_id | string | Bind to a specific Y-axis by ID (e.g. axis-diff). Overrides axis. |
style | line / area / bar | Chart style. Registry default if omitted. |
color | string | Hex color (e.g., #2563eb). Auto-assigned if omitted. |
label | string | Display label. Uses metric name if omitted. |
stroke_width | integer | Line width (0-5). Default: 2. Use 0 for bars without borders. |
fill_opacity | float | Fill opacity (0.0-1.0). For transparent bars, use low values like 0.2. |
stroke_dash | string | Dash pattern (e.g., 5 5). |
stack_group | string | Stack group ID for stacked charts. |
show_in_legend | boolean | Whether to show in the chart legend. Default: true. |
visible | boolean | Show/hide. Default: true. |
Custom Y-Axes
The y_axes field defines the Y-axes available to metrics and formulas. Each axis has a unique id that can be referenced via y_axis_id on metrics or formulas. You can define more than two axes — for example, a separate axis for computed differences:
"y_axes": [
{"id": "axis-left", "side": "left", "scale": "linear", "format": "number"},
{"id": "axis-right", "side": "right", "scale": "log", "format": "currency"},
{"id": "axis-diff", "side": "left", "scale": "linear", "format": "number"}
]
| Field | Type | Description |
|---|---|---|
id | string | Unique axis identifier. Referenced by y_axis_id on metrics/formulas. |
side | left / right | Which side of the chart the axis appears on. |
scale | linear / log | Axis scale. Default: linear. |
format | number / currency / percent | Number format for axis labels. |
range | [number, number] | Vertical zone as [from%, to%]. 0 = bottom, 100 = top. Default: full height. Use to stack axes vertically (e.g. volume in bottom 20%, price in top 80%). |
domain_min | number | Hard minimum domain clamp. The axis will never go below this value. |
domain_max | number | Hard maximum domain clamp. The axis will never go above this value. |
no_padding | "top" / "bottom" / "both" | Remove automatic 10% padding from edges. Useful when a domain clamp is a hard boundary (e.g. drawdown capped at 0). |
If y_axes is omitted, axes are auto-generated based on metric axis values.
Example: Price + Volume with Vertical Zones
Stack volume bars in the bottom 20% and price in the remaining space:
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": [
{"id": "price", "style": "line", "color": "#374151", "y_axis_id": "axis-price"},
{"id": "volume", "style": "bar", "color": "#3b82f6", "fill_opacity": 0.3, "stroke_width": 0, "y_axis_id": "axis-vol"}
],
"y_axes": [
{"id": "axis-price", "side": "right", "scale": "log", "format": "currency", "range": [20, 100]},
{"id": "axis-vol", "side": "left", "format": "number", "range": [0, 20], "no_padding": "bottom"}
],
"days": 365,
"title": "BTC Price + Volume (Zoned)"
}' --output price_volume_zones.png
What this produces:
- Volume bars fill the bottom 20% of the chart (
range: [0, 20]) with no padding at the bottom edge - Price occupies the top 80% (
range: [20, 100]) on a log scale - The two series never overlap, creating a clean stacked layout
Example: Drawdown with Domain Clamp
Cap drawdown at 0 (top edge) so the line touches the top of its zone:
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["price"],
"formulas": [
{"expression": "drawdown(price)", "label": "Drawdown from ATH", "style": "area", "color": "#dc2626", "fill_opacity": 0.15, "y_axis_id": "axis-dd"}
],
"y_axes": [
{"id": "axis-right", "side": "right", "scale": "log", "format": "currency"},
{"id": "axis-dd", "side": "left", "format": "percent", "domain_max": 0, "no_padding": "top"}
],
"days": 1825,
"title": "BTC Price + Drawdown from ATH"
}' --output drawdown.png
What this produces:
- Drawdown is always ≤ 0, so
domain_max: 0clamps the top edge no_padding: "top"removes the automatic 10% padding above 0, making the line touch the top when drawdown is 0%- Price is on the right axis with log scale
Formulas
The formulas field lets you define computed series derived from your metrics. Formulas can reference metrics by their id (e.g. lth_supply) or by positional index (m1, m2, etc. based on order in the metrics array).
"formulas": [
{
"expression": "lth_supply - shift(lth_supply, 30)",
"label": "LTH 30d Change",
"color": "#16a34a",
"style": "bar",
"y_axis_id": "axis-diff",
"fill_opacity": 0.2,
"stroke_width": 0
}
]
Supported functions (30 total):
Moving Averages & Rolling Statistics
| Function | Syntax | Description |
|---|---|---|
sma | sma(series, period) | Simple Moving Average |
ema | ema(series, period) | Exponential Moving Average |
median | median(series, period) | Rolling median |
sum | sum(series, period) | Rolling sum |
std | std(series, period) | Rolling standard deviation |
Cumulative
| Function | Syntax | Description |
|---|---|---|
cumsum | cumsum(series) | Expanding cumulative sum |
cummean | cummean(series) | Expanding cumulative mean |
cummedian | cummedian(series) | Expanding cumulative median |
cumstd | cumstd(series) | Expanding cumulative std dev |
cummax | cummax(series) | All-time cumulative max |
cummin | cummin(series) | All-time cumulative min |
Changes
| Function | Syntax | Description |
|---|---|---|
percent_change | percent_change(series, period) | Percentage change (decimal: 0.20 = +20%) |
diff | diff(series, period) | Absolute value change |
Math
| Function | Syntax | Description |
|---|---|---|
abs | abs(series) | Absolute value |
pow | pow(series, n) | Raise to power n |
log | log(series) | Base-10 logarithm |
round | round(series, digits) | Round to N decimal places |
max | max(a, b, ...) | Pointwise maximum |
min | min(a, b, ...) | Pointwise minimum |
Technical Indicators
| Function | Syntax | Description |
|---|---|---|
rsi | rsi(series, period) | Relative Strength Index (0-100) |
corr | corr(s1, s2, period) | Pearson correlation (-1 to 1) |
drawdown | drawdown(series) | Drawdown from ATH (negative decimal) |
Risk & Return
| Function | Syntax | Description |
|---|---|---|
mean_return | mean_return(series, period) | Annualized rolling mean return |
realized_vol | realized_vol(series, period) | Annualized realized volatility |
sharpe_ratio_arithmetic | sharpe_ratio_arithmetic(series, period) | Sharpe ratio (arithmetic) |
sharpe_ratio_geometric | sharpe_ratio_geometric(series, period) | Sharpe ratio (geometric) |
Series Manipulation
| Function | Syntax | Description |
|---|---|---|
shift | shift(series, period) | Shift series by N periods |
if | if(a, "op", b, then, else) | Conditional (op: =, !=, >, >=, <, <=) |
Operators
Arithmetic: +, -, *, /
Grouping: (, )
Referencing
- Metrics by name:
lth_supply + sth_supply— use metric IDs directly - Metrics by position:
m1 + m2— positional references (m1 = first metric, m2 = second, etc.) - Other formulas:
f1 * 2— reference earlier formulas (f1 = first formula, etc.) - Formulas are evaluated in order, so f2 can reference f1, but not vice versa.
Formula options:
| Field | Type | Description |
|---|---|---|
expression | string | Required. Formula expression using metric IDs or positional refs (m1, m2). |
label | string | Required. Display label for the legend. |
color | string | Hex color. Auto-assigned if omitted. |
style | line / area / bar | Chart style. Default: line. |
y_axis_id | string | Bind to a specific Y-axis by ID (e.g. axis-diff). Overrides axis. |
axis | left / right | Y-axis side. Default: left. Ignored if y_axis_id is set. |
fill_opacity | float | Fill opacity (0.0-1.0). For transparent bars, use low values like 0.2. |
stroke_width | integer | Stroke width (0-5). Use 0 for bars without borders. |
stroke_dash | string | Dash pattern (e.g., 6 3). |
stack_group | string | Stack group ID for stacking multiple formula series. |
Reference Lines & Areas
Reference lines add horizontal guide lines to highlight specific values (e.g. break-even at 1.0, overbought threshold). Reference areas add shaded zones to highlight value ranges (e.g. undervalued zone, Bollinger-like bands). Both support static values and dynamic formulas using the same formula engine as the formulas field.
Reference Line Options
| Field | Type | Description |
|---|---|---|
y | number | Static Y value. |
y_formula | string | Formula expression for dynamic Y (e.g. "sma(m1, 200)"). Uses the same engine as formulas. |
y_axis_id | string | Y-axis ID (defaults to first left axis). |
stroke | string | Line color hex (default: #9ca3af). |
stroke_dasharray | string | Dash pattern, e.g. "3 3" for dashed. |
label | string | Label text. |
Provide either y (static) or y_formula (dynamic), not both. Maximum 10 reference lines per chart.
Reference Area Options
| Field | Type | Description |
|---|---|---|
y1 | number | Static lower Y bound. |
y2 | number | Static upper Y bound. |
y1_formula | string | Formula for dynamic lower bound. |
y2_formula | string | Formula for dynamic upper bound. |
y_axis_id | string | Y-axis ID (defaults to first left axis). |
fill | string | Fill color hex (default: #3b82f6). |
fill_opacity | number | Fill opacity 0–1 (default: 0.1). |
label | string | Label text. |
Provide static (y1/y2) or formula-based (y1_formula/y2_formula) bounds — you can mix them (e.g. static y1 with dynamic y2_formula). Maximum 10 reference areas per chart.
Example: MVRV with Value Zones
Add green undervalued zone (0–0.85), red overvalued zone (8–100), and a dashed break-even line at 1.0:
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"metric": "mvrv",
"days": 1825,
"title": "MVRV Ratio — Value Zones",
"reference_lines": [
{"y": 1.0, "stroke": "#9ca3af", "stroke_dasharray": "3 3", "label": "Break-even"}
],
"reference_areas": [
{"y1": 0, "y2": 0.85, "fill": "#16a34a", "fill_opacity": 0.08, "label": "Undervalued"},
{"y1": 8, "y2": 100, "fill": "#dc2626", "fill_opacity": 0.08, "label": "Overvalued"}
]
}' --output mvrv_zones.png
Example: Formula-Based Band
Create a Bollinger-like band around the first formula (±10% envelope):
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["price"],
"days": 365,
"formulas": [
{"expression": "sma(m1, 50)", "label": "50-day SMA", "color": "#2563eb", "style": "line"}
],
"reference_areas": [
{"y1_formula": "f1 * 0.9", "y2_formula": "f1 * 1.1", "fill": "#2563eb", "fill_opacity": 0.06, "label": "±10% Band"}
],
"reference_lines": [
{"y_formula": "sma(m1, 200)", "stroke": "#9333ea", "stroke_dasharray": "6 3", "label": "200-day SMA"}
]
}' --output price_bands.png
Output Format
The format field controls the output:
| Format | Content-Type | Description |
|---|---|---|
png (default) | image/png | Rasterized chart image |
svg | image/svg+xml | Vector graphics (scalable, embeddable) |
json | application/json | Chart metadata (no rendering) |
Alternatively, use the Accept header:
Accept: image/png- PNG (default)Accept: image/svg+xml- SVGAccept: application/json- JSON metadata
JSON Metadata Response
When format=json or Accept: application/json:
{
"success": true,
"title": "BTC Price",
"metrics": [{"id": "price", "label": "BTC Price"}],
"days": 365,
"start_date": null,
"end_date": null,
"theme": "light",
"width": 1200,
"height": 600,
"formulas": [],
"data_points": 365,
"cached": false,
"render_time_ms": 0
}
Examples
# POST with single metric
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"metric": "price", "days": 365}' \
--output price.png
# Multi-metric with custom styling
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": [
{"id": "price", "axis": "right", "style": "line", "color": "#374151"},
{"id": "lth_supply", "axis": "left", "style": "area", "color": "#2563eb"}
],
"days": 730,
"title": "BTC Price vs LTH Supply",
"theme": "dark"
}' \
--output chart.png
# SVG output
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"template": "mvrv_ratio", "format": "svg"}' \
--output mvrv.svg
# JSON metadata
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"metric": "price", "format": "json"}' | jq
Heatmap Rendering
The Snapshot API can render heatmap charts for distribution-based metrics like Cost Basis Distribution. Heatmaps use a separate set of parameters from standard metric charts.
Heatmap Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
heatmap_id | string | - | Heatmap identifier (e.g., cost-basis-distribution) |
heatmap_period | string | 1y | Time period: 3m, 6m, 1y, 2y, 3y, 5y, all |
heatmap_color_scale | string | viridis | Color scale: viridis, plasma, inferno, magma, cividis |
heatmap_y_scale | string | linear | Y-axis scale: linear or log |
theme | string | light | Color theme: light or dark |
title | string | auto | Chart title |
width | integer | 1200 | Image width in pixels |
height | integer | 600 | Image height in pixels |
Example
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"heatmap_id": "cost-basis-distribution",
"heatmap_period": "1y",
"heatmap_color_scale": "viridis",
"heatmap_y_scale": "log",
"theme": "dark",
"title": "Cost Basis Distribution"
}' --output cbd_heatmap.png
Note: Heatmap parameters (heatmap_id, etc.) are mutually exclusive with standard metric parameters (metric, metrics, template). Heatmap metrics require Enterprise tier.
The color scale legend is included in the rendered image, showing the value range mapped to the selected color palette.
Cycle Performance Overlay Charts
Use x_axis: "day_offset" to render cycle performance overlay charts where all Bitcoin halving cycles are aligned to Day 0 for comparison.
x_axis Parameter
| Value | Description |
|---|---|
date (default) | Standard date-based X axis |
day_offset | Days since cycle start (Day 0, Day 100, etc.). All cycles overlay on the same axis for comparison. |
Example
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"metric": "cycle_performance",
"x_axis": "day_offset",
"title": "BTC Cycle Performance Comparison",
"theme": "dark",
"scale": "log"
}' --output cycle_overlay.png
Per-Metric Legend Control
Use show_in_legend on individual metric config objects to control whether a metric appears in the chart legend. This is useful when combining many series where some are context/background lines.
{
"metrics": [
{"id": "price", "show_in_legend": true},
{"id": "sma_200", "show_in_legend": false}
]
}
| Field | Type | Default | Description |
|---|---|---|---|
show_in_legend | boolean | true | Whether the metric appears in the chart legend |
Smart Defaults
The Snapshot API uses intelligent defaults so you can get great-looking charts with minimal configuration:
| Parameter | How Default Is Determined |
|---|---|
| Chart style | From metric registry (chart_types[0]) |
| Color | From metric registry, then palette rotation |
| Y-axis side | First metric on left; same-format metrics share axis; different format on right |
| Y-axis scale | linear (override with scale=log) |
| Time range | Category-based: 365 days for price/valuation/profit, 730 for supply, 180 for blockchain |
| Title | Single metric: metric name. Multiple: "Name1 vs Name2" |
| Image size | 1200 x 600 pixels |
| Theme | light |
Error Responses
All errors return JSON:
// 400 Bad Request
{"success": false, "error": "invalid_params", "message": "Exactly one of 'metric', 'metrics', or 'template' must be provided"}
// 401 Unauthorized
{"success": false, "error": "unauthorized", "message": "API key required"}
// 403 Forbidden
{"success": false, "error": "insufficient_tier", "message": "Metric 'lth_sopr' requires Pro tier", "upgrade_url": "https://blocklens.co/pricing"}
// 429 Rate Limited
{"success": false, "error": "rate_limited", "message": "Snapshot rate limit exceeded. Max 60 per hour for pro tier.", "retry_after": 120}
// 504 Timeout
{"success": false, "error": "render_timeout", "message": "Chart rendering timed out after 20.0s. Try a shorter date range."}
MCP Tool: render_chart
The Blocklens MCP server includes a render_chart tool that lets AI agents generate chart images directly in conversations. The tool calls the Snapshot API and returns the image inline.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
metric | string | - | Single metric ID |
metrics | array | - | Multiple metrics (strings or objects) |
template | string | - | Template ID |
days | integer | 365 | Days of history |
start_date | string | - | Start date (YYYY-MM-DD) |
end_date | string | - | End date (YYYY-MM-DD) |
overlay | price | - | Add price overlay (currently BTC) |
theme | light / dark | light | Color theme |
width | integer | 1200 | Image width |
height | integer | 600 | Image height |
title | string | auto | Chart title |
style | line / area / bar | auto | Chart style |
scale | linear / log | linear | Y-axis scale |
format | png / json | png | Output format |
y_axes | array | - | Custom Y-axes with zones (see Custom Y-Axes) |
reference_lines | array | - | Horizontal reference lines (see Reference Lines & Areas) |
reference_areas | array | - | Shaded reference zones (see Reference Lines & Areas) |
Usage Examples
User: "Show me the MVRV ratio for the last 2 years"
Agent calls: render_chart({ template: "mvrv_ratio", days: 730 })
-> Returns PNG image inline
User: "Chart BTC price vs LTH supply"
Agent calls: render_chart({
metrics: [
{ id: "price", axis: "right" },
{ id: "lth_supply", axis: "left", style: "area" }
],
days: 365
})
-> Returns PNG image inline
User: "Is there capitulation? Show SOPR"
Agent calls: render_chart({ template: "sopr", days: 180, overlay: "price" })
-> Returns PNG image inline
MCP Configuration
Add to your Claude Desktop or Cursor config to enable chart rendering:
{
"mcpServers": {
"blocklens": {
"command": "npx",
"args": ["-y", "blocklens-mcp-server"],
"env": {
"BLOCKLENS_API_KEY": "your_api_key_here"
}
}
}
}
See MCP Server for full setup instructions.
Advanced Example: LTH Supply Chart
This example replicates the full Long-Term Holder Supply chart from the Blocklens dashboard — two metrics, two computed formula series, and three Y-axes:
curl -X POST "https://api.blocklens.co/v1/chart/snapshot" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": [
{"id": "price", "label": "BTC Price", "style": "line", "color": "#6b7280", "axis": "right", "fill_opacity": 0, "stroke_width": 1},
{"id": "lth_supply", "label": "LTH Supply", "style": "line", "color": "#2563eb", "axis": "left", "stroke_width": 2}
],
"y_axes": [
{"id": "axis-left", "side": "left", "scale": "linear"},
{"id": "axis-right", "side": "right", "scale": "log"},
{"id": "axis-diff", "side": "left", "scale": "linear"}
],
"formulas": [
{"expression": "max(lth_supply - shift(lth_supply, 30), 0)", "label": "LTH 30d+ diff", "color": "#16a34a", "style": "bar", "y_axis_id": "axis-diff", "fill_opacity": 0.2, "stroke_width": 0},
{"expression": "min(0, lth_supply - shift(lth_supply, 30))", "label": "LTH 30d- diff", "color": "#dc2626", "style": "bar", "y_axis_id": "axis-diff", "fill_opacity": 0.2, "stroke_width": 0}
],
"days": 730,
"title": "Long-Term Holder Supply"
}' --output lth_supply.png
What this produces:
- BTC Price — gray line on the right axis (log scale)
- LTH Supply — blue line on the left axis (linear)
- 30-day positive accumulation — semi-transparent green bars on a separate
axis-diffaxis - 30-day distribution — semi-transparent red bars on the same
axis-diffaxis
Key techniques used:
shift(lth_supply, 30)computes the 30-day lookback valuemax(..., 0)andmin(0, ...)split positive and negative changes into separate seriesy_axis_id: "axis-diff"binds both formula bars to a dedicated axis independent of the main metric axesfill_opacity: 0.2+stroke_width: 0creates subtle, borderless transparent bars
Chart Templates
Full chart configurations (including metrics, formulas, axes, and styling) are available as database-backed templates via:
GET /api/lab/templates
These templates can serve as reference for building your own POST request bodies. Each template contains the complete config that produces a specific chart on the Blocklens dashboard.
Watermark
All rendered chart images include a blocklens.co watermark and copyright notice. This applies to both PNG and SVG output formats.
Caching
Rendered snapshots are cached for 1 hour in Redis. Cache behavior:
- Identical chart configurations return cached results instantly
- Cache key is derived from the full chart config (metrics, axes, time range, theme, size)
- The
X-Snapshot-Cacheresponse header indicatesHITorMISS - The
X-Snapshot-Render-Msheader shows render time (0 for cache hits) - Popular charts are pre-warmed after each daily data update (05:00 UTC)