Developer

GraphQL vs REST APIs

Here we present a comparison of Bluescape v3 REST and GraphQL APIs. You can appreciate the advantages of each implementation, and maybe use this list to as a help to port your queries from REST to GraphQL.

Use HTTP POST for GraphQL

See the details below regarding the different methods REST and GraphQL API use.

REST
GraphQL
REST API calls use different methods for the HTTP calls, to implement specific operations, such as:
  • GET: Read
  • POST: Create
  • PATCH: Partial update/modification
  • PUT: Update/replace
  • DELETE: Delete
In GraphQL, the API calls are always an HTTP POST, and operations are queries or mutations. For more details, read the Bluescape GraphQL Schema (please see details in the GraphQL Playground page).
A summary of the equivalents to the REST methods is below :
  • REST GET: GraphQL query
  • REST POST: GraphQL mutation, generally named create* (e.g. createCanvas, createText, etc.)
  • REST PATCH, PUT: GraphQL mutation, generally named update* (e.g. updateCanvas, updateText, etc.)
  • DELETE: GraphQL mutation, delete
NOTE: Technically, you can also use an HTTP GET, but there is a limit to the URL length. With POST you can use an arbitrarily sized payload.

Filtering elements by Type

GraphQL provides a great flexibility to get just the data you need, and for that you need to clearly specify what are the fields you want to be retrieved in each query

REST
GraphQL
In REST APIs, you can query just one type at a time, or you can pull all the elements of the workspace or Canvas and filter down the answer, later, in your script.
e.g. If I need all the Canvases and Text elements in a workspace, I could run these 2 queries:
/v3/workspaces/{workspace_id}/elements?type=Canvas
/v3/workspaces/{workspace_id}/elements?type=Text
In GraphQL, you can specify one or more types at a time. This feature allows you to add great flexibility to your scripts.

query getTextAndCanvas{
  elements(workspace: "G1N2bS42uGwMhL_fGfzW", type: [Text,Canvas]) {
    type:__typename
    id
    transform {
      x y
    }
  }
}

If you want to use a single Type, then remove the array brackets in the query. For example, if you want only Test types:

query getTextAndCanvas{
  elements(workspace: "G1N2bS42uGwMhL_fGfzW", type: Text) {
    type:__typename
    id
    transform {
      x y
    }
  }
}

For queries, some fields can be Unions in GraphQL

GraphQL provides great flexibility to get just the data you need, and for that you need to clearly specify what are the fields you want to be retrieved in each query. Sometimes the fields in the GraphQL are defined as Unions, not as a specific Type. Review the Bluescape GraphQl Schema for more details.
Unions in GraphQL are specified using this format:

...on {Type} {
    {Fields-to-retrieve}
}

REST
GraphQL
In REST APIs, for queries we use a GET. You can specify some filtering fields, but in general they are very easy to run. The results generally over fetch, they deliver all the fields available for those elements and you need to filter them later in tour script. In GraphQL, all the requests are always an HTTP POST. You can specify exactly what fields will be returned, and in some cases those fields will need to be specified as Unions. For example, for a Line element, when you query the start and end fields, you need to specify them as a Union (according to the current GraphQl Schema). See this example:
query GetLinesFromWorkspace($workspaceId: String!){
    elements(workspaceId: $workspaceId, type: Line) {        
        type: __typename
        id
        ... on Line {
            start{
                ... on AbsoluteLinePoint{
                    x y
                }
            }
            end{
                ... on AbsoluteLinePoint{
                    x y
                }
            }
        }
    }
}

Run multiple queries or mutation in one call in GraphQL

GraphQL allows you to consolidate multiple queries and mutations in a single call. In the example below you can see how 3 different mutations are grouped in a single call. You can add all the mutations you want. Please note some details:

  • Each mutation is using an alias (canvas1, canvas2, text1) to identify them and to avoid GraphQL to merge them into a single mutation.
  • For the createCanvas mutations, we are using a fragment (canvasData) to consolidate what fields we want to be reported for all the newly created canvases.
mutation createMultipleElementsInOneGroup($workspaceId: String!) {
    canvas1: createCanvas(workspaceId: $workspaceId, input: {
        transform : { x: 1000 y:1000}
        name: "Canvas 1"
    }) {
        ... canvasData
    } 

    canvas2: createCanvas(workspaceId: $workspaceId, input: {
        transform : { x: 1000 y:2000}
        name: "Canvas 2"
    }) {
        ... canvasData
    } 

    text1: createText(workspaceId: $workspaceId, 
        input: {
            text: "New Text created!",
            transform : { x:500 y:500}
        }) {
            id
        }
}

fragment canvasData on Canvas {
    name
    id
    transform {x y }
}
with these variables:
{
    "workspaceId": "<workspaceID>"
}

and the output is (the values in the id field are just a reference, they will change every time you run the mutations):

{
    "data": {
        "canvas1": {
            "name": "Canvas 1",
            "id": "60aeb666ea1ae5d10306fb00",
            "transform": {
                "x": 1000,
                "y": 1000
            }
        },
        "canvas2": {
            "name": "Canvas 2",
            "id": "60aeb667ea4aeA691906fb04",
            "transform": {
                "x": 1000,
                "y": 2000
            }
        },
        "text1": {
            "id": "60aeb667eP4ae581cc060b08"
        }
    }
}

If you have any questions or comments, please contact us at Bluescape support.