Last updated July 11, 2014. Created on May 5, 2010.
Edited by nicxvan, topsitemakers, Mile23, benjamin_dk. Log in to edit this page.

To get the most out of this page, you should first take a look at Working with REST Server to get more of a conceptual overview on how the REST Server works.

As described on that page, there are six types of resources you can define

We will test each one with the user service. When testing, use the URL you figured out in the previous section.


Retrieve

Retrieving information from your resource is very simple. The format is

http://<url>/<identifier>.<format>

Identifier is the unique identifier of the data you are attempting to retrieve (in this example, the user ID.) Format is one of the formats the REST server supports returning data in. Lets use XML for the time being. So to test the user resource, enter the following

http://<url>/1.xml

And you should receive something that looks like this:

<result><uid>1</uid><name>admin</name><pass>xyzzyxyzzyxyzzyxyzzy</pass><mail>gdd@heyrocker.com</mail><mode>0</mode><sort>0</sort><threshold>0</threshold><theme></theme><signature></signature><signature_format>0</signature_format><created>1267194321</created><access>1272894373</access><login>1272853099</login><status>1</status><timezone/><language></language><picture></picture><init>gdd@heyrocker.com</init><data>a:0:{}</data><roles is_array="true"><item>authenticated user</item></roles></result>


Create

In order to create through a resource, you have to POST data to the URL. For posting, you just use the base URL without the identifier and format.

There are a couple ways to go about POSTing data to a resource. First, there is a handy Firefox plugin called Poster which allows the posting of arbitrary data to specified URLs. Poster can be downloaded at https://addons.mozilla.org/en-US/firefox/addon/2691.
For Google Chrome, you can use the Advanced REST Client extension found here: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofdd...
It is fairly simple to use and it remembers your last entry so you can easily continue to test even after closing the browser.
The steps below are for Poster plugin for Firefox, but they are similar to Advanced REST Client for Chrome.

Here is a short tutorial on using Poster to POST data to create a new user through the user resource.

  1. After installing Poster you will need to reboot Firefox. Once you have rebooted you can active Poster from the menu at Tools->Poster.
  2. In the URL field, enter the base URL for your resource.
  3. Click the Parameters tab. This is where you enter the data to be submitted, which mimics the fields that would be posted from a web form. This data is entered in kay/value pairs. For a user these value are
    • name (username)
    • pass (plain text password)
    • mail (email address)

    Enter a key/value pair and click the Add/Change button to add it to the list.

    Note that for other types of data like nodes, you will need quite a bit more information than this. For more information on what type of data is needed to create a resource, please reference the documentation for that resource's create method.

  4. Now click back to the Content to Send tab and click Parameter Body. This will convert your Parameters to properly encoded data, and change the Content Type to 'application/x-www-form-urlencoded'.

  5. Under Actions you'll see several buttons. Create requests are POSTed to the resource, so click Post. Ideally, if all went well, you will see something like the following:

    This is an XML representation of the user you just created. Success!

If you would rather test from code, you can do this using a Drupal bootstrap script with the following code. The $account array created here is just an array representation of the parameters above.

$account = array(
  'name' => 'test_user',
  'pass' => 'xyzzy',
  'mail' => 'test_user@xyzzy.com',
);
              
$response = drupal_http_request($url, $headers, 'POST', http_build_query($account, '', '&'));

If your test did not succeed, here are some things to check

  • Are your parameters named correctly? They have to be exactly right or the submission will not validate.
  • Load your server's home page. Often a failed form submission will trigger a drupal_set_message(), however these messages are only mirrored to the screen, not to our service's response. You will often not see these messages until your next page load.
  • Check the dblog on your server to see if any errors occurred.
  • For users specifically, note that two users can not have the same username or email. If you resubmit with data that you previously submitted, your submission will fail.

These will often provide clues to your problem.


Update


Update functions work exactly the same as Create functions, except for a couple of small differences.

  • The URL you submit to has the unique identifier appended to it
  • Instead of using POST you will use PUT.

So in the above example, you can see in the response dialog that the UID of our new user is 7. So we can add this into our URL, and perhaps we want to change the user's email address as demonstrated below.

Click the PUT button and you will receive back the updated user information.


Delete


Delete functions work exactly the same as Update functions except for a couple of small differences

  • You don't actually need to submit any parameters (you can submit them but they will be ignored.)
  • You use DELETE instead of PUT

Beyond that everything should work as above. Typically this won't return anything.

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

Comments

polarbear128’s picture

At the moment this doc is missing Actions, and I've just spent some time working it out, so I'm going to leave this here:

The below is assuming Services 3.0

Logging in a user is an action. Action URLs generally follow this pattern:
http://<domain>/<drupal_site_name_if_used>/<endpoint_name>/<resource_alias>/<action>
An example of this for the user login and the site settings above would look something like
http://localhost/services_upgrade/test_endpoint/users/login

NB: to find the actions and aliases, you can use the endpoint export feature at /admin/build/services/<endpoint_name>/export once you've created the endpoint.

Before you can login though, you have to get a session id. You do this through the system.connect method.

Using REST, the URL looks like
http://localhost/services_upgrade/test_endpoint/system/connect

If you try the GET method on this URL, you'll get a 404. You have to POST to it. You can't POST nothing though (at least, not through cURL or Poster), so just post anything. (I used the string "whatever". Like, whatever.)

If all goes well, you'll get a response similar to the below:

<?xml version="1.0" encoding="utf-8"?>
<result>
<sessid>2c038ba6326f12f132502e98434857cc</sessid>
<user>
<uid>0</uid>
<hostname>127.0.0.1</hostname>
<roles is_array="true">
<item>anonymous user</item>
</roles>
<session></session>
<cache>0</cache>
</user>
</result>

Now the sessid can be used to login the user:
URL:
http://localhost/services_upgrade/test_endpoint/users/login
Request:
POST sessid=2c038ba6326f12f132502e98434857cc&name=<username>&pass=<password>

If successful you'll get a 302 response and, depending on your client, may get a redirection. If already logged in, I get a 406 response. Not sure what the correct response is supposed to be.

To logout, the URL is of the form:
http://localhost/services_upgrade/test_endpoint/users/logout
Request:
POST name=<username>

And the response will be similar to

<?xml version="1.0" encoding="utf-8"?>
<result>1</result>

Hope this helps someone out there.

bricef’s picture

Thanks for your help. It was very usefule.

My blog http://pelmel.org/
I'm currently working for SQLI http://www.sqli.com/

polarbear128’s picture

I should add - the reason I was getting a 302 redirect response on logging in is because there was a trigger on the site to redirect on login. Unfortunately, that trigger also fires for login over web-service.
To get round it I had to install the Rules module and make a Rule to trigger a redirect for web login, but not for web-service login.
When this is in, you'll get a 200 response for successful login, and the response will look something like:

<?xml version="1.0" encoding="utf-8"?>
<result>
    <sessid>bdd7f59556ba31f3f1717f628d13ef03</sessid>
    <session_name>SESSc926dcbf8f9ff16891c1969cc8f6ce18</session_name>
    <user>
        <uid>113</uid>
        <name>theusername</name>
        <pass>encryptedpassword</pass>
        <mail>usersemail</mail>
        <mode>0</mode>
        <sort>0</sort>
        <threshold>0</threshold>
        <theme></theme>
        <signature></signature>
        <signature_format>0</signature_format>
        <created>1283767512</created>
        <access>1296568054</access>
        <login>1296651720</login>
        <status>1</status>
        <timezone/>
        <language></language>
        <picture></picture>
        <init>initstuff</init>
        <data>somedata</data>
        <roles is_array="true">
            <item>authenticated user</item>
        </roles>
        <profile_name>username</profile_name>
        <profile_user_status>status text</profile_user_status>
        <profile_read_aboutus>1</profile_read_aboutus>
    </user>
</result>

Which should be persisted somewhere locally.

Anonymous’s picture

I'm running drupal 7.0 with services-3.0-rc2 and I want to point out that I am able to just login (using Poster) without a sessionid and hence without having to connect first.

I do have problems performing a POST request with Content Type set to 'application/x-www-form-urlencoded' as demonstrated in the documentation. Instead I login using json (Content Type set to 'application/json' and add the following to the textarea in Poster:

{"username":"myusername","password":"mypassword"}

Note: the url is offcourse the same http://localhost/services_upgrade/test_endpoint/users/login.

andorraclaim’s picture

What I don't understand still is where does the 'session_name' value exist in this way of calling system/connect. You can not register a user without the full cookie and when posting to system/connect you get returned just the sessID (as the above example shows). The header to send with user/create is something like 'Cookie: SESS5913ad7ed2adf92cab1103dad2f5596c=213d28535c6972e16430a4e1e03ce7ea' See: http://drupal.org/node/910598

I am a lost about this.

w.e.s-l

bluekylin’s picture

I try to post to http://localhost/services_upgrade/test_endpoint/system/connect, but I always get the error:
HTTP/1.0 404 Not found: Could not find the controller.
What's the error?

Ashish Madkaikar’s picture

Thank you polarbear128 your comments helped.
I was able to POST the initial session ID request from Poster by setting the Content type to "application/json".

dpi’s picture

Parameters for drupal_http_request have changed in Drupal 7.

Drupal 6:

<?php
$response
= drupal_http_request($url, $headers, 'POST', http_build_query($account, '', '&'));
?>

Drupal 7

<?php
$response
= drupal_http_request(
 
$url,
  array(
   
'headers' => $headers,
   
'method' => 'POST',
   
'data' => http_build_query($account, '', '&'),
  )
);
?>

Australian Drupal Dev - http://dpi.id.au/

Anonymous’s picture

I was unable to create a user following the guidelines described above in the create user section with Poster (mail, pass, name => "Body from Parameters" & "Content type" = "application/x-www-form-urlencoded"). I used the services 3.0-rc2 for drupal 7.

I recieved a "401 Unauthorized: Missing required argument node" status back.

The solution for my problem was passing it as json:

  1. Set "Content Type" to "application/json" in Poster
  2. In the body field add the following:
    {"account":{"name":"username","pass":"password ","mail":"username@test.com"}}
barnettech’s picture

I would be very happy if you could post your code to create a user. I can currently only do GET requests using Drupal 7 and services. And actually I'm trying to connect without the Drupal API.

thanks.

epinapala’s picture

<?php
/*
 * :Author: | Eswara Rajesh Pinapala : mailme@beingrajesh.com.
 */

/**
 * Description of DrupalREST
 * This class enables communication with Drupal REST API
 * @author epinapala
 */
class drupalRest {

    var
$username;
    var
$password;
    var
$session;
    var
$endpoint;
    var
$debug;

    function
__construct($endpoint, $username, $password, $debug) {
       
$this->username = $username;
       
$this->password = $password;
        if ((
substr($endpoint, -1) != "/")) {
           
//no trailing slash! Add one!
           
$endpoint .= "/";
        }
       
$this->endpoint = $endpoint;
       
$this->debug = $debug;
    }

    function
login() {
       
$ch = curl_init($this->endpoint . 'user/login/');
       
$post_data = array(
           
'username' => $this->username,
           
'password' => $this->password,
        );
       
$post = json_encode($post_data);
       
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       
curl_setopt($ch, CURLOPT_HEADER, false);
       
curl_setopt($ch, CURLOPT_POST, true);
       
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
       
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
           
"Accept: application/json",
           
"Content-type: application/json"
       
));
       
$response = json_decode(curl_exec($ch));
       
curl_close($ch);
       
//Save Session information to be sent as cookie with future calls
       
$this->session = $response->session_name . '=' . $response->sessid;
    }

   
// Retrieve a node from a node id
   
function retrieveNode($nid) {
       
//Cast node id as integer
       
$nid = (int) $nid;
       
$ch = curl_init($this->endpoint . 'node/' . $nid . '/');
       
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       
curl_setopt($ch, CURLOPT_HEADER, TRUE);
       
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
       
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
           
"Accept: application/json",
           
"Cookie: $this->session"
       
));
       
$result = $this->_handleResponse($ch);

       
curl_close($ch);

        return
$result;
    }

    function
createNode($node_json) {
       
$ch = curl_init($this->endpoint . 'node/');
       
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
       
curl_setopt($ch, CURLOPT_HEADER, TRUE); // Ask to not return Header
       
curl_setopt($ch, CURLOPT_POST, TRUE);
       
curl_setopt($ch, CURLOPT_POSTFIELDS, $node_json);
       
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json'));
       
curl_setopt($ch, CURLOPT_COOKIE, "$this->session"); // use the previously saved session
       
curl_setopt($ch, CURLOPT_FAILONERROR, TRUE);
       
$result = $this->_handleResponse($ch);
       
curl_close($ch);
        return
$result;
    }

   
// Private Helper Functions
   
private function _handleResponse($ch) {
       
$response = curl_exec($ch);
       
$info = curl_getinfo($ch);

       
//break apart header & body
       
$header = substr($response, 0, $info['header_size']);
       
$body = substr($response, $info['header_size']);

       
$result = new stdClass();

        if (
$info['http_code'] != '200') {
           
$header_arrray = explode("\n", $header);
           
$result->ErrorCode = $info['http_code'];
           
$result->ErrorText = $header_arrray['0'];
        } else {
           
$result->ErrorCode = NULL;
           
$decodedBody = json_decode($body);
           
$result = (object) array_merge((array) $result, (array) $decodedBody);
        }

        if (
$this->debug) {
           
$result->header = $header;
           
$result->body = $body;
        }

        return
$result;
    }

}
?>
barnettech’s picture

Creating a user using rest and curl without Drupal installed: I just got it working posting a user in Drupal 7 using curl, but it's a bit quirky. If anyone can answer why its throwing away the first element in the array (see this link) then let me know thanks: http://www.barnettech.com/content/drupal-7-create-user-using-rest-and-curl The code does create a user though, just quirky.

redsd’s picture

The examples are not very clear how to implement this for drupal 7 services.

for creating a new user the content that needs to be send to the REST server needs to look like this:

&account[name]=test_user&account[mail]=test@example.com&account[pass]=example

so when you use poster(firefox add-on) in combination with drupal 7 services you have to fill in the following:

url: http://localhost/servicename/users/
content type: application/x-www-form-urlencoded
body: &account[name]=test_user&account[mail]=test@example.com&account[pass]=example

for a compleet overview I would like to point to:
https://gist.github.com/affc9864487bb1b9c918

redsd’s picture

Here is an example how to create a new user with D7 using a REST server that is also hosted in D7.

<?php
    $url
= 'http://localhost/servicename/users/';//this is the user module, I renamed it to users (mind the extra "s" at the end)

   
$data = '&username=username&password=password';//replace the username and password with an existing account available on the site you call the service on
   
$options = array(
     
'headers' => array(
       
'Accept' => 'application/json',
      ),
     
'method' => 'POST',
     
'data' => $data
   
);
   
$headers = array("content-type"=>"application/x-www-form-urlencoded");

   
//here we call the login
   
$login = drupal_http_request(
     
$url.'login',
     
$options
   
);
   
   
$arSes=explode(';',$login->headers["set-cookie"]);//get the session info we need.

   
$account = array(
     
'name' => 'test_user',
     
'pass' => 'xyzzy',
     
'mail' => 'test_user@xyzzy.com',
    );

   
$query = http_build_query($account=array('account'=>$account), '', '&');
   
//if we got code 200, the login was a succes, we can procede to create a user account
   
if($login->code==200){

       
$options['headers']['Cookie'] = $arSes[0];//set the active session
       
$options['data'] = $query;
       
$options['method'] = 'POST';

       
$response = drupal_http_request(
         
$url,
         
$options
       
);
    }

   
//create a dump from all the data that we got back
   
var_dump($query,$login,$response);
?>
lahode’s picture

Hi,

After having spent several days finding out how to connect remotely with services module, I finally found your nice example, thank you!

However, it still doesn't work :(

What I did is :

    Install service 7.x-3.0 module dated on 2011-Sep-30 + Service Tools 7.x-3.x-dev to be sure the url called is correct
    Create a new user named webservice, password webservice + a role webservice and give all the right to the user, system and service module
    Create a new service named createuser, attached a REST Server, named the endpoint createuser, activated the "Debug mode enabled" and "Session authentification". Then on "Edit Resource", I checked all user, system and node resources.
    Create a new module called service_perso copied your function and a hook_menu calling your function
    I only changed :
$url = 'http://localhost/createuser/user/';
$data = '&username=webservice&password=webservice;

Here is the result I get :

[code]=> 406
[error]=>Not Acceptable: There is no user with ID 0.

Some other post mentioned the use of "http://localhost/createuser/system/connect" to retrieve a session key, but when I do that, I get back a :

[code] => 404
[error] => Not found: Could not find the controller.

I also found other post, but with D6 mentioning the use of a key authentification module, but I found nothing for D7 and I believe it is the "Session authentification" checkbox.

Thank you for your help, I turned everything upside down and found no solution.

Cheers

Fredrik Lahode
Hôptaux Universitaires de Genève - Suisse

randa.elayan’s picture

Hi,

I am not sure if this is the correct place to post this, but I tested my service, and it seems working fine.
but I still get this exception when debugging

Exception is: exception 'ServicesException' with message 'Could not find the controller.' in /home/yousrvc/public_html/cms/sites/all/modules/services/services.runtime.inc:330 Stack trace: #0 /home/yousrvc/public_html/cms/sites/all/modules/services/servers/rest_server/includes/RESTServer.inc(83): services_error() #1 /home/yousrvc/public_html/cms/sites/all/modules/services/servers/rest_server/rest_server.module(34): RESTServer->handle('Could not find ...', 404) #2 /home/yousrvc/public_html/cms/sites/all/modules/services/services.module(205): rest_server_server('system/connect', 'mservice') #3 /home/yousrvc/public_html/cms/includes/menu.inc(516): services_endpoint_callback() #4 /home/yousrvc/public_html/cms/index.php(21): menu_execute_active_handler() #5 {main}

Thanks

Randa

ardnet’s picture

Hi all,

how about adding a node, how am I supposed to do this?
Sorry, not really sure what this is means from the instruction above:
"Note that for other types of data like nodes, you will need quite a bit more information that this. For more information on what type of data is needed to create a resource, please reference the documentation for that resource's create method."

Thanks in advance.

takinola’s picture

Here is an example that works for Drupal 6

key/value pairs should be

Name ->

Value
node[title] -> Node title of new node
node[type] -> Node type of new node
node[body] -> Text in body of new node
node[field_cck_field][0][value] -> Entry into CCK field named field_cck_field

This is about the minimum data you need to create a node

tyler.frankenstein’s picture

For Drupal 6.x & Services 3.x you need to set your Firefox Poster Add-on parameters to:

  • account[name]=foo
  • account[pass]=bar
  • account[mail]=foo@bar.com

DO NOT USE THIS (as the tutorial above suggests):

Using the above parameters will most likely result in this response: 406 Not Acceptable: Missing required argument account

cwsdi’s picture

Hello,

I need your assitant to send "email new password" with REST Server.
When user forgot password i need to send a "email new password" just with customer's email.

have you got solution to retrieve user without uid?

Thanks for your help

eugen80’s picture

How can I upload files like user pic for user profile?

blisteringherb’s picture

I upgraded from Services 2 to Services 3 and spent a bit of time figuring out exactly how to form the POST request to get the taxonomy data, and I figured someone else might also be looking for that information.

Path to Endpoint - 'services/json'
Server - REST

Here are the CURL requests:

taxonomy_vocabulary - alias 'vocabulary'
taxonomy.getTree
curl -d "vid=1&parent=3156" http://example.com/services/json/vocabulary/getTree.json
This POST request will return a tree from the VID 1 with a parent of 3156 in a json format. You can also use a max_depth param to limit the query.

taxonomy_term - alias 'term'
taxonomy.selectNodes
curl -d "tids=567,12" http://example.com/services/json/term/selectNodes.json
This POST request will return a list of nodes that have the TID of 567 or 12. selectNodes also takes optional fields, operator, depth, pager and order params.

moltra’s picture

I am trying to do this in D7 and I need all the nodes that have a certain tid in them, I do have multiple tid's per node. I am not sure if that will prevent it or not.

Weijian’s picture

Check the permission "access user profiles" for anonymous user, or retrieve user from browser by http:///1.json will get null. If using Poster to get the Uri, it will tells the 401 Unauthorized: Access denied for user 0 "anonymous" and this is straightforward.

nakeddesign’s picture

I have a custom retrieve resource configured which always returns a 401 error.
path/node and path/user can be retrieved fine so I really don't understand path/mytest is throwing a permission denied. access callback is TRUE.

$resource['mytest'] = array(
          'retrieve' => array(
              'help' => 'Retrieves Data',
              'callback' => '_myapi_data',
              'access callback' => TRUE,
              'args' => array(
                  array('name' => 'parameters',
                      'type' => 'string',
                      'description' => 'This is a test resource for services',
                      'source' => array('path' => '0'),
                      'optional' => FALSE,
                  ),
              ),
          ),
      );

Looking at various examples I can't see why this wouldn't work, but no doubt is something obvious I'm missing.

nakeddesign’s picture

You must have either a valid callback function or it will default to user access.

http://drupalcontrib.org/api/drupal/contributions!services!services.services.api.php/function/hook_services_resources/7

fAvorable’s picture

Post and Get work great. When I try to Update a node with a Put via Poster at 'domain/my_endpoint/node/nodeID' I am met with:

403 Forbidden, You don't have permission to access domain on this server.

Any ideas?

Oh and I get this in the logs:

Notice: Undefined index: test in RESTServer->resolveController() (line 542 of /home/nc94/public_html/drupal/sites/all/modules/services/servers/rest_server/includes/RESTServer.inc).

vinceb’s picture

I can create users using poster but haven't been able to assign a set of roles to anyone. Has anyone else managed to assign roles during the create process?

Thanks

Vince

redsd’s picture

I don't know this for sure, however normally you assign roles on user creation or modification.

This means when you post using poster in firefox(or any other browser) you get something like this:
&account[name]=test_user&account[mail]=test@example.com&account[pass]=example&account[roles][1]=authenticated user&account[roles][2]=other role&account[roles][5]=the fith role

So you got the basic: &account[roles] then followed by the role ID (the unique id that is definend in the table), followed by the name of the role(however this can be anything I think.)

This should set your roles when creating a user account, if it doesn't work it could be a permission issue.