POST for creating content entities
Configuration
This builds upon the GET example of the previous page.
See Getting started: REST configuration & REST request fundamentals — Configuration
Sample requests below assume this configuration:
resources:
entity:node:
GET:
supported_formats:
- hal_json
supported_auth:
- basic_auth
- cookie
POST:
supported_formats:
- hal_json
supported_auth:
- basic_auth
- cookie
NOTE: latest versions of Drupal 8 (at time of writing 8.9.x) don't have hal_json format available just json. Thus you need to substitute json wherever you see hal_json below.
Test with a POST request
In this example, we will use HAL+JSON. HAL+JSON has the concept of relations. Most of the content in Drupal has relations. Make sure the relations are properly added to the payload (they live under the _links
key).
For instance if you want to POST a new comment you need a _links
entry to the user and to the entity the comment is for. Best way to get this is to first GET an example and study its _links
.
Never POST a UUID (or node ID/comment ID/…) as you create a new entity.
In all of the examples below, you should get a 201 response, which includes the serialized entity in the body (since Drupal 8.1.0, i.e. since #2546216: Return entity object in REST response body after successful POST — before then, you'll get a 201 response, with an empty body)
Prior to Drupal 8.3.0, instead of /node
POST to /entity/node
- deprecated and will be removed in Drupal 9.
Prior to Drupal 8.2.0, obtain the CSRF token if needed from /rest/session/token
- deprecated and will be removed in Drupal 9
cURL (command line)
curl --include \
--request POST \
--user klausi:secret \
--header 'Content-type: application/hal+json' \
--header 'X-CSRF-Token: <obtained from http://example.com/session/token> (Only needed if authenticating with a cookie rather than user credentials)' \
http://example.com/entity/node?_format=hal_json \
--data-binary '{"_links":{"type":{"href":"http://example.com/rest/type/node/article"}},"title":[{"value":"Example node title"}],"type":[{"target_id":"article"}]}'
Guzzle
<?php
$serialized_entity = json_encode([
'title' => [['value' => 'Example node title']],
'type' => [['target_id' => 'article']],
'_links' => ['type' => [
'href' => 'http://example.com/rest/type/node/article'
]],
]);
$response = \Drupal::httpClient()
->post('http://example.com/entity/node?_format=hal_json', [
'auth' => ['klausi', 'secret'],
'form_params' => $serialized_entity,
'headers' => [
'Content-Type' => 'application/hal+json',
'X-CSRF-Token' => <obtained from /session/token>
],
]);
?>
jQuery
function getCsrfToken(callback) {
jQuery
.get(Drupal.url('session/token'))
.done(function (data) {
var csrfToken = data;
callback(csrfToken);
});
}
function postNode(csrfToken, node) {
jQuery.ajax({
url: 'http://example.com/node?_format=hal_json',
method: 'POST',
headers: {
'Content-Type': 'application/hal+json',
'X-CSRF-Token': csrfToken
},
data: JSON.stringify(node),
success: function (node) {
console.log(node);
}
});
}
var newNode = {
_links: {
type: {
href: 'http://example.com/rest/type/node/article'
}
},
type: {
target_id: 'article'
},
title: {
value: 'Example node title'
}
};
getCsrfToken(function (csrfToken) {
postNode(csrfToken, newNode);
});
Notes
Basic authentication
If using Basic Auth You need to set the "Authorization" header. Here is an example:
function formatBasicAuth(userName, password) {
var basicAuthCredential = userName + ":" + password;
var bace64 = btoa(basicAuthCredential);
return 'Basic ' + bace64;
}
// then in your post
var basic = formatBasicAuth('userName', 'password');
...
'X-CSRF-Token': csrfToken,
'Authorization': basic,
CORS
Also note if having trouble with this you may also need to check your cors (Cross-Origin Resource Sharing) settings in sites/default/services.yml and for development only you can change it to the following .. but remember to lock it down on production.
# Configure Cross-Site HTTP requests (CORS).
# Read https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
# for more information about the topic in general.
# Note: By default the configuration is disabled.
cors.config:
enabled: true
# Specify allowed headers, like 'x-allowed-header'.
allowedHeaders: ['*']
# Specify allowed request methods, specify ['*'] to allow all possible ones.
allowedMethods: ['*']
# Configure requests allowed from specific origins.
allowedOrigins: ['*']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: false
# Sets the Access-Control-Max-Age header.
maxAge: false
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: false
Dev HTTP client
POST with Taxonomy Term entity reference using HAL+JSON: cURL (command line)
The following is an example of a POST
request using HAL+JSON to create an article
Node with a taxonomy term entity reference for a "tagging" vocabulary.
This example applies only to HAL+JSON, since the concept of _embedded
is specific to HAL+JSON, it does not exist in JSON or XML.
Before you can actually POST the article node with a tag when using the HAL+JSON format, you first have to GET the tag to retrieve its UUID (because HAL+JSON requires references by UUID). If it's a new term, you must first POST it to create it. See also example 'POST term'.
curl --request POST -k -i -s --user user:password --header 'Content-type: application/hal+json' -H 'Cache-Control: no-cache' --header 'X-CSRF-Token: <obtained from http://example.com/session/token>' 'http://example.com/entity/node?_format=hal_json' --data-binary '
{
"_links": {
"type": {
"href": "http://example.com/rest/type/node/article"
},
"http://example.com/rest/relation/node/article/field_tags": {
"href": "http://example.com/taxonomy/term/1?_format=hal_json"
}
},
"type": {
"target_id": "article"
},
"title": {
"value": "My Article"
},
"body": {
"value": "some body content aaa bbb ccc"
},
"_embedded": {
"http://example.com/rest/relation/node/article/field_tags": [
{
"_links": {
"self": {
"href": "http://example.com/taxonomy/term/1?_format=hal_json"
},
"type": {
"href": "http://example.com/rest/type/taxonomy_term/tags"
}
},
"uuid": [
{
"value": "ff61ea71-2540-47fe-a4bb-384b12d4de47"
}
],
"lang": "en"
}
]
}
}'
POST New Taxonomy Term using HAL+JSON: cURL (command line)
Note: actual endpoint is '/entity/taxonomy_term/'
export JSON_DATA='
{
"_links": {
"type": {
"href": "https://example.com/rest/type/taxonomy_term/tags"
}
},
"vid": [
{
"target_id": "tags"
}
],
"name": [
{
"value": "RESTtag",
"lang": "en"
}
]
}'
curl --request POST \
-k \
-i \
-s \
--user "username:password" \
--header 'Content-type: application/hal+json' \
-H 'Cache-Control: no-cache' \
--header "X-CSRF-Token: ####YourTokenHash####" \
'https://example.com/entity/taxonomy_term/?_format=hal_json' \
--data-binary "$JSON_DATA"
POST new user with CURL request using Command line:
curl --include --request POST --header 'Content-type: application/hal+json' http://localhost/xyz/web/user/register?_format=hal_json --data-binary '{"_links":{"type":{"href":"http://localhost/xyz/web/rest/type/user/user"}},"name":[{"value":"username"}],"mail":[{"value":"xyz@xyz.com"}],"pass":[{"value": "xyz"}]}'
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion