Traits: API for elements traits

NOTICE: The current version of /v3/ GA release does not include REST API support for Traits, they are currently implemented only by GraphQL APIs. Traits will be released with REST API support in a future release for /v3/.

What are Traits?

Traits are a new feature that allows developers to associate metadata to objects within a workspace via a REST API. Traits are open-ended metadata for workspace objects. For example, if you upload assets (images, documents, etc.) that belong to a specific project, you can add that project information as Traits to each asset in the workspace. Later, you could download those assets, and the data in the Traits of each asset will provide insight to the original project data.

Highlights of Traits

Important points regarding Traits:

  • Traits are always represented as a JSON array.
  • Unlike Bluescape comments, traits can be specified on object creation.
  • Any number of traits can be associated with a workspace object, forming an ordered list.
  • Similarly to Bluescape comments, traits are append-only, i.e., traits can only grow monotonically over time, they cannot be deleted.

To what elements can I associate a Trait?

Traits may be associated with the following workspace elements (object_type):

  • Notes
  • Canvas
  • Browsers
  • Documents
  • Images
  • Strokes
  • Text

Traits may be associated with a workspace element upon its creation, or at a later time, until the deletion of the element. The following element types currently support trait association upon element creation:

  • Notes
  • Canvas
  • Browsers
  • Strokes
  • Text

Trait structure

In every request and response of the Bluescape REST API operating on elements of the supported types, traits are represented as a JSON array. Each item in the array must conform to the JSON-LD specification (https://json-ld.org/). While the JSON-LD specification contains a rich set of features for data modeling, their use is not necessary. The only relevant constraint imposed by the JSON-LD specification is that every JSON property name must either:

  • be a Uniform Resource Locator (URI)
  • be a JSON-LD keyword - one of 13 reserved names starting with the “@” symbol
  • resolve to a URI, this if you are using the “@context” keyword

IMPORTANT: If traits do not conform to this structure, traits API calls will produce HTTP error response 400 Bad Request.

API clients are encouraged to choose the HTTP URI schema to reduce the possibility of inadvertent namespace collisions, and use a base URI derived from the DNS name of their organization, thus enabling multiple organizations to cooperatively share the traits namespace. For instance, the traits specified above can be augmented by another organization. See example below:

Example of the data load:
For v2:

{
    // trait from framework A
    "http://acme.com/file-data/name":  “background-test-1.jpg”,
    "http://acme.com/file-data/version": "1.0.4-First-review"
},
{ // trait from framework B
    "http://ajax.com/project/": {
        "http://ajax.com/project/owner": "Joe Smith",
        "http://ajax.com/project/deadline": "2019Q4"
    },
    "http://ajax.com/project/name": "Lorem Ipsum, the Return"
}

For v3:

{
    context: "http://schema.org/", 
    content: {
        name: "hello world", 
        id: "ID-1234"
}

How to implement Traits?

This page contains the implementation details for v2 REST APIs and for v3 GraphQL APIs.

Implementation using REST APIs

Add Traits when creating an element, REST API

As mentioned above, you can add Traits to an element at the creation moment if the element is one of the following ones:

  • Notes
  • Canvas
  • Browsers
  • Strokes
  • Text

You will need to add the JSON Array as a 'traits' field in the data load. For example, when creating a Canvas, you can add Traits as in the example below:

{
    "x": 10000,
    "y": 1000,
    "width": 4000,
    "height": 4000,
    "name": "New Canvas",
    "borderColor": "Yellow",
    "traits" : [{"http://acme.com/project": "Lorem Ipsum, The Return"},{"http://acme.com/project/review" : "First Review, gathering Feedback"}]
}

Add Traits to an existing element, REST API

Endpoint /v2/workspaces/<workspaceId>/elements/<object_type>/<object_id>/traits
Method POST
Comments If traits do not conform to the specified structure, Traits API calls will produce HTTP error response 400 Bad Request.

When adding Traits to an object, you will need to provide a JSON Array in the body of the API request. An example of the data load body for adding Traits to an image object would be:

[{
    "http://acme.com/picture/title": "Sand dunes picture",
    "http://acme.com/picture/description": "Sand Dunes, big, light on one side, shadow on the other side",
    "http://acme.com/picture/tags": ["sand dunes","light","desert","blue sky","yellow sand","sand"]
}]

Get a list of the Traits in an object, REST API

Endpoint /v2/workspaces/<workspaceId>/elements/<object_type>/<object_id>/traits
Method GET
Comments

Cannot Delete/Edit Traits in v2 REST APIs: alternative

As previously mentioned, the traits of an element are never deleted during its lifetime, and all the traits association is cumulative. However, the API client is free to interpret cumulative traits associations as updates or deletions. For instance, another traits association may result in the traits array becoming this:

[
    { "http://acme.com/bluescape#assetId": "869C287E-59BB-4319-9261-F791F659C54A" },
    { "http://ajax.com/bscp#assetId": "98d03812452e0b6cabdbde5eff14e89f" },
    { "http://acme.com/bluescape#assetId": null }]

The API client using the "http://acme.com" prefix is free to interpret such associations as a deletion of the assetId property of the associated bluescape#assetId element by processing the values from older to newer (top to bottom in this example), being null the newest value to use.

Implementation using v3 GraphQL APIs

In v3 GraphQL traits, you have 2 options to specify the JSON-LD keyword in the Traits declaration: context and vocab. The table below provides more details about them.

JSON-LD keyword Details
context URI to append as a prefix to the content to be specified. MUST resolve to an actual URL.

Example

{
    context: "http://schema.org/", 
    content: {
        name: "Project - POC Data", 
        id: "RSE-12333"
}
JSON-LD keyword Details
vocab URI to append as a prefix to the content to be specified. Must have a URI syntax, but does not need to resolve to an actual URL. Useful when you want to add metadata that may not be associated with a specific URL.

Example

{
    vocab: "http://POC-0001.org/", 
    content: {
        name: "Project - POC Data", 
        id: "RSE-12333"
}

Add Traits when creating an element, GraphQL API

In this example, we will add Traits to a regular shape:

mutation createShape($workspaceId: String! $textContent: String! ) {
      createShape(
          workspaceId: $workspaceId
          input: {  
            text: $textContent
            transform: {x:0 y:0}
            style: {
                 regularShape: {
                    kind: Ellipse 
                    width:2000 height:2000 strokeWidth: 5 
                    fillColor: { r:255 g:100 b:255 a:1 }
                 }              
            }
            traits:{
                context: "http://schema.org/", 
                content: {
                    name: "shape with traits", 
                    shape: "ellipse"
                }
            }
          })
        {id kind traits }
    }

with the following variables:

{
    "workspace": "<workspaceId>",
    "textContent" : "New shape, with traits!"
}

In the Response body, see how the traits have been created (the id field value may be different):

{
    "data": {
        "createShape": {
            "id": "609b03f90a2389b24d65b9cd",
            "kind": "Ellipse",
            "traits": {
                "http://schema.org/name": "shape with traits",
                "http://schema.org/shape": "ellipse"
            }
        }
    }
}

Add Traits to an existing element, GraphQL API

Mutation addTraits
mutation addTraitsToElement($workspace: String!, $id:String!) {
  traits: addTraits(
    workspaceId: $workspace,
    id: $id, 
    compactOutput:false,
    input: {
            context: "http://schema.org/", 
            content: {
                project: "Special Project", 
                projectId : "<ADD-PROJECT-ID>"
                }
            }
    )
}

with the following variables:

{
    "workspace": "<workspaceId>",
    "id" : "<elementId>"
}

Overwrite the values of the Traits in an object, GraphQL API

New in v3 GraphQL Traits: You can overwrite the values of the Traits.

Previously, in v2, when you add a new value to a previously defined Trait, you got a list of all the values you have set for that specific value, and needed to loop through those values and select the newest one (the laters at the bottom of the list).

Now, in v3 GraphQL Traits, you always get the latest value specified for a Trait, it’s that simple.

For example, if for the previous example of how to add traits to an object, you run a new mutation to change the name of the “project” Trait to “Special Project - NEW CASE”, by this mutation:

mutation addTraitsToElement($workspace: String!, $id:String!) {
  traits: addTraits(
    workspaceId: $workspace,
    id: $id, 
    compactOutput:false,
    input: {
            context: "http://schema.org/", 
            content: {
                project: "Special Project - NEW CASE", 
                }
            }
    )
}

Then, when you examine the Traits values you will see that value as the new value of the Trait:

{
    "data": {
        "elements": [
            {
                "id": "<elementId>",
                "traits": {
                    "@id": "brn:ws:GDUWtDvSZGt7868PBBk2:609ede3c8f071b0018495fd9",
                    "http://schema.org/projectId": "Special Project - NEW CASE",
                    "http://schema.org/projectName": "<ADD-PROJECT-ID>",
                }
            }
        ]
    }
}

Note the new "@id" property. It specifies that a Traits has been updated.

Get a list of the Traits in an object, GraphQL API

Query elements

Example:

query getTraitsOfElementById($workspaceId: String!, $id:String!){
    elements(workspaceId: $workspaceId id:$id ) {
        type: __typename
        id
        traits        
    }
}

with the following variables:

{
    "workspace": "<workspaceId>",
    "id" : "<elementId>"
}

The response body will show you the traits:

{
    "data": {
        "elements": [
            {
                "__typename": "<element-type>",
                "id": "<elementId>",
                "traits": {
                    "@id": "brn:ws:GDUWtDvSZGt7868PBBk2:609ede3c8f071b0018495fd9",
                    "http://schema.org/projectId": "SOME-ID 3",
                    "http://schema.org/projectName": "mega project title 3",
                }
            }
        ]
    }
}

Where to Next?

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