1

In my company's existing CRM system we have a lot of public APIs that are accessible to everyone in the web (kinda like Flickr APIs).

We are planning to shift our CRM into Salesforce in the near future.

So I was wondering whether it is possible to create such publicly available open APIs in Salesforce also ?.

6

Definitely... one straightforward approach would be to spin up a custom public REST service on the SFDC stack.

Two basic parts to the exercise: 1) Write your web service 2) Expose it via public Force.com site

I'm going to pick a dead-simple example just to make the point. Let's say your goal is a public API to validate that a Contact exists in your SFDC database... you will pass an email and want a response back.

Let's start at the end and define how we can test our web service... I prefer curl to debug and test my web services, but use Fiddler or whatever if that's your preference:

test a POST to our webservice
curl -H “Content-Type: application/json” -d ‘{“email”:”emailToCheck@fake.com”}’
https://your-custom-domain.force.com/services/apexrest/checkemail

example HTTP 200 Response Body
{“email”:”emailToCheck@fake.com”, ”valid”:”true”}

Your URL pattern will always follow the pattern I've outlined above. The only parts that will vary are 'your-custom-domain.force.com' and the name of the service (in this case 'checkemail') as defined in your @RestResource URL map (more on that shortly).

PART 1: Create the web service

Create a new SFDC Apex class with the @RestResource URL map... the code I've included below is functional beta code, could be cleaned up a bit but should help you get started:

@RestResource(urlMapping='/checkemail/*')
global without sharing class checkemail {

    global class JSONResult {
        global Map<String,String> nameValuePairs = new Map<String,String>();
    }

    @HttpPost
    global static void doPost()
    {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        JSONResult payload = new JSONResult();
        String emailAddress = 'null';
        List<Contact> c = new List<Contact>();

        try {

            JSONParser p2 = JSON.createParser(cleanRequestBody);
            while (p2.nextToken() != null) {
                //get email address from request body
                if ((p2.getCurrentToken() == JSONToken.FIELD_NAME)) {
                    String fieldName = p2.getText();
                    p2.nextToken();
                    if(fieldName == 'email') {
                        emailAddress = p2.getText();
                    }
                }
            }

            if(String.isNotBlank(emailAddress)) {
                c = [   Select ID, Email, FROM Contact 
                        WHERE Email = :emailAddress LIMIT 1];
            }

            //if the email address is valid (e.g. there is a contact match)...
            if(c.size() > 0) {
                payload.nameValuePairs.put('valid','true');
                payload.nameValuePairs.put('email',emailAddress);
            }
            else {
                payload.nameValuePairs.put('valid','false');
                payload.nameValuePairs.put('email',emailAddress);
            }
            res.statusCode = 200;
            res.responseBody = Blob.valueOf(JSON.serialize(payload.nameValuePairs));
        }
        catch (Exception e) {
            res.statusCode = 500;
            res.responseBody = Blob.valueOf('Internal error: ' + e + '... line number = ' + e.getLineNumber());
        }
    }
}

PART 2: Public Force.com Site

To debug and consume your web service, you’ll need to setup a public site and expose the service through that site.

Setup > Develop > Sites > Click the NAME of the Site under the ‘Site Label’ column > Public Access Settings > Apex Class Access

Click-fest… if you end up in the wrong place, double-check your clicks.

Final Thoughts

I've encountered a fair amount of confusion surrounding SFDC web services and return types… people wrestling with quotes and escape sequences. I don't get it, why would you do that extra work. Simply set the responseBody and let the system do the serialization.

If you are generating a response similar to “{\”signup\”:{\”salesforce_id\”:\”003110022068XNz\”,\”nationbuilder_id\”:65536\”}” you should rethink your approach... you are doing it the hard way.

For services generating complex JSON responses your HTTP methods SHOULD NOT return anything... let SFDC do what it does, the proper non-escaped serialization can be done for you via the HttpResponse class as illustrated above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.