Platform Integrations
Chartly integrates seamlessly with popular platforms, frameworks, and services using simple HTTP requests. This guide covers platform-specific integration examples and best practices.
Quick Integration Links
Platform | Type | Use Case |
---|---|---|
JavaScript/Node.js | HTTP Client | Client & server usage |
Python | HTTP Client | Flask, Django, FastAPI |
React | Frontend Framework | Dynamic chart components |
Slack | Bot Integration | Slash commands & apps |
HTML/Email | Reports & notifications | |
No-Code | Automation | Zapier, Make.com |
JavaScript & Node.js
Basic HTTP Request
async function generateChart(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 400,
format: 'png'
})
});
if (!response.ok) {
throw new Error(`Chart generation failed: ${response.statusText}`);
}
return await response.arrayBuffer();
}
// Usage
const chartBuffer = await generateChart({
type: 'bar',
data: {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [{
label: 'Revenue',
data: [100, 120, 115, 134]
}]
},
options: { responsive: false }
});
// Save to file
require('fs').writeFileSync('chart.png', Buffer.from(chartBuffer));
Express.js Integration
const express = require('express');
const app = express();
app.use(express.json());
app.post('/generate-chart', async (req, res) => {
try {
const { chartConfig, width = 600, height = 400 } = req.body;
const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width,
height,
format: 'png'
})
});
if (!response.ok) {
return res.status(500).json({ error: 'Chart generation failed' });
}
const chartBuffer = await response.arrayBuffer();
res.setHeader('Content-Type', 'image/png');
res.setHeader('Cache-Control', 'public, max-age=3600');
res.send(Buffer.from(chartBuffer));
} catch (error) {
console.error('Chart generation error:', error);
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
Next.js API Route
// pages/api/chart.js or app/api/chart/route.js
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { chart, width = 600, height = 400, format = 'png' } = req.body;
const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart,
width,
height,
format
})
});
if (!response.ok) {
throw new Error('Chart generation failed');
}
const chartBuffer = await response.arrayBuffer();
res.setHeader('Content-Type', `image/${format}`);
res.setHeader('Cache-Control', 'public, max-age=3600');
res.send(Buffer.from(chartBuffer));
} catch (error) {
res.status(500).json({ error: 'Chart generation failed' });
}
}
Creating Permanent Chart URLs
async function createPermanentChartUrl(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 400,
format: 'png'
})
});
const data = await response.json();
return data.url;
}
// Usage
const chartUrl = await createPermanentChartUrl({
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{ data: [10, 20, 15] }]
},
options: { responsive: false }
});
console.log(`Chart available at: ${chartUrl}`);
Python
Basic HTTP Request
import requests
import json
def generate_chart(chart_config, width=600, height=400, format='png'):
"""Generate a chart using Chartly API"""
response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': chart_config,
'width': width,
'height': height,
'format': format
}
)
response.raise_for_status() # Raises an exception for bad status codes
return response.content
# Usage
chart_config = {
"type": "line",
"data": {
"labels": ["Jan", "Feb", "Mar", "Apr"],
"datasets": [{
"label": "Sales",
"data": [12, 19, 3, 5],
"borderColor": "rgb(75, 192, 192)",
"tension": 0.1
}]
},
"options": {"responsive": False}
}
chart_bytes = generate_chart(chart_config)
# Save to file
with open("chart.png", "wb") as f:
f.write(chart_bytes)
Flask Integration
from flask import Flask, request, jsonify, send_file
import requests
import io
import os
app = Flask(__name__)
@app.route('/chart', methods=['POST'])
def generate_chart():
"""Generate chart endpoint"""
try:
data = request.get_json()
response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': data['chart'],
'width': data.get('width', 600),
'height': data.get('height', 400),
'format': data.get('format', 'png')
}
)
if response.status_code != 200:
return jsonify({'error': 'Chart generation failed'}), 500
return send_file(
io.BytesIO(response.content),
mimetype=f"image/{data.get('format', 'png')}",
as_attachment=False,
download_name='chart.png'
)
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)
Django Integration
# views.py
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
import requests
import json
import os
@csrf_exempt
@require_http_methods(["POST"])
def generate_chart(request):
"""Django view for chart generation"""
try:
data = json.loads(request.body)
response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': data['chart'],
'width': data.get('width', 600),
'height': data.get('height', 400),
'format': data.get('format', 'png')
}
)
if response.status_code != 200:
return JsonResponse({'error': 'Chart generation failed'}, status=500)
http_response = HttpResponse(
response.content,
content_type=f"image/{data.get('format', 'png')}"
)
http_response['Cache-Control'] = 'public, max-age=3600'
return http_response
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('chart/', views.generate_chart, name='generate_chart'),
]
FastAPI Integration
from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
import requests
import os
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class ChartRequest(BaseModel):
chart: dict
width: Optional[int] = 600
height: Optional[int] = 400
format: Optional[str] = "png"
@app.post("/chart")
async def generate_chart(request: ChartRequest):
"""FastAPI endpoint for chart generation"""
try:
response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': request.chart,
'width': request.width,
'height': request.height,
'format': request.format
}
)
if response.status_code != 200:
raise HTTPException(status_code=500, detail="Chart generation failed")
media_type = f"image/{request.format}"
return Response(
content=response.content,
media_type=media_type,
headers={"Cache-Control": "public, max-age=3600"}
)
except requests.RequestException as e:
raise HTTPException(status_code=500, detail=str(e))
# Usage
# uvicorn main:app --reload
React
Chart Component with HTTP Requests
import { useState, useEffect } from 'react';
function Chart({ config, width = 600, height = 400 }) {
const [chartUrl, setChartUrl] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const generateChart = async () => {
try {
setLoading(true);
setError(null);
// Call your backend endpoint that proxies to Chartly
const response = await fetch('/api/generate-chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
chart: config,
width,
height,
format: 'png'
})
});
if (!response.ok) {
throw new Error('Chart generation failed');
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
setChartUrl(url);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
if (config) {
generateChart();
}
// Cleanup blob URL
return () => {
if (chartUrl) {
URL.revokeObjectURL(chartUrl);
}
};
}, [config, width, height]);
if (loading) return <div>Loading chart...</div>;
if (error) return <div>Error: {error}</div>;
return chartUrl ? (
<img
src={chartUrl}
alt="Generated Chart"
width={width}
height={height}
style={{ maxWidth: '100%', height: 'auto' }}
/>
) : null;
}
// Usage
function Dashboard() {
const chartConfig = {
type: 'bar',
data: {
labels: ['Product A', 'Product B', 'Product C'],
datasets: [{
label: 'Sales',
data: [100, 150, 120],
backgroundColor: 'rgba(54, 162, 235, 0.8)'
}]
},
options: { responsive: false }
};
return (
<div>
<h1>Sales Dashboard</h1>
<Chart config={chartConfig} width={600} height={400} />
</div>
);
}
Custom Hook for Chart Generation
import { useState, useEffect } from 'react';
function useChart(config, options = {}) {
const [chartUrl, setChartUrl] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const { width = 600, height = 400, format = 'png' } = options;
useEffect(() => {
if (!config) return;
const generateChart = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch('/api/generate-chart', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chart: config,
width,
height,
format
})
});
if (!response.ok) {
throw new Error('Failed to generate chart');
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
// Clean up previous URL
if (chartUrl) {
URL.revokeObjectURL(chartUrl);
}
setChartUrl(url);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
generateChart();
}, [config, width, height, format]);
// Cleanup on unmount
useEffect(() => {
return () => {
if (chartUrl) {
URL.revokeObjectURL(chartUrl);
}
};
}, [chartUrl]);
return { chartUrl, loading, error };
}
// Usage
function ChartWidget({ data }) {
const chartConfig = {
type: 'line',
data: data,
options: { responsive: false }
};
const { chartUrl, loading, error } = useChart(chartConfig, {
width: 500,
height: 300
});
if (loading) return <div>Loading chart...</div>;
if (error) return <div>Error: {error}</div>;
return chartUrl ? (
<img src={chartUrl} alt="Chart" width={500} height={300} />
) : null;
}
Slack
Basic Slack Bot Integration
const { App } = require('@slack/bolt');
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
// Slash command: /chart
app.command('/chart', async ({ command, ack, respond }) => {
await ack();
try {
// Parse command text for chart data
const chartData = parseChartCommand(command.text);
// Generate chart via Chartly API
const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartData,
width: 600,
height: 400,
format: 'png'
})
});
if (!response.ok) {
throw new Error('Chart generation failed');
}
const chartBuffer = await response.arrayBuffer();
// Upload chart to Slack
await app.client.files.uploadV2({
token: process.env.SLACK_BOT_TOKEN,
channel_id: command.channel_id,
file: Buffer.from(chartBuffer),
filename: 'chart.png',
title: 'Generated Chart',
initial_comment: `Chart generated from: ${command.text}`
});
} catch (error) {
await respond(`Error generating chart: ${error.message}`);
}
});
function parseChartCommand(text) {
// Simple example - parse "bar 10 20 30" into chart config
const parts = text.split(' ');
const type = parts[0] || 'bar';
const data = parts.slice(1).map(Number).filter(n => !isNaN(n)) || [1, 2, 3];
return {
type,
data: {
labels: data.map((_, i) => `Item ${i + 1}`),
datasets: [{
label: 'Data',
data: data,
backgroundColor: 'rgba(54, 162, 235, 0.8)'
}]
},
options: { responsive: false }
};
}
(async () => {
await app.start(process.env.PORT || 3000);
console.log('⚡️ Slack bot is running!');
})();
Slack Block Kit Integration
app.command('/dashboard', async ({ command, ack, respond }) => {
await ack();
try {
// Generate multiple charts and get permanent URLs
const [salesChartUrl, trafficChartUrl] = await Promise.all([
createPermanentChart(salesChartConfig),
createPermanentChart(trafficChartConfig)
]);
await respond({
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: "📊 Weekly Dashboard"
}
},
{
type: "section",
text: {
type: "mrkdwn",
text: "*Sales Performance*"
}
},
{
type: "image",
image_url: salesChartUrl,
alt_text: "Sales Chart"
},
{
type: "section",
text: {
type: "mrkdwn",
text: "*Website Traffic*"
}
},
{
type: "image",
image_url: trafficChartUrl,
alt_text: "Traffic Chart"
}
]
});
} catch (error) {
await respond(`Error generating dashboard: ${error.message}`);
}
});
async function createPermanentChart(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 400
})
});
const data = await response.json();
return data.url;
}
Email & HTML
HTML Email Templates
<!DOCTYPE html>
<html>
<head>
<title>Monthly Report</title>
<style>
.chart-container {
text-align: center;
margin: 20px 0;
}
.chart-image {
max-width: 100%;
height: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
}
</style>
</head>
<body>
<h1>Monthly Performance Report</h1>
<div class="chart-container">
<h2>Revenue Trends</h2>
<!-- Using permanent chart URL -->
<img src="https://api.chartly.dev/v1/chart/abc123def456"
alt="Monthly Revenue Chart"
class="chart-image"
width="600"
height="400">
</div>
<div class="chart-container">
<h2>Traffic Analysis</h2>
<!-- Using signed URL for time-limited access -->
<img src="https://api.chartly.dev/v1/chart?chart=...&exp=1642262400&sig=hmac_signature"
alt="Traffic Analysis Chart"
class="chart-image"
width="500"
height="300">
</div>
</body>
</html>
Email Service Integration
const nodemailer = require('nodemailer');
async function sendReportEmail(recipients, reportData) {
// Generate permanent chart URLs
const [salesChartUrl, trafficChartUrl] = await Promise.all([
createPermanentChart({
type: 'line',
data: reportData.sales,
options: { responsive: false }
}),
createPermanentChart({
type: 'bar',
data: reportData.traffic,
options: { responsive: false }
})
]);
// Configure email transporter
const transporter = nodemailer.createTransporter({
host: process.env.SMTP_HOST,
port: 587,
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
});
// Send email with embedded charts
await transporter.sendMail({
from: '"Reports Team" <reports@yourcompany.com>',
to: recipients.join(', '),
subject: `Monthly Report - ${new Date().toLocaleDateString()}`,
html: `
<h1>Monthly Performance Report</h1>
<h2>Sales Performance</h2>
<img src="${salesChartUrl}"
alt="Sales Chart"
width="600"
height="300"
style="max-width: 100%; height: auto;">
<h2>Website Traffic</h2>
<img src="${trafficChartUrl}"
alt="Traffic Chart"
width="600"
height="300"
style="max-width: 100%; height: auto;">
<p>Best regards,<br>The Analytics Team</p>
`
});
}
async function createPermanentChart(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 300
})
});
const data = await response.json();
return data.url;
}
No-Code Platforms
Zapier Integration
Chartly provides native Zapier integration for no-code automation workflows.
Setup Steps:
- Search for "Chartly" in Zapier
- Connect your account with your API key
- Choose from available triggers and actions
Available Actions:
- Generate Chart from Data - Create charts from spreadsheet data
- Create Permanent Chart URL - Generate shareable chart links
- Get Chart Analytics - Retrieve usage metrics
Example Zap Workflow:
Trigger: New row in Google Sheets
Action: Generate chart from row data
Action: Post chart to Slack channel
Action: Send chart via email
Webhook Alternative: If using custom webhooks, send POST requests to:
https://api.chartly.dev/v1/chart/create
With payload:
{
"chart": {
"type": "{{chart_type}}",
"data": {
"labels": {{label_array}},
"datasets": [{
"data": {{data_array}},
"backgroundColor": "rgba(54, 162, 235, 0.8)"
}]
},
"options": {"responsive": false}
},
"width": 600,
"height": 400
}
Make.com (Integromat)
{
"scenario": {
"name": "Weekly Report Charts",
"modules": [
{
"type": "trigger",
"app": "schedule",
"config": {
"interval": "weekly",
"time": "09:00"
}
},
{
"type": "action",
"app": "airtable",
"action": "list_records",
"config": {
"table": "Sales Data"
}
},
{
"type": "http",
"method": "POST",
"url": "https://api.chartly.dev/v1/chart/create",
"headers": {
"Content-Type": "application/json",
"X-Api-Key": "{{your_api_key}}"
},
"body": {
"chart": {
"type": "line",
"data": {
"labels": "{{airtable.labels}}",
"datasets": [{
"data": "{{airtable.data}}"
}]
},
"options": {"responsive": false}
},
"width": 800,
"height": 400
}
},
{
"type": "action",
"app": "email",
"action": "send_email",
"config": {
"to": "team@company.com",
"subject": "Weekly Report",
"body": "<img src='{{http.url}}'>"
}
}
]
}
}
Bubble.io Integration
API Connector Setup:
- Go to Plugins → API Connector
- Add new API call:
- Name: Chartly Generate Chart
- Type: Action
- Method: POST
- URL:
https://api.chartly.dev/v1/chart/create
Headers:
X-Api-Key: [Your API Key]
Content-Type: application/json
Body (JSON):
{
"chart": {
"type": "<chart_type>",
"data": {
"labels": <label_list>,
"datasets": [{
"data": <data_list>,
"backgroundColor": "rgba(54, 162, 235, 0.8)"
}]
},
"options": {"responsive": false}
},
"width": <width>,
"height": <height>
}
Usage in Workflows:
- Trigger: Button clicked or data change
- Action: Call Chartly Generate Chart API
- Result: Use returned URL in Image element
Mobile Apps
React Native HTTP Integration
import React, { useState, useEffect } from 'react';
import { View, Image, ActivityIndicator, Text } from 'react-native';
const ChartComponent = ({ chartConfig, width = 350, height = 200 }) => {
const [chartUri, setChartUri] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const generateChart = async () => {
try {
setLoading(true);
setError(null);
// Call your backend API that proxies to Chartly
const response = await fetch('https://your-backend.com/api/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${userToken}`, // Your app's auth
},
body: JSON.stringify({
chart: chartConfig,
width,
height,
format: 'png'
})
});
if (!response.ok) {
throw new Error('Chart generation failed');
}
const blob = await response.blob();
const uri = URL.createObjectURL(blob);
setChartUri(uri);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
if (chartConfig) {
generateChart();
}
}, [chartConfig, width, height]);
if (loading) {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', height }}>
<ActivityIndicator size="large" />
<Text>Generating chart...</Text>
</View>
);
}
if (error) {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', height }}>
<Text>Error: {error}</Text>
</View>
);
}
return chartUri ? (
<Image
source={{ uri: chartUri }}
style={{ width, height }}
resizeMode="contain"
/>
) : null;
};
// Usage
export default function Dashboard() {
const chartConfig = {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{
label: 'Sales',
data: [100, 150, 120],
backgroundColor: 'rgba(54, 162, 235, 0.8)'
}]
},
options: { responsive: false }
};
return (
<View style={{ padding: 20 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 10 }}>
Sales Chart
</Text>
<ChartComponent
chartConfig={chartConfig}
width={350}
height={200}
/>
</View>
);
}
Flutter HTTP Integration
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:typed_data';
class ChartlyService {
final String apiKey;
final String baseUrl = 'https://api.chartly.dev';
ChartlyService({required this.apiKey});
Future<String> createChart(Map<String, dynamic> chartConfig, {
int width = 600,
int height = 400,
String format = 'png'
}) async {
final response = await http.post(
Uri.parse('$baseUrl/v1/chart/create'),
headers: {
'X-Api-Key': apiKey,
'Content-Type': 'application/json',
},
body: json.encode({
'chart': chartConfig,
'width': width,
'height': height,
'format': format,
}),
);
if (response.statusCode == 201) {
final data = json.decode(response.body);
return data['url'];
} else {
throw Exception('Failed to create chart: ${response.body}');
}
}
Future<Uint8List> generateChart(Map<String, dynamic> chartConfig, {
int width = 600,
int height = 400,
String format = 'png'
}) async {
final response = await http.post(
Uri.parse('$baseUrl/v1/chart'),
headers: {
'X-Api-Key': apiKey,
'Content-Type': 'application/json',
},
body: json.encode({
'chart': chartConfig,
'width': width,
'height': height,
'format': format,
}),
);
if (response.statusCode == 200) {
return response.bodyBytes;
} else {
throw Exception('Failed to generate chart: ${response.body}');
}
}
}
// Widget usage
class ChartWidget extends StatefulWidget {
final Map<String, dynamic> chartConfig;
final int width;
final int height;
const ChartWidget({
Key? key,
required this.chartConfig,
this.width = 400,
this.height = 300,
}) : super(key: key);
@override
_ChartWidgetState createState() => _ChartWidgetState();
}
class _ChartWidgetState extends State<ChartWidget> {
String? chartUrl;
bool loading = true;
String? error;
final chartly = ChartlyService(apiKey: 'your_api_key_here');
@override
void initState() {
super.initState();
generateChart();
}
void generateChart() async {
try {
setState(() {
loading = true;
error = null;
});
final url = await chartly.createChart(
widget.chartConfig,
width: widget.width,
height: widget.height,
);
setState(() {
chartUrl = url;
loading = false;
});
} catch (e) {
setState(() {
error = e.toString();
loading = false;
});
}
}
@override
Widget build(BuildContext context) {
if (loading) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 10),
Text('Generating chart...'),
],
),
);
}
if (error != null) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error, color: Colors.red),
Text('Error: $error'),
ElevatedButton(
onPressed: generateChart,
child: const Text('Retry'),
),
],
),
);
}
return chartUrl != null
? Image.network(
chartUrl!,
width: widget.width.toDouble(),
height: widget.height.toDouble(),
fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) {
return const Center(
child: Text('Failed to load chart'),
);
},
)
: const Center(child: Text('No chart available'));
}
}
// Usage example
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final chartConfig = {
'type': 'bar',
'data': {
'labels': ['A', 'B', 'C'],
'datasets': [
{
'data': [10, 20, 30],
'backgroundColor': 'rgba(54, 162, 235, 0.8)',
}
]
},
'options': {'responsive': false}
};
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Chart Example')),
body: Center(
child: ChartWidget(
chartConfig: chartConfig,
width: 400,
height: 300,
),
),
),
);
}
}
Next Steps:
- Check Usage & Billing for rate limits and pricing
- Review Troubleshooting for common integration issues
- Explore Chart Types for comprehensive chart examples
- Visit api.chartly.dev for interactive API documentation