Model Management

The Model Management API provides basic resources for monitoring performance, comparing models, and running workflow processes.

Making an API Call

Once a client has a valid access token, use it to make requests to SAS Viya REST APIs.

The authenticated token is passed on requests to identify the caller. If a valid OAuth2 token is not provided on the call, the operation fails with a standard 401 Unauthorized response code. SAS REST APIs use the OAuth2 tokens to authorize specific REST API operations. For example, an authenticated user can have authorization to read a resource via a GET method, but not have authorization to update or delete a resource via a PUT or a DELETE methods.

The following call lists top level folders:

cURL

    curl -k -X GET "https://sasserver.sas.com/folders/folders/" \
       -H "Accept: application/json" \
       -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZ..."

Python

import requests
url = "https://sasserver.sas.com/folders/folders/"
payload={}
headers = {"Accept": "application/json", "Authorization": "Bearer eyJhbGciOiJSUzI1NiIsImtpZ..."}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)

Response

{
   "links": [
       {
           "method": "GET",
           "rel": "collection",
           "href": "/folders/folders",
           "uri": "/folders/folders",
           "type": "application/vnd.sas.collection"
       },
       {
           "method": "GET",
...
}

For more examples and information about making REST API calls, refer to this series of articles.


API Organization and Usage Information

The following sections provide information about the organization of SAS Viya rest APIs and the options that can be used when sending calls.

Categories

APIs are grouped for convenience into the following API categories:

API CategoryDescription
Automated Machine LearningAutomates machine learning capabilities
CASCloud Analytic Services API enables users to manage and perform CAS Actions
Compute and JobsActs on SAS compute and analytic servers, including Cloud Analytic Services (CAS)
Data ManagementEnables data manipulation and data quality operations on data sources
Fraud and ComplianceProvides and entry point for ION messages to apply a decision on an incoming message
Health and Life SciencesCRUD operations for Health and Life Sciences processes
Models and DecisionsProvides access to machine scoring and business rules
Platform AdministrationProvides operations for shared resources such as files and folders
Visual InvestigatorEnables users to execute and manage workflows created within SAS Visual Investigator
Visualization and ReportsProvides access to reports and report images

Collections

In SAS Viya REST APIs, collections are aggregations of zero or more resources. Most collections are sets of resources. Alternatively, you can think of collections as a map from resource IDs to a resource.

Most SAS Viya APIs manage collections of resources. For example, the Reports API has a collection of report resources as a top-level resource, and the Files API a collection of file resources as a top-level resource. Each collection is identified with a URL that typically uses the plural form of the noun, such as /reports/reports or /files/files. That means that in the URI /reports/reports, the first 'reports' is the namespace of the API and the second 'reports' represents the name of the collection of reports.

Collection resources are represented with the application/vnd.sas.collection media type, which provides support for paginating, filtering, and sorting those collections.


Filtering

SAS REST APIs support filtering to return only a subset of items in a collection.

SAS REST APIs support two forms of filtering:

  • basic filtering – selects resources by matching one or more members of the resource to the exact values passed as query parameters.
  • filter query parameter – selects resources by matching members of the resource, using comparison operators such as eq, ne, lt, and gt and the logical operators such as AND and OR.

Support for these two filtering methods varies across different SAS APIs. If both are available in a given API, the two forms can be combined. Consider, for example, the report resource from the following REST call:

https://sasserver.sas.com/reports/reports/

The response returns a collection of reports. The following JSON is a partial representation of the report resource:

"items": [
{
  "id": "4eb3b675-e107-4857-a8f4-51aa555ac7e7",
  "name": "Production Report",
  "description": "Production forecasts by region and market segment.",
  "createdBy": "dale",
  "links"[]"iconUri": "/reports/icons/report.gif"
},
{
  "id": "44089b79-0195-47c3-b1ca-4c358623db3",
  "name": "API Changed data source Report",
  "description": "Transform-Created Report Description",
  "createdBy": "jasmine   ",
  "links"[]"iconUri": "/reports/icons/report.gif"
     }]

Now, say we want to only see the reports created by ‘dale’. Filtering can be used to return a subset of reports. The filtering explanations for both types of filtering below use this report example scenario.

Basic Filtering

Basic filtering allows selecting resources by matching one or more members of the resource to values passed as query parameters. For example, to find all reports created by the user dale, a basic filter is:

GET /reports/reports?createdBy=dale

The names of members in the resource representation (such as description, name, createdBy, modifiedBy etc.) are used as the name of the corresponding query parameters. The general form is":

GET /reports/reports?memberName=value&...&memberName=value

Basic filtering supports only exact matches of members or simple set containment. Do not use quotation marks around either the names or the string values when using basic filtering.

Some APIs support nested resources. You can use dot notation to select a nested member, such as imageUris.icon , to filter based on the icon member of the imageUris object.

When multiple basic query parameters are used, there is an implicit AND operation. That is, all basic filter values must match for a resource to be included in the response. For example, the request:

GET /reports/reports?createdBy=dale&name=Production%20Report

returns reports that were created by dale and that have the name Production Report.

Some members are not well suited to exact matching, such as the modifiedTimeStamp, which is a date-time value with sub-second precision: ?modifiedTimeStamp=2017-04-19T14:55:11.643Z. For such requirements, use the filter parameter described below to select resources based on ranges, comparisons, and other selection criteria.

Basic Set Containment Filtering

When using basic filtering, you can pass a pipe-separated set of values. The basic filter matches if the named member matches any of the values in the set. As with simple query parameters, do not use quotation marks around the values.

For example, to find reports created by users dale or elaine or jasmine, use the pipe-separated set containment notation to express the set of values. For example:

GET /reports/reports?createdBy=dale|elaine|jasmine

is URL encoded as:

GET /reports/reports?createdBy=dale|elaine|jasmine

Filtering with the 'filter' Query Parameter

The filter query parameter provides a flexible way to subset the resources from collections by combining comparison and other functions. The general syntax is as follows:

?filter=filterExpression

Unlike basic filtering, the filterExpression enables you to:

  • combine multiple expressions with logical operations (and, or, and, not)
  • make comparisons using relational operators (eq, ne, lt, le, gt, ge)
  • use other functions such as contains, startsWith, in, match, and so on

The simple filter ?filter=true evaluates to true for all items in the collection — this is the default behavior if no filter is provided.

The filter query parameter names a filter expression, which uses a simple expression notation. The filter expression syntax expresses the same condition as a combination of function calls:

and(or(e,not(b)),gt(C,0))

Parentheses surround the comma-separated arguments to each function and are required to differentiate a function from a member name.

For example, the ‘basic’ query used above:

GET /reports/reports?createdBy=dale&name=Production%20Report

can be expressed by combining two equality test functions on the members createdBy and name, combined with the and function:

GET /reports/reports?filter=and(eq(createdBy,'dale'),eq(name,'Production%20Report'))

Filter Expressions

There are three types of expressions that can be used in the filterExpression of a filter query: literals, names, and functions.

Filter Literals

Literals (also known as constants) are fixed values, such as

the string 'dale'
the string 'Production Report'
Boolean literals true and false
numbers such as 100 or -5.75 date, time, and date-time literals

Literals are typically used as arguments to functions.

In filter query parameters, strings can be enclosed in either single or double quotes.
"Dale Smith's ID is 'dale'" 'Dale chose the ID "dale".' Alternatively, you can escape single or double quote characters by doubling them: 'IT assigned the user ID ''dale'' to Dale Smith.'

Names in filter expressions refer to members of the items in the collection, such as the members name, createdBy, modifiedBy, or imageUris.icon from the example report resource above. Names are typically used as arguments to functions, such as comparing the members to literal values, as described below. An example is the expression:

eq(createdBy,'dale')

which is true for any item in the collection that has the exact value 'dale' as its createdBy member.

Date, time, and date-time literals are other name filters.

  • A date literal uses the form yyyy-MM-dd such as 2017-07-27.
  • A time literal uses the form HH:mm:ss and HH:mm:ss.SSSZ where the hours HH range from 00 to 24 and the fractional seconds and time zone are optional. The time zone code Z means UTC (GMT) time zone. Time zone offsets if +HH:mm and -HH:mm are also allowed instead of Z.
  • A date-time literal uses the form yyyy-MM-ddTHH:mm:ss.SSSZ where the fractional seconds and time zone are optional; for example, 2017-06-28T03:18:53.0717Z ?filter=lt(createdBy,2025-09-23T09:52:00Z)

Note: date, time, and date-time values are not quoted as strings.

Filter Function Expressions

Functions operate on one or more values, which form the arguments to the function. A function expression has the form:

ExpressionRule
and(e0, e1 [,..., en])true if and only if all expressions are true; at least two expressions required.
or(e0, e1, [... en])true if one or more expressions are true; at least two expressions required
not(e)true if expression e is false
isNull(e)true if e is null or unset
Relational Functions

Relational functions compare two or more expressions. Most functions accept two or more arguments, in which case the relation must hold for consecutive values. In other words, lt(a,b,c,d) is equivalent to and(lt(a,b),lt(b,c),lt(c,d)) (that is, a < b && b < c && c < d).
This syntax cannot express combinations of relational operators, such as minInclusive ≤ x < maxExclusive; one must use and(le(minInclusive,x),lt(x,maxExclusive)).

ExpressionRule
eq(e0, e1 [,..., en])true if all expressions are equal.
ne(e0, e1)true if the e0 is not equal to e1
lt(e0, e1 [,..., en])true if and only if each expression ei is less than ei+1
le(e0, e1 [,..., en])true if each expression ei is less than or equal to ei+1
gt(e0, e1 [,..., en])true if each expression ei is greater than ei+1
ge(e0, e1 [,..., en])true if each expression ei is greater than or equal to ei+1
in(e, v0, v1 [,..., vn])Set containment, true if the value e is equal to at least one of the vi values.

Relational functions can be combined with date, time, and date-time literals. To find all reports created between January and March 2017 (using GMT).

GET /reports/reports?filter=le(2017-01-01T00:00:00Z,creationTimeStamp,2017-03-31T24:00:00Z)

String Functions

Functions that manipulate string values.

ExpressionRule
match(e,regularExpression)true if the string e matches a regular expression. The regularExpression is a quoted string literal or other expression that yields a string pattern.
matchAll(regularExpression, exp1,...,expn)true if all expressions match the regular expression
matchAny(regularExpression, exp1,...,expn)true if any expressions match the regular expression
match(map,name,regularExpression)true if the member map is a Map or Properties object, which contains an item (key,value) such that and(match(key,name),match(value,regularExpression) is true
contains(e,substring)true if the string e contains the substring; or if e is a list/set/collection, true if an element of e equals substring
startsWith(e,prefix)true if the string e starts with prefix
endsWith(e,suffix)true if the string e ends with the suffix
blank(e)true if the string a consists of only whitespace
length(e)the integer length of the string expression e
substr(e,start,len)the substring of e, starting at start (zero-based index) and including len characters. Negative index start counts backward from the end. If len is omitted, the substring will extend to the end of the string.
upCase(s)convert all character in s to uppercase.
downCase(s)convert all character in s to lowercase.
Locale-sensitive Collation

Several of the above functions require locale-sensitive collation, where the locale is derived by the Accept-Language header passed by the client.

Locale-sensitive collation strength is passed to these functions using one of several reserved identifiers, as optional first arguments. The identifier name is obtained by prefixing the collation options below with a dollar sign ('$'):

Locale-sensitive collationDescription
$primarynormal case-insensitive comparison
$secondaryonly different accent characters are significant
$tertiarynormal case-sensitive comparison
$quaternarypunctuation is considered
$identicalcase, accents, and punctuation differences are significant

If the first parameter is not one of these special identifiers, the default is $identical. These reserved identifiers are ignored when comparing numeric and Boolean values.

Examples of locale-sensitive functions using $tertiary:

ExpresionnDescription
eq($tertiary, a, b,...)equal
ne($tertiary, a, b)not equal
lt($tertiary, a, b,...)less than
le($tertiary, a, b,...)less than or equal
gt($tertiary, a, b,...)greather than
ge($tertiary, a, b,...)greater than or equal
in($tertiary, e, v0, v1, [..., vn])list inclution
contains($tertiary, e, substring)string inclusion
startsWith($tertiary, e, prefix)string prefix
endsWith($tertiary, e, suffix)string suffix

Combining Basic Filtering and the Filter Query Parameter

An API request can combine basic filtering and the filter query parameter. When both are used, the request combines them by adding an implicit and function to the existing filter query parameter. For example, for

GET .../resource?name=dale&format=ruled&filter=or(bounded,lt(shipDate,2017-07-27))

The basic filters (name=dale and format=ruled) will be merged into the filter expression, or(bounded,lt(shipDate,2017-07-27)), yielding the effective filter query

GET .../resource?filter=and(eq(name,'dale'),eq(format,'ruled'),or(bounded,lt(shipDate,2017-07-27)))

Note that the resulting filter expression is always false if the basic filter and the filter specify mutually exclusive values:

GET .../resource?name=dale&format=ruled&filter=eq(name,'jack')

The effective filter query:

GET .../resource?filter=and(eq(name,'dale'),eq(format,'ruled'),eq(name,'robert')

This is always false (resulting in an empty collection result) because name cannot be 'dale' and 'robert' at the same time.


Sorting

When making a request for a collection or applying a query on its subset, a client often requires that the response data is returned in a sorted order. Sort criteria are specified by the sortBy query parameter:

GET /reports/reports?sortBy=name,description

This API request results in a paginated collection view that is sorted -- first by the report name, then by the description.

The value of the sortBy parameter is one or more sort criteria, separated by commas. Sort criteria must include one or more keys that match the members of a resource. Each sort criteria can also have sort options, which specify sort order or collation strength.

Note: Not all APIs support collation strength options. In those cases, values specified in the sortBy parameter are not honored by the underlying service.

sortBy Syntax

The syntax of the sortBy criteria is defined by the following Backus-Naur form syntax:

sortCriteria ::= criteria [ ',' sortCriteria ]
criteria ::= key [ ':' options ]
options ::= option [ ':' options ]
option ::= 'ascending' | 'descending'
option ::= 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'identical'

The key is the name of a member (also known as a field) in the resources that are being sorted. For example, if a collection resource /someApi/models contains a collection of models in which each model has member names model, type, modifiedTimeStamp and modifiedBy, then a client can request that the collection of models is sorted first by modifiedTimeStamp (most recent first), then by modifiedBy (who last modified the resource), then by type, then by name, and finally by model name:

GET /someApi/models?sortBy=modifiedTimeStamp:descending,modifiedBy,type,name

If more than one criterion exists, they are considered subgroup sorting criteria. The order is important: the second sort criteria, if present, applies to items that are equal according to the first sort criteria, and so on. It is unlikely that many resources will have the same modifiedTimeStamp. For the query

GET /someApi/models?sortBy=modifiedBy,type,modifiedTimeStamp:descending

there are likely to be several models modified by each user, and for each user, several models with the same type. Within those subgroups, the items are sorted by descending modified timestamp.

sortBy Criteria Options

Ordering Options

OptionDescription
ascending (Default)sort in ascending order
descendingsort in descending order

Matching Options

OptionDescription
primarynormal case-sensitive comparison; for example, "a" ≠ "b", "a" == "A"
secondarydifferent accent characters are significant; for example, "as" ≠ "às" ≠ "at", "at" == "At"
tertiary (Default)normal case-sensitive comparison; for example, "ao" ≠ "Ao" ≠ "aò", "A" == "Ⓐ"
quaternarypunctuation is considered; for example, "ab" ≠ "a-b" ≠ "aB").
identicalcase, accents, and punctuation differences are significant
  • If you want case-sensitive comparison, use tertiary. For case-insensitive comparison, use either primary or secondary; for example, depending on whether you want á to be grouped with â.

  • If more than one of {ascending,descending} appear, the last occurrence is used. If more than one of {primary,secondary,tertiary,identical} appear, the last occurrence is used. The default sorting strength is tertiary.

  • Consult the documentation for each API to determine the default sort order for its orderable collections. If it is not documented, assume that the collection order is not guaranteed and the service might return items in a different order in future requests.

  • For pagination, the first, next, prev, and last link relations, if present, preserve the sortBy query parameter if it was used. For pagination, the start query parameters are relative to sorted collection indexes.

The sort keys are selected from the full set of fields in the collection's underlying resource, which can be a superset of the fields in the requested representation on any specific query.


SAS Viya APIs follow conventions including links in responses. Just like an HTML page can include links that connect the page to related pages, links in responses connect the resources of the API to operations available for that resource or to related resources.

Here is an example of using the Reports API to retrieve a report:

GET /reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7

The response includes a set of links, such as the following:

{
  "id": "4ebf1327-c72b-4857-a8f4-421a555ac7e7",
  "name": "monthly-sales-analysis",
  "description": "Monthly sales analysis report",
  ....,
  "links": [{
      "method": "GET",
      "rel": "self",
      "href": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7",
      "uri": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7",
      "type": "application/vnd.sas.report"},
    {
      "method": "PUT",
      "rel": "update",
      "href": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7",
      "uri": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7",
      "type": "application/vnd.sas.report",
      "responseType": "application/vnd.sas.report"},
    {
      "method": "DELETE",
      "rel": "delete",
      "href": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7",
      "uri": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7"},
    {
      "method": "GET",
      "rel": "content",
      "href": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7/content",
      "uri": "/reports/reports/4ebf1327-c72b-4857-a8f4-421a555ac7e7/content",
      "type": "application/vnd.sas.report.content"}
  ],
  ....
}

The returned links indicate actions, operations, or state transitions that the client can make from the current resource or related resources. In the example above, the links with the "rel" values of "update" and "delete" indicate state transitions available from the current resource. Specifically, the links define operations to update or delete the report.

Links can also represent an object's relationships to other resources. For example, the link with the value "content" for the "rel" member in the above example (called "the content link") associates the report with the report's content.


Pagination

Collections in SAS Viya REST APIs can contain large numbers of resources, and it is inefficient to request all of them at once. APIs use pagination, which returns one page of items at a time - each page representing a manageable subset of the collection. Each page can also contain links to other pages, such as the first and last pages, and the previous and next pages. Pagination can also be combined with sorting and filtering.

Pagination Query Parameters

For collections, APIs use start and limit query parameters to fetch (GET) subsets of collections. Given that a client application might only be displayed or operate on a small subset of the collection, the pagination query parameters prevent the transmission of entire, large collections across networks. Consider the following:
GET /collection?start=item-index&limit=max-item-count
GET /collection?start=item-index
GET /collection?limit=max-item-count

ParameterDescription
startStart is a zero-based integer index that specifies the starting point in the collection. The default value is 0, which refers to the first item in the index.
limitAn integer that specifies the maximum number of items to return in the response.

Examples
The following call to the Reports API returns 20 records by default: https://sasserver.sas.com/reports/reports

To return the first 100 items: https://sasserver.sas.com/reports/reports?start=0&limit=100

To return items 101-200: https://sasserver.sas.com/reports/reports?start=101&limit=100

Check the documentation for each API to determine the default limit for its paginated collections.

Collection responses return hypermedia controls with links to navigate pages:

ParameterDescription
firstLink to the first page in the collection (?start=0).
prevA link to the previous page in the collection, if there is one.
nextA link to the next page in the collection, if there is one.
lastA link to the last page in the collection.
selfA link to the current page in the collection, using the same filter and sort criteria

Example Shape
For the reports call (above), a response might include:
“method”: “GET”,
“rel”: “self”,
“href”: “/reports/reports/72642fd5-780e-4406-a177-9067a9a6f5bc”,
“uri”: “/reports/reports/72642fd5-780e-4406-a177-9067a9a6f5bc”,
“type”: “application/vnd.sas.report”

Conditional Operations

SAS Viya REST APIs support conditional operations to help manage concurrent access to resources. This ensures that the update requests (PUT or PATCH, for example) apply only if the client's version of the resource is current. These operations rely on HTTP/1.1 headers to ensure updates are only applied if the client’s version of the resource is current:

  • Not all SAS APIs support preconditions
  • They are commonly used in endpoints where concurrent updates are likely.
  • Supported APIs rely on either entity tags (ETags) or last-modified timestamps to validate preconditions.

Entity Tags

An entity tag (ETag) is an opaque string that marks (or “tags”) the current state of a resource. The ETag changes each time the resource is updated, and it is returned in the ETag response header when supported by the operation.

SAS APIs that use ETags must include the latest ETag value (from the latest operation on the resource) in the If-Match request header. This acts as a precondition: the update operation fails if the value of the If-Match header on the request does not match the current entity tag of the resource. A precondition failure means that a client has stale data, and the resource has been updated since the current client last obtained the entity tag. Clients can simply make a GET request to the resource to obtain a new ETag and then retry the operation, if appropriate.

Last-Modified Timestamps

APIs that use a Last-Modified timestamp return a timestamp that changes each time a resource is updated. Preconditions based on “last-modified” return a Last-Modified response header. Resources expect an If-Unmodified-Since precondition request header with the timestamp value based on the previous Last-Modified timestamp.

Timestamps use the format EEE, dd MMM yyyy HH:mm:ss GMT (e.g., Thu, 13 Sep 2016 07:27:08 GMT).

Precondition Status Codes

SAS Viya APIs return standard precondition HTTP status codes:

CodeStatusDescription
412Precondition FailedReturned if an API operation specifies preconditions and the precondition is not satisfied
428Precondition RequiredReturned if an operation requires preconditions but the client does not pass the required preconditions request headers

Precondition failures occur when a client has stale data, and the resource has been updated since the current client last obtained the entity tag. Clients can simply make a GET request to the resource to obtain a new entity tag and then retry the operation if appropriate.

Note that if an operation receives both If-Match and If-Unmodified-Since preconditions, only the If-Match precondition is checked and If-Unmodified-Since is ignored.