The Craftnote Public API allows you to manage data in Craftnote via HTTP REST.
You can explore the API via the included Open API 3.0 definition. Simply navigate to editor.swagger.io, press File ▸ Import URL and enter the URL of the Open API definition.
You will need to authenticate to the API via the X-CN-API-KEY
header. Make sure to include this header on all requests.
An API Key can be created in the API Keys section of the Craftnote settings by an owner of the company.
In addition to this API key, future versions of the Craftnote Public API will need a client ID that has to be send via the X-CN-CLIENT-ID
header and can be obtained by contacting Craftnote via schnittstelle@craftnote.de.
All entities are identified by version 4 UUIDs such as:
6FEB205E-E5F7-41C5-8BE7-9DBC8DA13998
or other alphanumeric IDs, such as
Ka3gh32ashtQJuuas9
Pagination is a way of accessing a list of data in smaller chunks which requires less memory on server and client, and fewer data to be transferred over the network. The default pagination mode of the Craftnote Public API is an offset-based pagination. Alternatively you can use token based pagination which brings some advantages over the offset-based variant. In order to understand how each of the pagination modes work let's look at a small example.
Let's consider the following projects:
GET /projects
{
"projects": [
{ "id": "a" },
{ "id": "b" },
{ "id": "c" },
{ "id": "d" },
{ "id": "e" },
{ "id": "f" },
{ "id": "g" },
{ "id": "h" },
{ "id": "i" },
{ "id": "j" },
{ "id": "k" }
]
}
With offset-based pagination you can control the number of items to skip, using the offset
parameter, and the maxmimum number of items to return using the limit
parameter.
So setting offset
to 2
and limit
to 5
would yield the following result:
GET /projects?offset=2&limit=5
{
"projects": [
{ "id": "c" },
{ "id": "d" },
{ "id": "e" },
{ "id": "f" },
{ "id": "g" }
]
}
If offset is omitted, it defaults to 0
. Items are always returned sorted ascending by ID.
The main issue with offset-based pagination is that if data is added or deleted while querying it can lead to items appearing multiple times, or even not be included at all. A solution to overcome this limitation is token-based pagination.
Token-based pagination needs to be enabled by sending the paginationMode=token
query parameter. While offset-based pagination simply uses object counts, token-based pagination assumes that each object has a unique ID and uses these IDs to identify the objects to skip.
Setting the query parameters limit
to 5
and startAfter
to c
, we get the following projects:
GET /projects?paginationMode=token&startAfter=c&limit=5
{
"projects": [
{ "id": "d" },
{ "id": "e" },
{ "id": "f" },
{ "id": "g" },
{ "id": "h" }
]
}
startAfter
always points to the ID of the last item to skip. If it is omitted, items will be returned from the start (here id "a"
).
limit
works the same way as with offset-based pagination and limits the number of items returned.
Items are always returned sorted ascending by ID.
A member is the representation of a user in a project or company. Example
{
"id": "Ka3gh32ashtQJuuas9",
"email": "cf@gauss.de",
"mobile": "+49-171-174282137",
"name": "Carl-Friedrich",
"lastname": "Gauss"
}
Craftnote is modelled around the concept of projects. A project has an address, contacts, members. There are two different types of projects: folder projects and normal (project) projects.
- Normal projects (
projectType: PROJECT
) have a project chat and a file share section. - Folder projects (
projectType: FOLDER
) can be used to organize projects and can contain other projects or project folders.
Folders keep links to their contained projects with the field projects
that contains IDs of other projects or folders.
Example
{
"id": "03AE0AA1-B699-4A9C-85BE-30328897446B",
"name": "MyFirstProject",
"projectType": "FOLDER",
"orderNumber": "12312344d",
"street": "Unter den Linden",
"zipcode": "01234",
"city": "Berlin",
"contacts": [
{
"name": "Max Mustermann",
"emails": ["mm@test.de"],
"phones": ["+49 711 21893732"]
}
],
"billingCity": "Berlin",
"parentProject": "DB5B9A4D-7589-4AF4-8C79-A96A3B796DC9"
}
Please refer to the swagger definition for a full list of available fields.
A project of type projectType: project
has a file section where users can upload files. Like with projects, files can organized in folders.
Folders are special files with a special type.
File types:
type: FOLDER
a folder that can contain other folders or files.type: DOCUMENT
a generic document, such as PDF.type: IMAGE
an image such as a .png or .jpeg file.type: VIDEO
a video.type: AUDIO
an audio message.
The folder of a file is referenced via the folderId
field.
Example
{
"id": "6FEB205E-E5F7-41C5-8BE7-9DBC8DA13998",
"projectId": "DB5B9A4D-7589-4AF4-8C79-A96A3B796DC9",
"name": "Projektbericht.pdf",
"folderId": "7A082960-E44C-4B67-AAB0-294BFB3F5095",
"type": "DOCUMENT",
"creationTimestamp": 1567685998,
"size": 2450
}
A deeplink is a collection of links that can be used to access a specific section from the mobile app or the website. Example
{
"webLink": "https://app.mycraftnote.de/#/project?id=0DDAAAA9-2508-4AAF-A576-E91E76EA8CDB",
"appDeepLink": "mycrafty://project?id=0DDAAAA9-2508-4AAF-A576-E91E76EA8CDB"
}
GET /company/members
{
"members": [
{
"id": "Ka3gh32ashtQJuuas9",
"email": "cf@gauss.de",
"mobile": "+49-171-174282137",
"name": "Carl-Friedrich",
"lastname": "Gauss"
}
]
}
GET /company/members/me
{
"id": "Ka3gh32ashtQJuuas9",
"email": "cf@gauss.de",
"mobile": "+49-171-174282137",
"name": "Carl-Friedrich",
"lastname": "Gauss"
}
This endpoint returns the member that belongs to the provided API key.
GET /projects
{
"projects": [
{
"id": "03AE0AA1-B699-4A9C-85BE-30328897446B",
"name": "MyProject",
"projectType": "FOLDER",
"orderNumber": "12312344d",
"street": "Unter den Linden",
"zipcode": "10234",
"city": "Berlin",
"contacts": [
{
"name": "Max Mustermann",
"emails": ["mm@test.de"],
"phones": ["+49 711 21893732"]
}
],
"billingCity": "Berlin",
"parentProject": "46B6D771-492E-4841-8D0C-012328BB1031",
"archived": false
},
{
"id": "46B6D771-492E-4841-8D0C-012328BB1031",
"name": "MyFolder",
"creationDate": 1568133915,
"projectType": "FOLDER",
"projects": [
"03AE0AA1-B699-4A9C-85BE-30328897446B"
],
"archived": true
}
]
}
The archived
flag shows if a project is archived for all non-external members.
GET /projects/03AE0AA1-B699-4A9C-85BE-30328897446B
{
"id": "03AE0AA1-B699-4A9C-85BE-30328897446B",
"name": "MyProject",
"projectType": "FOLDER",
"orderNumber": "12312344d",
"street": "Unter den Linden",
"zipcode": "10234",
"city": "Berlin",
"contacts": [
{
"name": "Max Mustermann",
"emails": ["mm@test.de"],
"phones": ["+49 711 21893732"]
}
],
"billingCity": "Berlin",
"parentProject": "46B6D771-492E-4841-8D0C-012328BB1031",
"archived": false
}
GET /projects/03AE0AA1-B699-4A9C-85BE-30328897446B/deeplink
{
"webLink": "https://app.mycraftnote.de/#/project?id=0DDAAAA9-2508-4AAF-A576-E91E76EA8CDB",
"appDeepLink": "mycrafty://project?id=0DDAAAA9-2508-4AAF-A576-E91E76EA8CDB"
}
POST /projects
{
"name": "MyProject",
"projectType": "FOLDER",
"orderNumber": "12312344d",
"street": "Unter den Linden",
"zipcode": "10234",
"city": "Berlin",
"contacts": [
{
"name": "Max Mustermann",
"emails": ["mm@test.de"],
"phones": ["+49 711 21893732"]
}
],
"billingCity": "Berlin",
"parentProject": "46B6D771-492E-4841-8D0C-012328BB1031"
}
PUT /projects/03AE0AA1-B699-4A9C-85BE-30328897446B
{
"name": "My Changed name",
"projectType": "FOLDER",
"orderNumber": "12312344d",
"street": "Unter den Linden",
"zipcode": "10234",
"city": "Berlin",
"contacts": [
{
"name": "Max Mustermann",
"emails": ["mm@test.de"],
"phones": ["+49 711 21893732"]
}
],
"billingCity": "Berlin",
"parentProject": "46B6D771-492E-4841-8D0C-012328BB1031"
}
You can archive projects for all non-external members by setting the archived
flag in an update request:
...
"archived": true
...
GET /projects/03AE0AA1-B699-4A9C-85BE-30328897446B/members
{
"members": [
{
"id": "Ka3gh32ashtQJuuas9",
"email": "cf@gauss.de",
"mobile": "+49-171-174282137",
"name": "Carl-Friedrich",
"lastname": "Gauss"
}
]
}
POST /projects/03AE0AA1-B699-4A9C-85BE-30328897446B/members
{
"userId": "Ka3gh32ashtQJuuas9"
}
DELETE /projects/03AE0AA1-B699-4A9C-85BE-30328897446B/members/Ka3gh32ashtQJuuas9
INFO: This manages project files. Please be aware that a project also has a chat section which can have files. These files are not managed with the followin endpoints.
GET /projects/DB5B9A4D-7589-4AF4-8C79-A96A3B796DC9/files
{
"files": [
{
"id": "7811C21D-AC17-479F-9C2D-D6AC6AF0F1C0",
"name": "myImage.jpg",
"projectId": "DB5B9A4D-7589-4AF4-8C79-A96A3B796DC9",
"folderId": "7A082960-E44C-4B67-AAB0-294BFB3F5095",
"type": "IMAGE",
"creationTimestamp": 1568133879,
"lastModifiedTimestamp": 1568133879,
},
{
"id": "7A082960-E44C-4B67-AAB0-294BFB3F5095",
"name": "myImage.jpg",
"projectId": "DB5B9A4D-7589-4AF4-8C79-A96A3B796DC9",
"folderId": null,
"type": "FOLDER",
"creationTimestamp": 1568133879,
"lastModifiedTimestamp": 1568133879,
}
]
}
GET /files/7811C21D-AC17-479F-9C2D-D6AC6AF0F1C0
{
"id": "7811C21D-AC17-479F-9C2D-D6AC6AF0F1C0",
"name": "myImage.jpg",
"projectId": "DB5B9A4D-7589-4AF4-8C79-A96A3B796DC9",
"folderId": "7A082960-E44C-4B67-AAB0-294BFB3F5095",
"type": "IMAGE",
"creationTimestamp": 1568133879
}
GET /files/7811C21D-AC17-479F-9C2D-D6AC6AF0F1C0?download=true
...
POST /projects/DB5B9A4D-7589-4AF4-8C79-A96A3B796DC9/files
type=image
name=myImage
file=<image.png>
PUT /files/7811C21D-AC17-479F-9C2D-D6AC6AF0F1C0
type=image
file=<image.png>