Content Objects 1¶
Once a Content Type has been defined in the system - the user can create Content Objects of that Content Type. This is done either directly through the API or via the convenient Content Entry tools provided within the Content Management Platform.
Note
You will need to use your Application Read and write API KEY
to perform this action
or User API KEY
scoped to accept create on the Content Type you wish to add.
Read more about API keys and scoped API keys.
Creating Content Objects through the API¶
For a Content Type
defined according to the create Content Type example, a very simple POST
payload can be sent
to the supporting endpoint https://api.flotiq.com/api/v1/content/{name}
(where name
is the name of the content type definition) to create a new Content Object:
{
"title": "New object",
"postContent": "This will be the new <b>content</b>"
}
Note
The maximum size of a single CO in the system is 1MB. If your project requires a larger CO size, please contact Flotiq support.
Note
You can send custom id
in the object data to assign a particular id
to the object.
Id must match a regular expression ^[a-zA-Z0-9-_.,:=!#$%&(\
\’{}\" ]*$.
Random
idwill be assigned when the
id` property is not present in the object.
Note
Content object's id
in endpoint https://api.flotiq.com/api/v1/content/contenttype/{id}
is case insensitive.
Example
curl --location --request POST 'https://api.flotiq.com/api/v1/content/blogposts' \
--header 'X-AUTH-TOKEN: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--data-raw '{
"title": "New object",
"postContent": "This will be the new <b>content</b>"
}'
var client = new RestClient("https://api.flotiq.com/api/v1/content/blogposts");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddHeader("X-AUTH-TOKEN", "YOUR_API_KEY");
request.AddParameter("application/json", "{\"title\":\"New object\",\"postContent\":\"This will be the new <b>content</b>\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.flotiq.com/api/v1/content/blogposts"
payload := strings.NewReader("{\"title\":\"New object\",\"postContent\":\"This will be the new <b>content</b>\"}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("content-type", "application/json")
req.Header.Add("X-AUTH-TOKEN", "YOUR_API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"title\":\"New object\",\"postContent\":\"This will be the new <b>content</b>\"}");
Request request = new Request.Builder()
.url("https://api.flotiq.com/api/v1/content/blogposts")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("X-AUTH-TOKEN", "YOUR_API_KEY")
.build();
Response response = client.newCall(request).execute();
HttpResponse<String> response = Unirest.post("https://api.flotiq.com/api/v1/content/blogposts")
.header("content-type", "application/json")
.header("X-AUTH-TOKEN", "YOUR_API_KEY")
.body("{\"title\":\"New object\",\"postContent\":\"This will be the new <b>content</b>\"}")
.asString();
const request = require('request');
const options = {
method: 'POST',
url: 'https://api.flotiq.com/api/v1/content/blogposts',
headers: {'content-type': 'application/json', 'X-AUTH-TOKEN': 'YOUR_API_KEY'},
body: {title: 'New object', postContent: 'This will be the new <b>content</b>'},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.flotiq.com/api/v1/content/blogposts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"title\":\"New object\",\"postContent\":\"This will be the new <b>content</b>\"}",
CURLOPT_HTTPHEADER => [
"X-AUTH-TOKEN: YOUR_API_KEY",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Response
Returned when data has been correct, and the object was saved
{
"id": "blogposts-456712",
"internal": {
"contentType": "blogposts",
"createdAt": "2021-04-09T13:30:48+00:00",
"updatedAt": "2021-04-09T13:30:48+00:00",
"deletedAt": ""
},
"title": "New object",
"postContent": "This will be the new <b>content</b>"
}
Returned when data has not been correct, and the object was not saved
{
"id": [
"This value is already used",
"Must be at least 1 characters long",
],
"title": [
"The property title is required",
"Must be at least 1 characters long",
"The property title is required"
],
"postContent": [
"The property postContent is required",
"Must be at least 1 characters long",
"The property postContent is required"
]
}
Returned when API key was missing or incorrect
{
"code": 401,
"massage": "Unauthorized"
}
Returned when content type definition wasn't found
{
"code": 404,
"massage": "Not found"
}
Returned when the size of the object exceeds the limit allowed in Flotiq (1MB, except Custom plan)
{
"code": 413,
"massage": "Content Object size limit exceeded by an object with ID: 185. Requested size 1.01 MB, limit: 1 MB)"
}
Possible validation errors¶
Error | Description |
---|---|
This value is already used | Send when the property has to be unique, and the value is already used in an existing object of that type |
Must be at least 1 characters long | Send when the property is required, and an empty string was sent in object |
The property {name} is required | Send when the property is required and was missing in the sent object |
String value found, but a number is required | Send when the type of the property is number and string was sent |
The value does not match possible options | Send when sent value do not match options in select and radio type |
Does not match the regex pattern {pattern} | Send when the value does not match regex pattern specified for the property |
This value does not exist in database | Send when object attached in relation or media array does not exist in the database |
One of the block types ({block type} on index {index}) does not match possible types | Send when one of the types in the property of the type block does not match types specified in the schema |
Creating Content Objects with relations to other types or media¶
To add objects with relations, you need to know ids and types of related objects.
Relations are always an array, even if only one relation object is allowed.
Order of relation object is preserved.
Every relation object have to have type
property (now only internal
is possible),
and dataUrl
property containing relative url to the object (/api/v1/content/{type}/{id}
).
Example
"relation": [
{
"dataUrl": "/api/v1/content/test/test-1",
"type": "internal"
}
]
"media": [
{
"dataUrl": "/api/v1/content/_media/_media-1",
"type": "internal"
},
{
"dataUrl": "/api/v1/content/_media/_media-2",
"type": "internal"
}
]
Creating Content Objects with the editor.js blocks¶
Blocks contain json definitions of the html blocks instead of the real html blocks to make sure that the data will be displayed correctly in every environment (developer can manage them correctly in the standard React and React Native for example).
Block parameters:
Parameter | Required | Description |
---|---|---|
id | true | Random identifier of the block |
data | true | Data of the block, the parameters depend on the type of the block |
type | true | Type of the block, the supported types are paragraph , header , list , image , youtubeEmbed , quote , warning , code , table and delimiter , types can be narrowed down in schema |
tunes | false | Additional settings of the block, parameters depend on the type of the block |
Blocks:
Paragraph
Contains standard text with limited text formatting (bolding, italicizing, alignment). Type: paragraph
.
Data parameters:
Parameter | Required | Description |
---|---|---|
text | true | Content of the paragraph, it can contain html formatting (<b></b> for bolding and <i></i> for italicizing) |
Tunes parameters:
Parameter | Required | Description |
---|---|---|
alignmentTuneTool | true | Information obout text alignment in the whole paragraph. |
alignmentTuneTool parameters:
Parameter | Required | Description |
---|---|---|
alignment | true | Information about text alignment in the whole paragraph. Possible values: left , center , right |
{
"id": "i5RZbGlOWy",
"data": {
"text": "<b>Exaple</b> <i>paragraph </i>with formatting"
},
"type": "paragraph",
"tunes": {
"alignmentTuneTool": {
"alignment": "left"
}
}
}
Header
Contains standard header text with limited text formatting (bolding, italicizing, alignment). Type: header
.
Data parameters:
Parameter | Required | Description |
---|---|---|
text | true | Content of the header, it can contain html formatting (<b></b> for bolding and <i></i> for italicizing) |
level | true | Level of the header. Possible values 1 , 2 , 3 , 4 , 5 , 6 . |
anchor | false | Name of the navigation anchor fo the header |
Tunes parameters:
Parameter | Required | Description |
---|---|---|
alignmentTuneTool | true | Information obout text alignment in the whole header. |
alignmentTuneTool parameters:
Parameter | Required | Description |
---|---|---|
alignment | true | Information about text alignment in the whole header. Possible values: left , center , right |
{
"id": "dPSax4QzPU",
"data": {
"text": "Example level 2 header",
"level": 2,
"anchor": "anchor"
},
"type": "header",
"tunes": {
"alignmentTuneTool": {
"alignment": "center"
}
}
}
List
Contains nested lists with limited text formatting (bolding, italicizing). Type: list
.
Data parameters:
Parameter | Required | Description |
---|---|---|
items | true | Items of the list |
style | true | Style of the list. Possible values ordered , unordered . |
Items parameters:
Parameter | Required | Description |
---|---|---|
items | true | Items of the sublist |
content | true | Text of the liust item, it can contain html formatting (<b></b> for bolding and <i></i> for italicizing) |
{
"id": "oCJRGb2FFb",
"data": {
"items": [
{
"items": [
{
"items": [],
"content": "Example <i>list</i>"
}
],
"content": "Exaple list"
}
],
"style": "ordered"
},
"type": "list"
}
Image
Contains image from Flotiq Media Library. Type: image
.
Data parameters:
Parameter | Required | Description |
---|---|---|
url | true | Url to full size file |
width | true | Width of the image |
height | true | Height of the image |
fileName | true | Name of the file |
extension | true | File extension |
caption | true | File caption |
stretched | true | Information whether the image should be stretched to full display width |
withBorder | true | Information whether the image should have border |
withBackground | true | Information whether the image should have background |
{
"id": "zX1gTCKJee",
"data": {
"url": "https://api.flotiq.com/image/0x0/_media-1bb7c3ad-53de-4029-a5a0-3500f9b8867e.png",
"width": 317,
"height": 265,
"caption": "Example Caption",
"fileName": "example.png",
"extension": "png",
"stretched": true,
"withBorder": true,
"withBackground": true
},
"type": "image"
}
Quote
Contains the quote with the caption. Type: quote
.
Data parameters:
Parameter | Required | Description |
---|---|---|
text | true | Text of the quote |
caption | true | Caption of the quote |
text | true | Alignment of the quote. Possible values: left , center |
{
"id": "V7WlZmeTuJ",
"data": {
"text": "Example quote",
"caption": "Example quote caption",
"alignment": "left"
},
"type": "quote"
}
Warning
Contains the warning with the name. Type: warning
.
Data parameters:
Parameter | Required | Description |
---|---|---|
message | true | Text of the warning |
title | true | Title of the warning |
{
"id": "sVDwJq9ZCe",
"data": {
"title": "Exaple warning name",
"message": "Example warning message"
},
"type": "warning"
}
Delimiter
Contains the information that displaying application should display delimiter, without other fomatting.
Type: delimiter
.
Data have to be empty object.
{
"id": "dPSax4QzPU",
"data": {},
"type": "delimiter"
}
Code
Contains the code block. Type: code
.
Data parameters:
Parameter | Required | Description |
---|---|---|
code | true | Code block |
{
"id": "sVDwJq9ZCf",
"data": {
"code": "npm run dev",
},
"type": "code"
}
Table
Contains the table. Type: table
.
Data parameters:
Parameter | Required | Description |
---|---|---|
content | true | Array of arrays of data in rows, every row is an array of srings |
withHeadings | true | Information if the first row should be treated as header |
{
"id": "sVDwJq9ZCg",
"data": {
"content": [
[
"First header",
"Second header",
"Third header"
],
[
"First column of the first row",
"Second column of the first row",
"Third column of the first row"
],
[
"First column of the second row",
"Second column of the second row",
"Third column of the second row"
]
],
"withHeadings": true
},
"type": "table"
}
If we are missing a block type or tune that you require for your project, please leave a comment below or contact us on hello@flotiq.com.
Example of an object containing all property types
This example represents object for Content Type with every type of property, described here
{
"id": "example-1",
"geo": {
"lat": 0,
"lon": 0
},
"date": "2021-12-12T12:00",
"list": [
{
"geo_in_subobject": {
"lat": 0,
"lon": 0
},
"date_in_subobject": "2021-12-12T12:00",
"text_in_subobject": "text_in_subobject",
"block_in_subobject": {
"time": "1624628260",
"version": "2.22.0",
"blocks": [
{
"id": "dPSax4QzPU",
"data": {
"text": "Example level 2 header",
"level": 2,
"anchor": "anchor"
},
"type": "header",
"tunes": {
"alignmentTuneTool": {
"alignment": "center"
}
}
},
{
"id": "i5RZbGlOWy",
"data": {
"text": "<b>Exaple</b> <i>paragraph </i>with formatting"
},
"type": "paragraph",
"tunes": {
"alignmentTuneTool": {
"alignment": "left"
}
}
},
{
"id": "oCJRGb2FFb",
"data": {
"items": [
{
"items": [
{
"items": [],
"content": "Example <i>list</i>"
}
],
"content": "Exaple list"
}
],
"style": "ordered"
},
"type": "list"
},
{
"id": "XB_EtsgceZ",
"data": {
"items": [
{
"items": [
{
"items": [],
"content": "Example bullet list"
}
],
"content": "Example bullet <b>list</b>"
}
],
"style": "unordered"
},
"type": "list"
},
{
"id": "zX1gTCKJee",
"data": {
"url": "https://api.flotiq.com/image/0x0/_media-1bb7c3ad-53de-4029-a5a0-3500f9b8867e.png",
"width": 317,
"height": 265,
"caption": "Example Caption",
"fileName": "example.png",
"extension": "png",
"stretched": true,
"withBorder": true,
"withBackground": true
},
"type": "image"
},
{
"id": "JIRwiQdzs9",
"data": {
"url": "https://www.youtube.com/watch?v=hz3RK5qqhrQ"
},
"type": "youtubeEmbed"
},
{
"id": "V7WlZmeTuJ",
"data": {
"text": "Example quote",
"caption": "Example quote caption",
"alignment": "left"
},
"type": "quote"
},
{
"id": "sVDwJq9ZCe",
"data": {
"title": "Exaple warning name",
"message": "Example warning message"
},
"type": "warning"
},
{
"id": "RTJ0lo2VGB",
"data": [],
"type": "delimiter"
},
{
"id": "sVDwJq9ZCf",
"data": {
"code": "npm run dev",
},
"type": "code"
},
{
"id": "sVDwJq9ZCg",
"data": {
"content": [
[
"First header",
"Second header",
"Third header"
],
[
"First column of the first row",
"Second column of the first row",
"Third column of the first row"
],
[
"First column of the second row",
"Second column of the second row",
"Third column of the second row"
]
],
"withHeadings": true
},
"type": "table"
}
]
},
"emain_in_subobject": "emain_in_subobject",
"media_in_subobject": [
{
"dataUrl": "/api/v1/content/_media/_media-1",
"type": "internal"
}
],
"radio_in_subobject": "radio_in_subobject",
"number_in_subobject": 0,
"select_in_subobject": "Option a",
"checkbox_in_subobject": false,
"markdown_in_subobject": "markdown_in_subobject",
"relation_in_subobject": [
{
"dataUrl": "/api/v1/content/test/test-1",
"type": "internal"
}
],
"textarea_in_subobject": "textarea_in_subobject",
"rich_text_in_subobject": "rich_text_in_subobject"
}
],
"text": "text",
"block": {
"time": "1624628260",
"version": "2.22.0",
"blocks": [
{
"id": "dPSax4QzPU",
"data": {
"text": "Example level 2 header",
"level": 2,
"anchor": "anchor"
},
"type": "header",
"tunes": {
"alignmentTuneTool": {
"alignment": "center"
}
}
},
{
"id": "i5RZbGlOWy",
"data": {
"text": "<b>Exaple</b> <i>paragraph </i>with formatting"
},
"type": "paragraph",
"tunes": {
"alignmentTuneTool": {
"alignment": "left"
}
}
},
{
"id": "oCJRGb2FFb",
"data": {
"items": [
{
"items": [
{
"items": [],
"content": "Example <i>list</i>"
}
],
"content": "Exaple list"
}
],
"style": "ordered"
},
"type": "list"
},
{
"id": "XB_EtsgceZ",
"data": {
"items": [
{
"items": [
{
"items": [],
"content": "Example bullet list"
}
],
"content": "Example bullet <b>list</b>"
}
],
"style": "unordered"
},
"type": "list"
},
{
"id": "zX1gTCKJee",
"data": {
"url": "https://api.flotiq.com/image/0x0/_media-1bb7c3ad-53de-4029-a5a0-3500f9b8867e.png",
"width": 317,
"height": 265,
"caption": "Example Caption",
"fileName": "example.png",
"extension": "png",
"stretched": true,
"withBorder": true,
"withBackground": true
},
"type": "image"
},
{
"id": "JIRwiQdzs9",
"data": {
"url": "https://www.youtube.com/watch?v=hz3RK5qqhrQ"
},
"type": "youtubeEmbed"
},
{
"id": "V7WlZmeTuJ",
"data": {
"text": "Example quote",
"caption": "Example quote caption",
"alignment": "left"
},
"type": "quote"
},
{
"id": "sVDwJq9ZCe",
"data": {
"title": "Exaple warning name",
"message": "Example warning message"
},
"type": "warning"
},
{
"id": "RTJ0lo2VGB",
"data": [],
"type": "delimiter"
},
{
"id": "sVDwJq9ZCf",
"data": {
"code": "npm run dev",
},
"type": "code"
},
{
"id": "sVDwJq9ZCg",
"data": {
"content": [
[
"First header",
"Second header",
"Third header"
],
[
"First column of the first row",
"Second column of the first row",
"Third column of the first row"
],
[
"First column of the second row",
"Second column of the second row",
"Third column of the second row"
]
],
"withHeadings": true
},
"type": "table"
}
]
},
"email": "email",
"media": [
{
"dataUrl": "/api/v1/content/_media/_media-1",
"type": "internal"
}
],
"radio": "Option 1",
"number": 0,
"select": "Option 1",
"checkbox": false,
"markdown": "markdown",
"relation": [
{
"dataUrl": "/api/v1/content/test/test-1",
"type": "internal"
}
],
"textarea": "textarea",
"rich_text": "rich_text"
}
Batch create Content Objects through API¶
There is a way to add up to 1002 Content Objects at once.
It is possible by using the /batch
endpoint
(in our example, the URL would be https://api.flotiq.com/api/v1/content/blogposts/batch
).
It can be only insert
or insert or update
operation. To use insert or update
you need to set updateExisting
to true
in the query.
All objects must meet the same conditions as when adding a single object. The only difference is an array of objects in the request body instead of one object.
Note
In the next examples we assume that we have an object with id existing-id-1
in our system.
Updating one blog post and adding one new:
Example
curl 'https://api.flotiq.com/api/v1/content/blogposts/batch?updateExisting=true' -H 'accept: application/json' -H 'X-AUTH-TOKEN: YOUR_API_TOKEN' -H 'Content-Type: application/json' --data-binary '[{"id":"existing-id-1","title":"Updated object","postContent":"This will be the updated <b>content</b>"},{"id":"new-object-1","title":"New object 2","postContent":"This will be the brand new <b>content</b>"}]'
response (code: 200):
{
"batch_total_count": 2,
"batch_success_count": 2,
"batch_error_count": 0,
"errors": []
}
Trying updating one blog post and adding one new with wrong data:
Example
curl 'https://api.flotiq.com/api/v1/content/blogposts/batch?updateExisting=true' -H 'accept: application/json' -H 'X-AUTH-TOKEN: YOUR_API_TOKEN' -H 'Content-Type: application/json' --data-binary '[{"id":"existing-id-1","title":"Updated object"},{"id":"new-object-2","title":"New object 3","postContent":"This will be the brand new <b>content</b>"}]'
response (code: 400):
{
"batch_total_count": 2,
"batch_success_count": 1,
"batch_error_count": 1,
"errors": [
{
"data": {
"id": "existing-id-1",
"title": "Updated object"
},
"errors": {
"postContent": [
"The property postContent is required"
]
}
}
]
}
Trying updating one blog post and adding one new with duplicated id:
Example
curl 'https://api.flotiq.com/api/v1/content/blogposts/batch?updateExisting=true' -H 'accept: application/json' -H 'X-AUTH-TOKEN: YOUR_API_TOKEN' -H 'Content-Type: application/json' --data-binary '[{"id":"example-id-1","title":"New object","content": "This will be the new <b>content</b>"},{"id":"example-id-1","title":"New object 2","postContent":"This will be the brand new <b>content</b>"}]'
response (code: 400):
{
"batch_total_count": 2,
"batch_success_count": 1,
"batch_error_count": 2,
"errors": [
{
"data": {
"id": "example-id-1",
"title": "New object",
"content": "This will be the new <b>content</b>"
},
"errors": {
"id": [
"There are duplications in object data, key: id"
]
}
}
]
}
Response parameters:
Parameter | Description |
---|---|
batch_total_count | number of elements sent in the request, present when there are no duplications in data |
batch_success_count | number of correct elements sent in the request, present when there are no duplications in data |
batch_error_count | number of incorrect elements sent in the request, present when there are no duplications in data |
batch_limit | max number of elements sent in a single request, present when the limit is exceeded |
errors | array of errors in the elements, errors are objects containing the id of the object and list of errors, present when there are no duplications in data |
data | listing keys containing duplications (see example above), present only when there are duplications in data or batch_limit exceeded |
Register to start creating your content objects
-
Number of available Content Objects depends on the chosen subscription plan. Check pricing and limits on the Flotiq Pricing page ↩
-
Limit can be changed in the Custom plan ↩