
In November, 2015, the Stanford Web Services team got to dive into Drupal 8 during a weeklong sprint. I was excited to look at the RESTful web services that Drupal 8 gives out-of-the-box; what follows is my documentation of the various types of requests supported, required headers, responses, and response codes.
This is not intended to be an exhaustive documentation of RESTful web services in Drupal 8. However, I have pulled information from various posts around the Web, and my own experimentation, into this post.
A REST client application (e.g., Paw for Mac OS X) is extremely handy for experimenting with RESTful web services in Drupal 8.
Contents
Resources
- Basic Auth Documentation from drupal.org
- "GET on content entities" from drupal.org
- Drupal 8 RESTful Web Services
- DELETE requests and Cookie Authentication in Drupal 8's REST
- POST, PATCH and DELETE request with Drupal 8 REST services
- Self-Documenting REST API Drupal contrib module
GET Request
The GET request is the simplest, and requires no authentication (if permissions are configured to allow anonymous users to "Access GET on Content resource"). Just send a GET request to the node path and add a _format=hal_json
URL parameter.
More documentation available at drupal.org.
Request
<a href="https://example.com/node/<nid>?_format=hal_json
">https://example.com/node/<nid>?_format=hal_json[/geshifilter-code]
Response
200 OK
"_links": {
"self": {
"href": "<a href="https://example.com/node/8?_format=hal_json"
">https://example.com/node/8?_format=hal_json"
</a> },
"type": {
"href": "<a href="https://example.com/rest/type/node/article"
">https://example.com/rest/type/node/article"
</a> },
"<a href="https://example.com/rest/relation/node/article/uid":">https://example.com/rest/relation/node/article/uid":</a> [
{
"href": "<a href="https://example.com/user/3?_format=hal_json",
">https://example.com/user/3?_format=hal_json",
</a> "lang": "en"
}
],
"<a href="https://example.com/rest/relation/node/article/revision_uid":">https://example.com/rest/relation/node/article/revision_uid":</a> [
{
"href": "<a href="https://example.com/user/3?_format=hal_json"
">https://example.com/user/3?_format=hal_json"
</a> }
],
"<a href="https://example.com/rest/relation/node/article/field_tags":">https://example.com/rest/relation/node/article/field_tags":</a> [
{
"href": "<a href="https://example.com/taxonomy/term/2?_format=hal_json",
">https://example.com/taxonomy/term/2?_format=hal_json",
</a> "lang": "en"
}
]
},
"uuid": [
{
"value": "a57f21eb-a4fe-4c04-8507-7a9cb1255834"
}
],
"type": [
{
"target_id": "article"
}
],
"langcode": [
{
"value": "en",
"lang": "en"
}
],
"title": [
{
"value": "Test Article 2",
"lang": "en"
}
],
"_embedded": {
"<a href="https://example.com/rest/relation/node/article/uid":">https://example.com/rest/relation/node/article/uid":</a> [
{
"_links": {
"self": {
"href": "<a href="https://example.com/user/3?_format=hal_json"
">https://example.com/user/3?_format=hal_json"
</a> },
"type": {
"href": "<a href="https://example.com/rest/type/user/user"
">https://example.com/rest/type/user/user"
</a> }
},
"uuid": [
{
"value": "46a5a516-2d00-41fa-b300-f0342bec87f5"
}
],
"lang": "en"
}
],
"<a href="https://example.com/rest/relation/node/article/revision_uid":">https://example.com/rest/relation/node/article/revision_uid":</a> [
{
"_links": {
"self": {
"href": "<a href="https://example.com/user/3?_format=hal_json"
">https://example.com/user/3?_format=hal_json"
</a> },
"type": {
"href": "<a href="https://example.com/rest/type/user/user"
">https://example.com/rest/type/user/user"
</a> }
},
"uuid": [
{
"value": "46a5a516-2d00-41fa-b300-f0342bec87f5"
}
]
}
],
"<a href="https://example.com/rest/relation/node/article/field_tags":">https://example.com/rest/relation/node/article/field_tags":</a> [
{
"_links": {
"self": {
"href": "<a href="https://example.com/taxonomy/term/2?_format=hal_json"
">https://example.com/taxonomy/term/2?_format=hal_json"
</a> },
"type": {
"href": "<a href="https://example.com/rest/type/taxonomy_term/tags"
">https://example.com/rest/type/taxonomy_term/tags"
</a> }
},
"uuid": [
{
"value": "14bd6eeb-f0f1-4fd1-b200-e27246318b7c"
}
],
"lang": "en"
}
]
},
"status": [
{
"value": "1",
"lang": "en"
}
],
"created": [
{
"value": "1446588457",
"lang": "en"
}
],
"changed": [
{
"value": "1446589578",
"lang": "en"
}
],
"promote": [
{
"value": "1",
"lang": "en"
}
],
"sticky": [
{
"value": "0",
"lang": "en"
}
],
"revision_timestamp": [
{
"value": "1446588457"
}
],
"revision_translation_affected": [
{
"value": "1",
"lang": "en"
}
],
"default_langcode": [
{
"value": "1",
"lang": "en"
}
],
"comment": [
{
"status": "2",
"cid": "0",
"last_comment_timestamp": "1446588457",
"last_comment_name": null,
"last_comment_uid": "3",
"comment_count": "0",
"lang": "en"
}
]
}
Authentication
POST, DELETE and PATCH requests require a CSRF token, as well as HTTP Basic Authentication (with a user's Drupal user name and password).
Get the token at <a href="https://example.com/rest/session/token
">https://example.com/rest/session/token[/geshifilter-code]
POST Request
Request
<a href="https://example.com/entity/node
">https://example.com/entity/node[/geshifilter-code]
Headers
Header Name | Header Value |
---|---|
X-CSRF-Token |
(token from rest/session/token ) |
Authorization |
Basic (hashed username/password) |
Content-Type |
application/hal+json |
Body
"_links": {
"type": {
"href": "<a href="https://example.com/rest/type/node/article"
">https://example.com/rest/type/node/article"
</a> }
},
"title": {
"value": "Test Article 2"
},
"type": {
"target_id": "article"
}
}
Response
200 OK
DELETE Request
Request
<a href="https://example.com/node/<nid>
">https://example.com/node/<nid>[/geshifilter-code]
Headers
Header Name | Header Value |
---|---|
X-CSRF-Token |
(token from rest/session/token ) |
Authorization |
Basic (hashed username/password) |
Response
204 No Content
PATCH Request
Use the PATCH method to update an existing entity.
Request
<a href="https://example.com/node/<nid>
">https://example.com/node/<nid>[/geshifilter-code]
Headers
Header Name | Header Value |
---|---|
X-CSRF-Token |
(token from rest/session/token ) |
Authorization |
Basic (hashed username/password) |
Content-Type |
application/hal+json |
Body
"_links": {
"type": {
"href": "<a href="https://example.com/rest/type/node/article"
">https://example.com/rest/type/node/article"
</a> }
},
"nid": {
"": {
"value": "8"
}
},
"type": {
"target_id": "article"
},
"promote": {
"value": "1"
},
"body": {
"": {
"value": "<p>foo bar baz</p>",
"lang": "en"
}
}
}
Response
204 No Content
Comments
Checkout drupal.org/project
Checkout drupal.org/project/rest_api_doc to have this auto built for your site
Self Documenting REST API
Ah, thanks for the reminder. We did lean heavily on the Self-Documenting REST API module (which is awesome).
I've updated the post to add that as a resource.
Just what's needed to help a
Just what's needed to help a developer get started with Drupal 8 REST.
D8 REST POST Entity Reference
Did you try posting a node with an Entity Reference field linking to another content type?
How is an Entity Reference field populated? A Postman example?
Thanks!
Entity Reference - hal_json format
What is the format for an entity reference in POST for a node?
Bundle Field is Entity Reference
The bundle field is an example of setting the value for an entity reference field. In that case the entity id is a string but if it was numeric you can set the target_id to the relevant entity id
Retrieve all nodes
Hi,
How can i retrieve all nodes (by passing page and limit parameters).
Thanks
BBI fondative
File entity?
I'm trying to POST a .pdf to be saved in my files directory. Any luck doing something like that?
Add new comment