Skip navigation
All Places > Developer > Blog > 2014 > February
2014

Developer

February 2014 Previous month Next month

Post originally written by sugarmajed.

 

This is the final section of the School of Rest. We'll be covering filtering on relationships as well as Global Search, Favorites, and Deleting records.

 

We've already created our Account "Burger Palace" in Part 1 and showed how to filter lists with various conditions.

 

And in Part 2 we created our Contact "Bob Burger" and related him to "Burger Palace". Now we'll show how these same concepts apply to relationships.

 

11. Filtering on Relationships

 

All the same stuff that we learned for filtering on lists can be applied to relationships as well. Let's retrieve all the Contacts that are related to "Burger Palace" whose first and last name starts with "B" and who we have marked as a favorite.

 

To filter on first and last name we know the filter looks like

filter[0][first_name][$starts]=B and filter[0][last_name][$starts]=B

 

But what about favorites? Favorites are a way for users to specify which records are important to them and they have a special filter condition that looks like

filter[0][$favorite]=_this

 

So we will do a GET request to /rest/v10/Accounts/demo_burger_palace/link/contacts?filter[0][last_name][$starts]=b&filter[0][first_name][$starts]=b&filter[0][$favorite]=_this&fields=name,first_name,last_name,email,description

 

CURL Filter Relationships.sh

curl -X GET -H OAuth-Token:8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4 -H Cache-Control:no-cache -H Postman-Token:a86bc38a-8c3f-d364-fbfe-282e41b10645 http://server/pro720/rest/v10/Accounts/demo_burger_palace/link/contacts?filter[0][last_name][$starts]=b&filter[0][first_name][$starts]=b&filter[0][$favorite]=_this

GET Filter Relationships.http

GET /pro720/rest/v10/Accounts/demo_burger_palace/link/contacts?filter%5B0%5D%5Blast_name%5D%5B%24starts%5D=b&filter%5B0%5D%5Bfirst_name%5D%5B%24starts%5D=b&filter%5B0%5D%5B%24favorite%5D=_this HTTP/1.1
Host: server
OAuth-Token: 8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4
Cache-Control: no-cache
Postman-Token: fc8df8eb-c475-28bc-ca03-6b7ee511a069


Response.json

{
"next_offset": -1,
"records": []
}

 

 

Well that didn't work to well. First, we need to mark "Bob Burger" as a favorite.

 

12. Mark a Contact as a Favorite - Bob Burger

 

All we need to do is a PUT to  /rest/v10/Contacts/demo_bob_burger/favorite

 

This works on all modules that support favorites, and allows us to quickly filter our favorite records.

 

CURL PUT Favorite Contact.sh

curl -X PUT -H OAuth-Token:8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4 -H Cache-Control:no-cache -H Postman-Token:69fc3540-0acd-0186-c0c9-cb95ac352bd8 -H Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryp7MA4YWxkTrZu0gW http://server/pro720/rest/v10/Contacts/demo_bob_burger/favorite

PUT Favorite Contact.http

PUT /pro720/rest/v10/Contacts/demo_bob_burger/favorite HTTP/1.1
Host: server
OAuth-Token: 8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4
Cache-Control: no-cache
Postman-Token: cb2d99d7-241d-e4e2-71b3-f9a432d72a12
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryp7MA4YWxkTrZu0gW


Response.json

{
"id": "demo_bob_burger",
"name": "Bob Burger",
"date_entered": "2014-02-25T12:16:41-08:00",
"date_modified": "2014-02-25T12:21:22-08:00",
"modified_user_id": "1",
"modified_by_name": "Administrator",
"created_by": "1",
"created_by_name": "Administrator",
"doc_owner": "",
"user_favorites": [
"1"
    ],
"description": "Bob Burger was updated",
"deleted": false,
"assigned_user_id": "",
"assigned_user_name": "",
"team_count": "",
"team_name": [
        {
"id": 1,
"name": "Global",
"name_2": "",
"primary": true
        }
    ],
"email": [
        {
"email_address": "bob.burger@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
        }
    ],
"email1": "bob.burger@example.com",
"email2": "",
"invalid_email": false,
"email_opt_out": false,
"salutation": "",
"first_name": "Bob",
"last_name": "Burger",
"full_name": "Bob Burger",
"title": "",
"facebook": "",
"twitter": "",
"googleplus": "",
"department": "",
"do_not_call": false,
"phone_home": "",
"phone_mobile": "",
"phone_work": "",
"phone_other": "",
"phone_fax": "",
"primary_address_street": "",
"primary_address_street_2": "",
"primary_address_street_3": "",
"primary_address_city": "",
"primary_address_state": "",
"primary_address_postalcode": "",
"primary_address_country": "",
"alt_address_street": "",
"alt_address_street_2": "",
"alt_address_street_3": "",
"alt_address_city": "",
"alt_address_state": "",
"alt_address_postalcode": "",
"alt_address_country": "",
"assistant": "",
"assistant_phone": "",
"picture": "",
"email_and_name1": "",
"lead_source": "",
"account_name": "Burger Palace",
"account_id": "demo_burger_palace",
"dnb_principal_id": "",
"opportunity_role_fields": "",
"opportunity_role_id": "",
"opportunity_role": "",
"reports_to_id": "",
"report_to_name": "",
"birthdate": "",
"campaign_id": "",
"campaign_name": "",
"c_accept_status_fields": "",
"m_accept_status_fields": "",
"accept_status_id": "",
"accept_status_name": "",
"accept_status_calls": "",
"accept_status_meetings": "",
"sync_contact": false,
"mkto_sync": false,
"mkto_id": null,
"mkto_lead_score": null,
"my_favorite": true,
"_acl": {
"fields": {}
    },
"following": true,
"_module": "Contacts"
}

 

You'll notice in the response the record now says "my_favorite" is true.

 

If we wanted to unmark a record as a favorite we would just do a DELETE  to /rest/v10/Contacts/demo_bob_burger/favorite

 

13. Try Step 11 Again!

 

Let's re-run the relationship filter from Step 10! Let's do a GET request to /rest/v10/Accounts/demo_burger_palace/link/contacts?filter[0][last_name][$starts]=b&filter[0][first_name][$starts]=b&filter[0][$favorite]=_this&fields=name,first_name,last_name,email,description

 

CURL filter relationships again.sh

curl -X GET -H OAuth-Token:d1645103-c562-e439-c0d0-530d2f4e3801 -H Cache-Control:no-cache -H Postman-Token:4ab308ee-7902-6a3f-dc9c-f8bb595dec97 http://server/pro720/rest/v10/Accounts/demo_burger_palace/link/contacts?filter[0][last_name][$starts]=b&filter[0][first_name][$starts]=b&filter[0][$favorite]=_this&fields=name,first_name,last_name,email,description

GET Filter Relationships Again.http

GET /pro720/rest/v10/Accounts/demo_burger_palace/link/contacts?filter%5B0%5D%5Blast_name%5D%5B%24starts%5D=b&filter%5B0%5D%5Bfirst_name%5D%5B%24starts%5D=b&filter%5B0%5D%5B%24favorite%5D=_this&fields=name%2Cfirst_name%2Clast_name%2Cemail%2Cdescription HTTP/1.1
Host: server
OAuth-Token: d1645103-c562-e439-c0d0-530d2f4e3801
Cache-Control: no-cache
Postman-Token: 8ee8836c-e7c4-51e8-a187-bbfd92e6a790


Response.json

{
"next_offset": -1,
"records": [
        {
"id": "demo_bob_burger",
"name": "Bob Burger",
"date_modified": "2014-02-25T15:03:01-08:00",
"description": "Bob Burger was updated",
"email": [
                {
"email_address": "bob.burger@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
                }
            ],
"first_name": "Bob",
"last_name": "Burger",
"_acl": {
"fields": {}
            },
"_module": "Contacts"
        }
    ]
}

 

 

Excellent! Now that's what we expected!

 

14. Filter by a Related record

 

Now, let's filter our Accounts list for only records that have a contact with the last name "burger". Our filter condition will look like filter[0][contacts.last_name]=burger and remember that "contacts" in this case is the Link or Relationship Name not the module name.

 

So let's do a GET to rest/v10/Accounts?filter[0][contacts.last_name]=burger

curl -X GET \  'http://server/pro720/rest/v10/Accounts?filter%5B0%5D%5Bcontacts.last_name%5D=burger&fields=name%2Cfirst_name%2Clast_name%2Cemail%2Cdescription' \  -H 'cache-control: no-cache' \  -H 'oauth-token: 39ba05eb-2289-4770-ac39-9fe03f99c77a' \  -H 'postman-token: 65094f2f-ae73-851b-11b1-995e66eb1779'
GET /pro720/rest/v10/Accounts?filter[0][contacts.last_name]=burger&fields=name,first_name,last_name,email,description HTTP/1.1
Host: server
OAuth-Token: 39ba05eb-2289-4770-ac39-9fe03f99c77a
Cache-Control: no-cache
Postman-Token: 598e3c09-43cd-2e7c-704e-0ffbd0378a1e
{
     "next_offset": -1,
     "records": [
         {
             "id": "demo_burger_palace",
             "name": "Burger Palace",
             "date_modified": "2017-07-28T10:14:29-04:00",
             "description": "My Example Account",
             "locked_fields": [],
             "email": [
                 {
                     "email_address": "burgers@example.com",
                     "primary_address": true,
                     "reply_to_address": false,
                     "invalid_email": false,
                     "opt_out": false
                 }
             ],
             "_acl": {
                 "fields": {}
             },
             "_module": "Accounts"
         }
    ]
}

Great! We got "Burger Palace" which is what we wanted.

 

15. Global Search/Full Text Search 

 

Now let's just search everywhere for the word "burger" and see what we get! All we have to do is a GET request to /rest/v10/search?q=burger  and that will search against SugarCRM's Full Text Search.

 

CURL Full Text Search.sh

curl -X GET -H OAuth-Token:4ef8594d-5b45-20f4-0a01-530d20d69d1f -H Cache-Control:no-cache -H Postman-Token:e76d2d29-bc10-bea7-c2b6-761e49a8a197 http://server/ent720/rest/v10/search?q=burger&fields=name,email,description

GET Full Text Search.http

GET /ent720/rest/v10/search?q=burger&fields=name%2Cemail%2Cdescription HTTP/1.1
Host: server
OAuth-Token: 4ef8594d-5b45-20f4-0a01-530d20d69d1f
Cache-Control: no-cache
Postman-Token: 7aeedc64-602a-535d-7c0d-b32bf2e1a035

Response.json

{
"next_offset": -1,
"records": [
        {
"id": "demo_bob_burger",
"name": "Bob Burger",
"date_modified": "2014-02-25T23:03:01+00:00",
"description": "Bob Burger was updated",
"email": [
                {
"email_address": "bob.burger@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
                }
            ],
"_acl": {
"fields": {}
            },
"_module": "Contacts",
"_search": {
"score": 1,
"highlighted": {
"last_name": {
"text": "<strong>Burger</strong>",
"module": "Contacts",
"label": "LBL_LAST_NAME"
                    }
                }
            },
"following": true
        },
        {
"id": "demo_burger_palace",
"name": "Burger Palace",
"date_modified": "2014-02-25T23:01:42+00:00",
"description": "My Example Account",
"email": [
                {
"email_address": "burgers@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
                }
            ],
"_acl": {
"fields": {}
            },
"_module": "Accounts",
"_search": {
"score": 1,
"highlighted": {
"name": {
"text": "<strong>Burger</strong> Palace",
"module": "Accounts",
"label": "LBL_NAME"
                    },
"email1": {
"text": "<strong>burgers</strong>@example.com",
"module": "Accounts",
"label": "LBL_EMAIL_ADDRESS"
                    }
                }
            },
"following": true
        }
    ]
}

 

We got two records back - "Burger Palace" and "Bob Burger". So using Global Search/Full Text Search we can search against all of our objects at once!

 

16.  Let's Clean Up

 

All we need to do is a DELETE request to /rest/v10/Accounts/demo_burger_palace

 

and another DELETE request to /rest/v10/Contacts/demo_bob_burger

 

And remember there is more documentation at /rest/v10/help!

Post originally written by sugarmajed.

 

This is part 2 of 3 of The School of REST. In Part 1 we covered creating our Account "Burger Palace" and using the filter API to get just the records we wanted. Today we'll cover retrieving records, creating our Contact "Bob Burger", updating records, and associating records together. 

 

6. Retrieve a specific Account - Burger Palace 

 

We created "Burger Palace" with the id "demo_burger_palace". To retrieve it using the RESTful interface, we just need to do a GET to rest/v10/Accounts/demo_burger_palace

 

CURL GET Account.sh

curl -X GET -H OAuth-Token:e2505ba8-fc56-de05-ce9f-530d1bf56227 -H Cache-Control:no-cache -H Postman-Token:7e4c0a5d-db74-55d7-64a7-8c363686f9de http://server/pro720/rest/v10/Accounts/demo_burger_palace?fields=name,email,account_type,description


GET Account.http

GET /pro720/rest/v10/Accounts/demo_burger_palace?fields=name%2Cemail%2Caccount_type%2Cdescription HTTP/1.1
Host: server
OAuth-Token: e2505ba8-fc56-de05-ce9f-530d1bf56227
Cache-Control: no-cache
Postman-Token: 7e2f14d9-3868-3d38-c9f2-b3c36a3105b0


Response.json

{
"id": "demo_burger_palace",
"date_modified": "2014-02-25T14:32:25-08:00",
"description": "My Example Account",
"email": [
        {
"email_address": "burgers@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
        }
    ],
"account_type": "Customer",
"_acl": {
"fields": {}
    },
"_module": "Accounts"
}


7. Create a Contact - Bob Burger 

 

We have our customer account "Burger Palace", but relationships are all about the people. Let's create a Contact named "Bob Burger". Using what we learned against Accounts, we can apply it to Contacts. Let's do a POST to /rest/v10/Contacts

 

We'll create "Bob Burger" with the id "demo_bob_burger". Remember the we DO NOT need to pass in the id. We are only doing this for demo purposes right now. SugarCRM will automatically generate an id and return it as part of the response.

 

CURL POST Contacts.sh

curl -X POST -H OAuth-Token:8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4 -H Cache-Control:no-cache -H Postman-Token:0444b90d-ba1d-c395-a259-694115e5ec1e -d '{ "id":"demo_bob_burger", "first_name":"Bob", "last_name": "Burger", "description":"Bob Burger is a new contact" }' http://server/pro720/rest/v10/Contacts


POST Contacts.http

POST /pro720/rest/v10/Contacts HTTP/1.1
Host: server
OAuth-Token: 8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4
Cache-Control: no-cache
Postman-Token: 27bb113b-ef6f-86dc-601e-e2f8e2c4878c

{ "id":"demo_bob_burger", "first_name":"Bob", "last_name": "Burger", "description":"Bob Burger is a new contact" }

Response.json

{
"id": "demo_bob_burger",
"name": "Bob Burger",
"date_entered": "2014-02-25T12:16:41-08:00",
"date_modified": "2014-02-25T12:16:41-08:00",
"modified_user_id": "1",
"modified_by_name": "Administrator",
"created_by": "1",
"created_by_name": "Administrator",
"doc_owner": "",
"user_favorites": "",
"description": "Bob Burger is a new contact",
"deleted": false,
"assigned_user_id": "",
"assigned_user_name": "",
"team_count": "",
"team_name": [
        {
"id": 1,
"name": "Global",
"name_2": "",
"primary": true
        }
    ],
"email": [],
"email1": "",
"email2": "",
"invalid_email": "",
"email_opt_out": "",
"salutation": "",
"first_name": "Bob",
"last_name": "Burger",
"full_name": "Bob Burger",
"title": "",
"facebook": "",
"twitter": "",
"googleplus": "",
"department": "",
"do_not_call": false,
"phone_home": "",
"phone_mobile": "",
"phone_work": "",
"phone_other": "",
"phone_fax": "",
"primary_address_street": "",
"primary_address_street_2": "",
"primary_address_street_3": "",
"primary_address_city": "",
"primary_address_state": "",
"primary_address_postalcode": "",
"primary_address_country": "",
"alt_address_street": "",
"alt_address_street_2": "",
"alt_address_street_3": "",
"alt_address_city": "",
"alt_address_state": "",
"alt_address_postalcode": "",
"alt_address_country": "",
"assistant": "",
"assistant_phone": "",
"picture": "",
"email_and_name1": "",
"lead_source": "",
"account_name": "",
"account_id": "",
"dnb_principal_id": "",
"opportunity_role_fields": "",
"opportunity_role_id": "",
"opportunity_role": "",
"reports_to_id": "",
"report_to_name": "",
"birthdate": "",
"campaign_id": "",
"campaign_name": "",
"c_accept_status_fields": "",
"m_accept_status_fields": "",
"accept_status_id": "",
"accept_status_name": "",
"accept_status_calls": "",
"accept_status_meetings": "",
"sync_contact": false,
"mkto_sync": false,
"mkto_id": null,
"mkto_lead_score": null,
"my_favorite": false,
"_acl": {
"fields": {}
    },
"following": true,
"_module": "Contacts"
}

 

8. Update a Record - Bob Burger 

 

Great, we've created "Bob Burger" by doing a POST request. Now let's update him by doing a PUT request to /rest/v10/Contacts/demo_bob_burger

 

CURL PUT Contact.sh

curl -X PUT -H OAuth-Token:8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4 -H Cache-Control:no-cache -H Postman-Token:63ba84bf-612d-7210-c328-29f50f3f4b92 -d '{ "email":[{"email_address":"bob.burger@example.com"}], "description":"Bob Burger was updated" }' http://server/pro720/rest/v10/Contacts/demo_bob_burger

PUT Contact.http

PUT /pro720/rest/v10/Contacts/demo_bob_burger HTTP/1.1
Host: server
OAuth-Token: 8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4
Cache-Control: no-cache
Postman-Token: 24ae44a6-1720-b644-f236-f347226f18e4

{ "email":[{"email_address":"bob.burger@example.com"}], "description":"Bob Burger was updated" }

Response.json

{
"id": "demo_bob_burger",
"name": "Bob Burger",
"date_entered": "2014-02-25T12:16:41-08:00",
"date_modified": "2014-02-25T12:21:22-08:00",
"modified_user_id": "1",
"modified_by_name": "Administrator",
"created_by": "1",
"created_by_name": "Administrator",
"doc_owner": "",
"user_favorites": "",
"description": "Bob Burger was updated",
"deleted": false,
"assigned_user_id": "",
"assigned_user_name": "",
"team_count": "",
"team_name": [
        {
"id": 1,
"name": "Global",
"name_2": "",
"primary": true
        }
    ],
"email": [
        {
"email_address": "bob.burger@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
        }
    ],
"email1": "bob.burger@example.com",
"email2": "",
"invalid_email": false,
"email_opt_out": false,
"salutation": "",
"first_name": "Bob",
"last_name": "Burger",
"full_name": "Bob Burger",
"title": "",
"facebook": "",
"twitter": "",
"googleplus": "",
"department": "",
"do_not_call": false,
"phone_home": "",
"phone_mobile": "",
"phone_work": "",
"phone_other": "",
"phone_fax": "",
"primary_address_street": "",
"primary_address_street_2": "",
"primary_address_street_3": "",
"primary_address_city": "",
"primary_address_state": "",
"primary_address_postalcode": "",
"primary_address_country": "",
"alt_address_street": "",
"alt_address_street_2": "",
"alt_address_street_3": "",
"alt_address_city": "",
"alt_address_state": "",
"alt_address_postalcode": "",
"alt_address_country": "",
"assistant": "",
"assistant_phone": "",
"picture": "",
"email_and_name1": "",
"lead_source": "",
"account_name": "",
"account_id": "",
"dnb_principal_id": "",
"opportunity_role_fields": "",
"opportunity_role_id": "",
"opportunity_role": "",
"reports_to_id": "",
"report_to_name": "",
"birthdate": "",
"campaign_id": "",
"campaign_name": "",
"c_accept_status_fields": "",
"m_accept_status_fields": "",
"accept_status_id": "",
"accept_status_name": "",
"accept_status_calls": "",
"accept_status_meetings": "",
"sync_contact": false,
"mkto_sync": false,
"mkto_id": null,
"mkto_lead_score": null,
"my_favorite": false,
"_acl": {
"fields": {}
    },
"following": true,
"_module": "Contacts"
}

 

9. Let's associate our Contact and Account 

 

We have "Burger Palace" and "Bob Burger" now let's bring them together by doing a POST to /rest/v10/Accounts/demo_burger_palace/link

 

We'll need to pass two arguments.

  1.  a list of ids we wish to relate to "Burger Palace" which in this case is demo_bob_burger.
  2.  a link_name which is the name of the relationship we wish to use. In this case it is "contacts", but it's not always the name of the related module.

 

CURL Associate Account Contact.sh

curl -X POST -H OAuth-Token:8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4 -H Cache-Control:no-cache -H Postman-Token:f6e69685-303c-14b4-d1a7-c70cfa00f17f -d '{ "link_name": "contacts", "ids": ["demo_bob_burger"] }' http://server/pro720/rest/v10/Accounts/demo_burger_palace/link

POST Link.http

POST /pro720/rest/v10/Accounts/demo_burger_palace/link HTTP/1.1
Host: server
OAuth-Token: 8f027f7a-266a-dcd0-8dc4-530cfa3ce6d4
Cache-Control: no-cache
Postman-Token: 20fc86b9-644b-f2fb-ca11-8b304587eff6

{ "link_name": "contacts", "ids": ["demo_bob_burger"] }


Response.json

{
"related_records": [
        {
"id": "demo_bob_burger",
"name": "Bob Burger",
"date_entered": "2014-02-25T12:16:41-08:00",
"date_modified": "2014-02-25T12:21:22-08:00",
"modified_user_id": "1",
"modified_by_name": "Administrator",
"created_by": "1",
"created_by_name": "Administrator",
"doc_owner": "",
"user_favorites": "",
"description": "Bob Burger was updated",
"deleted": false,
"assigned_user_id": "",
"assigned_user_name": "",
"team_count": "",
"team_name": [
                {
"id": 1,
"name": "Global",
"name_2": "",
"primary": true
                }
            ],
"email": [
                {
"email_address": "bob.burger@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
                }
            ],
"email1": "bob.burger@example.com",
"email2": "",
"invalid_email": false,
"email_opt_out": false,
"salutation": "",
"first_name": "Bob",
"last_name": "Burger",
"full_name": "Bob Burger",
"title": "",
"facebook": "",
"twitter": "",
"googleplus": "",
"department": "",
"do_not_call": false,
"phone_home": "",
"phone_mobile": "",
"phone_work": "",
"phone_other": "",
"phone_fax": "",
"primary_address_street": "",
"primary_address_street_2": "",
"primary_address_street_3": "",
"primary_address_city": "",
"primary_address_state": "",
"primary_address_postalcode": "",
"primary_address_country": "",
"alt_address_street": "",
"alt_address_street_2": "",
"alt_address_street_3": "",
"alt_address_city": "",
"alt_address_state": "",
"alt_address_postalcode": "",
"alt_address_country": "",
"assistant": "",
"assistant_phone": "",
"picture": "",
"email_and_name1": "",
"lead_source": "",
"account_name": "",
"account_id": "",
"dnb_principal_id": "",
"opportunity_role_fields": "",
"opportunity_role_id": "",
"opportunity_role": "",
"reports_to_id": "",
"report_to_name": "",
"birthdate": "",
"campaign_id": "",
"campaign_name": "",
"c_accept_status_fields": "",
"m_accept_status_fields": "",
"accept_status_id": "",
"accept_status_name": "",
"accept_status_calls": "",
"accept_status_meetings": "",
"sync_contact": false,
"mkto_sync": false,
"mkto_id": null,
"mkto_lead_score": null,
"my_favorite": false,
"_acl": {
"fields": {}
            },
"following": true,
"_module": "Contacts"
        }
    ],
"record": {
"id": "demo_burger_palace",
"name": "Burger Palace",
"date_entered": "2014-02-25T10:51:51-08:00",
"date_modified": "2014-02-25T10:51:51-08:00",
"modified_user_id": "1",
"modified_by_name": "Administrator",
"created_by": "1",
"created_by_name": "Administrator",
"doc_owner": "",
"user_favorites": "",
"description": "My Example Account",
"deleted": false,
"assigned_user_id": "",
"assigned_user_name": "",
"team_count": "",
"team_name": [
            {
"id": 1,
"name": "Global",
"name_2": "",
"primary": true
            }
        ],
"email": [
            {
"email_address": "burgers@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
            }
        ],
"email1": "burgers@example.com",
"email2": "",
"invalid_email": false,
"email_opt_out": false,
"facebook": "",
"twitter": "",
"googleplus": "",
"account_type": "Customer",
"industry": "",
"annual_revenue": "",
"phone_fax": "",
"billing_address_street": "",
"billing_address_street_2": "",
"billing_address_street_3": "",
"billing_address_street_4": "",
"billing_address_city": "",
"billing_address_state": "",
"billing_address_postalcode": "",
"billing_address_country": "",
"rating": "",
"phone_office": "",
"phone_alternate": "",
"website": "",
"ownership": "",
"employees": "",
"ticker_symbol": "",
"shipping_address_street": "",
"shipping_address_street_2": "",
"shipping_address_street_3": "",
"shipping_address_street_4": "",
"shipping_address_city": "",
"shipping_address_state": "",
"shipping_address_postalcode": "",
"shipping_address_country": "",
"parent_id": "",
"sic_code": "",
"duns_num": "",
"parent_name": "",
"campaign_id": "",
"campaign_name": "",
"my_favorite": false,
"_acl": {
"fields": {}
        },
"following": true,
"_module": "Accounts"
    }
}


10. Get Contacts Associated to an Account - Burger Palace

 

We just related "Bob Burger" to "Burger Palace" now let's view that relationship by retrieving the contacts related to "Burger Palace". All we need to do is a GET request to /rest/v10/Accounts/demo_burger_palace/link/contacts where "contacts" is the same link_name we passed up in step 9. 

 

CURL Related Contacts.sh

curl -X GET -H OAuth-Token:e2505ba8-fc56-de05-ce9f-530d1bf56227 -H Cache-Control:no-cache -H Postman-Token:54bc4cd3-b893-ca1e-1ad4-2eaf40ca9f8e http://server/pro720/rest/v10/Accounts/demo_burger_palace/link/contacts?fields=name,first_name,last_name,email,description

GET  Related Contacts.http

GET /pro720/rest/v10/Accounts/demo_burger_palace/link/contacts?fields=name%2Cfirst_name%2Clast_name%2Cemail%2Cdescription HTTP/1.1
Host: server
OAuth-Token: e2505ba8-fc56-de05-ce9f-530d1bf56227
Cache-Control: no-cache
Postman-Token: 7edacde4-62c2-72ea-8c33-645df954e0cf


Response.json

{
"next_offset": -1,
"records": [
        {
"id": "demo_bob_burger",
"name": "Bob Burger",
"date_modified": "2014-02-25T14:44:24-08:00",
"description": "Bob Burger was updated",
"email": [
                {
"email_address": "bob.burger@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
                }
            ],
"first_name": "Bob",
"last_name": "Burger",
"_acl": {
"fields": {}
            },
"_module": "Contacts"
        }
    ]
}

 

Now you'll see in the response that "Bob Burger" is associated to "Burger Palace"

 

Continue on to Part 3  - Filtering on Relationships, Favorites, and Deleting Records 

Post originally written by sugarmajed.

 

Welcome to the School of REST - our first installment in the Sugar 7 Cookbook Series! We've always believed that DATA belongs to you and it should always be accessible to you! With Sugar 7 we've added a completely revamped REST API. Today we are going to cover all the basics of pushing data into and getting data out of your SugarCRM instance. For each of the API calls we'll show how to do it in curl, a generic HTTP Request, as well as showing you the response. Also, before we get started you can always hit /rest/v10/help for detailed documentation on all the APIs.

 

In this Guide we will be creating an Account "Burger Palace" and relating it to a Contact "Bob Burger". We will then show you the ins and outs of Creating and Updating Records, Filtering Lists, Creating Relationships, Filtering on Relationships, Marking Records as Favorites, and Deleting Records.

 

This guide is broken into 3 sections.

 

Part 1 - Connecting, Creating Records, and Filtering Lists

Part 2 - Retrieving, Updating, and Relating Records 

Part 3  - Filtering on Relationships, Favorites, and Deleting Records 

 

You may want to download PostMan for Chrome to follow along interactively from  http://www.getpostman.com/

 

You can download Our Cookbook1 PostMan collection from  https://gist.github.com/mitani/f39e8d94df9fbda4d97d

 

Step 1. Connecting/Authenticating

 

Sugar 7 uses two-legged OAuth2 for authentication. You simply need to do a POST to /rest/v10/oauth2/token with the following params:

grant_typeStringType of request. Available grant types are "password" and "refresh_token".
client_idStringThe client_id of "sugar" will automatically create an OAuth Key in the system and can be used for "password" authentication. The client_id of "support_portal" will create an OAuth Key if the portal system is enabled and will allow for portal authentication. Other client_id's can be created by the administrator in the OAuthKeys section in the Administration section and can be used in the future for additional grant types, if the client secret is filled in, it will be checked to validate use of the client id.
client_secretStringThe clients secret key.
usernameStringThe username of the user authenticating to the system.
passwordStringThe plaintext password the user authenticating to the system.
platformStringDefaults to "base" allows you to have custom meta-data per platform

 

 

So, first we are going to login using a grant_type of "password".

 

CURL.sh

curl -X POST -H Cache-Control:no-cache -H Postman-Token:a6ae8f76-442f-06cf-1072-db18b0ad29a3 -d '{ "grant_type":"password", "client_id":"sugar", "client_secret":"", "username":"username", "password":"password", "platform":"base" }' http://server/pro720/rest/v10/oauth2/token


POST token.http

POST /pro720/rest/v10/oauth2/token HTTP/1.1
Host: Server
Cache-Control: no-cache
Postman-Token: 83a606e1-26f6-ff21-dd5d-f25f6cb735eb

{ "grant_type":"password", "client_id":"sugar", "client_secret":"", "username":"username", "password":"password", "platform":"base" }

response.json

{
"access_token": "5ee48ec7-023e-ecff-5184-530bd0358868",
"expires_in": 3600,
"token_type": "bearer",
"scope": null,
"refresh_token": "5f197357-0167-f7a6-7912-530bd03275b6",
"refresh_expires_in": 1209600,
"download_token": "5f531625-e301-e3ea-1b11-530bd098be41"
}

 

 

Once you get the response you'll need to hold onto the access_token and the refresh_token. Anytime the access_token is invalidated, you'll want to make another request to the token endpoint with a grant_type of "refresh_token". Store just the refresh_token in long term storage - not the username and password.

 

For all the following requests we are going to pass in a header of OAuth-Token: {{your access token here}}

 

2. Create an Account - Burger Palace

 

Now that we have the access_token we can start having some fun! Let's create a new customer - "Burger Palace" as an Account.

 

Being that everything is RESTful creating a new record is just a POST away. In this case we just do a POST to /rest/v10/Accounts.

 

For this example we will be posting an id as part of the record. You do not need to do this as SugarCRM will automatically generate an id for your record.

 

CURL Accounts.sh

curl -X POST -H OAuth-Token:9126cdb4-0c4e-4796-1a4f-530bccd48060 -H Cache-Control:no-cache -H Postman-Token:cb3331fa-7e62-1f11-9fae-cb9731bc3500 -d '{ "id":"demo_burger_palace", "name":"Burger Palace", "account_type":"Customer", "description":"My Example Account", "email":[{"email_address":"burgers@example.com"}] }' http://server/pro720/rest/v10/Accounts


POST Accounts.http

POST /pro720/rest/v10/Accounts HTTP/1.1
Host: server
OAuth-Token: 9126cdb4-0c4e-4796-1a4f-530bccd48060
Cache-Control: no-cache
Postman-Token: 90329f95-f2a9-fd87-c4cf-421fdd9f24ae

{ "id":"demo_burger_palace", "name":"Burger Palace", "account_type":"Customer", "description":"My Example Account", "email":[{"email_address":"burgers@example.com"}] }

Response.json

{
"id": "demo_burger_palace",
"name": "Burger Palace",
"date_entered": "2014-02-25T10:51:51-08:00",
"date_modified": "2014-02-25T10:51:51-08:00",
"modified_user_id": "1",
"modified_by_name": "Administrator",
"created_by": "1",
"created_by_name": "Administrator",
"doc_owner": "",
"user_favorites": "",
"description": "My Example Account",
"deleted": false,
"assigned_user_id": "",
"assigned_user_name": "",
"team_count": "",
"team_name": [
        {
"id": 1,
"name": "Global",
"name_2": "",
"primary": true
        }
    ],
"email": [
        {
"email_address": "burgers@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
        }
    ],
"email1": "burgers@example.com",
"email2": "",
"invalid_email": false,
"email_opt_out": false,
"facebook": "",
"twitter": "",
"googleplus": "",
"account_type": "Customer",
"industry": "",
"annual_revenue": "",
"phone_fax": "",
"billing_address_street": "",
"billing_address_street_2": "",
"billing_address_street_3": "",
"billing_address_street_4": "",
"billing_address_city": "",
"billing_address_state": "",
"billing_address_postalcode": "",
"billing_address_country": "",
"rating": "",
"phone_office": "",
"phone_alternate": "",
"website": "",
"ownership": "",
"employees": "",
"ticker_symbol": "",
"shipping_address_street": "",
"shipping_address_street_2": "",
"shipping_address_street_3": "",
"shipping_address_street_4": "",
"shipping_address_city": "",
"shipping_address_state": "",
"shipping_address_postalcode": "",
"shipping_address_country": "",
"parent_id": "",
"sic_code": "",
"duns_num": "",
"parent_name": "",
"campaign_id": "",
"campaign_name": "",
"my_favorite": false,
"_acl": {
"fields": {}
    },
"following": true,
"_module": "Accounts"
}

 

And of course you can add any additional fields that you would like to set.

 

3. Retrieve a list of Accounts 

 

Great, now that we have records in our system let's fetch them back.  Being RESTful you just need to do a GET request to /rest/v10/Accounts. Don't forget to pass in the OAuth-Token header.  To speed things up be specific about the fields that you want. Let's just fetch the name, account type, and description by passing in fields=name,account_type,description. We'll pass in max_num to specify that we only want 3 records at a time. By default if max_num isn't set it will return 20 records. In this case the request will look like /rest/v10/Accounts?fields=name,account_type,description&max_num=3

 

CURL Accounts.sh

curl -X GET -H OAuth-Token:df488865-4a70-6d88-036c-530ce62453d0 -H Cache-Control:no-cache -H Postman-Token:19a88a98-b2bf-da03-a1f9-ab22730bd3e2 http://server/pro720/rest/v10/Accounts?fields=name,account_type,description&max_num=3


GET Accounts.http

GET /pro720/rest/v10/Accounts?fields=name%2Caccount_type%2Cdescription&max_num=3 HTTP/1.1
Host: server
OAuth-Token: df488865-4a70-6d88-036c-530ce62453d0
Cache-Control: no-cache
Postman-Token: 74200fe5-a926-a5d4-d07d-d899bb1a573e


Response.json

{
"next_offset": 3,
"records": [
        {
"id": "demo_burger_palace",
"name": "Burger Palace",
"date_modified": "2014-02-25T10:51:51-08:00",
"description": "My Example Account",
"account_type": "Customer",
"_acl": {
"fields": {}
            },
"_module": "Accounts"
        },
        {
"id": "ec125a78-f202-250b-e75e-530ca4d7d1d0",
"name": "Ink Conglomerate Inc",
"date_modified": "2014-02-25T06:11:00-08:00",
"description": "",
"account_type": "Customer",
"_acl": {
"fields": {}
            },
"_module": "Accounts"
        },
        {
"id": "ebc56ea4-ef13-b024-c07d-530ca40c97e4",
"name": "Constrata Trust LLC",
"date_modified": "2014-02-25T06:11:00-08:00",
"description": "",
"account_type": "Customer",
"_acl": {
"fields": {}
            },
"_module": "Accounts"
        }
    ]
}

 

 

Excellent! If we wanted to paginate we could just add the offset parameter to the request. That is the number of records you want to skip in the list before returning anything. So passing an offset of 3 would get us to the next page of records.

 

4. Filter a list of Accounts by Name 

 

Now, let's filter our list for records that have the name "Burger Palace". To do this we just need to do a GET request to /rest/v10/Accounts and to pass in the filter parameter. In this case the request would look like /rest/v10/Accounts?filter[0][name]=Burger Palace&fields=name,account_type,description

 

CURL Accounts Filter.sh

curl -X GET -H OAuth-Token:34b05aba-e8be-0db8-5fbe-530d19787689 -H Cache-Control:no-cache -H Postman-Token:347571b3-c873-f846-b469-c002810f4538 http://server/pro720/rest/v10/Accounts?filter[0][name]=Burger Palace&fields=name,account_type,description,email

GET Accounts Filter.http

GET /pro720/rest/v10/Accounts?filter%5B0%5D%5Bname%5D=Burger%20Palace&fields=name%2Caccount_type%2Cdescription%2Cemail HTTP/1.1
Host: server
OAuth-Token: 34b05aba-e8be-0db8-5fbe-530d19787689
Cache-Control: no-cache
Postman-Token: 548a67ec-ebfe-fa37-51a3-698783eaff16


Response.json

{
"next_offset": -1,
"records": [
        {
"id": "demo_burger_palace",
"name": "Burger Palace",
"date_modified": "2014-02-25T14:32:25-08:00",
"description": "My Example Account",
"email": [
                {
"email_address": "burgers@example.com",
"invalid_email": false,
"opt_out": false,
"primary_address": false,
"reply_to_address": false
                }
            ],
"account_type": "Customer",
"_acl": {
"fields": {}
            },
"_module": "Accounts"
        }
    ]
}

 

 

You'll notice in the response that the next_offset in the response is set to -1 which means that there are no more records in the collection.

 

5. Filter a list of Accounts by Names starting with "B" and a specific email address

 

Now, let's pass in multiple filter conditions and let's use some of the filter operations.

 

Sugar 7 supports the following filter operations

$equalsPerforms an exact match on that field.
$not_equalsMatches on non-matching values.
$startsMatches on anything that starts with the value.
$inFinds anything where field matches one of the values as specified as an array.
$not_inFinds anything where field does not match any of the values as specified as an array.
$is_nullChecks if the field is null. This operation does not need a value specified.
$not_nullChecks if the field is not null. This operation does not need a value specified.
$ltMatches when the field is less than the value.
$lteMatches when the field is less than or equal to the value.
$gtMatches when the field is greater than the value.
$gteMatches when the field is greater than or equal to the value.

 

 

So to filter for Account names starting with the letter "B" we'll use the $starts operator. So instead of "filter[0][name]=Burger Palace" we can use filter[0][name][$starts]=B.

 

SugarCRM stores email addresses as normalized values. To search for an Account with an email address we need to search using the relationship for email addresses which is email_addresses. Specifically, we want to filter on the field email_address within that relationship. So to do an exact match on a specific email address we pass in  filter[0][email_addresses.email_address]=burgers@example.com Our request will look like /rest/v10/Accounts?filter[0][name][$starts]=B&filter[0][email_addresses.email_address]=burgers@example.com&fields=name,account_type,description,email . You will notice that we also added email to the list of fields that we wish to have returned which will cause it to return a collection of all the email addresses that are associated with this record.

 

curl -X GET -H OAuth-Token:e2505ba8-fc56-de05-ce9f-530d1bf56227 -H Cache-Control:no-cache -H Postman-Token:cb452a8c-2bb9-ebf6-ae66-a0700b10cdcc http://honey-b/pro720/rest/v10/Accounts?filter[0][name][$starts]=B&filter[0][email_addresses.email_address]=burgers@example.com&fields=name,account_type,description,email
GET /pro720/rest/v10/Accounts?filter%5B0%5D%5Bname%5D%5B%24starts%5D=B&filter%5B0%5D%5Bemail_addresses.email_address%5D=burgers%40example.com&fields=name%2Caccount_type%2Cdescription%2Cemail HTTP/1.1
Host: server
OAuth-Token: e2505ba8-fc56-de05-ce9f-530d1bf56227
Cache-Control: no-cache
Postman-Token: 29bd612a-828d-ad84-7f6a-dd8ba2314956
{
    "next_offset": -1,
    "records": [
        {
            "id": "demo_burger_palace",
            "name": "Burger Palace",
            "date_modified": "2014-02-25T14:32:25-08:00",
            "description": "My Example Account",
            "email": [
                {
                    "email_address": "burgers@example.com",
                    "invalid_email": false,
                    "opt_out": false,
                    "primary_address": false,
                    "reply_to_address": false
                }
            ],
            "account_type": "Customer",
            "_acl": {
                "fields": {}
            },
            "_module": "Accounts"
        }
    ]
}


Continue to Part 2 - Retrieving, Updating, and Relating Records 

Post originally written by sugarmajed.

 

Sometimes the best way to learn something is to dive right in and to get hands on experience. While there are several documents on developing Models, Views, and Controllers for Sugar 7, the core developers wanted to do something a bit different to help everyone get caught up to speed. We want to create a rich set of step by step examples or "recipes" for all the different things that you would want to do with Sugar 7.

 

So I am pleased to announce that we will be publishing a series of blog posts that cover real world applications of customizations and integrations you can build with Sugar 7. We are going to start with the basics and continuously get deeper and more complex. We'll provide support materials to help you follow along at your own pace. You'll need a copy of Sugar 7 that is up and running and don't forget to install elasticsearch before you install Sugar 7.

 

Without further ado,  let's get started cooking with Sugar 7.

Post originally written by John Mertic.

 

http://sugarcon.com

 

App Throwdown is back! Are you ready for it?

 

That's right, we are excited to bring back one of our attendee's favorite parts of SugarCon. It's THE event to see the latest and most innovative ways our incredible partner ecosystem bend and shape Sugar to make it more powerful for customers worldwide. And as a developer, you have the chance to get that amazing app you've built in front of not only other Sugar customers, but the whole tech world.

 

So, do you have a killer customization you’ve done into Sugar? Have you built an interesting application on top of the Sugar platform? Or have you taken Sugar to the next level with integrations into popular applications and services?

 

If you answer "yes" to any of these, it's time to submit your app now before February 28th.

We often get asked how to extend the Record view in Sugar 7. The Record view in Sugar 7 is one of the more complex views in the application so extending it can be a little tricky.

 

The examples below are based on Sugar 7.1.5.

 

The first question I would ask is “are you overriding the Record view for a single module?”

 

In that case, then what you need can be accomplished using a single file. All you need to do is define your custom module Record view.  Create your new Record view under custom/modules/MODULE/clients/views/. This is fairly easy and upgrade safe.

 

custom_modules_Foo_clients_base_views_record_record.js

({
    extendsFrom: 'RecordView',

/**
     * Some extra functionality
*/
doSomethingCool: function() {
    },

_dispose: function() {
//additional stuff before calling the core create _dispose goes here
this._super('_dispose');
    }
})

 

If you needed to change all Record views then the next question I would ask is “are you just trying to add something to the Record layout?”

 

Adding a new view to the Record layout would be the (upgrade) safest way to add content to the base Record user interface in Sugar 7.https://gist.github.com/mmarum-sugarcrm/8744135

 

This is what Sugar 7 looks like when you have the files above dropped into your custom/ directory. Underscores in the file names above are used to denote subdirectories.

This gives you the freedom of having full control over your view without worrying about interactions with other components may also be trying to override the Record view.  It also keeps your customizations from being tightly coupled to the Record view so that it can be reused in more places in the user interface.

But if you really need to override the base Record view in Sugar 7 to accomplish your goals, here a recommended way to do it.

https://gist.github.com/mmarum-sugarcrm/8657382

Try dropping the files above into your custom/ directory.  Underscores in the file names above are used to denote subdirectories.

This approach involves creating a custom Record view with a different name.  The new view controller extends Record view and configures it appropriately so that it pulls in all the original record metadata including actions and fields.  In the custom view metadata, it is setup so that it reuses the Handlebars template from the original Record view.  You can then define any custom HTML that you need within separate templates that get serialized to the client along with your custom view.



 

I hope that helps!  Let us know if you've got questions.