<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: PROC HTTP and ServiceNow oauth Token in SAS Procedures</title>
    <link>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983615#M84115</link>
    <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;Wow, thanks for letting your curiosity getting the best of you!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have been pestering my ServiceNow tech team about my privileges (amongst other things).&amp;nbsp; It seems to me that my SNOW team has some more work to do, but I'll surely be taking the route that you did and use the developer portal which I had no idea existed.&amp;nbsp; ServiceNow is definitely not my day-to-day job; neither is SAS, but a Mainframer has to build their own tools ;).&amp;nbsp; I appreciate you!&lt;/P&gt;</description>
    <pubDate>Tue, 17 Feb 2026 15:01:20 GMT</pubDate>
    <dc:creator>DumDum</dc:creator>
    <dc:date>2026-02-17T15:01:20Z</dc:date>
    <item>
      <title>PROC HTTP and ServiceNow oauth Token</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983345#M84111</link>
      <description>&lt;P&gt;I am currently struggling to interact with ServiceNOW API.&amp;nbsp; I have been issued a client_id and client_secret which must be protected so I opted to use an authdomain.&amp;nbsp; I have already validated that my id and secret are valid and have acquired a token through Postman.&amp;nbsp; However, I am consistently receiving 401 Unauthorized when trying to utilize PROC HTTP&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Program:&lt;/P&gt;&lt;PRE&gt;filename req temp;
filename resp temp;

%let SN_INSTANCE   = https://xxxxxxxxx.service-now.com;

data _null_;
  file req;
  put "grant_type=client_credentials";
run;

proc http
  url    ="&amp;amp;SN_INSTANCE./oauth_token.do"
  proxyhost="xxxxxxxxxxxxxxx"
  proxyport=xxxx
  method="POST"
  ct="application/x-www-form-urlencoded"
  in=req
  out=resp
  webauthdomain="SN_API_DEV";
  debug level=3 output_text;
run;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 11 Feb 2026 16:38:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983345#M84111</guid>
      <dc:creator>DumDum</dc:creator>
      <dc:date>2026-02-11T16:38:11Z</dc:date>
    </item>
    <item>
      <title>Re: PROC HTTP and ServiceNow oauth Token</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983366#M84112</link>
      <description>&lt;P&gt;WEBAUTHDOMAIN is used for Basic Authentication, but that's not what your client-id and client-secret or token supports.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;These values need to go in the HEADERS statement or if it's OAuth, you can use the OAuth_bearer= option for the token value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can and should p&lt;STRONG&gt;rotect these credentials&lt;/STRONG&gt; by storing them outside of your program in a file that only you can access. I don't have a ServiceNow example, but here's one from a different service. In my example, the tokens are stored in another SAS program that is in a location that only my account can read.&amp;nbsp; See more &lt;A href="https://blogs.sas.com/content/sasdummy/2018/01/16/hide-rest-api-tokens/" target="_self"&gt;in this blog post for guidance&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;/* I stored this in hidden folder in my user home with chmod 600 permissions */
%include "/u/&amp;amp;sysuserid./.creds/on24_tokens.sas";

  filename resp temp;
  proc http
   method="GET"
   url="https://api.on24.com/v2/client/&amp;amp;&amp;amp;clientId_&amp;amp;region./event/&amp;amp;eventId."
   out=resp
   ;
   headers
    "accesstokenkey" = "&amp;amp;&amp;amp;accesstokenkey_&amp;amp;region."
    "accesstokensecret" = "&amp;amp;&amp;amp;accesstokensecret_&amp;amp;region."
    "Accept" = "application/json";
  run;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 11 Feb 2026 19:09:42 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983366#M84112</guid>
      <dc:creator>ChrisHemedinger</dc:creator>
      <dc:date>2026-02-11T19:09:42Z</dc:date>
    </item>
    <item>
      <title>Re: PROC HTTP and ServiceNow oauth Token</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983370#M84113</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;Thank you for taking the time to reply!&amp;nbsp; I've read a lot of your posts as I have been lurking in the background&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Somehow, I have been able to cobble together something that works to acquire the token.&amp;nbsp; I'm now fighting to pass the token, but that should be the easy part...right? &lt;span class="lia-unicode-emoji" title=":winking_face:"&gt;😉&lt;/span&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;PRE&gt;/* Where we'll store the HTTP response */
filename sn_resp  temp;
filename sn_body  temp;
filename sn_hdrs  temp;

/* Build x-www-form-urlencoded body (URL-encoded HTTP POST body) */
data _null_;
  file sn_body lrecl=32767;
  put "grant_type=client_credentials";
run;

proc http
  url    ="&amp;amp;SN_INSTANCE./oauth_token.do"
  proxyhost="&amp;amp;PROXY."
  proxyport=&amp;amp;PROXY_PORT
  method ="POST"
  in="grant_type=client_credentials"
  out=sn_resp
  WEBAUTHDOMAIN="SN_API_DEV";
  headers
    "Content-Type"="application/x-www-form-urlencoded";
  headers "Accept"="application/json";
/*   debug level=3 output_text; */
run;

%put &amp;amp;SYS_PROCHTTP_STATUS_CODE;
data _null_;
 rc=jsonpp('sn_resp','log');
run;

libname auth json fileref=sn_resp;

data _null_;
  set auth.root; /* typically contains access_token, token_type, expires_in, etc. */
  call symputx('ACCESS_TOKEN', access_token, 'G');
  call symputx('TOKEN_TYPE',   token_type,   'G');
  call symputx('EXPIRES_IN',   expires_in,   'G');
run;

%put NOTE: Got token_type=&amp;amp;TOKEN_TYPE expires_in=&amp;amp;EXPIRES_IN;
%put NOTE: ACCESS TOKEN=&amp;amp;ACCESS_TOKEN;

filename api_out temp;


/* This crap isn't working yet 02/11/2026 */


proc http
  url    ="&amp;amp;SN_INSTANCE./api/now/table/incident"
  proxyhost="&amp;amp;PROXY."
  proxyport=&amp;amp;PROXY_PORT
  method ="GET"
/*   oauth_bearer="&amp;amp;access_token" */
  out    =api_out;
  headers
    "Accept" = "application/json"
    "Authorization" = "Bearer &amp;amp;ACCESS_TOKEN.";
/*   debug level=3 output_text; */
run;

/* Optional: parse the API JSON response */
libname api json fileref=api_out;

proc print data=api.result(obs=5);
run;&lt;/PRE&gt;</description>
      <pubDate>Wed, 11 Feb 2026 20:51:27 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983370#M84113</guid>
      <dc:creator>DumDum</dc:creator>
      <dc:date>2026-02-11T20:51:27Z</dc:date>
    </item>
    <item>
      <title>Re: PROC HTTP and ServiceNow oauth Token</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983583#M84114</link>
      <description>&lt;P&gt;Hi, this has taken me a while to work out, but I was motivated because we&amp;nbsp;&lt;STRONG&gt;also&lt;/STRONG&gt; use ServiceNow here. And I have had some ServiceNow admin training, although it's not part of my day-to-day job.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I was able to get it working and tested by using the ServiceNow developer portal, which gave me access to a dev instance that I could control! I started at:&amp;nbsp;&lt;A title="Original URL: https://protect.checkpoint.com/v2/r01/___https://developer.servicenow.com/___.YzJ1OnNhc2luc3RpdHV0ZTpjOm86ZGE4MmIyMGZiMzc3OTU3NjgyYTQ0NjE4NzdhOGU2ODc6NzplMzNjOjI3ZWYxMjlhYjAxMzU2NmM1M2ZiMmI0ZDI0ZGVmNWUzN2VjMzhiY2I2MGRlZmRmMTY0ZmJiZjZlOTEyMzJjYTE6aDpUOk4. Click or tap if you trust this link." href="https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect.checkpoint.com%2Fv2%2Fr01%2F___https%3A%2F%2Fdeveloper.servicenow.com%2F___.YzJ1OnNhc2luc3RpdHV0ZTpjOm86ZGE4MmIyMGZiMzc3OTU3NjgyYTQ0NjE4NzdhOGU2ODc6NzplMzNjOjI3ZWYxMjlhYjAxMzU2NmM1M2ZiMmI0ZDI0ZGVmNWUzN2VjMzhiY2I2MGRlZmRmMTY0ZmJiZjZlOTEyMzJjYTE6aDpUOk4&amp;amp;data=05%7C02%7Cchris.hemedinger%40sas.com%7Ca1ef04a7478847e7fd5908de6a4d6828%7Cb1c14d5c362545b3a4309552373a0c2f%7C0%7C0%7C639065077876369298%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&amp;amp;sdata=51yA1FII8loTfXZ5uoY8yRJs9cTYbAsoKgkefdMwfdg%3D&amp;amp;reserved=0" data-auth="NotApplicable" data-linkindex="2" data-olk-copy-source="MessageBody" target="_blank"&gt;https://developer.servicenow.com/&lt;/A&gt;&lt;SPAN&gt;. I have a ServiceNow signin, and I used that to get an instance.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Then I created a user in the SN instance specifically for machine-only API access. Once created, I had to grant that user access to the tables that I wanted to use for the API calls. Simple way is to make the user an admin, but in real life that isn't practical. Here's the user I made. I think making a user for this purpose is easier and more manageable than using your own identity.&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ChrisHemedinger_0-1771280302716.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/113203i29EA3A1DAF5766A9/image-size/medium?v=v2&amp;amp;px=400" role="button" title="ChrisHemedinger_0-1771280302716.png" alt="ChrisHemedinger_0-1771280302716.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;Then from the&amp;nbsp;&lt;STRONG&gt;Application Registry&lt;/STRONG&gt; screen, I created an OAuth client application. I marked as "Broadly Scoped".&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ChrisHemedinger_1-1771280435171.png" style="width: 730px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/113204i183175F100CB16F5/image-dimensions/730x320?v=v2" width="730" height="320" role="button" title="ChrisHemedinger_1-1771280435171.png" alt="ChrisHemedinger_1-1771280435171.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;Now I had all necessary data items in hand: client ID, client secret, username, and user password. All of these are needed to get the access token. I created a&amp;nbsp;&lt;STRONG&gt;CSV&lt;/STRONG&gt; file with these fields and stored it in a secure folder that only my SAS user account can access. Here's my code to get the access token and then run a simple query, which results in some output from ServiceNow!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ChrisHemedinger_2-1771280687399.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/113205i64EDF9A9759B6EFB/image-size/medium?v=v2&amp;amp;px=400" role="button" title="ChrisHemedinger_2-1771280687399.png" alt="ChrisHemedinger_2-1771280687399.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt;/* my dev instance from the developer portal */
%let SN_INSTANCE=https://devNNNNN.service-now.com;
/* Store the credentials in a secure area */
%let credsLoc = /u/&amp;amp;sysuserid./.creds;

/* ===== Build application/x-www-form-urlencoded body ===== */
filename tok temp;
data _null_;
  infile "&amp;amp;credsLoc./service-now-creds.csv"  dsd firstobs=2;
  length client_id $ 40 client_secret $ 40 username $ 40 password $ 250 out $ 500;
  length d1-d5 $ 600;
  input client_id client_secret username password;
  d1 = "grant_type=password";
  d2 = catt('client_id=',urlencode(trim(client_id)));
  d3 = catt('client_secret=',urlencode(trim(client_secret)));
  d4 = catt('username=',urlencode(trim(username)));
  d5 = catt('password=',urlencode(trim(password)));
  out = catx('&amp;amp;',d1,d2,d3,d4,d5);
  ;
  /* Store API input data in macro var */
  call symputx('SN_CRED',out);
  put out;
  
run;
options ls=max;
/* ===== Call token endpoint ===== */
filename tokresp temp;

proc http
  url="&amp;amp;SN_INSTANCE./oauth_token.do"
  method="POST"
  in="&amp;amp;SN_CRED"
  out=tokresp
  ct="application/x-www-form-urlencoded";

debug level=3 ;
run;

/* ===== Parse JSON and extract access_token ===== */
libname tokjson json fileref=tokresp;

/* token fields often appear in tokjson.root */
data _null_;
  set tokjson.root;
  if not missing(access_token) then do;
    call symputx('accessToken', access_token, 'G');
  end;
run;

/* Debugging only */
%put NOTE: Token acquired successfully: &amp;amp;accessToken;

libname tokjson clear;
filename tokresp clear;

/* Query the Incident table with limited parms */
filename results temp;
proc http
  url="&amp;amp;SN_INSTANCE./api/now/table/incident?sysparm_fields=number%2Cresolved_by%2Copened_by%2Cshort_description&amp;amp;sysparm_limit=10"
  method="GET"
  out=results
  ct="application/json"
  oauth_bearer="&amp;amp;accessToken.";
run;

libname incident json fileref=results;

proc print data=incident.result(obs=5);
 var number short_description;
run;
libname incident clear;
filename results clear;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I found the API to be very finicky, especially in getting the token. I might have overengineered, but I needed to URLENCODE all of the values I passed in the HTTP POST call, which I guess is how it's documented -- but I've used a lot of APIs that don't need that step. I first got things working using PowerShell; the Invoke-RestAPI method does a lot for you. Once I got that working, I knew I could do the same in SAS.&lt;/P&gt;</description>
      <pubDate>Mon, 16 Feb 2026 22:29:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983583#M84114</guid>
      <dc:creator>ChrisHemedinger</dc:creator>
      <dc:date>2026-02-16T22:29:48Z</dc:date>
    </item>
    <item>
      <title>Re: PROC HTTP and ServiceNow oauth Token</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983615#M84115</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4"&gt;@ChrisHemedinger&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;Wow, thanks for letting your curiosity getting the best of you!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have been pestering my ServiceNow tech team about my privileges (amongst other things).&amp;nbsp; It seems to me that my SNOW team has some more work to do, but I'll surely be taking the route that you did and use the developer portal which I had no idea existed.&amp;nbsp; ServiceNow is definitely not my day-to-day job; neither is SAS, but a Mainframer has to build their own tools ;).&amp;nbsp; I appreciate you!&lt;/P&gt;</description>
      <pubDate>Tue, 17 Feb 2026 15:01:20 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983615#M84115</guid>
      <dc:creator>DumDum</dc:creator>
      <dc:date>2026-02-17T15:01:20Z</dc:date>
    </item>
    <item>
      <title>Re: PROC HTTP and ServiceNow oauth Token</title>
      <link>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983722#M84116</link>
      <description>&lt;P&gt;This side quest inspired me to capture the steps in an article for future searchers:&amp;nbsp;&lt;LI-MESSAGE title="How to use SAS to work with ServiceNow APIs" uid="983715" url="https://communities.sas.com/t5/SAS-Communities-Library/How-to-use-SAS-to-work-with-ServiceNow-APIs/m-p/983715#U983715" discussion_style_icon_css="lia-mention-container-editor-message lia-img-icon-tkb-thread lia-fa-icon lia-fa-tkb lia-fa-thread lia-fa"&gt;&lt;/LI-MESSAGE&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 18 Feb 2026 20:25:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Procedures/PROC-HTTP-and-ServiceNow-oauth-Token/m-p/983722#M84116</guid>
      <dc:creator>ChrisHemedinger</dc:creator>
      <dc:date>2026-02-18T20:25:54Z</dc:date>
    </item>
  </channel>
</rss>

