Developer

Create a Canvas and add a Text Element to it for v3

Objective: Create a new Canvas in your Workspace and add a Text element to this new Canvas. You will learn how to get the IDs of newly created objects within your Workspace, and how to use them to associate other objects with them. You will need the workspaceId.
This page contains the implementation details for v3 REST APIs and for v3 GraphQL APIs. You can also see the example for v2 REST APIs.

Implementation using REST APIs

Create Canvas

Endpoint /v3/workspaces/<workspaceId>/elements
Method POST
Body
{
     "type": "Canvas",
     "name": "<SET_CANVAS_NAME>"
}
Comments You need to know the workspace ID.

Create Text within Canvas

Endpoint /v3/workspaces/<workspaceId>/elements
Method POST
Body
{
     "type": "Text",
     "text": "<SET_TEXT>"
}
Comments You need to ensure that the Text's size fits within the Canvas' boundaries. You also need to ensure that the Text's position falls within the Canvas' boundaries.
If you need to change the dimensions or position of the Text, you'll need to add extra parameters in the Body of your request.
To change the dimensions of the Text object, the body should look like this:
{
     "type": "Text",
     "text": "<SET_TEXT>",
     "style": {"width": "<SET_WIDTH>", "height": "<SET_HEIGHT>"}
}
By specifying the relativeToOriginOf query parameter in the endpoint, /v3/workspaces/{workspaceId}/elements?relativeToOriginOf={CANVAS_ID}, the position of the text content will be relative to the top-left corner of the Canvas.
To change the position of the Text, the body should look like this:
 
{
     "type": "Text",
     "text": "<SET_TEXT>",
     "transform": {"x": "<SET_X>", "y": "<SET_Y>"}
}
To change the font of the Text, the body should look like this:
 
{
     "type": "Text",
     "text": "<SET_TEXT>",
     "style": {"fontSize": "<SET_SIZE>"}
}
You can place the style and transform parameters into the body of the request to change the dimensions, position and font simultaneously.

NOTE: For this basic example, the above "Comments" section is not applicable.

Code sample

See below code samples in Python and Node.js.

# Python Code (python 3.5+)
import requests
import datetime
import pprint

'''

Required modules:
    requests 2.22.0

'''

token = '<SET_TOKEN>'        

if __name__ == "__main__":
    portal = '' 
    workspaceId = '<SET_WORKSPACE_ID>'  # REMEMBER TO ADD WORKSPACE ID

    # Create new Canvas
    # Path:     /v3/workspaces/<workspaceId>/elements

    API_endpoint = '/v3/workspaces/' + workspaceId + '/elements'

    timestamp = datetime.datetime.now()

    data_load = {
        "type": "Canvas",
        "name": "<SET_CANVAS_NAME>"
    }

    the_request = requests.post(
        portal + API_endpoint,
        headers={"Authorization": "Bearer " + token,
                    "Content-Type": "application/json"
                    },
        json=data_load
    )

    json_response = the_request.json()
    # pprint.pprint(json_response) # Uncomment to see the response body

    canvasId = json_response['data']['id']
    print("Canvas ID: ", canvasId)

    # Add Text to a canvas  
    # Path: 	/v3/workspaces/<workspaceId>/elements

    API_endpoint = '/v3/workspaces/' + workspaceId + '/elements' + '?relativeToOriginOf=' + canvasId
    params = ''

    timestamp = datetime.datetime.now()

    # The X and Y coordinates for objects within a Canvas are relative to the top left corner of the Canvas
    data_load = {
        "type": "Text",
        "text": "<SET_TEXT>"
    }

    the_request = requests.post(
        portal + API_endpoint,
        headers={"Authorization": "Bearer " + token,
                    "Content-Type": "application/json"
                    },
        json=data_load
    )

    json_response = the_request.json()

    # pprint.pprint(json_response) # Uncomment to see the response body

    textId = json_response['data']['id']
    print("Text ID: ", textId)

// Node.js Javascript
/*

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 = '';
const workspaceId = '<SET_WORKSPACE_ID>';
const api_version = 'v3';
var api_endpoint = '/workspaces/' + workspaceId + '/elements';

function runRequest(portal,api_version,api_endpoint,the_method,data_load) {
    var request_values = {
        url : portal + '/' + api_version + api_endpoint,
        method : the_method ,
        headers : {
            'Authorization': "Bearer " + token,
            'Content-Type' : 'application/json'    
        },
        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 runAPIRequests() {
    try {

        // Create canvas

        api_endpoint = '/workspaces/' + workspaceId + '/elements';
        the_method = 'POST';
        var currtime = new Date().toISOString().slice(0,16).replace('T',' ');

        data_load = {
            "type": "Canvas",
            "name": "<SET_CANVAS_NAME>"
        }
        
        var canvas_creation = await runRequest(portal,api_version,api_endpoint,the_method,data_load);

        const canvasId = canvas_creation.data.data.id;
        console.log("canvas ID: " + canvasId);

        // Now add Text to the Canvas

        currtime = new Date().toISOString().slice(0,16).replace('T',' ');

        api_endpoint = '/workspaces/' + workspaceId + '/elements' + '?relativeToOriginOf=' + canvasId
        method = 'POST';
        data_load = {
            "type": "Text",
            "text": "<SET_TEXT>"
        }


        var text_creation = await runRequest(portal,api_version,api_endpoint,the_method,data_load);

        var textId = text_creation.data.data.id;
        console.log('Text ID: ' + textId);

    } catch (error) {
        console.error('ERROR:');
        console.error(error.message);
    }
}

// Run the requests
runAPIRequests();

OUTPUT

Each time you run a POST API, you will get back a Response Body with the properties of the newly created object. Within this data you can get the object ID and other important information.

Element Json
Element ID ['data']['id']
Element Type ['data']['type']
Element Position and Size ['data']['transform']

Output Json sample

Canvas creation

From this response, you can obtain the newly created Canvas ID: ['data']['id']

{
    "data": {
        "id": "600223e68de4a9001c434fe4",
        "zIndex": 36,
        "transform": {
            "x": 0,
            "y": 0
        },
        "traits": null,
        "pinned": false,
        "type": "Canvas",
        "name": "Test Canvas",
        "style": {
            "width": 1000,
            "height": 1000,
            "borderColor": {
                "r": 238,
                "g": 85,
                "b": 80,
                "a": 1
            }
        }
    }
}

Text Creation

{
    "data": {
        "id": "604abe996a3fdb001f7cec3b",
        "zIndex": 0,
        "transform": {
            "x": 0,
            "y": 0,
            "scaleX": 1,
            "scaleY": 1
        },
        "traits": null,
        "pinned": false,
        "type": "Text",
        "text": "Text Example",
        "style": {
            "width": 256,
            "height": 298,
            "fontWeight": "normal",
            "textTransform": "none",
            "fontSize": 64,
            "fontFamily": "Dosis",
            "fontStyle": "normal",
            "color": {
                "r": 234,
                "g": 62,
                "b": 53,
                "a": 1
            },
            "backgroundColor": {
                "r": 0,
                "g": 0,
                "b": 0,
                "a": 1
            }
        }
    }
}

Implementation using v3 GraphQL APIs

To begin, you will need to create a Canvas in your Workspace that can be used to group your elements in. To do this, you will need only the WorkspaceID in which you want to create the Canvas. For information on how to get this, see our previous guide on Getting a List of Workspaces using GraphQL. The information you'll need returned from this call is only the (x,y) coordinates of where it is placed, so that you can add a Text element to the Canvas in the next step. Many additional properties can be given to the Canvas upon creation, but it will be kept simple for the sake of this introduction. This can be specified in a relatively simple query as follows:

mutation createCanvasExample($workspaceId: String!, $input: CreateCanvasInput!){
    createCanvas(workspaceId: $workspaceId, input: $input) {
        __typename
        name
        id
        transform { x y }
    }
}

Notice that this is a mutation operation and not a query. This is because it is a Create request instead of just retrieving data, similar to creating a POST request instead of a GET in typical REST APIs. This can be called with the following example parameters:

{
    "workspaceId": "<SET_WORKSPACEID>",
    "input": {
        "name": "Example Canvas",
        "transform": {
            "x": 100,
            "y": 100}
    }
}

Output

{
    "data": {
        "createCanvas": {
            "__typename": "Canvas",
            "name": "Example Canvas",
            "id": "606216cdebc71453d4d758bf",
            "transform": {
                "x": 100,
                "y": 100
            }
        }
    }
}

In the output above, the value of "id" will change every time that you run the createCanvas mutation.

You can now create a Text element within the newly created Canvas. To do this, construct another query to create a Text element. You will need to ensure that the Text position and size fit within the canvas. For that, we can provide de ID of the Canvas we just created as the value for relativeToOriginOf in the new mutation. We will use that Canvas as the starting point for the x,y position in transform, where the position will be relative to the top-left corner of the Canvas. If you do not use the relativeToOriginOf parameter, then the x,y position is absolute to the center of the workspace.
Also, the style parameters give you the ability to define additional properties such as height, width, and font.

mutation createTextExample($workspaceId: String!, $input: CreateTextInput!, $idRelativeTo: String! ){
    createText(workspaceId: $workspaceId, relativeToOriginOf: $idRelativeTo, input: $input) {
        __typename
        id
        text
        transform {x y }
    }
}      

Which can be ran with parameters such as:

{
    "workspaceId": "<SET_WORKSPACEID>",
    "idRelativeTo" : "<SET_CANVAS_ID>"
    "input": {
        "text": "Example text inside canvas",
        "transform": {
            "x": 150,
            "y": 150,
            "scaleX": 1,
            "scaleY": 1
        },
        "style": {
            "height": 100,
            "width": 300,
            "fontFamily": "Helvetica",
            "fontSize": 24
        }
    }
}

Code sample

See below for full code examples of this implementation in Python and Node.js.

const axios = require('axios');

const url = "/v3/graphql"
const token = "<SET_TOKEN>"
const workspaceId = "<SET_WORKSPACEID>"

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 startProcess() {

    const canvasQuery = 
        `mutation createCanvasExample($workspaceId: String!, $input: CreateCanvasInput!){
            createCanvas(workspaceId: $workspaceId, input: $input) {
                __typename
                name
                id
                transform { x y }
            }
        }`

    const canvasParams = {
        "workspaceId": workspaceId,
        "input": {
            "name": "Example Canvas",
            "transform": {
                "x": 100,
                "y": 100
                }
            }
        
        }
    const canvasResponse = await makeQuery(canvasQuery, canvasParams);
    console.log(canvasResponse);

    // The answer has the mutation name in it to wrap the results
    canvasID = canvasResponse.data.createCanvas.id; 

    const textQuery =
        `mutation createTextExample($workspaceId: String!, $input: CreateTextInput! $idRelativeTo:String!){
            createText(workspaceId: $workspaceId, relativeToOriginOf: $idRelativeTo, input: $input) {
            __typename
            id
            text
            transform { x y }
            }
        }`

    const textParams = {
        "workspaceId": workspaceId,
        "idRelativeTo" : canvasID,
        "input": {
            "text": "Example text inside canvas",
            "transform": {
                "x": 200,
                "y": 200,
                "scaleX": 1,
                "scaleY": 1
            },
            "style": {
                "height": 100,
                "width": 300,
                "fontFamily": "Helvetica",
                "fontSize": 24
            }
        }
    }

    const textResponse = await makeQuery(textQuery, textParams);
    console.log(textResponse);
}

startProcess();

import requests
import pprint

url = "/v3/graphql"
token = "<SET_TOKEN>"
workspaceId = "<SET_WORKSPACEID>"

def makeQuery(query, params):

    response = requests.post(url, 
    headers={"Authorization": "Bearer " + token
    },
    json={
            'query': query,
            'variables': params
        })

    return response.json()

if __name__ == "__main__":
    canvasQuery = """
    mutation createCanvasExample($workspaceId: String!, $input: CreateCanvasInput!){
        createCanvas(workspaceId: $workspaceId, input: $input) {
            __typename
            name
            id
            transform { x y }
        }
    }
    """

    canvasParams = {
    "workspaceId": workspaceId,
    "input": {
        "name": "Example Canvas",
        "transform": {
            "x": 50,
            "y": 50
            }
        }
    }

    canvasResponse = makeQuery(canvasQuery, canvasParams)
    pprint.pprint(canvasResponse)

    # The answer has the mutation name in it to wrap the results
    canvasID = canvasResponse['data']['createCanvas']['id']

    textQuery = """
    mutation createTextExample($workspaceId: String!, $input: CreateTextInput! $idRelativeTo: String!){
        createText(workspaceId: $workspaceId, relativeToOriginOf: $idRelativeTo, input: $input) {
            __typename
            id
            text
            transform { x y }
        }
    }
    """
    textParams = {
        "workspaceId": workspaceId,
        "idRelativeTo" : canvasID,
        "input": {
            "text": "Example text inside canvas",
            "transform": {
                "x": 200,
                "y": 200,
                "scaleX": 1,
                "scaleY": 1
            },
            "style": {
                "height": 100,
                "width": 300,
                "fontFamily": "Helvetica",
                "fontSize": 24
            }
        }
    }
    
    textResponse = makeQuery(textQuery, textParams)
    pprint.pprint(textResponse)


If you have any questions or comments, please contact us in the Bluescape Community site.