Download OpenAPI specification:Download
Discover the Cintoo API 2.0 documentation: https://aec.cintoo.com/api/2
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
Download
button to get the openapi.json
file generated and import in your favorite API clientWith 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).
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.
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.
There are 2 kind of tokens:
Token management recipes
at the end of the documentation)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
Access Token
+ Refresh Token
pair.Token management recipes
at the end of the documentation)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 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
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
Once you click on Allow
the page should lead you to:
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
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}
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 |
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:
redirect_uri
(callback-url) it wants Cintoo to send the authorization code tostate
uses a random code made of [a-z0-9]+
with a "correct length". More information about the state-parameterscode_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.
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}"
}
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.
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 manyInvoke-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
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.
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
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.
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": {
- "owner": true,
- "admin": true,
- "manager": true
}
}
[- {
- "id": "{accountId}",
- "type": "account",
- "name": "My Account",
- "createdAt": "2017-07-21T17:32:28Z",
- "createdBy": "{userId}",
- "ownerId": "{userId}",
- "permissions": {
- "owner": true,
- "admin": true,
- "manager": true
}
}
]
Get an Account with the accountId
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
{- "id": "{accountId}",
- "type": "account",
- "name": "My Account",
- "createdAt": "2017-07-21T17:32:28Z",
- "createdBy": "{userId}",
- "ownerId": "{userId}",
- "permissions": {
- "owner": true,
- "admin": true,
- "manager": true
}
}
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
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
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} |
[- {
- "accountId": "{accountId}",
- "planId": "{subscriptionId}",
- "projectId": "{projectId}",
- "projectName": "Project Name",
- "lastAccessedDate": "2017-07-21"
}
]
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
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
[- {
- "userId": "{userId}",
- "userFirstname": "John",
- "userLastname": "Doe",
- "userEmail": "user@example.com",
- "userCompanyName": "Cintoo",
- "lastActivityDate": "2017-07-21"
}
]
Find the corresponding Project from a workzoneId or project id list.
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
workzoneId | string Modify the query to only return the project owning a workzoneId |
[- {
- "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": {
- "lat": 43.694388901753,
- "lng": 7.2489004116933
}, - "isDeleted": false,
- "deletedBy": "{userId}",
- "deletedAt": "2017-07-21T17:32:28Z",
- "scanCount": 103,
- "scanSize": 2799564730,
- "workzoneCount": 1,
- "rootWorkzoneCount": 1,
- "userIds": [
- "{userId}"
], - "groupIds": [
- "{groupId}"
], - "roleIds": [
- "{roleId}"
], - "workzones": [
- {
- "projectId": "{projectId}",
- "id": "{workzoneId}",
- "type": "workzone",
- "root": "{workzoneId}",
- "name": "My workzone",
- "roleIds": [
- "{roleId}"
]
}
], - "permissions": {
- "administrator": true,
- "manager": true,
- "contributor": true
}
}
]
Get Project.
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 |
{- "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": {
- "lat": 43.694388901753,
- "lng": 7.2489004116933
}, - "isDeleted": false,
- "deletedBy": "{userId}",
- "deletedAt": "2017-07-21T17:32:28Z",
- "scanCount": 103,
- "scanSize": 2799564730,
- "workzoneCount": 1,
- "rootWorkzoneCount": 1,
- "userIds": [
- "{userId}"
], - "groupIds": [
- "{groupId}"
], - "roleIds": [
- "{roleId}"
], - "workzones": [
- {
- "projectId": "{projectId}",
- "id": "{workzoneId}",
- "type": "workzone",
- "root": "{workzoneId}",
- "name": "My workzone",
- "roleIds": [
- "{roleId}"
]
}
], - "permissions": {
- "administrator": true,
- "manager": true,
- "contributor": true
}
}
Modify the project subscription
For a more comprehensive project modification (description, location, name, owner, subscription) use the API 2 here
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 |
op | string Value: "replace" |
value | string |
[- {
- "op": "replace",
- "path": "{subscriptionId}",
- "value": "{newSubscriptionId}"
}
]
{- "status": 400,
- "type": "Does not have a value in the enumeration [\"replace\"]"
}
List project files.
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 |
Array of ModelCategory (string) or ScanCategory (string) or GeoImageCategory (string) (FileCategory) Examples:
Comma separated list of categories |
[- {
- "projectId": "{projectId}",
- "parentId": "{workzoneId}",
- "parentUuid": "{uuId}",
- "id": "{fileId}",
- "type": "model",
- "uuid": "{uuId}",
- "name": "fileName",
- "formatId": "{fileFormatId}",
- "size": 0,
- "createdBy": "{userId}",
- "createdAt": "2017-07-21T17:32:28Z",
- "updatedAt": "2017-07-21T17:32:28Z",
- "updatedBy": "{userId}",
- "importedAt": "2017-07-21T17:32:28Z",
- "translation": {
- "x": 0.1,
- "y": 0.1,
- "z": 0.1
}, - "rotation": {
- "x": 0.1,
- "y": 0.1,
- "z": 0.1,
- "w": 0.1
}, - "contentId": "string",
- "src": {
- "type": "string",
- "data": "string",
- "name": "string",
- "createdAt": "2017-07-21T17:32:28Z",
- "createdBy": "string",
- "version": 0,
- "treeBlob": "string",
- "metadataBlob": "string"
}
}
]
List Project Tag Lists.
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 |
DateTime (string) or Date (string) if specified, it will only fetch TagLists updated after that moment |
[- {
- "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": {
- "name": "object_1 detected by AI",
- "description": "supposedly a thing object",
- "color": "#0698ec",
- "pending": true,
- "metadataDefinitions": [
- {
- "id": "string",
- "name": "string"
}
]
}
}
]
Create a Project Tag List.
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 |
Json object of tag list
parentId required | string |
required | object (Tag List Data) |
object (AIDetectParams) | |
Array of objects (Tag Data) | |
cleanRemovedMetadataIds | boolean |
{- "parentId": "string",
- "data": {
- "name": "object_1 detected by AI",
- "description": "supposedly a thing object",
- "color": "#0698ec",
- "pending": true,
- "metadataDefinitions": [
- {
- "id": "string",
- "name": "string"
}
]
}, - "detect": {
- "classes": [
- "string"
], - "fileIds": [
- "{fileId}"
]
}, - "insert": [
- {
- "id": "string",
- "subId": "string",
- "name": "string",
- "boundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "orientedBoundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "model": {
- "type": "AxisAlignedList",
- "list": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
]
]
}, - "class": "pump",
- "cameraState": {
- "position": [
- 0,
- 0,
- 0
], - "target": [
- 0,
- 0,
- 0
], - "rotation": [
- 0,
- 0,
- 0
], - "overviewAngle": "string",
- "viewDirection": "string",
- "rotationQuaternion": [
- 0,
- 0,
- 0,
- 0
], - "fov": 0,
- "overviewScale": 0,
- "ortho": true,
- "camType": "string"
}, - "unit": 0,
- "functionalSystem": "string",
- "description": "string",
- "confidence": 0.1,
- "scanUuids": [
- "{uuId}"
], - "needValidation": true,
- "nature": "AI",
- "customFields": [
- {
- "name": "string",
- "value": "string"
}
], - "metadata": [
- {
- "id": "string",
- "value": "string"
}
]
}
], - "cleanRemovedMetadataIds": true
}
{- "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": {
- "name": "object_1 detected by AI",
- "description": "supposedly a thing object",
- "color": "#0698ec",
- "pending": true,
- "metadataDefinitions": [
- {
- "id": "string",
- "name": "string"
}
]
}
}
Get a detailed Tag List.
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 |
DateTime (string) or Date (string) If the |
[- {
- "id": "{tagId}",
- "type": "tag",
- "parentId": "{tagListId}",
- "createdAt": "2017-07-21T17:32:28Z",
- "createdBy": "{userId}",
- "updatedAt": "2017-07-21T17:32:28Z",
- "updatedBy": "{userId}",
- "data": {
- "id": "string",
- "subId": "string",
- "name": "string",
- "boundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "orientedBoundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "model": {
- "type": "AxisAlignedList",
- "list": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
]
]
}, - "class": "pump",
- "cameraState": {
- "position": [
- 0,
- 0,
- 0
], - "target": [
- 0,
- 0,
- 0
], - "rotation": [
- 0,
- 0,
- 0
], - "overviewAngle": "string",
- "viewDirection": "string",
- "rotationQuaternion": [
- 0,
- 0,
- 0,
- 0
], - "fov": 0,
- "overviewScale": 0,
- "ortho": true,
- "camType": "string"
}, - "unit": 0,
- "functionalSystem": "string",
- "description": "string",
- "confidence": 0.1,
- "scanUuids": [
- "{uuId}"
], - "needValidation": true,
- "nature": "AI",
- "customFields": [
- {
- "name": "string",
- "value": "string"
}
], - "metadata": [
- {
- "id": "string",
- "value": "string"
}
]
}
}
]
Update a Project Tag List
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 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 |
{- "data": {
- "name": "object_1 detected by AI",
- "description": "supposedly a thing object",
- "color": "#0698ec",
- "pending": true,
- "metadataDefinitions": [
- {
- "id": "string",
- "name": "string"
}
]
}, - "insert": [
- {
- "id": "string",
- "subId": "string",
- "name": "string",
- "boundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "orientedBoundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "model": {
- "type": "AxisAlignedList",
- "list": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
]
]
}, - "class": "pump",
- "cameraState": {
- "position": [
- 0,
- 0,
- 0
], - "target": [
- 0,
- 0,
- 0
], - "rotation": [
- 0,
- 0,
- 0
], - "overviewAngle": "string",
- "viewDirection": "string",
- "rotationQuaternion": [
- 0,
- 0,
- 0,
- 0
], - "fov": 0,
- "overviewScale": 0,
- "ortho": true,
- "camType": "string"
}, - "unit": 0,
- "functionalSystem": "string",
- "description": "string",
- "confidence": 0.1,
- "scanUuids": [
- "{uuId}"
], - "needValidation": true,
- "nature": "AI",
- "customFields": [
- {
- "name": "string",
- "value": "string"
}
], - "metadata": [
- {
- "id": "string",
- "value": "string"
}
]
}
], - "update": { },
- "detect": {
- "classes": [
- "string"
], - "fileIds": [
- "{fileId}"
]
}, - "delete": [
- "{tagId}"
], - "cleanRemovedMetadataIds": true
}
{- "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": {
- "name": "object_1 detected by AI",
- "description": "supposedly a thing object",
- "color": "#0698ec",
- "pending": true,
- "metadataDefinitions": [
- {
- "id": "string",
- "name": "string"
}
]
}, - "tags": [
- {
- "id": "{tagId}",
- "type": "tag",
- "parentId": "{tagListId}",
- "createdAt": "2017-07-21T17:32:28Z",
- "createdBy": "{userId}",
- "updatedAt": "2017-07-21T17:32:28Z",
- "updatedBy": "{userId}",
- "data": {
- "id": "string",
- "subId": "string",
- "name": "string",
- "boundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "orientedBoundingBox": [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - "model": {
- "type": "AxisAlignedList",
- "list": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
], - [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
]
]
}, - "class": "pump",
- "cameraState": {
- "position": [
- 0,
- 0,
- 0
], - "target": [
- 0,
- 0,
- 0
], - "rotation": [
- 0,
- 0,
- 0
], - "overviewAngle": "string",
- "viewDirection": "string",
- "rotationQuaternion": [
- 0,
- 0,
- 0,
- 0
], - "fov": 0,
- "overviewScale": 0,
- "ortho": true,
- "camType": "string"
}, - "unit": 0,
- "functionalSystem": "string",
- "description": "string",
- "confidence": 0.1,
- "scanUuids": [
- "{uuId}"
], - "needValidation": true,
- "nature": "AI",
- "customFields": [
- {
- "name": "string",
- "value": "string"
}
], - "metadata": [
- {
- "id": "string",
- "value": "string"
}
]
}
}
]
}
Delete a Project Tag Lists.
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 |
[- {
- "id": "{tagId}",
- "isDeleted": true
}
]
Create the required parameters to start a Cintoo Connect import
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 |
{- "url": "string",
- "slug": "string"
}
List Groups.
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
[- {
- "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": [
- "{userId}"
], - "accountIds": [
- "{accountId}"
]
}
]
Get a Group from the GroupId
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 |
{- "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": [
- "{userId}"
], - "accountIds": [
- "{accountId}"
]
}
List Roles.
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
[- {
- "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": [
- "upload"
], - "accountIds": [
- "{accountId}"
]
}
]
Get a Role from the RoleId
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 |
{- "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": [
- "upload"
], - "accountIds": [
- "{accountId}"
]
}
List the Subscriptions attached to an account
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
[- {
- "id": "{subscriptionId}",
- "type": "subscription",
- "accountId": "{accountId}",
- "isVa": true,
- "isActive": true,
- "isTrial": true,
- "name": "My Subscription",
- "start": "2017-07-21T17:32:28Z",
- "tagCapacity": 50,
- "scanCapacity": 500,
- "createdAt": "2017-07-21T17:32:28Z",
- "UpdatedAt": "2017-07-21T17:32:28Z"
}
]
List Users.
accountId required | string (AccountId) [ 1 .. 50 ] characters ^[a-zA-Z0-9_-]+$ Example: {accountId} The id of the account |
[- {
- "id": "{userId}",
- "type": "user",
- "firstname": "John",
- "lastname": "Doe",
- "company": "Cintoo",
- "title": "Account Manager",
- "email": "user@example.com",
- "accountIds": [
- "{accountId}"
]
}
]
Get a User from the UserId
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 |
{- "id": "{userId}",
- "type": "user",
- "firstname": "John",
- "lastname": "Doe",
- "company": "Cintoo",
- "title": "Account Manager",
- "email": "user@example.com",
- "accountIds": [
- "{accountId}"
]
}
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}' ]
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.
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}' ]
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.
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"
}
]
To get your files call the accounts/{accountId}/projects/{projectId}/files?category=scan,model
.
Full spec about the files endpoint here.
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.
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
Our recommendation in that case would be to have
Note: the Access Token is a JWT and can easily be decoded to check the expiration date
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.