Show examples in:
Javascript HTTP

Content Management API > Upload

Create a new upload

⚠️ We highly advocate for utilizing our JavaScript client when uploading new assets, as it comes equipped with high-level helper methods that handle all the nitty-gritty for you.

Uploading a new asset to a DatoCMS project manually is a process that necessitates several HTTP calls. This approach significantly accelerates the upload process for DatoCMS, as it eliminates the need for us to act as an intermediary between you, the user aiming to upload an asset, and the storage bucket.

First, send a POST request to the /upload-requests endpoint to obtain the location on which to perform the physical file upload:

1
POST https://site-api.datocms.com/upload-requests HTTP/1.1
2
Authorization: Bearer YOUR-API-TOKEN
3
Accept: application/json
4
X-Api-Version: 3
5
Content-Type: application/vnd.api+json
6
7
{
8
"data": {
9
"type": "upload_request",
10
"attributes": {
11
"filename": "image.png"
12
}
13
}
14
}
Terminal window
1
curl -g 'https://site-api.datocms.com/upload-requests' \
2
-X POST \
3
-H "Authorization: Bearer YOUR-API-TOKEN" \
4
-H "Accept: application/json" \
5
-H "X-Api-Version: 3" \
6
-H "Content-Type: application/vnd.api+json" \
7
--data-binary '{"data":{"type":"upload_request","attributes":{"filename":"image.png"}}}'
1
await fetch("https://site-api.datocms.com/upload-requests", {
2
method: "POST",
3
headers: {
4
Authorization: "Bearer YOUR-API-TOKEN",
5
Accept: "application/json",
6
"X-Api-Version": "3",
7
"Content-Type": "application/vnd.api+json",
8
},
9
body: JSON.stringify({
10
data: { type: "upload_request", attributes: { filename: "image.png" } },
11
}),
12
});
1
HTTP/1.1 202 Accepted
2
Content-Type: application/json
3
Cache-Control: cache-control: max-age=0, private, must-revalidate
4
X-RateLimit-Limit: 30
5
X-RateLimit-Remaining: 28
6
7
{
8
"data": {
9
"type": "upload_request",
10
"id": "/7/1455102967-image.png",
11
"attributes": {
12
"url": "https://dato-images.s3.eu-west-1.amazonaws.com/205/1565776891-image.png?x-amz-acl=public-read&...",
13
"request_headers": {
14
"X-Foo": "bar"
15
}
16
}
17
}
18
}

Now it is possible to use the obtained information to build an HTTP request that effectively uploads the file:

  • The HTTP method MUST be PUT
  • The URL is the one specified in the url attribute of the previous response
  • Each header specified in the request_headers attribute of the previous response MUST be set as a request header
  • It is possible to add a Content-Type header to specify the type of file being uploaded
  • The content of the file must be inserted as the raw body of the request (no multipart upload)
1
PUT https://dato-images.s3.eu-west-1.amazonaws.com/205/1565776891-image.png?x-amz-acl=public-read&... HTTP/1.1
2
Content-Type: image/png
3
X-Foo: bar
4
5
<YOUR_FILE_BINARY_CONTENT>
Terminal window
1
curl -g 'https://dato-images.s3.eu-west-1.amazonaws.com/205/1565776891-image.png?x-amz-acl=public-read&...' \
2
-X PUT \
3
-H "Content-Type: image/png" \
4
-H "X-Foo: bar" \
5
--data-binary '<YOUR_FILE_BINARY_CONTENT>'
1
await fetch(
2
"https://dato-images.s3.eu-west-1.amazonaws.com/205/1565776891-image.png?x-amz-acl=public-read&...",
3
{
4
method: "PUT",
5
headers: { "Content-Type": "image/png", "X-Foo": "bar" },
6
body: "<YOUR_FILE_BINARY_CONTENT>",
7
},
8
);
1
HTTP/1.1 202 Accepted
2
X-Amz-Request-Rd: XXX
3
Server: AmazonS3
4
5
{
6
"data": {
7
"type": "job",
8
"id": "4235"
9
}
10
}

Make a POST request to the /uploads endpoint with the path being the ID of the request made on step 1.

1
POST https://site-api.datocms.com/uploads HTTP/1.1
2
Authorization: Bearer YOUR-API-TOKEN
3
Accept: application/json
4
X-Api-Version: 3
5
Content-Type: application/vnd.api+json
6
7
{
8
"data": {
9
"type": "upload",
10
"attributes": {
11
"path": "/205/1565776891-image.png",
12
"author": "Mark",
13
"copyright": "2020 DatoCMS",
14
"default_field_metadata": {
15
"en": {
16
"alt": "Nyan the cat",
17
"title": "My cat",
18
"custom_data": {}
19
}
20
}
21
}
22
}
23
}
Terminal window
1
curl -g 'https://site-api.datocms.com/uploads' \
2
-X POST \
3
-H "Authorization: Bearer YOUR-API-TOKEN" \
4
-H "Accept: application/json" \
5
-H "X-Api-Version: 3" \
6
-H "Content-Type: application/vnd.api+json" \
7
--data-binary '{"data":{"type":"upload","attributes":{"path":"/205/1565776891-image.png","author":"Mark","copyright":"2020 DatoCMS","default_field_metadata":{"en":{"alt":"Nyan the cat","title":"My cat","custom_data":{}}}}}}'
1
await fetch("https://site-api.datocms.com/uploads", {
2
method: "POST",
3
headers: {
4
Authorization: "Bearer YOUR-API-TOKEN",
5
Accept: "application/json",
6
"X-Api-Version": "3",
7
"Content-Type": "application/vnd.api+json",
8
},
9
body: JSON.stringify({
10
data: {
11
type: "upload",
12
attributes: {
13
path: "/205/1565776891-image.png",
14
author: "Mark",
15
copyright: "2020 DatoCMS",
16
default_field_metadata: {
17
en: { alt: "Nyan the cat", title: "My cat", custom_data: {} },
18
},
19
},
20
},
21
}),
22
});
1
HTTP/1.1 202 Accepted
2
Content-Type: application/json
3
Cache-Control: cache-control: max-age=0, private, must-revalidate
4
X-RateLimit-Limit: 30
5
X-RateLimit-Remaining: 28
6
7
{
8
"data": {
9
"type": "job",
10
"id": "facf9248be977002c9bae231"
11
}
12
}

You can now check if the job is complete. While the job is still processing, the endpoint returns a 404 status code. Once the job is finished, it will return a 200 status code, with the upload object in the payload.

1
GET https://site-api.datocms.com/job-results/facf9248be977002c9bae231 HTTP/1.1
2
Authorization: Bearer YOUR-API-TOKEN
3
Accept: application/json
4
X-Api-Version: 3
5
Content-Type: application/vnd.api+json
Terminal window
1
curl -g 'https://site-api.datocms.com/job-results/facf9248be977002c9bae231' \
2
\
3
-H "Authorization: Bearer YOUR-API-TOKEN" \
4
-H "Accept: application/json" \
5
-H "X-Api-Version: 3" \
6
-H "Content-Type: application/vnd.api+json"
1
await fetch(
2
"https://site-api.datocms.com/job-results/facf9248be977002c9bae231",
3
{
4
headers: {
5
Authorization: "Bearer YOUR-API-TOKEN",
6
Accept: "application/json",
7
"X-Api-Version": "3",
8
"Content-Type": "application/vnd.api+json",
9
},
10
},
11
);
1
HTTP/1.1 202 Accepted
2
Content-Type: application/json
3
Cache-Control: cache-control: max-age=0, private, must-revalidate
4
X-RateLimit-Limit: 30
5
X-RateLimit-Remaining: 28
6
7
{
8
"data": {
9
"type": "job-result",
10
"id": "facf9248be977002c9bae231",
11
"attributes": {
12
"status": 200,
13
"payload": {
14
"data": {
15
"type": "upload",
16
"id": "666",
17
"attributes": {
18
"size": 444,
19
"width": 30,
20
"height": 30,
21
"path": "/205/1565776891-image.png",
22
"url": "https://www.datocms-assets.com/205/1565776891-image.png",
23
"basename": "image",
24
"format": "jpg",
25
"alt": "Nyan the cat",
26
"title": "My cat",
27
"is_image": true,
28
"author": "Mark",
29
"copyright": "2020 DatoCMS",
30
"default_field_metadata": {
31
"en": {
32
"alt": "Nyan the cat",
33
"title": "My cat",
34
"custom_data": {}
35
}
36
}
37
}
38
}
39
}
40
}
41
}
42
}

Body parameters

id string Optional

RFC 4122 UUID of upload expressed in URL-safe base64 format

Example: "q0VNpiNQSkG6z0lif_O1zg"
type string Required

Must be exactly "upload".

attributes.path string Required

Upload path

Example: "/45/1496845848-digital-cats.jpg"
attributes.copyright string, null Optional

Copyright

Example: "2020 DatoCMS"
attributes.author string, null Optional

Author

Example: "Mark Smith"
attributes.notes string, null Optional

Notes

Example: "Nyan the cat"
attributes.default_field_metadata object Optional

For each of the project's locales, the default metadata to apply if nothing is specified at record's level.

Example: { en: { title: "this is the default title", alt: "this is the default alternate text", custom_data: { foo: "bar" }, focal_point: { x: 0.5, y: 0.5 }, }, }
attributes.tags Optional

Tags

Type: Array<string>
Example: ["cats"]
relationships.upload_collection.data Optional

Upload collection to which the asset belongs

Returns

Returns a Job ID. You can then poll for the completion of the job that will eventually return a resource object of type upload