curl --request POST \
--url https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters \
--header 'Content-Type: application/json' \
--header 'authorization: <api-key>' \
--data '
{
"field": "<string>",
"apiKey": "<string>",
"organizationId": "<string>",
"connectionId": "<string>",
"displayName": "<string>",
"fieldKeys": [
"<string>"
],
"itemIds": [
"<string>"
],
"selectedValue": "<string>",
"sort_order": 0,
"dataModelVersion": 123
}
'import requests
url = "https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters"
payload = {
"field": "<string>",
"apiKey": "<string>",
"organizationId": "<string>",
"connectionId": "<string>",
"displayName": "<string>",
"fieldKeys": ["<string>"],
"itemIds": ["<string>"],
"selectedValue": "<string>",
"sort_order": 0,
"dataModelVersion": 123
}
headers = {
"authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
field: '<string>',
apiKey: '<string>',
organizationId: '<string>',
connectionId: '<string>',
displayName: '<string>',
fieldKeys: ['<string>'],
itemIds: ['<string>'],
selectedValue: '<string>',
sort_order: 0,
dataModelVersion: 123
})
};
fetch('https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters', 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.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters",
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([
'field' => '<string>',
'apiKey' => '<string>',
'organizationId' => '<string>',
'connectionId' => '<string>',
'displayName' => '<string>',
'fieldKeys' => [
'<string>'
],
'itemIds' => [
'<string>'
],
'selectedValue' => '<string>',
'sort_order' => 0,
'dataModelVersion' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"authorization: <api-key>"
],
]);
$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.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters"
payload := strings.NewReader("{\n \"field\": \"<string>\",\n \"apiKey\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"connectionId\": \"<string>\",\n \"displayName\": \"<string>\",\n \"fieldKeys\": [\n \"<string>\"\n ],\n \"itemIds\": [\n \"<string>\"\n ],\n \"selectedValue\": \"<string>\",\n \"sort_order\": 0,\n \"dataModelVersion\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("authorization", "<api-key>")
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://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters")
.header("authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"field\": \"<string>\",\n \"apiKey\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"connectionId\": \"<string>\",\n \"displayName\": \"<string>\",\n \"fieldKeys\": [\n \"<string>\"\n ],\n \"itemIds\": [\n \"<string>\"\n ],\n \"selectedValue\": \"<string>\",\n \"sort_order\": 0,\n \"dataModelVersion\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"field\": \"<string>\",\n \"apiKey\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"connectionId\": \"<string>\",\n \"displayName\": \"<string>\",\n \"fieldKeys\": [\n \"<string>\"\n ],\n \"itemIds\": [\n \"<string>\"\n ],\n \"selectedValue\": \"<string>\",\n \"sort_order\": 0,\n \"dataModelVersion\": 123\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"data": {
"filter": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"canvas_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"filter_config": {
"filterType": "Input",
"filterSubType": "Input Equals",
"filterRestrictions": null,
"displayName": "<string>",
"layout": {
"i": "<string>",
"x": 123,
"y": 123,
"w": 123,
"h": 123,
"minW": 123,
"maxW": 123,
"minH": 123,
"maxH": 123,
"moved": true,
"static": true,
"isDraggable": true,
"isResizable": true,
"resizeHandles": [
"s"
],
"isBounded": true
},
"filterTargets": [
{
"type": "Before logic",
"columns": [
{
"type": "string",
"columnName": "<string>",
"columnMetadata": "<string>",
"columnSummary": {
"values": [
"<unknown>"
],
"isExhaustive": true
}
}
],
"chartId": "<string>",
"targetTable": "<string>",
"targetColumn": "<string>"
}
],
"controlKey": "<string>",
"globalFilterColumns": [
"<string>"
],
"selectedValue": "<string>",
"fieldKey": "<string>",
"fieldRef": {
"kind": "raw",
"table": "<string>",
"column": "<string>",
"columnType": "string"
},
"itemIds": [
"<string>"
],
"fieldKeys": [
"<string>"
],
"tileColumns": {},
"customFilterId": "<string>",
"filtersEveryTable": true
},
"sort_order": 0,
"created_at": "<unknown>",
"updated_at": "<unknown>"
}
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": {}
}
}Add Canvas Filter
Add a filter to a canvas, on a field from filterable-fields
curl --request POST \
--url https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters \
--header 'Content-Type: application/json' \
--header 'authorization: <api-key>' \
--data '
{
"field": "<string>",
"apiKey": "<string>",
"organizationId": "<string>",
"connectionId": "<string>",
"displayName": "<string>",
"fieldKeys": [
"<string>"
],
"itemIds": [
"<string>"
],
"selectedValue": "<string>",
"sort_order": 0,
"dataModelVersion": 123
}
'import requests
url = "https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters"
payload = {
"field": "<string>",
"apiKey": "<string>",
"organizationId": "<string>",
"connectionId": "<string>",
"displayName": "<string>",
"fieldKeys": ["<string>"],
"itemIds": ["<string>"],
"selectedValue": "<string>",
"sort_order": 0,
"dataModelVersion": 123
}
headers = {
"authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
field: '<string>',
apiKey: '<string>',
organizationId: '<string>',
connectionId: '<string>',
displayName: '<string>',
fieldKeys: ['<string>'],
itemIds: ['<string>'],
selectedValue: '<string>',
sort_order: 0,
dataModelVersion: 123
})
};
fetch('https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters', 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.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters",
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([
'field' => '<string>',
'apiKey' => '<string>',
'organizationId' => '<string>',
'connectionId' => '<string>',
'displayName' => '<string>',
'fieldKeys' => [
'<string>'
],
'itemIds' => [
'<string>'
],
'selectedValue' => '<string>',
'sort_order' => 0,
'dataModelVersion' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"authorization: <api-key>"
],
]);
$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.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters"
payload := strings.NewReader("{\n \"field\": \"<string>\",\n \"apiKey\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"connectionId\": \"<string>\",\n \"displayName\": \"<string>\",\n \"fieldKeys\": [\n \"<string>\"\n ],\n \"itemIds\": [\n \"<string>\"\n ],\n \"selectedValue\": \"<string>\",\n \"sort_order\": 0,\n \"dataModelVersion\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("authorization", "<api-key>")
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://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters")
.header("authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"field\": \"<string>\",\n \"apiKey\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"connectionId\": \"<string>\",\n \"displayName\": \"<string>\",\n \"fieldKeys\": [\n \"<string>\"\n ],\n \"itemIds\": [\n \"<string>\"\n ],\n \"selectedValue\": \"<string>\",\n \"sort_order\": 0,\n \"dataModelVersion\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upsolve.ai/v2/api/projects/{projectId}/workspaces/{workspaceId}/canvases/{canvasId}/filters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"field\": \"<string>\",\n \"apiKey\": \"<string>\",\n \"organizationId\": \"<string>\",\n \"connectionId\": \"<string>\",\n \"displayName\": \"<string>\",\n \"fieldKeys\": [\n \"<string>\"\n ],\n \"itemIds\": [\n \"<string>\"\n ],\n \"selectedValue\": \"<string>\",\n \"sort_order\": 0,\n \"dataModelVersion\": 123\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"data": {
"filter": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"canvas_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"filter_config": {
"filterType": "Input",
"filterSubType": "Input Equals",
"filterRestrictions": null,
"displayName": "<string>",
"layout": {
"i": "<string>",
"x": 123,
"y": 123,
"w": 123,
"h": 123,
"minW": 123,
"maxW": 123,
"minH": 123,
"maxH": 123,
"moved": true,
"static": true,
"isDraggable": true,
"isResizable": true,
"resizeHandles": [
"s"
],
"isBounded": true
},
"filterTargets": [
{
"type": "Before logic",
"columns": [
{
"type": "string",
"columnName": "<string>",
"columnMetadata": "<string>",
"columnSummary": {
"values": [
"<unknown>"
],
"isExhaustive": true
}
}
],
"chartId": "<string>",
"targetTable": "<string>",
"targetColumn": "<string>"
}
],
"controlKey": "<string>",
"globalFilterColumns": [
"<string>"
],
"selectedValue": "<string>",
"fieldKey": "<string>",
"fieldRef": {
"kind": "raw",
"table": "<string>",
"column": "<string>",
"columnType": "string"
},
"itemIds": [
"<string>"
],
"fieldKeys": [
"<string>"
],
"tileColumns": {},
"customFilterId": "<string>",
"filtersEveryTable": true
},
"sort_order": 0,
"created_at": "<unknown>",
"updated_at": "<unknown>"
}
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": {}
}
}Authorizations
Path Parameters
The project in the URL. The caller's project user is read from it.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$POST /v2/api/projects/:projectId/workspaces/:workspaceId/canvases/:canvasId/filters Parameter
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$POST /v2/api/projects/:projectId/workspaces/:workspaceId/canvases/:canvasId/filters Parameter
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$Body
POST /v2/api/projects/:projectId/workspaces/:workspaceId/canvases/:canvasId/filters Request body
The fieldKey of a field from GET …/filterable-fields — a column's, or a custom filter's (custom:<id>). The server resolves it into per-tile targets.
Filter type. Must suit the field's columnType: Select (string/date), Number (number), Date (date), Input (any). Toggle is not supported on canvases.
Input, Select, Number, Date, Toggle Operator, from the filterType's own list (e.g. 'Select Multi', 'Number Greater than', 'Date Range'). Null for Toggle.
Input Equals, Input Starts with, Input Ends with, Input Contains Upsolve API key, generated under Account → Developer settings in the Upsolve Hub. Keys are user-scoped: pass organizationId alongside the key to select which org to act on.
1The ID of the organization. Required when using Supabase JWT authentication.
The ID of the connection a guest has access to
Label shown on the filter pill. Defaults to the field's columnDisplayName, else the column name.
1Tables picked under one column name, each a raw:<table>.<column> key from a field's tableChoices, all of one type: each chart is filtered on every one of these tables it reads, or not at all, and a chart that reads none of them is not filtered (even one showing a column of the name). field must be the first of them.
1Restrict the filter to these tiles. Each must be one of the field's targets. Defaults to every target.
1Initial value. Omit to create the filter with no value (inactive).
Position of the filter in the filter bar.
-9007199254740991 <= x <= 9007199254740991Published data model version to resolve fields and run queries against. Defaults to the published version.
x <= 9007199254740991Was this page helpful?