In DatoCMS, every Model can specify a completely different set of Fields, so creating a new record always depends on the schema of its model.
Generally speaking, each field requires a different type of value. It's not required the presence of all the fields in the payload. If it's easier for you to include all of them, just pass null
, as it's a valid value for every field type.
When a field is not present in the payload, or its value is null
, then the field's default value will be used (if available).
The value of the DatoCMS fields are pretty easy to guess — ie. a Single-line string requires a string, an Integer field requires a number, etc:
{// If the model has a `title` single-line string field..."name": "Alfie",// If the model has an `age` integer field..."age": 4// And so on :)}
Some other fields, like Geo-location or Color fields, require objects instead of simple data types:
{// location field:"location": { "latitude": 45.0703393, "longitude": 7.686864 },// color field:"color": { "red": 239, "green": 208, "blue": 156, "alpha": 255 }}
We'll analyze in detail every different type of field that DatoCMS offers in the following sections.
Some fields might be localized. If that's the case, records need to express a value for multiple locales using an object, whose keys represent the locale itself:
{// If the model has a `title` single-line string field..."name": {"en": "Alfie","it": "Asso"},// If the model has an `color` field..."age": {"en": { "red": 255, "green": 0, "blue": 0, "alpha": 255 },"it": { "red": 0, "green": 255, "blue": 0, "alpha": 255 }}// And so on :)}
If your model requires all environment's locales to be present, then you have to express all environment's locales for all localized fields in model. Otherwise, you can define a subset of them, as long as all localized fields express the same subset. For example:
{// We are defining only Italian locale for these two fields"name": {"it": "Asso"},"age": {"it": { "red": 0, "green": 255, "blue": 0, "alpha": 255 }}}
The field accepts String
values.
The field accepts simple String
values.
The field accepts simple Boolean
values.
The field accepts simple Integer
values.
The field accepts simple Float
values.
The field accepts String
values in ISO 8601 date format (ie. "2015-12-29"
).
The field accepts String
values in ISO 8601 date-time format (ie. "2020-04-17T16:34:31.981+01:00"
).
When sending a datetime you should keep in mind that we are ignoring the timezone by dropping it, and we'll use the project's timezone instead.
The field accepts an object with the following properties:
Property | Required | Type |
---|---|---|
red | ✅ | Integer between 0 and 255 |
green | ✅ | Integer between 0 and 255 |
blue | ✅ | Integer between 0 and 255 |
alpha | ✅ | Integer between 0 and 255 |
The field accepts String
values that are valid JSON.
The field accepts an object with the following properties:
Property | Required | Type |
---|---|---|
latitude | ✅ | Float between -90.0 to 90 |
longitude | ✅ | Float between -180.0 to 180 |
The field accepts an object with the following properties:
Property | Required | Type | Description |
---|---|---|---|
title | String | Title meta tag (max. 320 characters) | |
description | String | Description meta tag (max. 320 characters) | |
image | Upload ID | Asset to be used for social shares | |
twitter_card | "summary" , "summary_large_image" | Type of Twitter card to use |
The field accepts String
values that satisfy the following regular expression: /^[a-z0-9_]+(?:\-[a-z0-9]+)*$/
.
The field accepts an object with the following properties:
Property | Required | Type | Description | Example |
---|---|---|---|---|
provider | ✅ | "youtube" , "vimeo" , "facebook" | External video provider | "youtube" |
provider_uid | ✅ | String | Unique identifier of the video within the provider | "vUdGBEb1i9g" |
url | ✅ | URL | URL of the video | "https://www.youtube.com/watch?v=vUdGBEb1i9g" |
width | ✅ | Integer | Video width | 459 |
height | ✅ | Integer | Video height | 344 |
thumbnail_url | ✅ | URL | URL for the video thumb | "https://i.ytimg.com/vi/vUdGBEb1i9g/hqdefault.jpg" |
title | ✅ | String | Title of the video | "Next.js Conf Booth Welcoming!" |
The field accepts an object with the following properties:
Property | Required | Type | Description | Example |
---|---|---|---|---|
upload_id | ✅ | Upload ID | ID of an asset | "3429022" |
title | String | Title for the asset, if you want to override the asset's default value (see Upload default_field_metadata ) | "From my trip to Italy" | |
alt | String | Alternate text for the asset, if you want to override the asset's default value (see Upload default_field_metadata ) | "Florence skyline" | |
focal_point | { x: Float, y: Float } , null | Focal point for the asset, if you want to override the asset's default value (see Upload default_field_metadata ). Values must be expressed as Float between 0 and 1. Focal point can only be specified for image assets. | { "x": 0.34, "y": 0.45 } | |
custom_data | Record<String, String> | An object containing custom keys that you can use on your frontend projects | { "watermark_image": "true" } |
This field accepts an Array
of objects with the following properties:
Property | Required | Type | Description | Example |
---|---|---|---|---|
upload_id | ✅ | Upload ID | ID of an asset | "3429022" |
title | String | Title for the asset, if you want to override the asset's default value (see Upload default_field_metadata ) | "https://www.youtube.com/watch?v=vUdGBEb1i9g" | |
alt | String | Alternate text for the asset, if you want to override the asset's default value (see Upload default_field_metadata ) | "vUdGBEb1i9g" | |
focal_point | { x: Float, y: Float } , null | Focal point for the asset, if you want to override the asset's default value (see Upload default_field_metadata ). Values must be expressed as Float between 0 and 1. Focal point can only be specified for image assets. | { "x": 0.34, "y": 0.45 } | |
custom_data | Record<String, String> | An object containing custom keys that you can use on your frontend projects | { "watermark_image": "true" } |
This field accepts a String
representing the ID of the linked record.
This field accepts an Array<String>
representing the IDs of the linked records.
When a record is being read, this field returns an Array<String>
representing the IDs of the inner block records.
When a record is being created, this field must contain an Array
of objects representing the inner block records:
Example:
[{"type": "item","attributes": {// ... put your attributes here},"relationships": {"item_type": {"data": {// the block model"id": "435822","type": "item_type",}}},},// ...]
When a record is being updated, make sure to include the ID of the already existing block records:
[{"id": "9862639","type": "item","attributes": {// ... put your attributes here},"relationships": {"item_type": {"data": {// the block model"id": "435822","type": "item_type",}}},},// ...]
This field accepts a Structured text document.
When a record is being created, the item
attribute of block
nodes must be the entire block record instead of the ID:
Example:
{"schema": "dast","document": {"type": "root","children": [{"type": "block","item": {"type": "item","attributes": {// ... put your attributes here},"relationships": {"item_type": {"data": {// the block model"id": "435822","type": "item_type",}}},}}]},}
When a record is being updated, make sure to include the ID of the already existing block records:
{"schema": "dast","document": {"type": "root","children": [{"type": "block","item": {"id": "34823424","type": "item","attributes": {// ... put your attributes here},"relationships": {"item_type": {"data": {// the block model"id": "435822","type": "item_type",}}},}}]},}
Date of creation
Date of first publication
The record model
Suppose our project contains a "Dog" model (ID: 1234
, API key: dog
) with the following fields:
Field API key | Field type |
---|---|
name | Single-line string |
breed | Single-line string |
description | Multiple-paragraph text |
age | Integer |
We can create a new dog record like this:
const { SiteClient } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {const record = await client.items.create({itemType: "1234", // model IDname: "Gigio",breed: "Labrador",description: "Very friendly and calm.\nI love it.",age: 4,});console.log(record);}createRecord();
{id: '4572128',name: 'Gigio',breed: 'Labrador',description: 'Very friendly and calm.\nI love it.',age: 4,meta: {createdAt: '2020-04-17T16:34:31.981+01:00',updatedAt: '2020-04-17T16:34:32.005+01:00',publishedAt: '2020-04-17T16:34:32.004+01:00',firstPublishedAt: '2020-04-17T16:34:32.004+01:00',publicationScheduledAt: null,unpublishingScheduledAt: null,status: 'published',isValid: true,currentVersion: '8045084'},itemType: '1234',creator: { id: '322', type: 'access_token' }}
Suppose our project contains a "Dog" model (ID: 1234
, API key: dog
) with the following fields:
Field API key | Field type |
---|---|
name | Single-line string |
breed | Single-line string |
description | Multiple-paragraph text |
age | Integer |
height | Float |
date_of_birth | Date-time |
available | Boolean |
location | Geo-location |
color | Color |
json | JSON |
A couple of gotchas when writing our call to client.items.create()
:
You can read all the details about the value that each specific type of field requires in the Field type values section.
const { SiteClient } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {const record = await client.items.create({itemType: "1234", // model IDname: "Gigio",breed: "Labrador",description: "Very friendly and calm.\nI love it.",age: 4,height: 50.5,dateOfBirth: "2020-04-17T17:25:00",available: true,location: {latitude: 45.0703393,longitude: 7.686864,},color: {alpha: 255,blue: 156,green: 208,red: 239,},json: JSON.stringify({ additionalData: "1234" }),});console.log(record);}createRecord();
{id: '4572180',name: 'Gigio',breed: 'Labrador',description: 'Very friendly and calm.\nI love it.',age: 4,height: 50.5,dateOfBirth: '2020-04-17T17:25:00+01:00',available: true,location: { latitude: 45.0703393, longitude: 7.686864 },color: { red: 239, green: 208, blue: 156, alpha: 255 },json: '{"additionalData": "1234"}',updatedAt: '2020-04-17T16:58:27.498+01:00',createdAt: '2020-04-17T16:58:27.488+01:00',meta: {createdAt: '2020-04-17T16:58:27.488+01:00',updatedAt: '2020-04-17T16:58:27.498+01:00',publishedAt: '2020-04-17T16:58:27.498+01:00',firstPublishedAt: '2020-04-17T16:58:27.498+01:00',publicationScheduledAt: null,unpublishingScheduledAt: null,status: 'published',isValid: true,currentVersion: '8045322'},itemType: '1234',creator: { id: '322', type: 'access_token' }}
As discussed in the Field type values section, a Single asset field requires an object in the following form:
{uploadId: "1737955",alt: "Dog picture",title: "Gigio",focalPoint: {x: 0.3,y: 0.2,},customData: {addWatermark: true,},}
While the Asset gallery field requires an array of object with the same format.
All the keys except uploadId
are optional.
Suppose our project contains a "Dog" model (ID: 1234
, API key: dog
) with the following fields:
Field API key | Field type |
---|---|
name | Single-line string |
picture | Single asset |
gallery | Asset gallery |
To create a new dog record, we need to fill in both the single and multiple asset fields.
To fill in the uploadId
property of both fields, we could either reference an already-existing asset, or create a brand new Upload record.
In the following example we'll leverage the client.createUploadPath
helper to upload a new file, and then client.uploads.create
to actually create the Upload record, as discussed the Create a new upload endpoint.
const { SiteClient } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {// upload file using URL:const path = await client.createUploadPath("http://i.giphy.com/NXOF5rlaSXdAc.gif");// you can then use the returned path to create a new upload:const upload = await client.uploads.create({ path });const record = await client.items.create({itemType: "1234", // model IDname: "Gigio",picture: {// in this case we're just passing the upload ID, as the// asset's defaults for alt, title, etc. are fine:uploadId: upload.id,},gallery: [// here we want to override the asset's defaults:{uploadId: upload.id,alt: "Dog picture",title: "Gigio",focalPoint: {x: 0.3,y: 0.2,},customData: {addWatermark: true,},},],});console.log(record);}createRecord();
{id: "4725799",name: "Gigio",picture: {uploadId: "1737955",alt: null,title: null,focalPoint: null,customData: {},},gallery: [{uploadId: "1737955",alt: "Dog picture",title: "Gigio",focalPoint: {x: 0.3,y: 0.2,},customData: {},},],meta: {createdAt: "2020-05-18T14:46:26.470+01:00",updatedAt: "2020-05-18T14:46:26.484+01:00",publishedAt: "2020-05-18T14:46:26.483+01:00",firstPublishedAt: "2020-05-18T14:46:26.483+01:00",publicationScheduledAt: null,unpublishingScheduledAt: null,status: "published",isValid: true,currentVersion: "8526589",},itemType: "1234",creator: { id: "322", type: "access_token" },};
We now want to add links to other records.
Suppose our project contains a "Dog" model (ID: 1234
, API key: dog
) with the following fields:
Field API key | Field type |
---|---|
name | Single-line string |
friends | Multiple links field, referencing other dog records |
best_friend | Single link field, referencing other dog records |
As you can see, for simplicity our links point to other dog records, so that we don't need other models.
In the example we first retrieve some records and then we create a new record which references them:
const { SiteClient } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {// Let's retrieve some other dogs firstconst friends = await client.items.all({ filter: { type: "dog" } });const record = await client.items.create({itemType: "1234", // model IDname: "Gigio",friends: friends.map((f) => f.id),bestFriend: friends[0].id,});console.log(record);}createRecord();
{id: "4579273",name: "Gigio",friends: ["4572300", "4572298", "4572297", "4572180", "4572128"],bestFriend: "4572300",meta: {createdAt: "2020-04-20T11:06:29.126+01:00",updatedAt: "2020-04-20T11:06:29.150+01:00",publishedAt: "2020-04-20T11:06:29.150+01:00",firstPublishedAt: "2020-04-20T11:06:29.150+01:00",publicationScheduledAt: null,unpublishingScheduledAt: null,status: "published",isValid: true,currentVersion: "8062918",},itemType: "1234",creator: { id: "322", type: "access_token" },};
To make our dog's description more dynamic we are going to add a Modular content field. This will allow us to compose the description by combining multiple blocks of different kind. Each block model will have its set of fields and can be repeated as many times as needed.
This is our "Dog" model (ID: 1234
, API key: dog
):
Field API key | Field type |
---|---|
name | Single-line string |
description | Modular content |
The modular content field accepts three different types of blocks:
A "Prize" block model (ID: 1235
, API key: prize_block
):
Field API key | Field type |
---|---|
name | Single-line string |
year | Integer |
picture | Single asset |
A "Description" block model (ID: 1236
, API key: description_block
):
Field API key | Field type |
---|---|
description | Multi-paragraph text |
A "Gallery" block model (ID: 1237
, API key: gallery_block
):
Field API key | Field type |
---|---|
gallery | Asset gallery |
In this example we'll use the buildModularBlock()
function to help us creating blocks more easily. You just need to specify the block model ID and all the fields, just like a normal record:
const { SiteClient, buildModularBlock } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {// upload file using a local file:const path = await client.createUploadPath("./2018-10-17-194326.jpg");// you can then use the returned path to create a new upload:const upload = await client.uploads.create({ path });const record = await client.items.create({itemType: "1234", // model IDname: "Gigio",description: [// prize blockbuildModularBlock({itemType: "1235",name: "Best dog in the world",year: 2020,picture: { uploadId: upload.id },}),// description blockbuildModularBlock({itemType: "1236",description: "Very friendly and calm.\nI love it.",}),// gallery blockbuildModularBlock({itemType: "1237",gallery: [{ uploadId: upload.id }],}),],});console.log(record);}createRecord();
{id: '4579897',name: 'Gigio',description: [ '4579894', '4579895', '4579896' ],meta: {createdAt: '2020-04-20T13:38:35.972+01:00',updatedAt: '2020-04-20T13:38:36.005+01:00',publishedAt: '2020-04-20T13:38:36.004+01:00',firstPublishedAt: '2020-04-20T13:38:36.004+01:00',publicationScheduledAt: null,unpublishingScheduledAt: null,status: 'published',isValid: true,currentVersion: '8065211'},itemType: '1234',creator: { id: '322', type: 'access_token' }}
To make our dog's description more dynamic we are going to add a Structured text field. This will allow us to compose the description by combining text and blocks of different kind.
This is our "Dog" model (ID: 1234
, API key: dog
):
Field API key | Field type |
---|---|
name | Single-line string |
description | Structured text |
The structured text field accepts three different types of blocks:
A "Prize" block model (ID: 1235
, API key: prize_block
):
Field API key | Field type |
---|---|
name | Single-line string |
year | Integer |
picture | Single asset |
A "Description" block model (ID: 1236
, API key: description_block
):
Field API key | Field type |
---|---|
description | Multi-paragraph text |
A "Gallery" block model (ID: 1237
, API key: gallery_block
):
Field API key | Field type |
---|---|
gallery | Asset gallery |
In this example we'll use the buildModularBlock()
function to help us creating blocks more easily. You just need to specify the block model ID and all the fields, just like a normal record:
const { SiteClient, buildModularBlock } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {// upload file using a local file:const path = await client.createUploadPath("./2018-10-17-194326.jpg");// you can then use the returned path to create a new upload:const upload = await client.uploads.create({ path });const record = await client.items.create({itemType: "1234", // model IDname: "Gigio",description: {schema: "dast",document: {type: "root",children: [// simple header{type: "heading",level: 1,children: [{type: "span",marks: [],value: "Hello world!"}]},// prize block{type: "block",item: buildModularBlock({itemType: "1235",name: "Best dog in the world",year: 2020,picture: { uploadId: upload.id },}),},// description block{type: "block",item: buildModularBlock({itemType: "1236",description: "Very friendly and calm.\nI love it.",}),},// gallery block{type: "block",item: buildModularBlock({itemType: "1237",gallery: [{ uploadId: upload.id }],})}]}},});console.log(record);}createRecord();
{id: '4579897',name: 'Gigio',description: {schema: 'dast',document: {type: 'root',children: [{type: 'heading',level: 1,children: [{ type: 'span', marks: [], value: 'Hello world!' }]},{ type: 'block', item: '4579894', },{ type: 'block', item: '4579895', },{ type: 'block', item: '4579896' }]}},meta: {createdAt: '2020-04-20T13:38:35.972+01:00',updatedAt: '2020-04-20T13:38:36.005+01:00',publishedAt: '2020-04-20T13:38:36.004+01:00',firstPublishedAt: '2020-04-20T13:38:36.004+01:00',publicationScheduledAt: null,unpublishingScheduledAt: null,status: 'published',isValid: true,currentVersion: '8065211'},itemType: '1234',creator: { id: '322', type: 'access_token' }}
Suppose our project is set up to have two different locales ("en"
and "it"
), and contains a "Dog" model (ID: 1234
, API key: dog
) with the following fields:
Field API key | Localized | Field type |
---|---|---|
name | ✅ | Single-line string |
age | ✅ | Integer |
On localized fields, records express a value for multiple locales using an object, whose keys represent the locale itself:
const { SiteClient, buildModularBlock } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {const record = await client.items.create({itemType: "1234", // model IDname: {en: "Alfie",it: "Asso",},age: {en: 30,it: 12,},});console.log(record);}createRecord();
{id: "4668524",name: {en: "Alfie",it: "Asso",},age: {en: 30,it: 12,},meta: {createdAt: "2020-05-06T13:11:27.442+01:00",updatedAt: "2020-05-06T13:11:27.483+01:00",publishedAt: "2020-05-06T13:11:27.482+01:00",firstPublishedAt: "2020-05-06T13:11:27.482+01:00",publicationScheduledAt: null,unpublishingScheduledAt: null,status: "published",isValid: true,currentVersion: "8329850",},itemType: "1234",creator: { id: "322", type: "access_token" },}
If your model does not require all environment's locales to be present for all localized fields, then you can create a record defining only a subset of environment's locales. For example:
const { SiteClient, buildModularBlock } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecord() {const record = await client.items.create({itemType: "1234", // model IDname: {it: "Asso",},age: {it: 12,},});console.log(record);}createRecord();
{id: "4668524",name: {it: "Asso",},age: {it: 12,},meta: {createdAt: "2020-05-06T13:11:27.442+01:00",updatedAt: "2020-05-06T13:11:27.483+01:00",publishedAt: "2020-05-06T13:11:27.482+01:00",firstPublishedAt: "2020-05-06T13:11:27.482+01:00",publicationScheduledAt: null,unpublishingScheduledAt: null,status: "published",isValid: true,currentVersion: "8329850",},itemType: "1234",creator: { id: "322", type: "access_token" },}
Suppose our project contains a "Menu Item" model (ID: 1234
, API key: menu_item
) that is configured to be organized as a tree, and has a single field:
Field API key | Localized | Field type |
---|---|---|
name | ✅ | Single-line string |
In this example we'll create a hierarchy of three records.
In tree-like collections, records can specify two additional fields, parentId
and position
, so that they can express who is their parent record, and which is their position relative to its siblings:
const { SiteClient } = require("datocms-client");const client = new SiteClient("YOUR-API-TOKEN");async function createRecords() {const parent = await client.items.create({itemType: "1234",name: "Parent",});console.log(parent);const child1 = await client.items.create({itemType: "1234",name: "Child 1",parentId: parent.id,position: 1,});console.log(child1);const child2 = await client.items.create({itemType: "1234",name: "Child 2",parentId: parent.id,position: 2,});console.log(child2);}createRecords();
{id: '4679744',name: 'Parent',parentId: null,position: 1,...}{id: '4679745',name: 'Child 2',parentId: '4679744',position: 1,...}{id: '4679746',name: 'Child 1',parentId: '4679744',position: 2,...}