Last updated 12 April 2013. Created on 27 April 2010.
Edited by gcbound, abautu, mindbat, Konstantin Komelin. Log in to edit this page.

This is a brief introduction to how the rest server works.


Tabulation of the controller mapping for the REST server. Requests gets mapped to different controllers based on the HTTP method used and the number of parts in the path.

Count refers to the number of path parts that come after the path to identify the resource type. The request for `/services/rest/node/123` would have the count of 1, as `/services/rest/node` identifies the resource type, followed by the nid identifying the desired resource.

C,R,U,D,I = Create, Read, Update, Delete (CRUD) and Index requests
A = Action
T = Targeted action
X = Relationship request

    COUNT |0|1|2|3|4|N|
    GET   |I|R|X|X|X|X|
    POST  |C|A|T|T|T|T|
    PUT   | |U| | | | |
    DELETE| |D| | | | |


The basis of the REST server. In the below:

  • [endpoint_path] refers to the Path to the endpoint you defined when setting up the endpoint.
  • [resource] is the name of the resource, like node or taxonomy_term.
  • [resource_id] is the id of the resource you're acting on.

Create: POST /[endpoint_path]/[resource] + body data
Retrieve: GET /[endpoint_path]/[resource]/[resource_id]
Update: PUT /[endpoint_path]/[resource]/[resource_id] + body data
Delete: DELETE /[endpoint_path]/[resource]/[resource_id]

And last but least, the little bastard sibling to Retrieve that didn't get its place in the acronym:

Index: GET /[endpoint_path]/[resource]

For example, to fetch a taxonomy term, you could use:

GET: /my_endpoint/taxonomy_term/5

Where 5 is the tid of the term to fetch.

If you wanted that term's data in json format, you'd use:

GET: /my_endpoint/taxonomy_term/5.json

In the REST server the index often doubles as a search function. The comment resource allows queries like the following for checking for new comments on a node (where 123456 is the timestamp for the last check and 123600 is now):

New comments: GET /services/comment?parameters[nid]=123&parameters[timestamp]=123456:


Actions are performed directly on the resource type, not a individual resource. The following example is hypothetical (but plausible). Say that you want to expose a API for the [apachesolr][apachesolr] module. One of the things that could be exposed is the functionality to reindex the whole site.

Reindex: POST /services/rest/apachesolr/reindex

Targeted actions

Targeted actions acts on a individual resource. A good, but again - hypothetical, example would be the publishing and unpublishing of nodes.

Publish: POST /my_endpoint/node/123/publish


Relationship requests are convenience methods (sugar) to get something that's related to an individual resource. A real example would be the relationship that the [comment_resource][comment_resource] module adds to the node resource:

Get comments: GET /my_endpoint/node/123/comments

This more or less duplicates the functionality of the comment index:

Get comments: GET /my_endpoint/comments?nid=123

Notes - Please rewrite me

This section is an incomplete list of helpful docs since we're moving away from using comments on Documentation pages.

Camil Sumodhee notes that if you are implementing a REST Server using XML where controller arguments / source are 'data', then you need to implement your own parser. You can define your own parser in hook_services_resources() as follows:

'rest request parsers' => array('text/xml' => '_mymodule_xml_parser'),

You want to make sure you return an array so it fits into the Services model $sources['data'][$key] where $key is the key of your resource argument.

Looking for support? Visit the forums, or join #drupal-support in IRC.


manu manu’s picture

There is an undocumented behavior at least in services-6.x-3.0-beta2:

The first argument of update action will be prepended to targeted action's arguments (see lines 165, 190).

It sounds logic because targeted actions focuses on individual resources like an update action.

So remember that if your targeted action doesn't share the same first argument with the update action, you may get a 'missing argument' error concerning a argument witch is not in your definition.

This may apply to relations too.

matt2000’s picture

Here's an example of using json data via curl to create a node:

curl --data '{"title":"hello world!","type":"page"}' --header "Content-Type:application/json"
zaurav’s picture


Could you help me out with a curl example for retrieving node #2 (for example)?

Your help would be much appreciated.

sanguis’s picture

Just add the id /service/node/2

branana’s picture

user/logout for example is considered an action. Even though there is no data to send, you still have to send the request as POST.

D6 code:

$headers['Cookie'] = $data->session_name . '=' . $data->sessid;
$response = drupal_http_request($endpoint_url . '/user/logout', $headers, 'POST');
asdagari’s picture


i use my service with an android app. I can create user, nodes and use the general index functions on the user and node json service. unfortunatly i want to get all users of a certain role or nodes with a certain value in a custom field. how can i manage that?

parameters[roles][5]=users does not work

i would be really happy about help, because i need to sunmit my bachelor thesis in a week


j1oshss’s picture

Hi There,
Can someone give me an example on how to create a user?
i have been able to login with poster in firefox and retrieve nodes.
But i am now trying to create either nodes or users.
Also if i have new custom fields added to those users how would I add those fields in as well?

...IE. field_id_number = "3482733903".

Thanks Guys!

ranjeet1189’s picture

Please if you got this answer please post

dtrzynka’s picture

Is there a way when performing a filter such .../node?parameters[type]=article to return the full JSON and not ultimately just the node table type information? If I were to do a /node/6.json or /node to return all, it returns the full JSON for the nodes but once a filter is applied, it no longer returns the full content.

ravismula’s picture


I'm trying to update comments, but was unsuccessful.

Request :

URL : PUT localhost/drupal7//comment/3115
Headers :
X-CSRF-Token =
"data": {
"nid" : ,
"body": {
"und": [{
"value": "Updated!",
"format": "filtered_html"

I've tried to print the structure using comment_pre_save, and found that the comment_body[und][0][value] was holding the previous value rather than new one!

Can any one let me know how do I update a comment?

kenvuong34’s picture

I think you solved your problem. You duplicate a slash in your URL.

We need to check about URL carefully, sometimes data in body, content-type wrong can crash.