SAS Viya is an open analytics platform accessible from interfaces or various coding languages. REST API is one of the widely used interfaces. Multiple resources exist on how to access SAS Visual Analytics reports using SAS Viya REST API. For example Programmatically listing data sources in SAS Visual Analytics by my colleague Michael Drutar. His post shows how to list the data sources of VA reports. Also, in Using SAS Viya REST APIs to access images from SAS Visual Analytics, Joe Furbee demonstrates how to retrieve report images. In this post, I am going to show you how to get the path for SAS Visual Analytics reports using REST APIs.
Full API reference documentation for SAS REST APIs is on developer.sas.com. You can exercise REST APIs in several ways such as curl, browsers, browser plugins, or any other REST client. Here I am going to access the SAS Viya Visualization and Core Services REST API with SAS Code. The Visualization service APIs provide access for reports, report images, and report transforms. The Core Services APIs provides operations for resources like folders, files, authorization, and so on.
Composition of a report object
The chart below describes the object composition of VA reports, from an API perspective. We see the report object itself has metadata storing the report properties like id, name, creator, modified date, and links, etc. Each VA report object is identified uniquely by its ID in SAS Viya. The report content object, presented in either XML or JSON format, is stored separately from the report object. The report content object enumerates the data and image resources, generating visual elements such as graphs, tables, and images.
Get a list of reports
Let's begin with a scenario of getting a list of reports. These reports may be returned from a search or a filter in Viya, or a list you've got at hand. (The SAS Viya support filter link has more information on using the filter.) Here I'm using a filter to get a list of reports named 'Report 2'. I use Proc HTTP to access the Reports API in the Visualization service with a 'GET' request and '/reports/reports?filter=eq(name,'Report 2')' in the URL. Note, the HEADERS of Proc HTTP need to be set properly to generate expected results. Below is a snippet for this.
%let BASE_URI=%sysfunc(getoption(SERVICESBASEURL)); FILENAME rptFile TEMP ENCODING='UTF-8'; PROC HTTP METHOD = "GET" oauth_bearer=sas_services OUT = rptFile /* get a list of reports, say report name is 'Report 2' */ URL = "&BASE_URI/reports/reports?filter=eq(name,'Report 2')"; HEADERS "Accept" = "application/vnd.sas.collection+json" "Accept-Item" = "application/vnd.sas.summary+json"; RUN; LIBNAME rptFile json;
The results of running the code above returns a list in the ITEMS table, in the rptFile json library. It returns about 10 reports with the same name of 'Report 2', each with a unique id.
Get the report content object of a VA report
Using the Reports API of the Visualization service, we can get the report content object of a VA report. As shown in the snippet below, by making a 'GET' request to the SAS Viya server followed by the '/reports/reports/content' in the URL, the report content object is retrieved.
%let BASE_URI=%sysfunc(getoption(SERVICESBASEURL)); FILENAME rptFile TEMP ENCODING='UTF-8'; PROC HTTP METHOD="GET" oauth_bearer=sas_services OUT=rptFile URL = "&BASE_URI/reports/reports/<report id>/content"; HEADERS "Accept" = "application/vnd.sas.report.content+json"; RUN; LIBNAME rptFile json;
In the output, we see the rptFile json library enumerates the data and image resources in the report content object. Below shows what I retrieved from a report content object.
Notice the DATASOURCES_CASRESOURCE table, which Michael uses in Programmatically listing data sources in SAS Visual Analytics. You may explore more information in these tables if interested, such as report states, visual elements, etc. In this post, I won't dig further into the report content object.
Get the metadata of a report object
Next, I am going to get the metadata of a report object with its unique report id using the Reports API in the Visualization service. I use the 'GET' request and '/reports/reports/' in the URL. By runing the code snippet below, I get the metadata of the report object in the rptFile json library.
%let BASE_URI=%sysfunc(getoption(SERVICESBASEURL)); FILENAME rptFile TEMP ENCODING='UTF-8'; PROC HTTP METHOD="GET" oauth_bearer=sas_services OUT=rptFile URL = "&BASE_URI/reports/reports/cecac7d7-b957-412e-9709-a3fe504f00b1"; HEADERS "Accept" = "application/vnd.sas.report+json"; RUN; LIBNAME rptFile json;
Below is part of the ALLDATA table from the rptFile library. The table contains metadata of the report object, including its unique id, name, creator, creationTimeStamp, modifiedTimeStamp, links, and so on. But in the table, I can't find the folder location of the report object.
Get the report object folder location
So far, I've retrieved most of the metadata info we are looking for, but not the report object folder location. All VA reports are put under the /SAS Content/ folder or its subfolders in SAS Viya. Yet, no such information exists in the report object or the report content object. How can I get the path of a VA report under the /SAS Content/ folder?
The answer is to use the Folders service on the Core Services API. Folders provide an organizational structure for SAS content as well as external content in Viya. The Folders object itself is a virtual container for other resources or folders, and it persists only the URI of resources managed by other services.
A folder object has two types of members: child and reference. Whereas resources can have references in multiple folders, they are restricted to being the child in a single folder. Resources like VA reports are added as child members of a folder, and the folder persists the URI of the VA report. Thus, we get the folder reversely from the child report by looking for the ancestors of this report object.
By using the Folders API in Core services with a 'GET' request and '/folders/ancestors?childUri=' in the URL, the Proc HTTP code below gets the ancestors of the VA report before getting the full path.
%let BASE_URI=%sysfunc(getoption(SERVICESBASEURL)); FILENAME fldFile TEMP ENCODING='UTF-8'; PROC HTTP METHOD="GET" oauth_bearer=sas_services OUT=fldFile URL = "&BASE_URI/folders/ancestors?childUri=/reports/reports/cecac7d7-b957-412e-9709-a3fe504f00b1"; HEADERS "Accept" = "application/vnd.sas.content.folder.ancestor+json"; RUN; LIBNAME fldFile json;
From the fldFile.ANCESTORS table, we see the metadata of the ancestor folders, including folder id, folder name, creator, type, and its parentFolderURI, etc. The screenshot below is part of the ANCESTORS table. Thus, the path of the specific report concatenates these subfolders to a full path of /SAS Content/NLS/Cindy/.
Get the path for VA reports
Now I have several reports, I need to go through the above steps repeatedly for each report. So, I wrote SAS code to handle these:
- Filter those reports named 'Report 2', using the reports API in Visualization service. Save the list of reports in the ds_rpts dataset. The results include metadata for report id, name, createdBy, CreatedAt, and LastModified.
- For each report in the ds_rpts data set, call the macro named 'save_VA_Report_Path(reportURI)'. The macro accesses the Folders API in Core Services, and saves the path for a given report back in the rptPath column of the ds_rpts data set.
- Print the list of reports with path and other metadata.
The code yields the following output:
You may access my code samples from GitHub and give it a try in your environment. I run the code with SAS Studio 5.2 and VA on SAS Viya 3.5. You may prefer to modify the filter condition as needed (such as createdBy, contains, or more from SAS Viya support filter).
The Reports API is one of many SAS Viya REST APIs. In this post, I've provided multiple discovery paths to follow. You can find more information about this and other APIs on the SAS Viya REST APIs page on the developers portal.
tested your code and it really worked fine.
one additional question: i have a report level dropdown box in my report.
is there a chance to assign a special value to this dropdon box in the code?
You may check the filters supported by rest api at: https://developer.sas.com/apis/rest/Topics/#filters.
This is very useful blog. However, I can see only 20 reports in output list. Looks like default value is 20. Is there any way to change the limit from 20 to 'x' number? If yes, Could you please share the code?
Thanks in advance.
Yes, you are right. The default value is 20. And you may change the default value if necessary, by using the parameter 'limit'. Better to consider the network performance when making it a large value. You may refer details at: https://developer.sas.com/apis/rest/CoreServices/#get-a-list-of-folder-members.
Your code has been very helpful, but I'm looking for a way to execute an existing report from code and export it to Powerpoint or PDF. Do you know if that is possible once I have the path?
As far as I know, there are APIs that can save the entire report or the elements in the report to an SVG image. You may refer to https://developer.sas.com/apis/rest/Visualization/#usage-notes-2 for more.
Here I got a new post on Programmatically export a Visual Analytics report to PDF: https://blogs.sas.com/content/sgf/2021/03/25/programmatically-export-a-visual-analytics-report-to-pdf/.