Objective: find elements in the workspace that match a specific text string. This is done to get properties of that element, to edit it or to delete it. Also, you may want to find a specific canvas to retrieve its content or to add more elements to it. In this page we will search for a specific Canvas for its name and will display the content of that Canvas.
This page contains the implementation details for v3 REST APIs and for v3 GraphQL APIs.
Implementation using REST APIs
In v3 we have access to a search
API. This API allows to run a search for a string and we will get all the objects matching that string in their text content.
Endpoint | /v3/workspaces/<workspaceId>/search |
---|---|
Method | POST |
Comments | Searches a workspace with a query string, can filter by element types. |
IMPORTANT: currently this search API does not match or search the content of Comments in elements.
The output contains a “matchText” field that shows what is the text matching the search query.
Endpoint | /v3/workspaces/<workspaceId>/elements?canvas=<CANVAS_ID> |
---|---|
Method | GET |
Comments | Returns the content of the Canvas specified by <CANVAS_ID> |
You can specify what type of elements are included in the search. If you want to search only on Image, Shape and Text elements, you can specify the "filterTypes"
field with those values, as in this example of the request body:
{
"filterTypes": [
"Image", "Shape", "Text"
],
"orderDirection": "desc",
"query": "<STRING_TO_MATCH>"
}
If you want to run a search for all the elements in the workspace, and not for a specific set, then simply remove the “filterTypes” key in the body request of the API call.
{
"orderDirection": "desc",
"query": "<STRING_TO_MATCH>"
}
Below there is an example of the response body of this API. The search was for “January 2021”, for Canvas elements. The output contains 2 results.
- The
"matchText"
field shows the text that matched the search query. - The
"element"
key contains the properties of each matched element. - The values for the
"id"
fields are only examples, they will be different in your workspace.
This is an example of the results (response body) for a search for for “January 2021”:
{
"data": [
{
"matchText": "January 2021 reports: summary data",
"score": 0.046,
"element": {
"id": "5ef27790ff5317444e00052a",
"zIndex": 1330,
"transform": {
"x": 115610.49999999997,
"y": -33618,
"scaleX": 1,
"scaleY": 1
},
"pinned": false,
"comments": [],
"type": "Canvas",
"name": "January 2021 reports: summary data",
"style": {
"width": 47914,
"height": 25208,
"borderColor": {
"r": 238, "g": 85, "b": 80, "a": 1
}
}
}
},
{
"matchText": "January 2021: all projects",
"score": 0.032,
"element": {
"id": "617c44b4b9575c0c10e783c9",
"zIndex": 2963,
"transform": {
"x": 60092,
"y": -34409,
"scaleX": 1,
"scaleY": 1
},
"pinned": false,
"comments": [],
"type": "Canvas",
"name": "January 2021: all projects",
"style": {
"width": 43243,
"height": 20170,
"borderColor": {
"r": 153, "g": 198, "b": 255, "a": 1
}
}
}
}
]
}
Now you can process the results or run a new search with a search query with more specific terms, for example “January 2021 summary data”.
Code sample
See below code samples for a search on a Canvas (by name), to list the content of that Canvas.
We will run a search for the name, restricted to Canvas type (see the "filterTypes"
field in the request body). For these examples we are assuming that there will be a Canvas that has the name we are trying to match with the search query.
cURL
curl --location --request POST 'https://api.apps.us.bluescape.com/v3/workspaces/<workspaceId>/search' \
--header 'Authorization: Bearer <SET_TOKEN>' \
--data-raw '{
"filterTypes": [
"Canvas"
],
"orderDirection": "desc",
"query": "<STRING_TO_MATCH>"
}'
# if you want to get a shorter version of the results of the search, add the following line at to the script above, after "}'":
# | jq . | egrep "(matchText|\"id\"|type)"
Node.js
// Node.js Javascript REST API example for search and list content of Canvas
/*
How to run:
node this_script_name.js
Requires "axios" module (0.19.0), run:
npm install axios
website: https://github.com/axios/axios
*/
var axios = require('axios');
const token = '<SET_TOKEN>';
const portal = 'https://api.apps.us.bluescape.com';
const workspaceId = '<SET_WORKSPACE_ID>';
const api_version = 'v3';
function runRequest(portal, api_version, api_endpoint, the_method, data_load) {
var request_values = {
url: `${portal}/${api_version}${api_endpoint}`,
method: the_method,
headers: {
'Content-Type': 'application/json',
'Authorization': "Bearer " + token
},
data: data_load,
};
let req = axios(request_values)
.catch(error => {
console.error(`ERROR processing ${portal}/${api_version}${api_endpoint}`);
console.error(error.message);
console.error(error.response.data);
return Promise.reject(error);
});;
return req;
}
async function runSearchAndGetCanvasContent() {
try {
// Run search
// Path: /v3/workspaces//search
const canvasNameToMatch = '<STRING_TO_MATCH>';
var api_endpoint = `/workspaces/${workspaceId}/search`;
var the_method = 'POST';
var data_load = {
"filterTypes": [
"Canvas"
],
"orderDirection": "desc",
"query": canvasNameToMatch
}
var canvasSearchResponse = await runRequest(portal, api_version, api_endpoint, the_method, data_load);
const canvasList = canvasSearchResponse.data.data;
console.log("Search results:");
console.log(canvasList);
var canvasID = '';
for (var i in canvasList) {
theCanvasName = canvasList[i].element.name;
console.log("theCanvasName:", theCanvasName)
if (theCanvasName == canvasNameToMatch) {
canvasID = canvasList[i].element.id
break
}
}
// Let's get the content of the Canvas
api_endpoint = `/workspaces/${workspaceId}/elements?canvas=${canvasID}`;
the_method = 'GET';
data_load = '';
var listOfCanvasContent = await runRequest(portal, api_version, api_endpoint, the_method, data_load);
const canvasContent = listOfCanvasContent.data.data; // It is an array of elements data
console.log("Canvas Content:", canvasContent);
} catch (error) {
console.error('ERROR:');
console.error(error.message);
}
}
// Run the requests
runSearchAndGetCanvasContent();
Python
# Python Code (python 3.5+)
import requests
import datetime
import pprint
'''
Required modules:
requests 2.22.0
'''
token = ''
if __name__ == "__main__":
portal = 'https://api.apps.us.bluescape.com'
workspaceId = '<SET_WORKSPACE_ID>' # REMEMBER TO ADD THE WORKSPACE ID
canvasNameToMatch = '<STRING_TO_MATCH>'
# Run search
# Path: /v3/workspaces//search
API_endpoint = '/v3/workspaces/' + workspaceId + '/search'
data_load = {
"filterTypes": [
"Canvas"
],
"orderDirection": "desc",
"query": canvasNameToMatch
}
the_request = requests.post(
portal + API_endpoint,
headers={"Authorization": "Bearer " + token,
"Content-Type": "application/json"
},
json=data_load
)
canvasSearchResponse = the_request.json()
# pprint.pprint(canvasSearchResponse) # uncomment to see the list
canvasList = canvasSearchResponse['data']
print("Search results:")
pprint.pprint(canvasList)
canvasID = ''
for theElement in canvasList:
print(theElement)
theCanvasName = theElement['element']['name']
if theCanvasName == canvasNameToMatch:
canvasID = theElement['element']['id']
# Let's get the content from the canvas
API_endpoint = '/v3/workspaces/' + workspaceId + '/elements?canvas=' + canvasID
the_request = requests.get(
portal + API_endpoint,
headers={"Authorization": "Bearer " + token,
"Content-Type": "application/json"
}
)
listOfCanvasContent = the_request.json()
# You can process this list of arrays of elements data
canvasContent = listOfCanvasContent['data']
print("Canvas content:")
pprint.pprint(listOfCanvasContent)
OUTPUT
The scripts above will show 2 sets of outputs:
- The results of the search
- The content of the Canvas that matches the search query
Search Results output (values for "id"
are samples only, they will be different for your workspace):
{
"data": [
{
"matchText": "January 2021 meeting",
"score": 0.04,
"element": {
"comments": [],
"id": "618186ede12c4366912c6d18",
"name": "January 2021 meeting",
"pinned": false,
"style": {
"borderColor": {
"a": 1, "b": 255, "g": 198, "r": 153
},
"height": 2419, "width": 2159
},
"transform": {
"scaleX": 1, "scaleY": 1, "x": -1976, "y": 2972
},
"type": "Canvas",
"zIndex": 3751
}
}
]
}
Canvas Content output (values for "id"
and "url"
are samples only, they will be different for your workspace):
{
"data": [
{
"asset": {
"documentFormat": "pdf",
"url": "https://s3.us-east-1.amazonaws.com/acceptance-new.public-assets.bluescape.com/sessions/objects/E-IYMCBISe7QIPlxanns/61819fbdaf0a7a58abdf4ae9.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIVWWSYKG7DKFMQJA%2F20211103%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20211103T232428Z&X-Amz-Expires=300&X-Amz-Signature=bb7f45deefb4cea22c1f09d8f8d18d671febc123ce1acf74dda8e882abfd170c&X-Amz-SignedHeaders=host"
},
"attachments": [],
"comments": [],
"filename": "New_CICD_Process_slim-21-pages.pdf",
"height": 720,
"id": "61819fbdaf0a7a58abdf4ae9",
"ingestionState": "complete_success",
"pinned": false,
"preview": {
"imageFormat": "jpeg",
"url": "https://s3.us-east-1.amazonaws.com/acceptance-new.public-assets.bluescape.com/sessions/objects/E-IYMCBISe7QIPlxanns/61819fbdaf0a7a58abdf4ae9.pdf_thumb.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIVWWSYKG7DKFMQJA%2F20211103%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20211103T232428Z&X-Amz-Expires=300&X-Amz-Signature=d423bfdc3443d1a16fee63209de4564c55c767ab1dea51656228be8dd9d6b712&X-Amz-SignedHeaders=host"
},
"title": "New_CICD_Process_slim-21-pages.pdf",
"transform": {
"scaleX": 0.78125, "scaleY": 0.7819444444444444, "x": -1784, "y": 3451
},
"type": "Document",
"width": 1280,
"zIndex": 3758
},
{
"blocks": [
{
"align": "left",
"content": [
{
"text": "Description: documents for the January 2021 meeting"
}
],
"type": "TextBlock"
}
],
"comments": [],
"id": "61819feaaf0a7a58abdf4aeb",
"pinned": false,
"style": {
...
...
},
"text": "Description: documents for the January 2021 meeting",
"transform": {
"scaleX": 1, "scaleY": 1, "x": -1784, "y": 3200
},
"type": "Text",
"zIndex": 3759
},
...
...
{
"asset": {
"imageFormat": "jpeg",
"url": "https://s3.us-east-1.amazonaws.com/acceptance-new.public-assets.bluescape.com/sessions/objects/E-IYMCBISe7QIPlxanns/6181a214af0a7a58abdf4af9.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIVWWSYKG7DKFMQJA%2F20211103%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20211103T232428Z&X-Amz-Expires=300&X-Amz-Signature=ea7f72b657acb4ac40efe61209d93e75479370766e8261b60a2d23cf1742f7bc&X-Amz-SignedHeaders=host"
},
"attachments": [],
"comments": [],
"filename": "Compliance reviewer.jpg",
"height": 1920,
"id": "6181a214af0a7a58abdf4af9",
"ingestionState": "complete_success",
"pinned": false,
"title": "Compliance reviewer.jpg",
"transform": {
"scaleX": 0.5208333333333334, "scaleY": 0.5208333333333334, "x": -1784, "y": 4144
},
"type": "Image",
"width": 1920,
"zIndex": 3763
},
{
"blocks": [
{
"align": "left",
"content": [
{
"text": "Compliance Department person"
}
],
"type": "TextBlock"
}
],
"comments": [],
"id": "6181a50caf0a7a58abdf4afd",
"pinned": false,
"style": {
...
...
},
"text": "Compliance Department person",
"transform": {
"scaleX": 1, "scaleY": 1, "x": -1153, "y": 5132
},
"type": "Text",
"zIndex": 3764
}
]
}
Implementation using GraphQL APIs
In GraphQl we currently do not have a search API. The approach here is to run a query for the type of element you want, and then loop through the list of results looking for the specific element matching the string you are after.
cURL
# Uses 'jq' to filter the results, to filter the string to match: | jq '.data.elements[] | select(.name|test("<STRING_TO_MATCH>"))'
curl --location --request POST 'https://api.apps.us.bluescape.com/v3/graphql' \
--header 'Authorization: Bearer <SET_TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{"query":"query getCanvasesfromWorkspace($workspaceId: String!) {\n elements(workspaceId: $workspaceId, type: Canvas) {\n ... on Canvas {\n type: __typename\n id\n name\n transform {\n x\n y\n } \n }\n } \n}","variables":{"workspaceId":"<workspaceId>"}}' | jq '.data.elements[] | select(.name|test("<STRING_TO_MATCH>"))'
Node.js
// Node.js Javascript
// List the content of a canvas searching for a match for canvas "name" in list of canvases from the workspace
/*
How to run:
node this_script_name.js
Requires "axios" module (0.19.0), run:
npm install axios
website: https://github.com/axios/axios
*/
const axios = require('axios');
const url = "https://api.apps.us.bluescape.com/v3/graphql"
const token = "<SET_TOKEN>"
const workspaceId = "<workspaceId>"
// String to match on the Canvas "name" field
const canvasNameToMatch = 'January 2021 meeting'
const makeQuery = async (query, params) => {
try {
const response = await axios.post(url,
{
query: query,
variables: params
},
{
headers: { "Authorization": "Bearer " + token }
})
return response.data
}
catch (error) {
console.error(error)
}
}
async function getCanvasContentFoundByName() {
const canvasListQuery =
`query getCanvasesfromWorkspace($workspaceId: String!) {
elements(workspaceId: $workspaceId, type: Canvas) {
... on Canvas {
type: __typename
id
name
transform {
x
y
}
}
}
}`
const canvasListParams = {
"workspaceId": workspaceId
}
const canvasResponse = await makeQuery(canvasListQuery, canvasListParams);
const canvasList = canvasResponse.data.elements;
console.log("Canvases List:");
console.log(canvasList);
var canvasID = ''
// Search for the match in the "name" field
for (var i in canvasList) {
theCanvasName = canvasList[i].name;
if (theCanvasName == canvasNameToMatch) {
canvasID = canvasList[i].id
break
}
}
const getCanvasContentQuery =
`query getCanvasContent($workspaceId: String!, $canvasId: String!) {
elements(workspaceId: $workspaceId, canvasId: $canvasId ) {
type: __typename
id
transform {
x
y
}
...on Image {
title
filename
asset { imageFormat }
}
... on Text {
text
}
... on Document {
title
filename
asset { documentFormat }
}
}
}`
const textParamsGetCanvasContent = {
"workspaceId": workspaceId,
"canvasId": canvasID
}
const textResponse = await makeQuery(getCanvasContentQuery, textParamsGetCanvasContent);
const listOfCanvasContent = textResponse.data.elements; // Process this list as needed
console.log("Canvas Content:");
console.log(listOfCanvasContent);
}
// Run the requests
getCanvasContentFoundByName();
Python
import requests
import pprint
# List the content of a canvas searching for a match for canvas "name" in list of canvases from the workspace
'''
Required modules:
requests 2.22.0
'''
url = "https://api.apps.us.bluescape.com/v3/graphql"
token = "<SET_TOKEN>"
workspaceId = "<workspaceId>"
# String to match on the Canvas "name" field
canvasNameToMatch = '<STRING_TO_MATCH>'
getCanvasesQuery = """
query getCanvasesfromWorkspace($workspaceId: String!) {
elements(workspaceId: $workspaceId, type: Canvas) {
... on Canvas {
type: __typename
id
name
transform {
x
y
}
}
}
}
"""
getCanvasContentQuery = """
query getCanvasContent($workspaceId: String!, $canvasId: String!) {
elements(workspaceId: $workspaceId, canvasId: $canvasId ) {
type: __typename
id
transform {
x
y
}
...on Image {
title
filename
asset { imageFormat }
}
... on Text {
text
}
... on Document {
title
filename
asset { documentFormat }
}
}
}
"""
variables = {
"workspaceId": workspaceId
}
def makePostQuery(query, variables):
response = requests.post(url,
headers={"Authorization": "Bearer " + token
},
json={
'query': query,
'variables': variables
})
return response.json()
if __name__ == "__main__":
response = makePostQuery(getCanvasesQuery, variables)
listOfCanvases = response['data']['elements']
print("List of Canvases:")
pprint.pprint(listOfCanvases)
for canvasItem in listOfCanvases:
if canvasItem['name'] == canvasNameToMatch:
# Get the content of the matching Canvas
variablesLocal = {
"workspaceId": workspaceId,
"canvasId": canvasItem['id']
}
CanvasContent = makePostQuery(
getCanvasContentQuery, variablesLocal)
listOfCanvasContent = CanvasContent['data']['elements'] # Process this list as needed
print("Canvas content:")
pprint.pprint(ListCanvasContent) # uncomment to see the list
break # leave the loop
OUTPUT
The scripts above (that use GraphQL) will show 2 sets of outputs:
- The results of the search
- The content of the Canvas that matches the search query
Search Results output (values for "id"
are samples only, they will be different for your workspace):
[
{
"type": "Canvas",
"id": "60c40b72736f01e805f71b54",
"name": "FEBRUARY 2021",
"transform": {
"x": -11461,
"y": 11650
}
},
{
"type": "Canvas",
"id": "618186ede12c4366912c6d18",
"name": "January 2021 meeting",
"transform": {
"x": -1976,
"y": 2972
}
},
{
"type": "Canvas",
"id": "6182f80c0dab0b47b057decf",
"name": "COMPLIANCE MATRIX",
"transform": {
"x": 0,
"y": 0
}
},
...
...
{
"type": "Canvas",
"id": "6182f84c0dff0b47b057dea6",
"name": "Notes for next meeting",
"transform": {
"x": 0,
"y": 0
}
}
]
Canvas Content output (values for "id"
are samples only, they will be different for your workspace):
[
{
"type": "Document",
"id": "61819fbdaf0a7a58abdf4ae9",
"transform": {
"x": -1784,
"y": 3451
},
"title": "New_CICD_Process_slim-21-pages.pdf",
"filename": "New_CICD_Process_slim-21-pages.pdf",
"asset": {
"documentFormat": "pdf"
}
},
{
"type": "Text",
"id": "61819feaaf0a7a58abdf4aeb",
"transform": {
"x": -1784,
"y": 3200
},
"text": "Description: documents for the January 2021 meeting"
},
{
"type": "Image",
"id": "6181a214af0a7a58abdf4af9",
"transform": {
"x": -1784,
"y": 4144
},
"title": "Compliance reviewer.jpg",
"filename": "Compliance reviewer.jpg",
"asset": {
"imageFormat": "jpeg"
}
},
{
"type": "Text",
"id": "6181a50caf0a7a58abdf4afd",
"transform": {
"x": -1153,
"y": 5132
},
"text": "Compliance Department person"
}
]
Where to Next?
- How to use the findAvailableArea API in v3
- Bluescape API Guides
- Bluescape API Overview
- Latest Developer topics
Not what you were looking for? Reply below or Search the community and discover more Bluescape.