Cintoo Open API (1.1.0)

Download OpenAPI specification:Download

API Support: support@cintoo.com License: Apache 2.0

Discover the Cintoo API 2.0 documentation: https://aec.cintoo.com/api/2

API Specification

The Cintoo API specification document you are viewing is compliant with the Open API Specification 3.0.3 and can be exported to a json format that can be used by the API tool of your liking.

It also means the generated json will contain all the details present in this documentation about the

  • JSON Objects schema being returned
  • The status codes
  • The authentication
  • The verbs/paths/resources

Technical details

  • The API is resource oriented
  • The encoding is done in utf-8
  • Do not hesitate to click on the Download button to get the openapi.json file generated and import in your favorite API client
  • Any Cintoo valid user can use the API

Sandbox

With Cintoo Cloud API comes a Sandbox, which means a testing environment. This Sandbox is a separate tenant from the Cintoo Cloud platform that you are already familiar with.

The Sandbox is at your disposal so that you can test and use the API with no consequence on your production data (no unfortunate deletion by mistake for example).

Sandbox restrictions

  • Scan capacity of 20 scans per user.
  • Company SSO (if any) is not applicable since the Sandbox uses a different account.
  • Please contact support@cintoo.com to get the invitation link to the Sandbox account.
  • You can use the same email but you will be asked to set a new password by clicking on the invitation link.
  • Please note that this is an experimental platform, so we reserve the right to refresh/delete the data (unlike the production platform).
  • There is no limit in time for using the Sandbox.
  • The BIM & CAD Module (BCM) is activated in this Sandbox, so feel free to use your BIM or CAD model in this testing environment.

Registering to the Sandbox / Cintoo Cloud API

Please contact our Support Team support@cintoo.com to be invited to the Sandbox and get all the documentation for Cintoo Cloud API.


Authentication

The Cintoo API relies on JWT Tokens for authenticating users with the standard combination Access Token+ Refresh Token.

Note that the first acquisition of the token pair requires a manual step (see below) for security reasons, then it can be fully automated.

Access Tokens and Refresh Tokens

There are 2 kind of tokens:

  • Access token:
    • is short lived (3h)
    • is used to authenticate each query
    • is personal and should not be shared, except for service users (see Token management recipes at the end of the documentation)
    • is a JWT and is stateless, ie. there is NO limit of Access Token being valid for a given user simultaneously, and can be used in parallel.
    • example of API call to list accounts: curl -H Authorization="Bearer $access_token" https://aec.cintoo.com/api/accounts

Note: Calling the API with an already-used/expired token results in a response with status code 401

  • Refresh token:
    • is long lived (months)
    • is used once to obtain a new Access Token + Refresh Token pair.
    • cannot be used to make API calls.
    • is personal and should not be shared, except for service users (see Token management recipes at the end of the documentation)
    • there IS a limit of 10 Refresh Token being valid for a given user simultaneously
    • is stateful and CANNOT be used in parallel, as it is consumed when used
    • example of refresh token call to get a new pair of "Access Token" and "Refresh Token": curl -X POST https://aec.cintoo.com/oauth/token -d "grant_type=refresh_token&refresh_token=$refresh_token"

Note: Calling the API with an already-used/expired token results in a response with status code 401

The token flow

The Cintoo API follows the OAuth 2.0 Authorization Grant Type flow, and supports the PKCE extension which is recommended to provide better security (source: https://oauth.net/2/grant-types/authorization-code/)

Concretely, users are supposed to acquire the token once with a manual step (they have to click on approve), to get a first pair of tokens.

Once this is done, they can script the refresh with a simple curl command.

Note: a refresh token is valid for 21 days. It can be used only once. The refreshing mechanism can be done an unlimited number of times

Generating Tokens

  • You are just starting with the Cintoo API and want to test it manually -> look that "Generating the JWT Bearer Token with the cintoo-login.exe"
  • You are already familiar with oauth mechanisms/tools -> look at "Using tools/3rd party to manage Tokens from Cintoo Oauth Service"

Generating the Access Token & Refresh Token pair with the cintoo-login.exe

To generate an Access Token with OAuth please use the following nice CLI tool cintoo-login.exe and double click on it.

cintoo-login.exe

Opening OAuth page in browser.
To receive your JWT token:
        * Ensure you are logged-in
        * Click on the 'Allow' button
INFO: You have 30s to complete these actions

Which opens this page

Hint: if you wait more than 30s you will have to run the command again Hint: you can change the timeout duration to another value with --timeout 60

allow-button

Once you click on Allow the page should lead you to:

success

AND (most importantly) the token appears magically in your cmd output

Hint: Copy paste the Bearer xxxxx to avoid errors

Opening OAuth page in browser.
To receive your JWT token:
        * Ensure you are logged-in
        * Click on the 'Allow' button
INFO: You have 30s to complete these actions
Here is your token: to use it put in the Authorization header (copy paste below):
{"Authorization": "Bearer <access_token>"}
Its validity is of 3h
A new token can be-regenerated simply thanks to this refresh_token: <refresh_token>
Validating token
Success: API Token was successfully validated

Refreshing tokens ie. Generating programmatically a new Access Token + Refresh Token pair

While the Refresh Token is valid (within 21 days), you can consume it to get a new Access-Token + Refresh-Token pair.

Note: consuming the Refresh Token can be done before the expiration of the Access Token Note: consuming the Refresh Token does NOT invalidate other Access Token as they are short lived

Using shell (Linux, OSX)

refresh_token="<Your refresh token>"
curl -X POST https://aec.cintoo.com/oauth/token -d "grant_type=refresh_token&refresh_token=$refresh_token"

Which returns the following

{
    "access_token": "{access_token}",
    "refresh_token": "{refresh_token}",
    "token_type": "Bearer",
    "expires_in": 10800,
    "user_id": "{user_id}"
}

Using powershell (Linux, OSX)

$refresh_token = "<Your refresh token>"
$params = @{
    Uri         = 'https://aec.cintoo.com/oauth/token'
    Method      = 'POST'
    Body        = @{
        grant_type     = 'refresh_token'
        refresh_token  = $refresh_token
    }
    ContentType = 'application/x-www-form-urlencoded'
}
Invoke-RestMethod @params

Which returns the following

access_token  : {access_token}
refresh_token : {refresh_token}
token_type    : Bearer
expires_in    : 10800
user_id       : {user_id}

Using tools/3rd party to manage Tokens from Cintoo Oauth Service

The Cintoo API follows the oauth protocol Authorization Code Grant to generate the access-tokens and refresh-tokens.

As such, it is possible to use 3rd party libraries and tools that implement the Oauth2 Authorization Code protocol to manage the tokens (and perform automatic refresh).

The important fields are the following and they match those defined by the authorization code request, authorization code request with PKCE and refreshing access tokens :

Field Value
Grant Type Authorization Code or Authorization Code (With PKCE)
Callback URL localhost or 127.0.0.1 or /
Auth URL https://aec.cintoo.com/oauth/authorize
Access Token URL https://aec.cintoo.com/oauth/token
Refresh Token URL https://aec.cintoo.com/oauth/token
State use a random code made of [a-z0-9]+ with a "correct length". More information about the state-parameters
Code Challenge Method (only with PKCE) SHA-256 more info on PKCE

The flow in detail for acquiring the first Token pair

This section is here in case you want to build an oauth client for acquiring the first Token pair without the help of the cintoo-login or without 3rd party software.

The term "Client" is going to be described as the originator of the oauth token request.

  • Client calls the Cintoo oauth/authorize endpoint with from the browser method with the following query parameters:

    • the redirect_uri (callback-url) it wants Cintoo to send the authorization code to
    • the state uses a random code made of [a-z0-9]+ with a "correct length". More information about the state-parameters
    • (optional) code_challenge a random code that has been hashed using the SHA256 algorithm. More info on PKCE.

      code_verifier = high-entropy cryptographic random STRING using the unreserved characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" from Section 2.3 of [RFC3986], with a minimum length of 43 characters and a maximum length of 128 characters.

    • (optional but mandatory if code_challenge is set) code_challenge_method : "SHA256"
  • Cintoo API returns an html element with an approve button to be clicked by the user that started the action (the same shown in the previous chapter)

  • Once the approve button is pressed there is a Form Post URL redirect that will target the redirect_uri provided by the Client with the query parameters : code and state (+ code_challenge and code_challenge_method if specified before)

  • The Client should check that the state sent and received are the same to avoid CSRF attacks.

  • If they are the same, the Client can then send a POST query to the oauth/token endpoint with the following payload that contains the code it received on the previous steps.

    {
        "code": "{code}",
        "grant_type": "authorization_code",
        "authorization_code": "{redirect_uri}"
    }
    

    or with PKCE

    {
        "code": "{code}",
        "grant_type": "authorization_code",
        "authorization_code": "{redirect_uri}",
        "code_verifier": "{code_verifier}"
    }
    
  • Finally the Cintoo API answers the oauth/token with a json object that contains the access_token and refresh_token pair:

    {
        "access_token": "{access_token}",
        "refresh_token": "{refresh_token}",
        "token_type": "Bearer",
        "expires_in": 10800,
        "user_id": "{user_id}"
    }
    

Doing queries

Below you will find an example on how to use the token to do a query.

A good endpoint to start with is the isLogged resource which simply returns 200 and {"success": true} if the token was recognized by the Cintoo API.

We highly recommend that you try it, then start changing the resource type (like accounts for instance) to get used to the API.

Query example for Windows (with Powershell)

Copy the code below and try it in your Powershell terminal.

Hint: copy paste this while replacing the xxxxxxx with your token, and call as many Invoke-RestMethod as you want. Note: the token is surrounded by "

$token = "xxxxxxxxxxxxxxxxxx"
$headers = @{
    Authorization="Bearer $token"
    Content='application/json'
}
Invoke-RestMethod -Headers $headers -Method Get -Uri "https://aec.cintoo.com/api/isLogged"

The powershell command line should return this

success
-------
   True

Errors

To communicate errors, the Cintoo API

It is consensus in the industry that the status code is the source of truth on whether an API call was successful or not, the body is merely a BONUS.

Current error-body returned (soon to be replaced)

For the moment the payload sent on a failed query is the following object:

{
    "code": "{the http response code}",
    "message": "{the reason of the failure}"
}

We are going to replace that with a more standardized body

Future error-body returned

We are following this RFC whose content is the following

  • "type" (string) - A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be "about:blank".
  • "title" (string) - A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4).
  • "status" (number) - The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.
  • "detail" (string) - A human-readable explanation specific to this occurrence of the problem.
  • "instance" (string) - A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.

The mandatory fields that are going to be always present are : title and status. Others are optional.

{
    "status": "{the http status code}",
    "type": "{the reason of the failure}"
}

So the HTTP response status code is both in the HTTP header, and in the status attribute of the returned JSON object.


Login

Check if the user is logged in

This request will tell you if the user is logged in

Authorizations:
oauth2

Responses

Response samples

Content type
application/json
{
  • "success": true
}

Accounts

Account

id
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
type
required
string
Value: "account"
name
required
string
createdAt
required
string <date-time> (DateTime)

The date-time notation as defined by RFC 3339, section 5.6 (ex: 2017-08-18T12:41:31+0000)

createdBy
string (UserId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
ownerId
required
string (UserId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
required
object (AccountPermissions)
{
  • "id": "{accountId}",
  • "type": "account",
  • "name": "My Account",
  • "createdAt": "2017-07-21T17:32:28Z",
  • "createdBy": "{userId}",
  • "ownerId": "{userId}",
  • "permissions": {
    }
}

List accounts

List available accounts for the current user

Authorizations:
oauth2

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get an Account

Get an Account with the accountId

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

Responses

Response samples

Content type
application/json
{
  • "id": "{accountId}",
  • "type": "account",
  • "name": "My Account",
  • "createdAt": "2017-07-21T17:32:28Z",
  • "createdBy": "{userId}",
  • "ownerId": "{userId}",
  • "permissions": {
    }
}

Report Projects Last Accessed Date

Report Projects Last Accessed Date.

Note: The lastAccessedDate is updated when a project or any of its resources (ex: files, tags, ...) are accessed through the API

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

query Parameters
subscriptionId
string (SubscriptionId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: subscriptionId={subscriptionId}
projectId
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: projectId={projectId}

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Report Users Last Activity Date

Report Users Last Activity Date.

Note: The lastActivityDate is updated when a project or any of its resources (ex: files, tags, ...) are accessed through the API

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Project Resources

List Projects

Find the corresponding Project from a workzoneId or project id list.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

query Parameters
workzoneId
string

Modify the query to only return the project owning a workzoneId

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get a Project

Get Project.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

Responses

Response samples

Content type
application/json
{
  • "id": "{projectId}",
  • "type": "project",
  • "accountId": "{accountId}",
  • "planId": "{subscriptionId}",
  • "isdemo": false,
  • "region": "default",
  • "projectIdV0": "{workzoneId}",
  • "projectIdDefault": "{workzoneId}",
  • "ownerId": "{userId}",
  • "createdAt": "2017-07-21T17:32:28Z",
  • "createdBy": "{userId}",
  • "updatedAt": "2017-07-21T17:32:28Z",
  • "updatedBy": "{userId}",
  • "name": "New Project",
  • "description": "string",
  • "location": {
    },
  • "isDeleted": false,
  • "deletedBy": "{userId}",
  • "deletedAt": "2017-07-21T17:32:28Z",
  • "scanCount": 103,
  • "scanSize": 2799564730,
  • "workzoneCount": 1,
  • "rootWorkzoneCount": 1,
  • "userIds": [
    ],
  • "groupIds": [
    ],
  • "roleIds": [
    ],
  • "workzones": [
    ],
  • "permissions": {
    }
}

Modify a project subscription

Modify the project subscription

For a more comprehensive project modification (description, location, name, owner, subscription) use the API 2 here

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

Request Body schema: application/json
Array
op
string
Value: "replace"
value
string

Responses

Request samples

Content type
application/json
[
  • {
    }
]

Response samples

Content type
application/json
{
  • "status": 400,
  • "type": "Does not have a value in the enumeration [\"replace\"]"
}

List Files

List project files.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

query Parameters
Array of ModelCategory (string) or ScanCategory (string) or GeoImageCategory (string) (FileCategory)
Examples:
  • category=scan - Example of single category
  • category=geoImage,model - Example of multiple categories

Comma separated list of categories

Responses

Response samples

Content type
application/json
[
  • {
    }
]

List Tag Lists

List Project Tag Lists.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

query Parameters
DateTime (string) or Date (string)

if specified, it will only fetch TagLists updated after that moment

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create a Tag List

Create a Project Tag List.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

Request Body schema: application/json
required

Json object of tag list

parentId
required
string
required
object (Tag List Data)
object (AIDetectParams)
Array of objects (Tag Data)
cleanRemovedMetadataIds
boolean

Responses

Request samples

Content type
application/json
{
  • "parentId": "string",
  • "data": {
    },
  • "detect": {
    },
  • "insert": [
    ],
  • "cleanRemovedMetadataIds": true
}

Response samples

Content type
application/json
{
  • "projectId": "{projectId}",
  • "parentId": "{workzoneId}",
  • "parentUuid": "{uuId}",
  • "id": "{tagListId}",
  • "type": "tagList",
  • "createdAt": "2017-07-21T17:32:28Z",
  • "createdBy": "{userId}",
  • "updatedAt": "2017-07-21T17:32:28Z",
  • "updatedBy": "{userId}",
  • "data": {
    }
}

Get a Tag List

Get a detailed Tag List.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

tagListId
required
string (TagListId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {tagListId}

The id of Tag List

query Parameters
DateTime (string) or Date (string)

If the updated_from is specified, it returns the tags that have been updated in the list and partial tags information for those that have been deleted from the list. The partial/deleted-tags have the isDeleted set to true

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Update a Tag List

Update a Project Tag List

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

tagListId
required
string (TagListId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {tagListId}

The id of Tag List

Request Body schema: application/json
required

Request body to update the Tag List

object (Tag List Data)
Array of objects (Tag Data)
update
object
object (AIDetectParams)
delete
Array of strings (TagId) [^[a-zA-Z0-9_-]+$]
cleanRemovedMetadataIds
boolean

Responses

Request samples

Content type
application/json
{
  • "data": {
    },
  • "insert": [
    ],
  • "update": { },
  • "detect": {
    },
  • "delete": [
    ],
  • "cleanRemovedMetadataIds": true
}

Response samples

Content type
application/json
{
  • "projectId": "{projectId}",
  • "parentId": "{workzoneId}",
  • "parentUuid": "{uuId}",
  • "id": "{tagListId}",
  • "type": "tagList",
  • "createdAt": "2017-07-21T17:32:28Z",
  • "createdBy": "{userId}",
  • "updatedAt": "2017-07-21T17:32:28Z",
  • "updatedBy": "{userId}",
  • "data": {
    },
  • "tags": [
    ]
}

Delete a Tag Lists

Delete a Project Tag Lists.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

tagListId
required
string (TagListId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {tagListId}

The id of Tag List

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create requiered parameters to start a Cintoo Connect import

Create requiered parameters to start a Cintoo Connect import

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

projectId
required
string (ProjectId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {projectId}

The id of project

workzoneId
required
string (WorkzoneId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {workzoneId}

The id of the workzone

Responses

Response samples

Content type
application/json
{
  • "url": "string",
  • "slug": "string"
}

Group

List Groups

List Groups.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get a Group

Get a Group from the GroupId

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

groupId
required
string (GroupId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {groupId}

The id of the group

Responses

Response samples

Content type
application/json
{
  • "id": "{groupId}",
  • "type": "group",
  • "name": "group",
  • "description": "group description",
  • "color": "#0698ec",
  • "createdAt": "2017-07-21T17:32:28Z",
  • "createdBy": "{userId}",
  • "updatedAt": "2017-07-21T17:32:28Z",
  • "userIds": [
    ],
  • "accountIds": [
    ]
}

Role

List Roles

List Roles.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get Role

Get a Role from the RoleId

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

roleId
required
string (RoleId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {roleId}

The id of the role

Responses

Response samples

Content type
application/json
{
  • "id": "{roleId}",
  • "type": "role",
  • "name": "BIM / VDC Manager",
  • "description": "Can do anything except creating projects",
  • "color": "#0698ec",
  • "createdAt": "2017-07-21T17:32:28Z",
  • "updatedAt": "2017-07-21T17:32:28Z",
  • "permissions": [
    ],
  • "accountIds": [
    ]
}

Subscription

List Subscriptions

List the Subscriptions attached to an account

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

Responses

Response samples

Content type
application/json
[
  • {
    }
]

User

List Users

List Users.

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get a User

Get a User from the UserId

Authorizations:
oauth2
path Parameters
accountId
required
string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {accountId}

The id of the account

userId
required
string (UserId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$
Example: {userId}

The id of the user

Responses

Response samples

Content type
application/json
{
  • "id": "{userId}",
  • "type": "user",
  • "firstname": "John",
  • "lastname": "Doe",
  • "company": "Cintoo",
  • "title": "Account Manager",
  • "email": "user@example.com",
  • "avatar": "http://example.com",
  • "accountIds": [
    ]
}

Get accounts

Get the list of accounts

You can get your accounts with the accounts API: List Accounts

Here is an extract of what it returns:

[
    {
        "id": "{accountId}",
        "type": "account",
        "name": "My Account",
        "createdAt": "2017-07-21T17:32:28Z",
        "createdBy": "{userId}",
        "ownerId": "{userId}",
        "permissions": {}
    }
]

And here we are interested in the id field.

In javascript accessing those would looks like this:

// assuming you have the result of the in the projects variable
> accounts.flatMap((account) => account.id)
[ '{accountId1}', '{accountId2}' ]

Get projects

Prerequisites

Follow the tutorial to get the list of accounts first: here.

Once you have the project list pick the {accountId} corresponding to the account you want your projects from.

Get the list of Projects

You can get your projects with the projects API: List Projects

Here is an extract of what it returns:

[
    {
        "id": "{projectId}",
        "type": "project",
        "accountId": "{accountId}",
        "planId": "{subscriptionId}",
        ...
    }
]

And here we are interested in the id field.

In javascript accessing those would looks like this:

// assuming you have the result of the in the projects variable
> projects.flatMap((project) => project.id)
[ '{projectId}', '{projectId2}' ]

Get files

Prerequisites

Follow the tutorial to get the list of project first: here.

Once you have the project list pick the {projectId} corresponding to the project you want your files from.

Get the list of files

To get your files call the projects/{projectId}/files endpoint with the {projectId} in the URL that you have chosen in the "Prerequisites" section.

Full spec about the files endpoint here.

Example of response body:

[
  {
    "projectId": "{projectId}",
    "parentId": "string",
    "id": "{fileId}",
    "name": "string",
    "createdAt": "2019-08-24T14:15:22Z",
    "createdBy": "{userId}",
    "updatedAt": "2019-08-24T14:15:22Z",
    "updatedBy": "{userId}",
    "imageBlob": "547e638baece20bb63253287715eb87c.jpg",
    "imagePreviewBlob": "547e638baece20bb63253287715eb87c_preview.jpg",
    "type": "model",
    "translation": {
      "x": 0,
      "y": 0,
      "z": 0
    },
    "rotation": {
      "x": 0,
      "y": 0,
      "z": 0,
      "w": 0
    },
    "contentId": "string",
    "src": {
      "type": "string",
      "data": "string",
      "name": "string",
      "createdAt": "2019-08-24T14:15:22Z",
      "createdBy": "string",
      "version": 0,
      "treeBlob": "string",
      "metadataBlob": "string"
    },
    "importedAt": "2019-08-24T14:15:22Z"
  }
]

Get the list of scans/models/geoImages

To get your files call the accounts/{accountId}/projects/{projectId}/files?category=scan,model.

Full spec about the files endpoint here.

Token Management

Good practices

Each user should have their own tokens

Tokens are personal and are bound to the person who generated them with all their roles and permissions.

In The Cintoo platform a subscription can hold an unlimited number of users. Furthermore, there are roles (Project Managers) to grant access users to resources with different levels of privileges (read, write, etc.).

There are only positive outcomes to use as many users as possible.

Single refresher, multiple accessors

If you absolutely need to have a single user do all the API calls, but multiple applications share the same tokens, you might very quickly hit the limit of simultaneous refresh tokens valid for a single user.

Remember from the Access Tokens and Refresh Tokens section that

  • Access Tokens are JWT tokens, that are stateless and can be used in parallel
  • Refresh Tokens are stateful and cannot be used in parallel

Our recommendation in that case would be to have

  • A 'refreshing process/app' which would be the only one to use the refresh token and store both Refresh Token and Access Token. The stored Access Token should remain available for other processes
  • Multiple processes/apps that would ask for the Access Tokens, which could be either in the DB OR from the 'refreshing process/app'. These requests should be performed intermittently to prevent Access Token expiration, so that the processes/apps can perform all the queries to the Cintoo API

Note: the Access Token is a JWT and can easily be decoded to check the expiration date

Race conditions risk without proper synchronization

In case that it is not possible to refresh the token from a single app, the client should at least handle race conditions in which a single refresh token is used twice by two concurrent processes. In this case the second refresh will fail. The first client should have stored the new Access-Token/Refresh-Token immediately after the refresh process.