mikeski.net kotlin java javascript hugo development

mikeski.net development blog

Salesforce Api Curl

In this post we cover how to play with the salesforce.com api with cURL.

Setup

  1. Using https://brew.sh/ or however you do it, install
  • curl
  • jq
  1. Signup for a “Developer Edition” account on https://developer.salesforce.com/page/Developer_Edition and confirm your email.

  2. Login.

  3. On the left-hand menu, click “Apps”, “App Manager” and then on the top right side of the screen click “New Connected App”

  4. Fill in the required fields, for the callback URL you can just use https://localhost:8443/demo/callback. This does not need to be a valid URL, we just need to enter something so we can see what the Salesforce API is sending us.

  5. When that is complete, you are ready to get your settings. You do not need the app secret here, only the client id.

  6. Next, you create the following URL with your app information:

https://login.salesforce.com/services/oauth2/authorize?response_type=token&client_id=___YOUR_CLIENT_ID___&redirect_uri=https%3A%2F%2Flocalhost%3A8443%2FOauthDemo%2Foauth%2F_callback

Note that the redirect_uri should be the same one that you used above but encoded as a URI component. If you used a different URI for some reason, use the tool here to get your redirect_uri value: http://pressbin.com/tools/urlencode_urldecode/

So, after doing that copy and paste that URL into your browser window, you should get a salesforce login page. Once you login, salesforce will ask you to confirm that you want to allow access to the application. Click “Allow” and you will be redirected to your “redirect_uri”. In this case, you will get a browser error saying that the page is not available. This is good! Copy the address from your address bar and paste it into a text editor to look at it. It is something like this:

https://localhost:8443/OauthDemo/oauth/_callback#access_token=00Df4000003knBs%21AREAQBBOLGAEnstsVsHi5wKmUfsYpeO26VkWzvleJZBz_Y0Z1zXTiC5N93gEURiTUIA_wHBvGCIALYM8Wp1fISQcoIe3UmPG&instance_url=https%3A%2F%2Fna59.salesforce.com&id=https%3A%2F%2Flogin.salesforce.com%2Fid%2F00Df4000003knBsEAI%2F005f4000001jsGeAAI&issued_at=1526562578724&signature=BoVWC%2B22ewQNAMAt7t4JfmWwIL7%2FPUZZR8sBeXGPgSY%3D&scope=id+api&token_type=Bearer

We are interested in 2 parts of this, the access_token and the instance_url

access_token=00Df4000003knBs%21AREAQBBOLGAEnstsVsHi5wKmUfsYpeO26VkWzvleJZBz_Y0Z1zXTiC5N93gEURiTUIA_wHBvGCIALYM8Wp1fISQcoIe3UmPG

instance_url=https%3A%2F%2Fna59.salesforce.com

Both of these need to be URL decoded (use http://pressbin.com/tools/urlencode_urldecode/ if you need to), and you’ll get:

https://naXY.salesforce.com/

(XY will be a number, like 59) and something similar to (note the ! character, this is the decoded value):

00Df4000003knBs!AasdfasdfOLGAEnstsVsHi5wKmUfsYpeO26VkWzvleJZBz_Y0Z1zXTsdf1345a3gEURiTUIA_wHBvGCIALYM8Wp1asdf

Now we’re ready to query the API. To verify you have a good instance_url, you can see what services are available by running:

curl https://na59.salesforce.com/services/data/

The result of this us JSON, but ugly:

[{label:Winter 11,url:/services/data/v20.0,version:20.0},{label:Spring 11,url:/services/data/v21.0,version:21.0},{label:Summer 11,url:/services/data/v22.0,version:22.0},{label:Winter 12,url:/services/data/v23.0,version:23.0},{label:Spring 12,url:/services/data/v24.0,version:24.0},{label:Summer 12,url:/services/data/v25.0,version:25.0},{label:Winter 13,url:/services/data/v26.0,version:26.0},{label:Spring 13,url:/services/data/v27.0,version:27.0},{label:Summer 13,url:/services/data/v28.0,version:28.0},{label:Winter 14,url:/services/data/v29.0,version:29.0},{label:Spring 14,url:/services/data/v30.0,version:30.0},{label:Summer 14,url:/services/data/v31.0,version:31.0},{label:Winter 15,url:/services/data/v32.0,version:32.0},{label:Spring 15,url:/services/data/v33.0,version:33.0},{label:Summer 15,url:/services/data/v34.0,version:34.0},{label:Winter 16,url:/services/data/v35.0,version:35.0},{label:Spring 16,url:/services/data/v36.0,version:36.0},{label:Summer 16,url:/services/data/v37.0,version:37.0},{label:Winter 17,url:/services/data/v38.0,version:38.0},{label:Spring 17,url:/services/data/v39.0,version:39.0},{label:Summer 17,url:/services/data/v40.0,version:40.0},{label:Winter 18,url:/services/data/v41.0,version:41.0},{label:Spring 18,url:/services/data/v42.0,version:42.0}]

That’s where jq comes in handy. Pipe the cURL output to jq and you’ll run this command:

curl https://na59.salesforce.com/services/data/ | jq

and get this result:

[
  {
    "label": "Winter '11",
    "url": "/services/data/v20.0",
    "version": "20.0"
  },
  {
    "label": "Spring '11",
    "url": "/services/data/v21.0",
    "version": "21.0"
  },
  {
    "label": "Summer '11",
    "url": "/services/data/v22.0",
    "version": "22.0"
  },
  {
    "label": "Winter '12",
    "url": "/services/data/v23.0",
    "version": "23.0"
  },
  {
    "label": "Spring '12",
    "url": "/services/data/v24.0",
    "version": "24.0"
  },
  {
    "label": "Summer '12",
    "url": "/services/data/v25.0",
    "version": "25.0"
  },
  {
    "label": "Winter '13",
    "url": "/services/data/v26.0",
    "version": "26.0"
  },
  {
    "label": "Spring '13",
    "url": "/services/data/v27.0",
    "version": "27.0"
  },
  {
    "label": "Summer '13",
    "url": "/services/data/v28.0",
    "version": "28.0"
  },
  {
    "label": "Winter '14",
    "url": "/services/data/v29.0",
    "version": "29.0"
  },
  {
    "label": "Spring '14",
    "url": "/services/data/v30.0",
    "version": "30.0"
  },
  {
    "label": "Summer '14",
    "url": "/services/data/v31.0",
    "version": "31.0"
  },
  {
    "label": "Winter '15",
    "url": "/services/data/v32.0",
    "version": "32.0"
  },
  {
    "label": "Spring '15",
    "url": "/services/data/v33.0",
    "version": "33.0"
  },
  {
    "label": "Summer '15",
    "url": "/services/data/v34.0",
    "version": "34.0"
  },
  {
    "label": "Winter '16",
    "url": "/services/data/v35.0",
    "version": "35.0"
  },
  {
    "label": "Spring '16",
    "url": "/services/data/v36.0",
    "version": "36.0"
  },
  {
    "label": "Summer '16",
    "url": "/services/data/v37.0",
    "version": "37.0"
  },
  {
    "label": "Winter '17",
    "url": "/services/data/v38.0",
    "version": "38.0"
  },
  {
    "label": "Spring '17",
    "url": "/services/data/v39.0",
    "version": "39.0"
  },
  {
    "label": "Summer '17",
    "url": "/services/data/v40.0",
    "version": "40.0"
  },
  {
    "label": "Winter '18",
    "url": "/services/data/v41.0",
    "version": "41.0"
  },
  {
    "label": "Spring ’18",
    "url": "/services/data/v42.0",
    "version": "42.0"
  }
]

This shows you all the versions available and where they are located. Given the instance_url we have and the url for the version you want, you have your API access base url.

We’ll use version v37.0, so our url is:

curl https://na59.salesforce.com/services/data/v37.0/

Now, when you access the API you need to pass in your bearer token. You do this by specifying a header that is “Authorization: Bearer ${TOKEN}” where ${TOKEN} is your bearer token from above (the thing with the ! in it).

To make this easier, since I’m in a Mac shell, I set the token as a variable I can reference:

TOKEN=”00Df4000003knBs!AasdfasdfOLGAEnstsVsHi5wKmUfsYpeO26VkWzvleJZBz_Y0Z1zXTsdf1345a3gEURiTUIA_wHBvGCIALYM8Wp1asdf”

Now, I can run the following to query the API and pass my authentication token in:

curl https://na59.salesforce.com/services/data/v37.0/ -H “Authorization: Bearer ${TOKEN}

If you want to do this without the variable, you can just do:

curl https://na59.salesforce.com/services/data/v37.0/ -H “Authorization: Bearer 00Df4000003knBs!AasdfasdfOLGAEnstsVsHi5wKmUfsYpeO26VkWzvleJZBz_Y0Z1zXTsdf1345a3gEURiTUIA_wHBvGCIALYM8Wp1asdf”

If you’ve done it right, you’ll get more endpoints for all the services that this API provides

{
  "tooling": "/services/data/v37.0/tooling",
  "metadata": "/services/data/v37.0/metadata",
  "folders": "/services/data/v37.0/folders",
  "eclair": "/services/data/v37.0/eclair",
  "prechatForms": "/services/data/v37.0/prechatForms",
  "chatter": "/services/data/v37.0/chatter",
  "tabs": "/services/data/v37.0/tabs",
  "appMenu": "/services/data/v37.0/appMenu",
  "quickActions": "/services/data/v37.0/quickActions",
  "queryAll": "/services/data/v37.0/queryAll",
  "commerce": "/services/data/v37.0/commerce",
  "wave": "/services/data/v37.0/wave",
  "iot": "/services/data/v37.0/iot",
  "analytics": "/services/data/v37.0/analytics",
  "search": "/services/data/v37.0/search",
  "identity": "https://login.salesforce.com/id/00Df4000003knBsEAI/005f4000001jsGeAAI",
  "composite": "/services/data/v37.0/composite",
  "parameterizedSearch": "/services/data/v37.0/parameterizedSearch",
  "theme": "/services/data/v37.0/theme",
  "nouns": "/services/data/v37.0/nouns",
  "event": "/services/data/v37.0/event",
  "serviceTemplates": "/services/data/v37.0/serviceTemplates",
  "recent": "/services/data/v37.0/recent",
  "connect": "/services/data/v37.0/connect",
  "licensing": "/services/data/v37.0/licensing",
  "limits": "/services/data/v37.0/limits",
  "process": "/services/data/v37.0/process",
  "async-queries": "/services/data/v37.0/async-queries",
  "dedupe": "/services/data/v37.0/dedupe",
  "query": "/services/data/v37.0/query",
  "match": "/services/data/v37.0/match",
  "emailConnect": "/services/data/v37.0/emailConnect",
  "compactLayouts": "/services/data/v37.0/compactLayouts",
  "knowledgeManagement": "/services/data/v37.0/knowledgeManagement",
  "sobjects": "/services/data/v37.0/sobjects",
  "actions": "/services/data/v37.0/actions",
  "support": "/services/data/v37.0/support"
}

At this point, you can explore the API and query anything you’d like. The documentation from salesforce.com is here: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_user_tasks.htm and you can use the examples in this guide along with cURL and your access token to explore.