Drupal Services Examples
jDrupal: Be sure to check out jDrupal for an easy to use JavaScript Library to communicate with Drupal Services.
This document describes how to read/write entities to/from Drupal using the Services module. It also covers how to handle session authentication. Let's get started...
Installation and Setup
- Download the Services Module
- Enable It
- Drink Dr. Pepper
Now to create a service, we'll start with the basics... go to Structure -> Services -> Add, and enter some stuff like this:
Name | my_services |
Endpoint title | My Services |
Server | REST |
Path to endpoint | my_endpoint |
Ignore the other fields for now. Click 'Save' to, you guessed it, save your new service.
Next up, we need to enable some Resources for our Service. Go to Site Structure -> Services -> List, then click 'Edit Resources' next to your Service.
Check the boxes next to each resource that you'd like to enable, save, then flush all of Drupal's caches.
Examples
Each example below includes the HTTP method (GET, POST, PUT, or DELETE) and an example URL to use. When using POST or PUT, you must send along some data, and that example data will be listed on the line after the http method and url. If there is a special Content-Type header to use, it will be mentioned after the data, otherwise just use application/json.
C.R.U.D.I. = Create, Retrieve, Update, Delete, Index
X-CSRF-Token
For all POST, PUT and DELETE requests (except for user login), you must attach a token to the header of your request. The name of the header to use is:
X-CSRF-Token
The value of the token can be retrieved here:
http://localhost/drupal-7?q=services/session/token
Content-Type
Unless otherwise noted, the Content-Type header of your request should be set to:
application/json
Session Authentication
GET: http://localhost/drupal-7/?q=services/session/token POST: http://localhost/drupal-7/?q=my_endpoint/system/connect.json POST: http://localhost/drupal-7/?q=my_endpoint/user/login.json username=w5TmhqOvWF&password=4mBj5tYQu8 application/x-www-form-urlencoded POST: http://localhost/drupal-7/?q=my_endpoint/user/logout.json POST: http://localhost/drupal-7/?q=my_endpoint/user/register.json {"name":"yFzqH7dNEv","mail":"kT3miidPAx@example.com","pass":"MSQ4JvRhZh","pass2":"MSQ4JvRhZh"} application/x-www-form-urlencoded
User C.R.U.D.I.
POST: http://localhost/drupal-7/?q=my_endpoint/user.json {"name":"LSAwug2XxL","mail":"soRkkjZisJ@example.com","pass":"iPpNcwnEqW","pass2":"iPpNcwnEqW"} GET: http://localhost/drupal-7/?q=my_endpoint/user/52.json PUT: http://localhost/drupal-7/?q=my_endpoint/user/52.json {"uid":"52","mail":"8dGyPlGSrB@example.com","current_pass":"iPpNcwnEqW"} DELETE: http://localhost/drupal-7/?q=my_endpoint/user/52.json GET: http://localhost/drupal-7/?q=my_endpoint/user.json
Node C.R.U.D.I.
POST: http://localhost/drupal-7/?q=my_endpoint/node.json {"type":"article","title":"BEVVtDcZmL","language":"und"} GET: http://localhost/drupal-7/?q=my_endpoint/node/125.json PUT: http://localhost/drupal-7/?q=my_endpoint/node/125.json {"node":{"nid":"125","title":"KHrkDnudKR","language":"und"}} DELETE: http://localhost/drupal-7/?q=my_endpoint/node/125.json GET: http://localhost/drupal-7/?q=my_endpoint/node.json
Comment C.R.U.D.I.
POST: http://localhost/drupal-7/?q=my_endpoint/comment.json {"subject":"S5KeJTVFED","comment_body":{"und":[{"value":"gSXNfHPxgf"}]},"nid":"126"} GET: http://localhost/drupal-7/?q=my_endpoint/comment/30.json PUT: http://localhost/drupal-7/?q=my_endpoint/comment/30.json {"subject":"wULr64gdpj","comment_body":{"und":[{"value":"YhmemEQ4Cy"}]},"cid":"30"} DELETE: http://localhost/drupal-7/?q=my_endpoint/comment/30.json GET: http://localhost/drupal-7/?q=my_endpoint/comment.json¶meters[cid]=30
Taxonomy Vocabulary C.R.U.D.I.
POST: http://localhost/drupal-7/?q=my_endpoint/taxonomy_vocabulary.json {"name":"WkSTeYfABe","description":"RQoHVs22yZ","machine_name":"wksteyfabe"} GET: http://localhost/drupal-7/?q=my_endpoint/taxonomy_vocabulary/16.json PUT: http://localhost/drupal-7/?q=my_endpoint/taxonomy_vocabulary/16.json {"vid":"16","name":"gSXktVuVty","machine_name":"wksteyfabe"} DELETE: http://localhost/drupal-7/?q=my_endpoint/taxonomy_vocabulary/16.json GET: http://localhost/drupal-7/?q=my_endpoint/taxonomy_vocabulary.json¶meters[name]=WkSTeYfABe
Taxonomy Term C.R.U.D.I.
POST: http://localhost/drupal-7/?q=my_endpoint/taxonomy_term.json {"vid":"17","name":"V8m22sqRBO"} GET: http://localhost/drupal-7/?q=my_endpoint/taxonomy_term/13.json PUT: http://localhost/drupal-7/?q=my_endpoint/taxonomy_term/13.json {"vid":"17","tid":"13","name":"C5Kjy2WOxK"} DELETE: http://localhost/drupal-7/?q=my_endpoint/taxonomy_term/13.json GET: http://localhost/drupal-7/?q=my_endpoint/taxonomy_term.json¶meters[vid]=17¶meters[name]=V8m22sqRBO
Comments
Techie Talks (not verified)
Tue, 11/15/2011 - 23:43
Permalink
Thanks for sharing this. It
Thanks for sharing this. It really helped me a lot understand how to start developing a mobile app and integrate it with drupal.
Eduardo (not verified)
Tue, 01/17/2012 - 15:31
Permalink
Ok. I don't understand the
Ok. I don't understand the part of: system->connect. I don't have the access. Please, send me a e-mail.
tyler
Tue, 01/17/2012 - 16:06
Permalink
Hi Eduardo, Please check out
Hi Eduardo, Please check out the system->connect explanation in this article for more information about the system connect service resource.
Basically, when you make a call to system connect, it returns to you information about the user that made the call (user id, session id, etc).
Felix (not verified)
Tue, 10/30/2012 - 03:53
Permalink
Hi Tyler can you explaine the
Hi Tyler can you explaine the Server part a little bit more in detail? Do you use the REST Module or something else?
tyler
Tue, 10/30/2012 - 08:46
Permalink
Hello Felix,Please refer to
Hello Felix,
Please refer to this post for a much more detailed explanation on how to get Services up and running:
http://www.tylerfrankenstein.com/code/android-app-with-drupal-7-services...
Pritam Tiwari (not verified)
Wed, 03/13/2013 - 06:56
Permalink
It was really helpful to me.
It was really helpful to me. Can you add some more examples of webservices which shows the selected fields in the database tables.
Thanks a lot.
tyler
Thu, 03/14/2013 - 11:18
Permalink
Hi Pritam, I'm not sure what
Hi Pritam, I'm not sure what you mean by 'shows selected fields in the database tables'. You may want to check out the Views Datasource (Views JSON) module, or you can write your own service for the Services module.
akka (not verified)
Wed, 05/22/2013 - 17:11
Permalink
Hey,
Hey,
I followed your tutorials about rest & drupal, and I implemented the same logic in the Intel XDK/(appmobi earlier). thank you, that was very helpfull. now I have some questions if you dont mind :) :-
- this is for sure not the safest way to send the user's password. I tried using https instead of http, but the android webview does not allow secured requests, so I have to write a plugin to use the HttpsURLConnection class for that. but before doing that, I was woundering if you have any other Ideas for making the login secured.
- how do you manage the user recognition cookies/sessions ? , I read somewhere that you should save the session-id & send it with each request, I´m not looking for the code, just for the logic.
greetings :)
tyler
Thu, 05/23/2013 - 12:10
Permalink
Hi akka,
Hi akka,
I agree that this may not be the safest way to send the user's password, but that is how the User Login resource from the Services module works, so I stick with that and hope for the best. Using https is probably a bonus for security.
At this time, I don't have much experience with native Android development, so I am not qualified to speak about webview and HttpsURLConnection, sorry.
As for user recognition (cookies/session), that is managed by using the System Connect resource from the Services module. Once you are logged in, each subsequent Service Resource call will use Drupal's session management, so you don't need to pass along any session variables.
I personally use PhoneGap for all of my app development.
akka (not verified)
Fri, 05/24/2013 - 17:34
Permalink
ok thank you.
ok thank you.
but how do you manage it, when the user closes the app and starts it again. do they need to login again ? how do you manage that ? I read somewhere that you one should login with the sessionid , but I'm still not sure about this and how to manage it.
tyler
Sat, 05/25/2013 - 12:10
Permalink
You won't need to manage it
You won't need to manage it at all. When your app opens again, make a call to System Connect and Drupal will determine if there is a valid session or not for that device. If the System Connect returns a user id not equal to zero, then it thinks you are still logged in, if not, you will be an anonymous user. You won't need the session id at all.
upunkt (not verified)
Fri, 03/03/2017 - 19:43
Permalink
Thanks for this tutorial, it
Thanks for this tutorial, it helped me a lot. Still, I could not manage to login until I found out that one has to set the following header also, which might be a consequence of updated processes. It's worth mentioning this in your setup steps.
You'll be finding the values for session_name and sessid in the response on your login.
Cheers, u.
zef (not verified)
Wed, 05/29/2013 - 14:12
Permalink
Hello Tyler,
Hello Tyler,
Is it possible to export the content type (title, field name and value) to json or XML with the module services?
Thanks to help.
tyler
Wed, 05/29/2013 - 14:42
Permalink
Check out these modules:
Check out these modules:
https://drupal.org/project/views_datasource
https://drupal.org/project/services_views
zef (not verified)
Sun, 06/02/2013 - 20:25
Permalink
Thanks Taylor.
Thanks Taylor.
wal (not verified)
Thu, 07/25/2013 - 08:39
Permalink
Hello tyler,
Hello tyler,
Thanks for your tuto.
I follow your tuto http://www.tylerfrankenstein.com/code/android-app-with-drupal-7-services-phonegap-and-jquery-mobile but the url "http://localhost/test/system/connect.json" not work. I have a error "link broken". I don't understand I configured the service correctly like you but not work.
Need your help please.
Thanks.
tyler
Thu, 07/25/2013 - 08:56
Permalink
First verify the service is
First verify the service is set up correctly by POSTing to it with FireFox poster. Then use 10.0.2.2 in place of localhost when testing in an Android emulator. If you're testing directly to your mobile device, then your drupal site needs to be on the Internet, because your device most likely cannot access your localhost.
wal (not verified)
Thu, 07/25/2013 - 10:23
Permalink
I use addon "console rest"
I use addon "console rest" with chrome and I test the url in POST with content-type : application/x-www-form-urlencoded but it not work.
I try with Firefox but it's the same thing.
tyler
Thu, 07/25/2013 - 13:13
Permalink
Make sure you are not logged
Make sure you are not logged into your Drupal site in your browser when attempting to contact the System Connect. That's the only other thing I can think of. Please feel free to stop by IRC for more in depth support.
wal (not verified)
Thu, 07/25/2013 - 15:19
Permalink
Yes I'am logged out in my
Yes I'am logged out in my drupal site but not work.
I have the error 406.
Error to the addon "REST Console" in chrome:
tyler
Thu, 07/25/2013 - 15:29
Permalink
It sounds like 'session
It sounds like 'session authentication' is not enabled. It is a checkbox under your service resource settings. There are other troubleshooting techniques available here: https://drupal.org/node/2015065
wal (not verified)
Fri, 07/26/2013 - 05:44
Permalink
I have enable the "session
I have enable the "session authentification" when I create the service. I read your article but is not resovle my problem.
For the Module you activate juste the module "Service" and "REST Server"? no the "Oauth Authentification" ?
Sorry for my questions but it is a important project for my school.
tyler
Fri, 07/26/2013 - 09:28
Permalink
You need to also activate
You need to also activate Service Resources, for example:
wal (not verified)
Sun, 07/28/2013 - 05:17
Permalink
yes I have enable System
yes I have enable System Connect, Login, Logout etc but not work.
There's another way to do this? (another module or other)
Carlos (not verified)
Tue, 10/22/2013 - 13:35
Permalink
At firts let me tell you that
At firts let me tell you that your article is so great , it really healp me alot , but I want to know how to use this features in a drupal commerce site , I' ve downloaded commerce services module which allows to activate, product, cart an order , that are display in services resources section.However I don't how to use it in a url like your example I hope you can help me.
tyler
Tue, 10/22/2013 - 13:57
Permalink
Hi Carlos, this is something
Hi Carlos, this is something that I am still trying to learn as well. I've been working on a few tools to make this easier:
I still have very little knowledge about Commerce Services. The #drupal-commerce channel on IRC is a good place to chat with the experts.
handoyo (not verified)
Wed, 11/06/2013 - 23:41
Permalink
Hi Tyler,firs of all thanks
Hi Tyler,firs of all thanks for your tutorial about drupal services with phonegap.Currently i'm using drupal 7.29,services 3.5,phonegap 3.1,jquery 1.9.1,jquery mobile 1.3.2 . I cannot login by using the following script.Would you help me to point where is the problem ?Thanks a lot.
<a href="http://pastebin.com/VwuYmfqy">login.js</a>
<a href="http://pastebin.com/faR9CXD1">dashboard.js</a>
<a href="http://pastebin.com/kZn33Yg2">index.html</a>
tyler
Wed, 11/06/2013 - 23:57
Permalink
I'm guessing the problem is
I'm guessing the problem is in the login.js file. I don't think you need to retrieve the CSRF token before calling the User Login service resource. From my understanding, the CSRF token is only needed for authenticated users. So anonymous users making the login call don't need to pass along the token.
Be sure to check out DrupalGap, it takes care of login for you ;)
At this point DrupalGap is only designed to work with PhoneGap 2.9.0
Stop by #drupal-drupalgap on IRC to chat futher.
handoyo (not verified)
Thu, 11/07/2013 - 01:13
Permalink
Thanks a lot tyler.I'll check
Thanks a lot tyler.I'll check it out.
David (not verified)
Thu, 02/20/2014 - 04:54
Permalink
Hi Tyler, I have used your
Hi Tyler, I have used your tutorial at http://tylerfrankenstein.com/code/android-app-with-drupal-7-services-pho... to develop an application that creates nodes for a mapping site, thanks for the awesome work. Im having issues now using the node creation script to push dates and a digit(unique id) to a drupal site. The code im using to create the node is below and im currently testing everything in chromium browser:
http://pastebin.com/YC6A2FFP
The site has specified ISO date format and it is marked as required. The error in the chromium console is 406 (Not Acceptable: An illegal choice has been detected. Please contact the site administrator. A valid date is required for Date Visited. There are no entities matching "13975").
tyler
Thu, 02/20/2014 - 09:05
Permalink
Hi David,I had some troubles
Hi David,
I had some troubles populating a date field via Services as well. Here is what I found a few weeks ago:
Other than that, it sounds like there literally isn't an entity with an ID of 13975, please verify that exists.
Also, be sure to check out DrupalGap if you're using D7, it will make your life much easier! ;)
SniperSoft (not verified)
Wed, 03/05/2014 - 08:12
Permalink
Hello thank you for this
Hello thank you for this great tutorial.
I put a web service in drupal. Then I create a client symfoy2. The CRUD works very well.
In addition I add an action in my resource, but if I test it sends nothing.
tyler
Wed, 03/05/2014 - 12:33
Permalink
Are you using Drupal 8?
Are you using Drupal 8?
SniperSoft (not verified)
Thu, 03/06/2014 - 06:39
Permalink
Hello, no Drupal 7.
Hello, no Drupal 7.
Gaurav Gupta (not verified)
Wed, 04/02/2014 - 06:01
Permalink
Hey,
Hey,
I started development in drupal for about two months.
What i need is i have a form at a server and whole logic of saving and processing there.
Now i need that form on a different domain and i need to fetch that webpage.Getting stuck in it as i am a newbie.Can you help me in achieving this or can guide me giving suitable explanation.
tyler
Wed, 04/02/2014 - 10:47
Permalink
Take a stop by the Drupal
Take a stop by the Drupal channels on IRC for personalized support from the community
charubachi (not verified)
Fri, 04/11/2014 - 05:45
Permalink
Hi Tyler,
Hi Tyler,
Its actually very helpful. have you worked on the new release of services module 3.7.. I am not able to understand the logout functionality of it. its showing some CSRF invalide code error. I have checked for session authentication as well
tyler
Fri, 04/11/2014 - 08:18
Permalink
Check out user_logout() in
Check out user_logout() in jDrupal to see how User Logout works.
Salent (not verified)
Sun, 04/20/2014 - 09:55
Permalink
HI tyler.
HI tyler.
Its actually very helpful.But I'm having issues now using user login and connect
i use poster with my request :
url : http://localhost/homeShop/?q=service/user/login
My response status : 401 unauthorized CSRF validation failed
How to fix error ?
please help me
thanks in advance!
tyler
Sun, 04/20/2014 - 21:05
Permalink
Try logging out of your
Try logging out of your Drupal site in Firefox, before using Poster.
mitch (not verified)
Thu, 08/06/2015 - 11:38
Permalink
Hi Tyler ,
Hi Tyler ,
Thank you great help.
I've created 3 resources (all with CRUDI operations) now in a one of my cutom resources (this resource contain : create, update and a "specific" index(that show a list of items with a condition)) now i need to add another index (for other reasons)
My question : can i create a resource with multiple indexes in the CRUD operations ? (indexes are differents)
Thank you Tyler
tyler
Thu, 08/06/2015 - 12:05
Permalink
See these links:
See these links:
Franco Cedillo (not verified)
Fri, 11/13/2015 - 00:57
Permalink
hi
hi
I am pretty sure that when updating a taxonomy term there are two required fields
1. vid
2. name
vid could be determined from current vid
but, it could be possible that we want to change a tid from one taxonomy vocabulary to another
so, it is o.k. to consider vid a required field
but. name shouldn't be a required field when updating
¿don't you think so?
thanks for your answer
tyler
Fri, 11/13/2015 - 08:17
Permalink
The name is required in
The name is required in Drupal, therefore it's required via Services.
mhmd gomma (not verified)
Mon, 11/16/2015 - 09:16
Permalink
comment create/update
comment create/update resource needs to be updated as after services module update to be like (for the request body)
works for services 7.x-3.12 .
Conrads (not verified)
Tue, 03/07/2017 - 14:04
Permalink
If I'm logging into a
If I'm logging into a services endpoint over HTTPS, and I send
in plain text in the body of the request, like your example says, is that going to be safe?
I might need to edit customer data in Drupal Commerce, and I don't want hackers getting hold of the REST user's credentials
tyler
Tue, 03/07/2017 - 14:34
Permalink
Over https is safe.
Over https is safe.
Conrads (not verified)
Mon, 05/01/2017 - 14:53
Permalink
I can't assign a node to a
I can't assign a node to a taxonomy with Services. I've tried sending the "tid" value and the "name" value to the endpoint for the specific node, but neither one works. The node's field remains blank.
tyler
Mon, 05/01/2017 - 15:13
Permalink
It depends on what type of
It depends on what type of field you are using, i.e. taxonomy term reference field, or an entity reference field, and then it depends on what widget you are using for that field's configuration. I personally only use entity reference fields now when referencing taxonomy terms, and no longer use a taxonomy term reference field (provided by core). From there, just Google for "Drupal 7 Services Entity Reference Field" or "Drupal 7 Services Taxonomy Term Reference Field" and you should find responses from myself and others talking about the various formats to use depending on the widget you have selected for your field instance.
Optionally check out the services_entity project on d.o, that module makes it much easier to POST the straight JSON representation of an entity without having to worry about the nuances of the Services module in regards to it being built on top of the Drupal Forms API.
Conrads (not verified)
Tue, 05/02/2017 - 15:04
Permalink
That worked like a charm, but
That worked like a charm, but now I need to reassign the categories on thousands of nodes, and then rewrite my views to use the "entity reference" as the required relationship.
But another problem has come up: Do you know if there's any way to get a drupal commerce product to be assigned to a product display with Services?
tyler
Tue, 05/02/2017 - 15:11
Permalink
You can use a Batch script to
You can use a Batch script to process thousands of entities are re-assign values to your new field: http://tylerfrankenstein.com/code/drupal-batch-example
For Commerce Services, checkout this project: https://www.drupal.org/project/commerce_services
It's not very well maintained, I've got a few patches in the queue that are yet to be reviewed, but have used them in the past for clients.
Conrads (not verified)
Thu, 05/04/2017 - 17:19
Permalink
This can be done with rules.
This can be done with rules.
1.) Add a new field to your Product Display. For my project, I used "Item Number."
2.) Add a new field to your Commerce Product variations For my project, I used "Parent Item."
3.) Add new commerce product variations, and make sure to set a Parent Item that matches the Item Number you'll use in the Product Display.
4.) Set up a rule to run on the event "After updating existing content of type Product Display," or "After saving new content of type Product Display." Depending on your workflow needs, you may want the run to run after both events.
5.) Add any conditions you need to restrict the rule, so that it only runs based on your workflow needs.
6.) Add an action "Fetch Entity by Property."
7.) Set the entity type to "Commerce Products," and then set the Property to "Parent Item." Set the Value data selector to "node:field-item-number." Remove the number from "Limit Result Count" so that ALL your product variations that have the right "Parent Item" setting get used.
8.) Add a loop to your rule. Set the List data selector to "entity-fetched." It won't matter how many entities get fetched, the loop will handle all of them.
9.) Add "Add an item to a list" to the LOOP in the rule. Set the List data selector to "node:field-item-type," or whatever your Product Reference field is called. Set the Item to add data selector to "list-item." Set "enforce uniqueness" to "True." Set "Insert Position" to whatever your workflow needs are.
10.) Save the rule.
Always add your commerce products FIRST. Once you're finished adding them (you can add them in REST API also), then you can add your corresponding product display. If it works, your new product display will automatically contain your new commerce products.
If this does NOT work:
1.) Go to "Structure > Content Types > Product Display" and pick "Manage Fields."
2.) Change the Widget for your "Product reference" field to "Autocomplete text field."
3.) Save your product display content type.
I tested this method, and it worked. A product display t-shirt with sizes running "S," "M," "L," "XL," "2X," and "3X" had lost its commerce products due to a glitch I made when updating products via REST API. I used my item as a guinea pig and edited the "Body" field of the Product Display.
When the product display finished saving, I looked at it in my storefront, and the "Add to Cart" button had reappeared with my sizing options the way I needed them to appear.
maikel (not verified)
Sun, 03/25/2018 - 14:56
Permalink
Thank by your answer. I need
Thank by your answer. I need login with email. Any Idea ??
tyler
Mon, 03/26/2018 - 11:21
Permalink
https://www.drupal.org
https://www.drupal.org/project/logintoboggan/issues/1431724