There are many SAS Communities and other SAS resources on how to use PROC HTTP to connect to external systems and communicate via API calls. See the bottom of this article for a list of some of these resources. Today, in this article, I want to focus on how to create REST API calls from the API documentation, connect to SAS Viya, and make API calls from SAS Studio.
Then, in the second article we will offer a more technical perspective with SAS code samples that show how to set up an end-to-end use case.
The developer portal
The first place to start is is the API documentation itself. This is found on the SAS developer portal, developer.sas.com. The SAS Viya APIs are split up by categories. In today's example we'll use APIs from several categories and offer examples for various HTTP methods. The use case is setting up a job definition and executing the job.
The first step is to create a folder where we can place the job definition. From the developer portal home page, the Folders API is under the Platform Administration category. Just to note, we'll also use the Compute and Jobs API later on. Finally, you have the option browse all APIs.
Once in the Platform Administration category, select the Folders API.
The Folders API page lists all API endpoints. Since we need to find a folder to create an new location (folder) to house the job definition, we'll use the Get a list of folders endpoint.
The endpoint documentation has a sample API request call.
Notice the example call is using cURL. There are over a dozen language options such as Python requests, Go, JavaScript, R, etc; however, PROC HTTP is not one of them.
So, let's take the cURL command and convert it to SAS code.
Converting cURL to PROC HTTP
Now let's explore how to take the sample from the API documentation and convert it into a PROC HTTP call.
GET Method
For this use case, we need to create a folder in an existing folder, so let's start with identifying that folder. Here is the API call to get the Public folder id:
curl --request GET
--url 'https://sasserver.demo.sas.com/folders/folders?filter=eq(name,'Public')' \
--header 'Authorization: Bearer <access-token-goes-here>' \
--header 'Accept: application/json, application/vnd.sas.collection+json'
And here is the equivalent call using PROC HTTP:
/* 1 */ filename resp temp;
/* 2 */ proc http
method = 'GET'
url = "https://sasserver.demo.sas.com/folders/folders/?filter=eq(name,'Public')"
/* 3 */ oauth_bearer = sas_services
/* 4 */ out = resp;
headers 'Accept' = 'application/json, application/vnd.sas.collection+json';
run;
Now, let's explore some notes on how to make the conversion.
In the PROC HTTP example, we start with using the SAS FILENAME statement to define a location to store the API call response output.
The PROC HTTP code begins.
Since we are connecting directly to SAS Viya from SAS Studio, we use sas_services to authenticate. No token is required.
Put the API call response output in the resp variable.
POST Method
The next step in our scenario is creating a directory in the parent (Public) directory from the example GET above. We would again go to the developer portal, follow a similar path in the documentation, and access the Create a new folder API endpoint. Below is an example API call using cURL:
curl --request POST
--url 'https://sasserver.demo.sas.com/folders/folders?parentFolderUri=/folders/folders/F98c7f933-ec70-4736-b56c-bf29489ff03e' \
--header 'Accept: application/vnd.sas.content.folder+json' \
--header 'Authorization: Bearer <access-token-goes-here>' \
--header 'Content-Type: application/json' \
--data '{
"name": "API Job Exec",
"description": "My API tests folder.",
"type": "folder"
}'
And here is the equivalent call using PROC HTTP:
filename resp temp;
proc http
method = 'POST'
/* 1 */ in = '{
"name": "jobExecution_prochttp",
"description": "Job Execution for proc http",
"type": "folder"
}'
url = "https://sasserver.demo.sas.com/folders/folders?parentFolderUri=/folders/folders/F98c7f933-ec70-4736-b56c-bf29489ff03e"
/* 2 */ ct = 'application/json'
oauth_bearer = sas_services
out = resp;
headers 'Accept' = 'application/vnd.sas.content.folder+json';
run;
Again, let's explore some notes on how to make the conversion. I have not repeated some of the comments again, as they are the same as the previous PROC HTTP code.
ct is a special built-in option that takes the value of the Content Type header.
Use the in = option for the --data equivalent option in cURL. This is the body of the POST API call.
More Examples
Let's finish out the use case with two more examples:
create the job
execute the job
Create the job
The following cURL command creates a job definition that renders a simple table and writes it to the CAS server in the folder we created earlier:
curl --request POST
--url 'https://sasserver.demo.sas.com/jobDefinitions/definitions?parentFolderUri=/folders/folders/F44j5l654-gh47-5846-k36s-lf66624ah96r' \
--header 'Accept: application/json, application/vnd.sas.job.definition+json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <access-token-goes-here>' \
--data '{
"version":2,
"name":"Table Create",
"description":"Create a simple data set",
"type":"Compute",
"parameters":[
{
"version": 1,
"name": "_contextName",
"defaultValue": "SAS Job Execution compute context",
"type": "CHARACTER",
"label": "Context Name",
"required": false
}
],
"code":"cas mySess; caslib _all_ assign; data casuser.test(promote=yes); input a b c d; datalines;\n1 2 3 4\n5 6 7 8\n;"
}'
And here is the equivalent call using PROC HTTP:
proc http
method='POST'
in='{
"version": 2,
"name": "Table Create",
"description": "Create a simple data set",
"type": "Compute",
"parameters": [
{
"version": 1,
"name": "_contextName",
"defaultValue": "SAS Job Execution compute context",
"type": "CHARACTER",
"label": "Context Name",
"required": false
}
],
"code": "cas mySess; caslib _all_ assign; data casuser.test(promote=yes); input a b c d; datalines;\n1 2 3 4\n5 6 7 8\n;"
}'
ct = 'application/json'
url = "https://sasserver.demo.sas.com/jobDefinitions/definitions?parentFolderUri=/folders/folders/F44j5l654-gh47-5846-k36s-lf66624ah96r"
oauth_bearer = sas_services
out = resp;
headers 'Accept' = 'application/json, application/vnd.sas.job.definition+json';
run;
Execute the Job
Finally, we'll run the job, creating the simple table. Below is the cURL command:
curl --request POST
--url 'https://sasserver.demo.sas.com/jobExecution/jobs' \
--header 'Accept: application/json, application/vnd.sas.job.execution.job+json, application/vnd.sas.error+json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <access-token-goes-here>' \
--data '{
"name": "Simple proc print",
"description": "Execution of the job we previously created",
"jobDefinitionUri": "/jobDefinitions/definitions/{{job_id}}"
}'
And here is the equivalent call using PROC HTTP:
filename resp temp;
proc http
method = 'POST'
in = {
{
"name": "Simple proc print",
"description": "Execution of the job we previously created",
"jobDefinitionUri": "/jobDefinitions/definitions/{{job_id}}"
}
}
ct = 'application/json'
url = "https://sasserver.demo.sas.com/jobExecution/jobs"
oauth_bearer = sas_services
out = resp;
headers 'Accept' = 'application/json, application/vnd.sas.job.execution.job+json, application/vnd.sas.error+json';
run;
Wrapping Up
PROC HTTP allows you to include SAS Viya API calls and integrate it into your SAS code. We can take cURL commands and easily convert them to a SAS call. Stay tuned for the second article where we'll take this use case and create an end-to-end use case using SAS code.
PROC HTTP Resources
How to translate your cURL command into SAS code (blog post)
How to test PROC HTTP and the JSON library engine
HTTP procedure documentation
The ABCs of PROC HTTP (conference paper)
REST Just Got Easy with SAS® and PROC HTTP (conference paper)
PROC HTTP blog posts: PROC HTTP Archives on SAS Blogs
... View more