Salesforce REST API: authentication in Python

python, api
Published on 2017-05-11 | Jeremy Greze

The Salesforce.com REST API let one interact with the entire data of the CRM (accounts, contacts, opportunities…). An authentication is required beforehand, an access token must be obtained.

To obtain this token, we will use a connected app and an OAuth 2.0 authorization flow. The documentation indicates several available flows. In this snippet, I will use the Username-Password one, which is the easiest solution for data analysis purposes in my opinion. Alternatively, you might be interested in the Web Server and User-Agent flows that have the advantage to return also a refresh token that can be used to extend the validity of the access token.

Create an App

In any case, create a new “Connected App” in your Salesforce portal (prod or sandbox).

Go in “Setup”, open the “App Manager”. Then, create a “New Connected App”. Name your application. Tick the box “Enable OAuth Settings”. In “Selected OAuth Scopes”, make all scopes available. Type “http://localhost/” in “Callback URL”. Save.

At the end, you should get and note down the “Consumer Key” and the “Consumer Secret".

Use the Username-Password OAuth Flow to authenticate

With the user’s credentials and the the security token, use this Python script to get an access token.

import requests
params = {
    "grant_type": "password",
    "client_id": "XXX.YYY", # Consumer Key
    "client_secret": "0000000000000000", # Consumer Secret
    "username": "my@email.com", # The email you use to login
    "password": "MyPasswordMySecurityToken" # Concat your password and your security token
}
r = requests.post("https://login.salesforce.com/services/oauth2/token", params=params)
# if you connect to a Sandbox, use test.salesforce.com instead
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)

Make calls to the Salesforce REST API

After successfully getting an access token, one can make calls the Salesforce REST API to extract data (leads, opportunities, etc.) or to modify and create new records.

import requests

def sf_api_call(action, parameters = {}, method = 'get', data = {}):
    """
    Helper function to make calls to Salesforce REST API.
    Parameters: action (the URL), URL params, method (get, post or patch), data for POST/PATCH.
    """
    headers = {
        'Content-type': 'application/json',
        'Accept-Encoding': 'gzip',
        'Authorization': 'Bearer %s' % access_token
    }
    if method == 'get':
        r = requests.request(method, instance_url+action, headers=headers, params=parameters, timeout=30)
    elif method in ['post', 'patch']:
        r = requests.request(method, instance_url+action, headers=headers, json=data, params=parameters, timeout=10)
    else:
        # other methods not implemented in this example
        raise ValueError('Method should be get or post or patch.')
    print('Debug: API %s call: %s' % (method, r.url) )
    if r.status_code < 300:
        if method=='patch':
            return None
        else:
            return r.json()
    else:
        raise Exception('API error when calling %s : %s' % (r.url, r.content))

Very simple example: let's extract the next closing opportunities thanks to a SOQL request (Salesforce Object Query Language).

print(json.dumps(sf_api_call('/services/data/v39.0/query/', {
    'q': 'SELECT Account.Name, Name, CloseDate from Opportunity where IsClosed = False order by CloseDate ASC LIMIT 10'
}), indent=2))

The result is a JSON easy to exploit.

Voila!

You will find another snippet with more code examples.