I'm able to use Postman to connect to an API with some body data and get back a specific version of response data (based on the info passed in the body data). When I try to do the same using PROC HTTP in SAS, I cannot get back the version of response data I've specified. I assume it's because I'm not doing something right in my code:
%let service_url=https://abc.com/service();
filename head_out "D:\test.txt";
filename json_out "D:\test.json";
proc http
url="&service_url"
method="GET"
WEBUSERNAME="uid"
WEBPASSWORD="pwd"
AUTH_BASIC
in='{"version": {"major": "01", "minor": "03", "patch": "00"}}'
headerout=head_out
out=json_out ;
run;
My code runs fine & w/o errors. It just returns the default version of the data (1.2.1) instead of the (1.3.0) version specified in the json in the in statement. In Postman, I get version (1.3.0) as I should. Is there something I'm missing? I've tried messing around with the headers (Content-Type) some but nothing I've tried has worked.
I don't know your API but is it possible you need the braces?
proc http
url="&service_url"
method="GET"
WEBUSERNAME="uid"
WEBPASSWORD="pwd"
AUTH_BASIC
in='[{"version": {"major": "01", "minor": "03", "patch": "00"}}]'
headerout=head_out
out=json_out ;
run;
If that's not it, grab the cURL code the Postman can generate for you (it can generate code in a number scripting formats but not SAS, unfortunately) and paste it here (sanitize the URL and sensitive fields, of course).
Thanks Chris, unfortunately the braces didn't work. Here's the generated cURL code:
curl --location --request GET 'https://abc.com/service()' \
--header 'Authorization: Basic Ym9wMDAyMjg6SnVhblNvdG8jMjJNVlA=' \
--header 'Content-Type: text/plain' \
--header 'Cookie: xxxxx=0000HrDnccO3VbQV28Yp000TjT1:C3F02A179384BB400000031C000084440A0C0119; yyyyy=a0xZZUF/E6UoDhvt9rVpOf6yaD+ihUem0lEakU6eo30HmK7' \
--data-raw '{"version": {"major": "01", "minor": "03", "patch": "00"}}'
Okay, then you should use something like this (not webuser/password):
filename resp temp;
proc http
url="https://abc.com/service()"
in = '{"version": {"major": "01", "minor": "03", "patch": "00"}}'
out=resp
ct="text/plain";
;
headers "Authorization" = "Basic Ym9wMDAyMjg6SnVhblNvdG8jMjJNVlA=";
run;
/* print JSON resp to log */
data _null_;
rc=jsonpp('resp','log');
run;
I tried as you suggest & still no luck.
I had to add/use ‘method=”GET”’ to the code to override the default “PUT” method. The developer of the API specifically said to use “GET” and I get a 405 error with “PUT.”
Do you know if SAS somehow defaults to ignoring the in=/body data if the “GET” method is used? I’m not well versed with APIs, but it sounds like in=/body data is mostly used with “PUT” methods to insert new data, so I could see what I need to do as something of an outlier.
Also do you know of a way to confirm that the in=/body data has been read in? I’ve tried using “debug level=3” in my code & can see info in the log about the Authorization: header and Content-Type: but nothing about the in=/body data.
Thanks again for all you help.
Good points about the IN= (or body) implying a PUT or POST. Are you sure that the API uses GET and expects a body? Is this API documented somewhere on the internet that I can see?
Sorry the default is POST (not PUT, confusing my P words).
Unfortunately the API is internal to my organization. The developer definitely told me to use “GET” and the “GET” works in Postman.
From my understanding of it, the version data in the body just tells the API what version of a calculation to perform & then returns the data in a JSON file. When I run it in Postman, the version info in the return data says 1.3.0. When I run it in SAS, the version info in the return data says 1.2.1 which is the default/current version. So it’s like it didn’t receive/recognize the in=/body data I’m trying to send.
I think that PROC HTTP is not passing the IN= content when the GET method is used. We could get all self-righteous and point to the HTTP spec that says that a payload on the GET method has no semantic meaning:
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
But that's little comfort if your developer built the API this way and cannot/won't change it. The fact that some tools support sending it doesn't make it right, and PROC HTTP might be a little overzealous by not passing it along.
Is there another way to pass this data, perhaps on the URL string as URL-encoded data? That would be a more standard method for passing data to a GET method.
I sent an email to our developer to see if there was any other way of passing the data. As of yet, I haven't heard anything back - I believe he's on vacation this week.
If he can't/won't offer up another way, I hope (with the help of a co-worker) to be able to use some combo of SAS & Python to get the version of the response data I need.
Thanks so much for all your time, effort & help!
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.