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.