curl --request PUT \
--url https://api.formo.so/v0/boards/{boardId}/charts/{chartId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"chartId": "<string>",
"projectId": "<string>",
"title": "<string>",
"query": "<string>",
"description": "<string>",
"x_axis": "<string>",
"y_axis": [
"<string>"
],
"group_by": "<string>",
"steps": [
{
"event": "<string>"
}
],
"settings": {
"funnelType": "closed",
"endStep": {
"event": "<string>"
},
"maxSteps": 3,
"nodesPerStep": 5,
"filters": "<string>",
"retentionFilter": {
"event": "<string>"
},
"retentionUserFilters": [
{
"field": "<string>",
"value": "<string>"
}
],
"retentionSignalType": "event"
}
}
'import requests
url = "https://api.formo.so/v0/boards/{boardId}/charts/{chartId}"
payload = {
"chartId": "<string>",
"projectId": "<string>",
"title": "<string>",
"query": "<string>",
"description": "<string>",
"x_axis": "<string>",
"y_axis": ["<string>"],
"group_by": "<string>",
"steps": [{ "event": "<string>" }],
"settings": {
"funnelType": "closed",
"endStep": { "event": "<string>" },
"maxSteps": 3,
"nodesPerStep": 5,
"filters": "<string>",
"retentionFilter": { "event": "<string>" },
"retentionUserFilters": [
{
"field": "<string>",
"value": "<string>"
}
],
"retentionSignalType": "event"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
chartId: '<string>',
projectId: '<string>',
title: '<string>',
query: '<string>',
description: '<string>',
x_axis: '<string>',
y_axis: ['<string>'],
group_by: '<string>',
steps: [{event: '<string>'}],
settings: {
funnelType: 'closed',
endStep: {event: '<string>'},
maxSteps: 3,
nodesPerStep: 5,
filters: '<string>',
retentionFilter: {event: '<string>'},
retentionUserFilters: [{field: '<string>', value: '<string>'}],
retentionSignalType: 'event'
}
})
};
fetch('https://api.formo.so/v0/boards/{boardId}/charts/{chartId}', 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://api.formo.so/v0/boards/{boardId}/charts/{chartId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'chartId' => '<string>',
'projectId' => '<string>',
'title' => '<string>',
'query' => '<string>',
'description' => '<string>',
'x_axis' => '<string>',
'y_axis' => [
'<string>'
],
'group_by' => '<string>',
'steps' => [
[
'event' => '<string>'
]
],
'settings' => [
'funnelType' => 'closed',
'endStep' => [
'event' => '<string>'
],
'maxSteps' => 3,
'nodesPerStep' => 5,
'filters' => '<string>',
'retentionFilter' => [
'event' => '<string>'
],
'retentionUserFilters' => [
[
'field' => '<string>',
'value' => '<string>'
]
],
'retentionSignalType' => 'event'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://api.formo.so/v0/boards/{boardId}/charts/{chartId}"
payload := strings.NewReader("{\n \"chartId\": \"<string>\",\n \"projectId\": \"<string>\",\n \"title\": \"<string>\",\n \"query\": \"<string>\",\n \"description\": \"<string>\",\n \"x_axis\": \"<string>\",\n \"y_axis\": [\n \"<string>\"\n ],\n \"group_by\": \"<string>\",\n \"steps\": [\n {\n \"event\": \"<string>\"\n }\n ],\n \"settings\": {\n \"funnelType\": \"closed\",\n \"endStep\": {\n \"event\": \"<string>\"\n },\n \"maxSteps\": 3,\n \"nodesPerStep\": 5,\n \"filters\": \"<string>\",\n \"retentionFilter\": {\n \"event\": \"<string>\"\n },\n \"retentionUserFilters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"retentionSignalType\": \"event\"\n }\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.put("https://api.formo.so/v0/boards/{boardId}/charts/{chartId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"chartId\": \"<string>\",\n \"projectId\": \"<string>\",\n \"title\": \"<string>\",\n \"query\": \"<string>\",\n \"description\": \"<string>\",\n \"x_axis\": \"<string>\",\n \"y_axis\": [\n \"<string>\"\n ],\n \"group_by\": \"<string>\",\n \"steps\": [\n {\n \"event\": \"<string>\"\n }\n ],\n \"settings\": {\n \"funnelType\": \"closed\",\n \"endStep\": {\n \"event\": \"<string>\"\n },\n \"maxSteps\": 3,\n \"nodesPerStep\": 5,\n \"filters\": \"<string>\",\n \"retentionFilter\": {\n \"event\": \"<string>\"\n },\n \"retentionUserFilters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"retentionSignalType\": \"event\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.formo.so/v0/boards/{boardId}/charts/{chartId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"chartId\": \"<string>\",\n \"projectId\": \"<string>\",\n \"title\": \"<string>\",\n \"query\": \"<string>\",\n \"description\": \"<string>\",\n \"x_axis\": \"<string>\",\n \"y_axis\": [\n \"<string>\"\n ],\n \"group_by\": \"<string>\",\n \"steps\": [\n {\n \"event\": \"<string>\"\n }\n ],\n \"settings\": {\n \"funnelType\": \"closed\",\n \"endStep\": {\n \"event\": \"<string>\"\n },\n \"maxSteps\": 3,\n \"nodesPerStep\": 5,\n \"filters\": \"<string>\",\n \"retentionFilter\": {\n \"event\": \"<string>\"\n },\n \"retentionUserFilters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"retentionSignalType\": \"event\"\n }\n}"
response = http.request(request)
puts response.read_body"<string>"Update Chart
Update an existing chart on a dashboard board. Modify the chart query, type, title, or visualization settings through the Formo API.
curl --request PUT \
--url https://api.formo.so/v0/boards/{boardId}/charts/{chartId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"chartId": "<string>",
"projectId": "<string>",
"title": "<string>",
"query": "<string>",
"description": "<string>",
"x_axis": "<string>",
"y_axis": [
"<string>"
],
"group_by": "<string>",
"steps": [
{
"event": "<string>"
}
],
"settings": {
"funnelType": "closed",
"endStep": {
"event": "<string>"
},
"maxSteps": 3,
"nodesPerStep": 5,
"filters": "<string>",
"retentionFilter": {
"event": "<string>"
},
"retentionUserFilters": [
{
"field": "<string>",
"value": "<string>"
}
],
"retentionSignalType": "event"
}
}
'import requests
url = "https://api.formo.so/v0/boards/{boardId}/charts/{chartId}"
payload = {
"chartId": "<string>",
"projectId": "<string>",
"title": "<string>",
"query": "<string>",
"description": "<string>",
"x_axis": "<string>",
"y_axis": ["<string>"],
"group_by": "<string>",
"steps": [{ "event": "<string>" }],
"settings": {
"funnelType": "closed",
"endStep": { "event": "<string>" },
"maxSteps": 3,
"nodesPerStep": 5,
"filters": "<string>",
"retentionFilter": { "event": "<string>" },
"retentionUserFilters": [
{
"field": "<string>",
"value": "<string>"
}
],
"retentionSignalType": "event"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
chartId: '<string>',
projectId: '<string>',
title: '<string>',
query: '<string>',
description: '<string>',
x_axis: '<string>',
y_axis: ['<string>'],
group_by: '<string>',
steps: [{event: '<string>'}],
settings: {
funnelType: 'closed',
endStep: {event: '<string>'},
maxSteps: 3,
nodesPerStep: 5,
filters: '<string>',
retentionFilter: {event: '<string>'},
retentionUserFilters: [{field: '<string>', value: '<string>'}],
retentionSignalType: 'event'
}
})
};
fetch('https://api.formo.so/v0/boards/{boardId}/charts/{chartId}', 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://api.formo.so/v0/boards/{boardId}/charts/{chartId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'chartId' => '<string>',
'projectId' => '<string>',
'title' => '<string>',
'query' => '<string>',
'description' => '<string>',
'x_axis' => '<string>',
'y_axis' => [
'<string>'
],
'group_by' => '<string>',
'steps' => [
[
'event' => '<string>'
]
],
'settings' => [
'funnelType' => 'closed',
'endStep' => [
'event' => '<string>'
],
'maxSteps' => 3,
'nodesPerStep' => 5,
'filters' => '<string>',
'retentionFilter' => [
'event' => '<string>'
],
'retentionUserFilters' => [
[
'field' => '<string>',
'value' => '<string>'
]
],
'retentionSignalType' => 'event'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://api.formo.so/v0/boards/{boardId}/charts/{chartId}"
payload := strings.NewReader("{\n \"chartId\": \"<string>\",\n \"projectId\": \"<string>\",\n \"title\": \"<string>\",\n \"query\": \"<string>\",\n \"description\": \"<string>\",\n \"x_axis\": \"<string>\",\n \"y_axis\": [\n \"<string>\"\n ],\n \"group_by\": \"<string>\",\n \"steps\": [\n {\n \"event\": \"<string>\"\n }\n ],\n \"settings\": {\n \"funnelType\": \"closed\",\n \"endStep\": {\n \"event\": \"<string>\"\n },\n \"maxSteps\": 3,\n \"nodesPerStep\": 5,\n \"filters\": \"<string>\",\n \"retentionFilter\": {\n \"event\": \"<string>\"\n },\n \"retentionUserFilters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"retentionSignalType\": \"event\"\n }\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.put("https://api.formo.so/v0/boards/{boardId}/charts/{chartId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"chartId\": \"<string>\",\n \"projectId\": \"<string>\",\n \"title\": \"<string>\",\n \"query\": \"<string>\",\n \"description\": \"<string>\",\n \"x_axis\": \"<string>\",\n \"y_axis\": [\n \"<string>\"\n ],\n \"group_by\": \"<string>\",\n \"steps\": [\n {\n \"event\": \"<string>\"\n }\n ],\n \"settings\": {\n \"funnelType\": \"closed\",\n \"endStep\": {\n \"event\": \"<string>\"\n },\n \"maxSteps\": 3,\n \"nodesPerStep\": 5,\n \"filters\": \"<string>\",\n \"retentionFilter\": {\n \"event\": \"<string>\"\n },\n \"retentionUserFilters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"retentionSignalType\": \"event\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.formo.so/v0/boards/{boardId}/charts/{chartId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"chartId\": \"<string>\",\n \"projectId\": \"<string>\",\n \"title\": \"<string>\",\n \"query\": \"<string>\",\n \"description\": \"<string>\",\n \"x_axis\": \"<string>\",\n \"y_axis\": [\n \"<string>\"\n ],\n \"group_by\": \"<string>\",\n \"steps\": [\n {\n \"event\": \"<string>\"\n }\n ],\n \"settings\": {\n \"funnelType\": \"closed\",\n \"endStep\": {\n \"event\": \"<string>\"\n },\n \"maxSteps\": 3,\n \"nodesPerStep\": 5,\n \"filters\": \"<string>\",\n \"retentionFilter\": {\n \"event\": \"<string>\"\n },\n \"retentionUserFilters\": [\n {\n \"field\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"retentionSignalType\": \"event\"\n }\n}"
response = http.request(request)
puts response.read_body"<string>"Authorizations
Workspace API key (e.g. formo_xxx). Create one in the Formo dashboard under Team Settings > API Keys.
Body
Request body for updating an existing chart.
ID of the chart to update.
Project the chart belongs to.
Visualization type. Determines which other fields are required:
chart_type | Extra required fields |
|---|---|
table | query |
number | query (must return 1 row × 1 column) |
bar | query, x_axis, y_axis (≥ 1) |
line | query, x_axis, y_axis (≥ 1) |
area | query, x_axis, y_axis (≥ 1; exactly 1 if group_by set) |
pie | query, y_axis (exactly 1) |
stacked | query, x_axis, y_axis (exactly 1), group_by |
funnel | steps (≥ 2), query placeholder "SELECT 1" |
user_paths | query, settings.startStep |
retention | none (query ignored) |
table, number, funnel, bar, line, area, pie, stacked, user_paths, retention Display name shown on the chart and board.
1SQL query that powers the chart.
funnel: pass"SELECT 1"; the actual query is auto-generated fromsteps.retention: can be omitted or pass""; data is fetched automatically.- All other types: required; must be a valid SQL string.
1Optional description.
Column name for the X axis. Required for bar, line, and stacked.
Column name(s) used as Y axis metrics.
bar/line: at least 1 element required.pie/stacked: exactly 1 element required.
Column to group / stack series by. Required for stacked.
Ordered list of funnel steps. Required for funnel (minimum 2 steps).
Each element is a FunnelStep; add property filters as extra keys on the step object (e.g. "rdns": { "op": "equals", "value": "io.metamask" }).
2Show child attributes
Show child attributes
Chart-type-specific configuration. The fields that apply depend on chart_type:
- funnel:
funnelType,conversionWindow,breakdown - user_paths:
startStep,endStep,maxSteps,nodesPerStep,conversionWindow,filters - retention:
retentionFilter,retentionUserFilters,retentionSignalType,retentionLabelSignal
All fields are optional at the schema level; see per-type validation rules for which are functionally required.
Show child attributes
Show child attributes
Response
Chart updated
Chart ID