curl --request POST \
--url https://demo-api.mobula.io/api/2/perp/chart \
--header 'Content-Type: application/json' \
--data '
{
"candles": [
{
"t": 1780860000000,
"o": 1.0615964,
"h": 1.0656162,
"l": 1.0506006,
"c": 1.0605862
},
{
"t": 1780861800000,
"o": 1.0605862,
"h": 1.0655736,
"l": 1.0525683,
"c": 1.0630746
},
{
"t": 1780863600000,
"o": 1.0630746,
"h": 1.0695774,
"l": 1.0630746,
"c": 1.0655949
}
],
"width": 1024,
"height": 850,
"name": "FLUID/USD",
"lines": {
"stopLoss": 1.2876838333333334,
"takeProfit": 0.7358193333333334,
"liquidation": 1.4231453021582852
},
"headerData": {
"pair": "FLUID/USD",
"leverage": 3,
"currentPrice": 1.103729,
"priceChange": -6.305772495755514,
"openInterestL": {
"value": 0,
"total": 250000
},
"openInterestS": {
"value": 30.000026,
"total": 249969.999974
},
"holdingL": 0.00251711712,
"holdingS": 0.00251711712
},
"footerData": {
"high24h": 1.2151002,
"low24h": 1.0799406,
"volume24h": 2001.2866550754236
}
}
'import requests
url = "https://demo-api.mobula.io/api/2/perp/chart"
payload = {
"candles": [
{
"t": 1780860000000,
"o": 1.0615964,
"h": 1.0656162,
"l": 1.0506006,
"c": 1.0605862
},
{
"t": 1780861800000,
"o": 1.0605862,
"h": 1.0655736,
"l": 1.0525683,
"c": 1.0630746
},
{
"t": 1780863600000,
"o": 1.0630746,
"h": 1.0695774,
"l": 1.0630746,
"c": 1.0655949
}
],
"width": 1024,
"height": 850,
"name": "FLUID/USD",
"lines": {
"stopLoss": 1.2876838333333334,
"takeProfit": 0.7358193333333334,
"liquidation": 1.4231453021582852
},
"headerData": {
"pair": "FLUID/USD",
"leverage": 3,
"currentPrice": 1.103729,
"priceChange": -6.305772495755514,
"openInterestL": {
"value": 0,
"total": 250000
},
"openInterestS": {
"value": 30.000026,
"total": 249969.999974
},
"holdingL": 0.00251711712,
"holdingS": 0.00251711712
},
"footerData": {
"high24h": 1.2151002,
"low24h": 1.0799406,
"volume24h": 2001.2866550754236
}
}
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({
candles: [
{t: 1780860000000, o: 1.0615964, h: 1.0656162, l: 1.0506006, c: 1.0605862},
{t: 1780861800000, o: 1.0605862, h: 1.0655736, l: 1.0525683, c: 1.0630746},
{t: 1780863600000, o: 1.0630746, h: 1.0695774, l: 1.0630746, c: 1.0655949}
],
width: 1024,
height: 850,
name: 'FLUID/USD',
lines: {
stopLoss: 1.2876838333333334,
takeProfit: 0.7358193333333334,
liquidation: 1.4231453021582852
},
headerData: {
pair: 'FLUID/USD',
leverage: 3,
currentPrice: 1.103729,
priceChange: -6.305772495755514,
openInterestL: {value: 0, total: 250000},
openInterestS: {value: 30.000026, total: 249969.999974},
holdingL: 0.00251711712,
holdingS: 0.00251711712
},
footerData: {high24h: 1.2151002, low24h: 1.0799406, volume24h: 2001.2866550754236}
})
};
fetch('https://demo-api.mobula.io/api/2/perp/chart', 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://demo-api.mobula.io/api/2/perp/chart",
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([
'candles' => [
[
't' => 1780860000000,
'o' => 1.0615964,
'h' => 1.0656162,
'l' => 1.0506006,
'c' => 1.0605862
],
[
't' => 1780861800000,
'o' => 1.0605862,
'h' => 1.0655736,
'l' => 1.0525683,
'c' => 1.0630746
],
[
't' => 1780863600000,
'o' => 1.0630746,
'h' => 1.0695774,
'l' => 1.0630746,
'c' => 1.0655949
]
],
'width' => 1024,
'height' => 850,
'name' => 'FLUID/USD',
'lines' => [
'stopLoss' => 1.2876838333333334,
'takeProfit' => 0.7358193333333334,
'liquidation' => 1.4231453021582852
],
'headerData' => [
'pair' => 'FLUID/USD',
'leverage' => 3,
'currentPrice' => 1.103729,
'priceChange' => -6.305772495755514,
'openInterestL' => [
'value' => 0,
'total' => 250000
],
'openInterestS' => [
'value' => 30.000026,
'total' => 249969.999974
],
'holdingL' => 0.00251711712,
'holdingS' => 0.00251711712
],
'footerData' => [
'high24h' => 1.2151002,
'low24h' => 1.0799406,
'volume24h' => 2001.2866550754236
]
]),
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://demo-api.mobula.io/api/2/perp/chart"
payload := strings.NewReader("{\n \"candles\": [\n {\n \"t\": 1780860000000,\n \"o\": 1.0615964,\n \"h\": 1.0656162,\n \"l\": 1.0506006,\n \"c\": 1.0605862\n },\n {\n \"t\": 1780861800000,\n \"o\": 1.0605862,\n \"h\": 1.0655736,\n \"l\": 1.0525683,\n \"c\": 1.0630746\n },\n {\n \"t\": 1780863600000,\n \"o\": 1.0630746,\n \"h\": 1.0695774,\n \"l\": 1.0630746,\n \"c\": 1.0655949\n }\n ],\n \"width\": 1024,\n \"height\": 850,\n \"name\": \"FLUID/USD\",\n \"lines\": {\n \"stopLoss\": 1.2876838333333334,\n \"takeProfit\": 0.7358193333333334,\n \"liquidation\": 1.4231453021582852\n },\n \"headerData\": {\n \"pair\": \"FLUID/USD\",\n \"leverage\": 3,\n \"currentPrice\": 1.103729,\n \"priceChange\": -6.305772495755514,\n \"openInterestL\": {\n \"value\": 0,\n \"total\": 250000\n },\n \"openInterestS\": {\n \"value\": 30.000026,\n \"total\": 249969.999974\n },\n \"holdingL\": 0.00251711712,\n \"holdingS\": 0.00251711712\n },\n \"footerData\": {\n \"high24h\": 1.2151002,\n \"low24h\": 1.0799406,\n \"volume24h\": 2001.2866550754236\n }\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://demo-api.mobula.io/api/2/perp/chart")
.header("Content-Type", "application/json")
.body("{\n \"candles\": [\n {\n \"t\": 1780860000000,\n \"o\": 1.0615964,\n \"h\": 1.0656162,\n \"l\": 1.0506006,\n \"c\": 1.0605862\n },\n {\n \"t\": 1780861800000,\n \"o\": 1.0605862,\n \"h\": 1.0655736,\n \"l\": 1.0525683,\n \"c\": 1.0630746\n },\n {\n \"t\": 1780863600000,\n \"o\": 1.0630746,\n \"h\": 1.0695774,\n \"l\": 1.0630746,\n \"c\": 1.0655949\n }\n ],\n \"width\": 1024,\n \"height\": 850,\n \"name\": \"FLUID/USD\",\n \"lines\": {\n \"stopLoss\": 1.2876838333333334,\n \"takeProfit\": 0.7358193333333334,\n \"liquidation\": 1.4231453021582852\n },\n \"headerData\": {\n \"pair\": \"FLUID/USD\",\n \"leverage\": 3,\n \"currentPrice\": 1.103729,\n \"priceChange\": -6.305772495755514,\n \"openInterestL\": {\n \"value\": 0,\n \"total\": 250000\n },\n \"openInterestS\": {\n \"value\": 30.000026,\n \"total\": 249969.999974\n },\n \"holdingL\": 0.00251711712,\n \"holdingS\": 0.00251711712\n },\n \"footerData\": {\n \"high24h\": 1.2151002,\n \"low24h\": 1.0799406,\n \"volume24h\": 2001.2866550754236\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://demo-api.mobula.io/api/2/perp/chart")
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 \"candles\": [\n {\n \"t\": 1780860000000,\n \"o\": 1.0615964,\n \"h\": 1.0656162,\n \"l\": 1.0506006,\n \"c\": 1.0605862\n },\n {\n \"t\": 1780861800000,\n \"o\": 1.0605862,\n \"h\": 1.0655736,\n \"l\": 1.0525683,\n \"c\": 1.0630746\n },\n {\n \"t\": 1780863600000,\n \"o\": 1.0630746,\n \"h\": 1.0695774,\n \"l\": 1.0630746,\n \"c\": 1.0655949\n }\n ],\n \"width\": 1024,\n \"height\": 850,\n \"name\": \"FLUID/USD\",\n \"lines\": {\n \"stopLoss\": 1.2876838333333334,\n \"takeProfit\": 0.7358193333333334,\n \"liquidation\": 1.4231453021582852\n },\n \"headerData\": {\n \"pair\": \"FLUID/USD\",\n \"leverage\": 3,\n \"currentPrice\": 1.103729,\n \"priceChange\": -6.305772495755514,\n \"openInterestL\": {\n \"value\": 0,\n \"total\": 250000\n },\n \"openInterestS\": {\n \"value\": 30.000026,\n \"total\": 249969.999974\n },\n \"holdingL\": 0.00251711712,\n \"holdingS\": 0.00251711712\n },\n \"footerData\": {\n \"high24h\": 1.2151002,\n \"low24h\": 1.0799406,\n \"volume24h\": 2001.2866550754236\n }\n}"
response = http.request(request)
puts response.read_body{
"data": "<string>"
}Generate Perp Chart Image
Render a candlestick chart image for a perpetual market from OHLC candles plus header/footer metadata and optional overlay lines (stop-loss, take-profit, liquidation). The candle shape is identical to the /2/perp/ohlcv-history response, so its output can be passed straight in.
curl --request POST \
--url https://demo-api.mobula.io/api/2/perp/chart \
--header 'Content-Type: application/json' \
--data '
{
"candles": [
{
"t": 1780860000000,
"o": 1.0615964,
"h": 1.0656162,
"l": 1.0506006,
"c": 1.0605862
},
{
"t": 1780861800000,
"o": 1.0605862,
"h": 1.0655736,
"l": 1.0525683,
"c": 1.0630746
},
{
"t": 1780863600000,
"o": 1.0630746,
"h": 1.0695774,
"l": 1.0630746,
"c": 1.0655949
}
],
"width": 1024,
"height": 850,
"name": "FLUID/USD",
"lines": {
"stopLoss": 1.2876838333333334,
"takeProfit": 0.7358193333333334,
"liquidation": 1.4231453021582852
},
"headerData": {
"pair": "FLUID/USD",
"leverage": 3,
"currentPrice": 1.103729,
"priceChange": -6.305772495755514,
"openInterestL": {
"value": 0,
"total": 250000
},
"openInterestS": {
"value": 30.000026,
"total": 249969.999974
},
"holdingL": 0.00251711712,
"holdingS": 0.00251711712
},
"footerData": {
"high24h": 1.2151002,
"low24h": 1.0799406,
"volume24h": 2001.2866550754236
}
}
'import requests
url = "https://demo-api.mobula.io/api/2/perp/chart"
payload = {
"candles": [
{
"t": 1780860000000,
"o": 1.0615964,
"h": 1.0656162,
"l": 1.0506006,
"c": 1.0605862
},
{
"t": 1780861800000,
"o": 1.0605862,
"h": 1.0655736,
"l": 1.0525683,
"c": 1.0630746
},
{
"t": 1780863600000,
"o": 1.0630746,
"h": 1.0695774,
"l": 1.0630746,
"c": 1.0655949
}
],
"width": 1024,
"height": 850,
"name": "FLUID/USD",
"lines": {
"stopLoss": 1.2876838333333334,
"takeProfit": 0.7358193333333334,
"liquidation": 1.4231453021582852
},
"headerData": {
"pair": "FLUID/USD",
"leverage": 3,
"currentPrice": 1.103729,
"priceChange": -6.305772495755514,
"openInterestL": {
"value": 0,
"total": 250000
},
"openInterestS": {
"value": 30.000026,
"total": 249969.999974
},
"holdingL": 0.00251711712,
"holdingS": 0.00251711712
},
"footerData": {
"high24h": 1.2151002,
"low24h": 1.0799406,
"volume24h": 2001.2866550754236
}
}
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({
candles: [
{t: 1780860000000, o: 1.0615964, h: 1.0656162, l: 1.0506006, c: 1.0605862},
{t: 1780861800000, o: 1.0605862, h: 1.0655736, l: 1.0525683, c: 1.0630746},
{t: 1780863600000, o: 1.0630746, h: 1.0695774, l: 1.0630746, c: 1.0655949}
],
width: 1024,
height: 850,
name: 'FLUID/USD',
lines: {
stopLoss: 1.2876838333333334,
takeProfit: 0.7358193333333334,
liquidation: 1.4231453021582852
},
headerData: {
pair: 'FLUID/USD',
leverage: 3,
currentPrice: 1.103729,
priceChange: -6.305772495755514,
openInterestL: {value: 0, total: 250000},
openInterestS: {value: 30.000026, total: 249969.999974},
holdingL: 0.00251711712,
holdingS: 0.00251711712
},
footerData: {high24h: 1.2151002, low24h: 1.0799406, volume24h: 2001.2866550754236}
})
};
fetch('https://demo-api.mobula.io/api/2/perp/chart', 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://demo-api.mobula.io/api/2/perp/chart",
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([
'candles' => [
[
't' => 1780860000000,
'o' => 1.0615964,
'h' => 1.0656162,
'l' => 1.0506006,
'c' => 1.0605862
],
[
't' => 1780861800000,
'o' => 1.0605862,
'h' => 1.0655736,
'l' => 1.0525683,
'c' => 1.0630746
],
[
't' => 1780863600000,
'o' => 1.0630746,
'h' => 1.0695774,
'l' => 1.0630746,
'c' => 1.0655949
]
],
'width' => 1024,
'height' => 850,
'name' => 'FLUID/USD',
'lines' => [
'stopLoss' => 1.2876838333333334,
'takeProfit' => 0.7358193333333334,
'liquidation' => 1.4231453021582852
],
'headerData' => [
'pair' => 'FLUID/USD',
'leverage' => 3,
'currentPrice' => 1.103729,
'priceChange' => -6.305772495755514,
'openInterestL' => [
'value' => 0,
'total' => 250000
],
'openInterestS' => [
'value' => 30.000026,
'total' => 249969.999974
],
'holdingL' => 0.00251711712,
'holdingS' => 0.00251711712
],
'footerData' => [
'high24h' => 1.2151002,
'low24h' => 1.0799406,
'volume24h' => 2001.2866550754236
]
]),
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://demo-api.mobula.io/api/2/perp/chart"
payload := strings.NewReader("{\n \"candles\": [\n {\n \"t\": 1780860000000,\n \"o\": 1.0615964,\n \"h\": 1.0656162,\n \"l\": 1.0506006,\n \"c\": 1.0605862\n },\n {\n \"t\": 1780861800000,\n \"o\": 1.0605862,\n \"h\": 1.0655736,\n \"l\": 1.0525683,\n \"c\": 1.0630746\n },\n {\n \"t\": 1780863600000,\n \"o\": 1.0630746,\n \"h\": 1.0695774,\n \"l\": 1.0630746,\n \"c\": 1.0655949\n }\n ],\n \"width\": 1024,\n \"height\": 850,\n \"name\": \"FLUID/USD\",\n \"lines\": {\n \"stopLoss\": 1.2876838333333334,\n \"takeProfit\": 0.7358193333333334,\n \"liquidation\": 1.4231453021582852\n },\n \"headerData\": {\n \"pair\": \"FLUID/USD\",\n \"leverage\": 3,\n \"currentPrice\": 1.103729,\n \"priceChange\": -6.305772495755514,\n \"openInterestL\": {\n \"value\": 0,\n \"total\": 250000\n },\n \"openInterestS\": {\n \"value\": 30.000026,\n \"total\": 249969.999974\n },\n \"holdingL\": 0.00251711712,\n \"holdingS\": 0.00251711712\n },\n \"footerData\": {\n \"high24h\": 1.2151002,\n \"low24h\": 1.0799406,\n \"volume24h\": 2001.2866550754236\n }\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://demo-api.mobula.io/api/2/perp/chart")
.header("Content-Type", "application/json")
.body("{\n \"candles\": [\n {\n \"t\": 1780860000000,\n \"o\": 1.0615964,\n \"h\": 1.0656162,\n \"l\": 1.0506006,\n \"c\": 1.0605862\n },\n {\n \"t\": 1780861800000,\n \"o\": 1.0605862,\n \"h\": 1.0655736,\n \"l\": 1.0525683,\n \"c\": 1.0630746\n },\n {\n \"t\": 1780863600000,\n \"o\": 1.0630746,\n \"h\": 1.0695774,\n \"l\": 1.0630746,\n \"c\": 1.0655949\n }\n ],\n \"width\": 1024,\n \"height\": 850,\n \"name\": \"FLUID/USD\",\n \"lines\": {\n \"stopLoss\": 1.2876838333333334,\n \"takeProfit\": 0.7358193333333334,\n \"liquidation\": 1.4231453021582852\n },\n \"headerData\": {\n \"pair\": \"FLUID/USD\",\n \"leverage\": 3,\n \"currentPrice\": 1.103729,\n \"priceChange\": -6.305772495755514,\n \"openInterestL\": {\n \"value\": 0,\n \"total\": 250000\n },\n \"openInterestS\": {\n \"value\": 30.000026,\n \"total\": 249969.999974\n },\n \"holdingL\": 0.00251711712,\n \"holdingS\": 0.00251711712\n },\n \"footerData\": {\n \"high24h\": 1.2151002,\n \"low24h\": 1.0799406,\n \"volume24h\": 2001.2866550754236\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://demo-api.mobula.io/api/2/perp/chart")
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 \"candles\": [\n {\n \"t\": 1780860000000,\n \"o\": 1.0615964,\n \"h\": 1.0656162,\n \"l\": 1.0506006,\n \"c\": 1.0605862\n },\n {\n \"t\": 1780861800000,\n \"o\": 1.0605862,\n \"h\": 1.0655736,\n \"l\": 1.0525683,\n \"c\": 1.0630746\n },\n {\n \"t\": 1780863600000,\n \"o\": 1.0630746,\n \"h\": 1.0695774,\n \"l\": 1.0630746,\n \"c\": 1.0655949\n }\n ],\n \"width\": 1024,\n \"height\": 850,\n \"name\": \"FLUID/USD\",\n \"lines\": {\n \"stopLoss\": 1.2876838333333334,\n \"takeProfit\": 0.7358193333333334,\n \"liquidation\": 1.4231453021582852\n },\n \"headerData\": {\n \"pair\": \"FLUID/USD\",\n \"leverage\": 3,\n \"currentPrice\": 1.103729,\n \"priceChange\": -6.305772495755514,\n \"openInterestL\": {\n \"value\": 0,\n \"total\": 250000\n },\n \"openInterestS\": {\n \"value\": 30.000026,\n \"total\": 249969.999974\n },\n \"holdingL\": 0.00251711712,\n \"holdingS\": 0.00251711712\n },\n \"footerData\": {\n \"high24h\": 1.2151002,\n \"low24h\": 1.0799406,\n \"volume24h\": 2001.2866550754236\n }\n}"
response = http.request(request)
puts response.read_body{
"data": "<string>"
}Query Details
Send OHLC candles together with the header and footer blocks shown around the chart, and the rendered chart is returned indata. This is a synchronous proxy: one request in, one rendered chart out — nothing is stored.
- Candles use the same
t / o / h / l / cshape asGET /2/perp/ohlcv-history— feed that endpoint’s output directly. tis UNIX milliseconds.priceChangeis a percentage (e.g.-6.31means-6.31%), not a ratio.- Send candles ordered oldest → newest.
- All top-level fields except
linesare required. Withinlines, each ofstopLoss/takeProfit/liquidationis independently optional — send only the levels you have.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| candles | array | Yes | OHLC series ({t, o, h, l, c}), oldest-to-newest. Min 1 candle. |
| width | integer | Yes | Output image width in pixels. Positive integer. |
| height | integer | Yes | Output image height in pixels. Positive integer. |
| name | string | Yes | Chart title / pair label shown on the chart (e.g. FLUID/USD). |
| lines | object | No | Overlay lines: stopLoss, takeProfit, liquidation (all optional). |
| headerData | object | Yes | Header block (see below). |
| footerData | object | Yes | Footer block (see below). |
headerData:
| Field | Type | Description |
|---|---|---|
| pair | string | Trading pair label (e.g. FLUID/USD). |
| leverage | number | Position leverage multiplier. |
| currentPrice | number | Current mark/last price. |
| priceChange | number | Price change for the window, as a percentage (may be negative). |
| openInterestL | object | Long-side open interest: { value, total }. |
| openInterestS | object | Short-side open interest: { value, total }. |
| holdingL | number | Long holding amount. |
| holdingS | number | Short holding amount. |
footerData:
| Field | Type | Description |
|---|---|---|
| high24h | number | 24-hour high price. |
| low24h | number | 24-hour low price. |
| volume24h | number | 24-hour traded volume. |
Response
| Field | Type | Description |
|---|---|---|
| data | string | The rendered chart, passed through verbatim. Treat as an opaque string payload. |

Usage Example
curl -X POST "https://api.mobula.io/api/2/perp/chart" \
-H "Content-Type: application/json" \
-d '{
"candles": [
{ "t": 1780860000000, "o": 1.0615964, "h": 1.0656162, "l": 1.0506006, "c": 1.0605862 },
{ "t": 1780861800000, "o": 1.0605862, "h": 1.0655736, "l": 1.0525683, "c": 1.0630746 }
],
"width": 1024,
"height": 850,
"name": "FLUID/USD",
"lines": { "stopLoss": 1.28768, "takeProfit": 0.73582, "liquidation": 1.42315 },
"headerData": {
"pair": "FLUID/USD",
"leverage": 3,
"currentPrice": 1.103729,
"priceChange": -6.305772495755514,
"openInterestL": { "value": 0, "total": 250000 },
"openInterestS": { "value": 30.000026, "total": 249969.999974 },
"holdingL": 0.00251711712,
"holdingS": 0.00251711712
},
"footerData": { "high24h": 1.2151002, "low24h": 1.0799406, "volume24h": 2001.2866550754236 }
}'
Errors
| Status | When | message |
|---|---|---|
| 400 | Body failed validation (missing/invalid fields, empty candles, wrong keys) | zod validation failed |
| 502 | Upstream chart generator failed or was unreachable | upstream chart generator error |
| 500 | Unexpected internal error | failed to generate chart |
Body
OHLC series, oldest-to-newest by t. Same shape as the /2/perp/ohlcv-history response, so its output can be passed in directly. Must contain at least one candle.
1Show child attributes
Show child attributes
Output image width in pixels. Positive integer.
Output image height in pixels. Positive integer.
Chart title / pair label shown on the chart (e.g. FLUID/USD).
Header block shown above the chart.
Show child attributes
Show child attributes
Footer block shown below the chart.
Show child attributes
Show child attributes
Optional horizontal overlay lines. Each level is independently optional — send only the ones you have.
Show child attributes
Show child attributes
Response
Rendered chart
The rendered chart returned by the renderer, passed through verbatim. Treat as an opaque string payload.