GraphQL vs REST APIs

Here is a comparison of Bluescape `v3` REST and GraphQL APIs. You can appreciate the advantages of each implementation, and use this list to help you port queries from REST to GraphQL.

Use HTTP POST for GraphQL

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

REST

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

GraphQL

In GraphQL, the API calls are always an HTTP POST, and operations are queries or mutations. For more details, read the Bluescape GraphQL Schema (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: 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 great flexibility to get just the data you need, and for that, you need to clearly specify what fields you want to be retrieved in each query.

REST

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

GraphQL

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 Text types:

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

How to get the content of a Canvas

One operation you may run is to get and examine the content of a Canvas. See below how to do it in REST and in GraphQL.

REST

in REST APIs, to get the content of a Canvas, you need to get the Id of that particular Canvas and run the following GET query:

  • /v3/workspaces/<SET_WORKSPACEID>/elements?canvas=<CANVAS_ID>

`

GraphQL

In GraphQL, to get the content of a Canvas, you can add the "canvasId" parameter to an elements query. Remember that you need to add what you want to display of each element type:

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 }
          }
          
      }    
    }

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

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.

GraphQL

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 mutations 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. Note the following 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>"
}

The output is (the values in the id field are just a reference, they 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"
        }
    }
}

Where to Next?

Not what you were looking for? Reply below or Search the community and discover more Bluescape.